mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 17:35:36 +00:00
app: [Wayland] hard-code border resize gestures
We're about to remove the system.Action machinery for initiating resize gestures. This is the Wayland implementation that hard-codes the border drag gesture for resizing. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+110
-45
@@ -168,7 +168,23 @@ type window struct {
|
|||||||
cursor struct {
|
cursor struct {
|
||||||
theme *C.struct_wl_cursor_theme
|
theme *C.struct_wl_cursor_theme
|
||||||
cursor *C.struct_wl_cursor
|
cursor *C.struct_wl_cursor
|
||||||
surf *C.struct_wl_surface
|
// system is the active cursor for system gestures
|
||||||
|
// such as border resizes and window moves. It
|
||||||
|
// is nil if the pointer is not in a system gesture
|
||||||
|
// area.
|
||||||
|
system *C.struct_wl_cursor
|
||||||
|
surf *C.struct_wl_surface
|
||||||
|
cursors struct {
|
||||||
|
pointer *C.struct_wl_cursor
|
||||||
|
resizeNorth *C.struct_wl_cursor
|
||||||
|
resizeSouth *C.struct_wl_cursor
|
||||||
|
resizeWest *C.struct_wl_cursor
|
||||||
|
resizeEast *C.struct_wl_cursor
|
||||||
|
resizeNorthWest *C.struct_wl_cursor
|
||||||
|
resizeNorthEast *C.struct_wl_cursor
|
||||||
|
resizeSouthWest *C.struct_wl_cursor
|
||||||
|
resizeSouthEast *C.struct_wl_cursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fling struct {
|
fling struct {
|
||||||
@@ -363,9 +379,8 @@ func (d *wlDisplay) createNativeWindow(options []Option) (*window, error) {
|
|||||||
w.destroy()
|
w.destroy()
|
||||||
return nil, errors.New("wayland: wl_cursor_theme_load failed")
|
return nil, errors.New("wayland: wl_cursor_theme_load failed")
|
||||||
}
|
}
|
||||||
cname := C.CString("left_ptr")
|
w.loadCursors()
|
||||||
defer C.free(unsafe.Pointer(cname))
|
w.cursor.cursor = w.cursor.cursors.pointer
|
||||||
w.cursor.cursor = C.wl_cursor_theme_get_cursor(w.cursor.theme, cname)
|
|
||||||
if w.cursor.cursor == nil {
|
if w.cursor.cursor == nil {
|
||||||
w.destroy()
|
w.destroy()
|
||||||
return nil, errors.New("wayland: wl_cursor_theme_get_cursor failed")
|
return nil, errors.New("wayland: wl_cursor_theme_get_cursor failed")
|
||||||
@@ -388,6 +403,33 @@ func (d *wlDisplay) createNativeWindow(options []Option) (*window, error) {
|
|||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *window) loadCursors() {
|
||||||
|
w.cursor.cursors.pointer = w.loadCursor(pointer.CursorDefault)
|
||||||
|
w.cursor.cursors.resizeNorth = w.loadCursor(pointer.CursorNorthResize)
|
||||||
|
w.cursor.cursors.resizeSouth = w.loadCursor(pointer.CursorSouthResize)
|
||||||
|
w.cursor.cursors.resizeWest = w.loadCursor(pointer.CursorWestResize)
|
||||||
|
w.cursor.cursors.resizeEast = w.loadCursor(pointer.CursorEastResize)
|
||||||
|
w.cursor.cursors.resizeSouthWest = w.loadCursor(pointer.CursorSouthWestResize)
|
||||||
|
w.cursor.cursors.resizeSouthEast = w.loadCursor(pointer.CursorSouthEastResize)
|
||||||
|
w.cursor.cursors.resizeNorthWest = w.loadCursor(pointer.CursorNorthWestResize)
|
||||||
|
w.cursor.cursors.resizeNorthEast = w.loadCursor(pointer.CursorNorthEastResize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) loadCursor(name pointer.Cursor) *C.struct_wl_cursor {
|
||||||
|
if name == pointer.CursorNone {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
xcursor := xCursor[name]
|
||||||
|
cname := C.CString(xcursor)
|
||||||
|
defer C.free(unsafe.Pointer(cname))
|
||||||
|
c := C.wl_cursor_theme_get_cursor(w.cursor.theme, cname)
|
||||||
|
if c == nil {
|
||||||
|
// Fall back to default cursor.
|
||||||
|
c = w.cursor.cursors.pointer
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
func callbackDelete(k unsafe.Pointer) {
|
func callbackDelete(k unsafe.Pointer) {
|
||||||
callbackMap.Delete(k)
|
callbackMap.Delete(k)
|
||||||
}
|
}
|
||||||
@@ -833,6 +875,10 @@ func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t,
|
|||||||
switch wbtn {
|
switch wbtn {
|
||||||
case BTN_LEFT:
|
case BTN_LEFT:
|
||||||
btn = pointer.ButtonPrimary
|
btn = pointer.ButtonPrimary
|
||||||
|
if _, edge := w.systemGesture(); edge != 0 {
|
||||||
|
w.resize(serial, edge)
|
||||||
|
return
|
||||||
|
}
|
||||||
case BTN_RIGHT:
|
case BTN_RIGHT:
|
||||||
btn = pointer.ButtonSecondary
|
btn = pointer.ButtonSecondary
|
||||||
case BTN_MIDDLE:
|
case BTN_MIDDLE:
|
||||||
@@ -1031,8 +1077,6 @@ func (w *window) Perform(actions system.Action) {
|
|||||||
w.move()
|
w.move()
|
||||||
case system.ActionClose:
|
case system.ActionClose:
|
||||||
w.dead = true
|
w.dead = true
|
||||||
default:
|
|
||||||
w.resize(action)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1045,60 +1089,39 @@ func (w *window) move() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) resize(a system.Action) {
|
func (w *window) resize(serial, edge C.uint32_t) {
|
||||||
if w.inCompositor || w.seat == nil {
|
s := w.seat
|
||||||
return
|
if w.inCompositor || s == nil {
|
||||||
}
|
|
||||||
var edge int
|
|
||||||
switch a {
|
|
||||||
case system.ActionResizeNorth:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP
|
|
||||||
case system.ActionResizeSouth:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM
|
|
||||||
case system.ActionResizeEast:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_LEFT
|
|
||||||
case system.ActionResizeWest:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_RIGHT
|
|
||||||
case system.ActionResizeNorthWest:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT
|
|
||||||
case system.ActionResizeNorthEast:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT
|
|
||||||
case system.ActionResizeSouthEast:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT
|
|
||||||
case system.ActionResizeSouthWest:
|
|
||||||
edge = C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT
|
|
||||||
default:
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.inCompositor = true
|
w.inCompositor = true
|
||||||
s := w.seat
|
C.xdg_toplevel_resize(w.topLvl, s.seat, serial, edge)
|
||||||
C.xdg_toplevel_resize(w.topLvl, s.seat, s.serial, C.uint32_t(edge))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) SetCursor(cursor pointer.Cursor) {
|
func (w *window) SetCursor(cursor pointer.Cursor) {
|
||||||
|
w.cursor.cursor = w.loadCursor(cursor)
|
||||||
|
w.updateCursor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) updateCursor() {
|
||||||
ptr := w.disp.seat.pointer
|
ptr := w.disp.seat.pointer
|
||||||
if ptr == nil {
|
if ptr == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cursor == pointer.CursorNone {
|
|
||||||
C.wl_pointer_set_cursor(ptr, w.serial, nil, 0, 0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
xcursor := xCursor[cursor]
|
|
||||||
cname := C.CString(xcursor)
|
|
||||||
defer C.free(unsafe.Pointer(cname))
|
|
||||||
c := C.wl_cursor_theme_get_cursor(w.cursor.theme, cname)
|
|
||||||
if c == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.cursor.cursor = c
|
|
||||||
w.setCursor(ptr, w.serial)
|
w.setCursor(ptr, w.serial)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) setCursor(pointer *C.struct_wl_pointer, serial C.uint32_t) {
|
func (w *window) setCursor(pointer *C.struct_wl_pointer, serial C.uint32_t) {
|
||||||
|
c := w.cursor.system
|
||||||
|
if c == nil {
|
||||||
|
c = w.cursor.cursor
|
||||||
|
}
|
||||||
|
if c == nil {
|
||||||
|
C.wl_pointer_set_cursor(pointer, w.serial, nil, 0, 0)
|
||||||
|
return
|
||||||
|
}
|
||||||
// Get images[0].
|
// Get images[0].
|
||||||
img := *w.cursor.cursor.images
|
img := *c.images
|
||||||
buf := C.wl_cursor_image_get_buffer(img)
|
buf := C.wl_cursor_image_get_buffer(img)
|
||||||
if buf == nil {
|
if buf == nil {
|
||||||
return
|
return
|
||||||
@@ -1526,6 +1549,48 @@ func (w *window) onPointerMotion(x, y C.wl_fixed_t, t C.uint32_t) {
|
|||||||
Time: time.Duration(t) * time.Millisecond,
|
Time: time.Duration(t) * time.Millisecond,
|
||||||
Modifiers: w.disp.xkb.Modifiers(),
|
Modifiers: w.disp.xkb.Modifiers(),
|
||||||
})
|
})
|
||||||
|
c, _ := w.systemGesture()
|
||||||
|
if c != w.cursor.system {
|
||||||
|
w.cursor.system = c
|
||||||
|
w.updateCursor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateCursor updates the system gesture cursor according to the pointer
|
||||||
|
// position.
|
||||||
|
func (w *window) systemGesture() (*C.struct_wl_cursor, C.uint32_t) {
|
||||||
|
if w.config.Mode != Windowed {
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
border := w.w.w.metric.Dp(5)
|
||||||
|
x, y, size := int(w.lastPos.X), int(w.lastPos.Y), w.config.Size
|
||||||
|
north := y <= border
|
||||||
|
south := y >= size.Y-border
|
||||||
|
west := x <= border
|
||||||
|
east := x >= size.X-border
|
||||||
|
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case !north && !south && !west && !east:
|
||||||
|
return nil, 0
|
||||||
|
case north && west:
|
||||||
|
return w.cursor.cursors.resizeNorthWest, C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT
|
||||||
|
case north && east:
|
||||||
|
return w.cursor.cursors.resizeNorthEast, C.XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT
|
||||||
|
case south && west:
|
||||||
|
return w.cursor.cursors.resizeSouthWest, C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT
|
||||||
|
case south && east:
|
||||||
|
return w.cursor.cursors.resizeSouthEast, C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT
|
||||||
|
case north:
|
||||||
|
return w.cursor.cursors.resizeNorth, C.XDG_TOPLEVEL_RESIZE_EDGE_TOP
|
||||||
|
case south:
|
||||||
|
return w.cursor.cursors.resizeSouth, C.XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM
|
||||||
|
case west:
|
||||||
|
return w.cursor.cursors.resizeWest, C.XDG_TOPLEVEL_RESIZE_EDGE_LEFT
|
||||||
|
case east:
|
||||||
|
return w.cursor.cursors.resizeEast, C.XDG_TOPLEVEL_RESIZE_EDGE_RIGHT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) updateOpaqueRegion() {
|
func (w *window) updateOpaqueRegion() {
|
||||||
|
|||||||
Reference in New Issue
Block a user