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:
Elias Naur
2022-06-25 17:37:41 +02:00
parent fd3a3eb1b9
commit b34dc63531
+110 -45
View File
@@ -168,7 +168,23 @@ type window struct {
cursor struct {
theme *C.struct_wl_cursor_theme
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 {
@@ -363,9 +379,8 @@ func (d *wlDisplay) createNativeWindow(options []Option) (*window, error) {
w.destroy()
return nil, errors.New("wayland: wl_cursor_theme_load failed")
}
cname := C.CString("left_ptr")
defer C.free(unsafe.Pointer(cname))
w.cursor.cursor = C.wl_cursor_theme_get_cursor(w.cursor.theme, cname)
w.loadCursors()
w.cursor.cursor = w.cursor.cursors.pointer
if w.cursor.cursor == nil {
w.destroy()
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
}
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) {
callbackMap.Delete(k)
}
@@ -833,6 +875,10 @@ func gio_onPointerButton(data unsafe.Pointer, p *C.struct_wl_pointer, serial, t,
switch wbtn {
case BTN_LEFT:
btn = pointer.ButtonPrimary
if _, edge := w.systemGesture(); edge != 0 {
w.resize(serial, edge)
return
}
case BTN_RIGHT:
btn = pointer.ButtonSecondary
case BTN_MIDDLE:
@@ -1031,8 +1077,6 @@ func (w *window) Perform(actions system.Action) {
w.move()
case system.ActionClose:
w.dead = true
default:
w.resize(action)
}
})
}
@@ -1045,60 +1089,39 @@ func (w *window) move() {
}
}
func (w *window) resize(a system.Action) {
if w.inCompositor || w.seat == nil {
return
}
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:
func (w *window) resize(serial, edge C.uint32_t) {
s := w.seat
if w.inCompositor || s == nil {
return
}
w.inCompositor = true
s := w.seat
C.xdg_toplevel_resize(w.topLvl, s.seat, s.serial, C.uint32_t(edge))
C.xdg_toplevel_resize(w.topLvl, s.seat, serial, edge)
}
func (w *window) SetCursor(cursor pointer.Cursor) {
w.cursor.cursor = w.loadCursor(cursor)
w.updateCursor()
}
func (w *window) updateCursor() {
ptr := w.disp.seat.pointer
if ptr == nil {
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)
}
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].
img := *w.cursor.cursor.images
img := *c.images
buf := C.wl_cursor_image_get_buffer(img)
if buf == nil {
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,
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() {