mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
app: [Windows] support resize gestures for undecorated windows
We're about to remove the client-controlled system.Action machinery for resize gestures initiated by the client. This is the replacement implementation for Windows, where the behaviour is hard-coded to mimic the decorated automatic handling. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -113,7 +113,15 @@ const (
|
|||||||
|
|
||||||
HWND_TOPMOST = ^(uint32(1) - 1) // -1
|
HWND_TOPMOST = ^(uint32(1) - 1) // -1
|
||||||
|
|
||||||
HTCLIENT = 1
|
HTCLIENT = 1
|
||||||
|
HTLEFT = 10
|
||||||
|
HTRIGHT = 11
|
||||||
|
HTTOP = 12
|
||||||
|
HTTOPLEFT = 13
|
||||||
|
HTTOPRIGHT = 14
|
||||||
|
HTBOTTOM = 15
|
||||||
|
HTBOTTOMLEFT = 16
|
||||||
|
HTBOTTOMRIGHT = 17
|
||||||
|
|
||||||
IDC_APPSTARTING = 32650 // Standard arrow and small hourglass
|
IDC_APPSTARTING = 32650 // Standard arrow and small hourglass
|
||||||
IDC_ARROW = 32512 // Standard arrow
|
IDC_ARROW = 32512 // Standard arrow
|
||||||
@@ -146,13 +154,16 @@ const (
|
|||||||
|
|
||||||
SCS_SETSTR = GCS_COMPREADSTR | GCS_COMPSTR
|
SCS_SETSTR = GCS_COMPREADSTR | GCS_COMPSTR
|
||||||
|
|
||||||
|
SM_CXSIZEFRAME = 32
|
||||||
|
SM_CYSIZEFRAME = 33
|
||||||
|
|
||||||
SW_SHOWDEFAULT = 10
|
SW_SHOWDEFAULT = 10
|
||||||
SW_SHOWMINIMIZED = 2
|
SW_SHOWMINIMIZED = 2
|
||||||
SW_SHOWMAXIMIZED = 3
|
SW_SHOWMAXIMIZED = 3
|
||||||
SW_SHOWNORMAL = 1
|
SW_SHOWNORMAL = 1
|
||||||
SW_SHOW = 5
|
SW_SHOW = 5
|
||||||
SWP_FRAMECHANGED = 0x0020
|
|
||||||
|
|
||||||
|
SWP_FRAMECHANGED = 0x0020
|
||||||
SWP_NOMOVE = 0x0002
|
SWP_NOMOVE = 0x0002
|
||||||
SWP_NOOWNERZORDER = 0x0200
|
SWP_NOOWNERZORDER = 0x0200
|
||||||
SWP_NOSIZE = 0x0001
|
SWP_NOSIZE = 0x0001
|
||||||
@@ -231,6 +242,7 @@ const (
|
|||||||
WM_MOUSEMOVE = 0x0200
|
WM_MOUSEMOVE = 0x0200
|
||||||
WM_MOUSEWHEEL = 0x020A
|
WM_MOUSEWHEEL = 0x020A
|
||||||
WM_MOUSEHWHEEL = 0x020E
|
WM_MOUSEHWHEEL = 0x020E
|
||||||
|
WM_NCHITTEST = 0x0084
|
||||||
WM_PAINT = 0x000F
|
WM_PAINT = 0x000F
|
||||||
WM_QUIT = 0x0012
|
WM_QUIT = 0x0012
|
||||||
WM_SETCURSOR = 0x0020
|
WM_SETCURSOR = 0x0020
|
||||||
@@ -316,6 +328,7 @@ var (
|
|||||||
_GetMessage = user32.NewProc("GetMessageW")
|
_GetMessage = user32.NewProc("GetMessageW")
|
||||||
_GetMessageTime = user32.NewProc("GetMessageTime")
|
_GetMessageTime = user32.NewProc("GetMessageTime")
|
||||||
_GetMonitorInfo = user32.NewProc("GetMonitorInfoW")
|
_GetMonitorInfo = user32.NewProc("GetMonitorInfoW")
|
||||||
|
_GetSystemMetrics = user32.NewProc("GetSystemMetrics")
|
||||||
_GetWindowLong = user32.NewProc("GetWindowLongPtrW")
|
_GetWindowLong = user32.NewProc("GetWindowLongPtrW")
|
||||||
_GetWindowLong32 = user32.NewProc("GetWindowLongW")
|
_GetWindowLong32 = user32.NewProc("GetWindowLongW")
|
||||||
_GetWindowPlacement = user32.NewProc("GetWindowPlacement")
|
_GetWindowPlacement = user32.NewProc("GetWindowPlacement")
|
||||||
@@ -499,6 +512,11 @@ func GetMessageTime() time.Duration {
|
|||||||
return time.Duration(r) * time.Millisecond
|
return time.Duration(r) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSystemMetrics(nIndex int) int {
|
||||||
|
r, _, _ := _GetSystemMetrics.Call(uintptr(nIndex))
|
||||||
|
return int(r)
|
||||||
|
}
|
||||||
|
|
||||||
// GetWindowDPI returns the effective DPI of the window.
|
// GetWindowDPI returns the effective DPI of the window.
|
||||||
func GetWindowDPI(hwnd syscall.Handle) int {
|
func GetWindowDPI(hwnd syscall.Handle) int {
|
||||||
// Check for GetDpiForWindow, introduced in Windows 10.
|
// Check for GetDpiForWindow, introduced in Windows 10.
|
||||||
|
|||||||
+48
-2
@@ -54,8 +54,9 @@ type window struct {
|
|||||||
|
|
||||||
animating bool
|
animating bool
|
||||||
|
|
||||||
deltas winDeltas
|
deltas winDeltas
|
||||||
config Config
|
borderSize image.Point
|
||||||
|
config Config
|
||||||
}
|
}
|
||||||
|
|
||||||
const _WM_WAKEUP = windows.WM_USER + iota
|
const _WM_WAKEUP = windows.WM_USER + iota
|
||||||
@@ -210,6 +211,11 @@ func (w *window) update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.config.Size = size
|
w.config.Size = size
|
||||||
|
|
||||||
|
w.borderSize = image.Pt(
|
||||||
|
windows.GetSystemMetrics(windows.SM_CXSIZEFRAME),
|
||||||
|
windows.GetSystemMetrics(windows.SM_CYSIZEFRAME),
|
||||||
|
)
|
||||||
w.w.Event(ConfigEvent{Config: w.config})
|
w.w.Event(ConfigEvent{Config: w.config})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +285,15 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr
|
|||||||
w.w.Event(key.FocusEvent{Focus: true})
|
w.w.Event(key.FocusEvent{Focus: true})
|
||||||
case windows.WM_KILLFOCUS:
|
case windows.WM_KILLFOCUS:
|
||||||
w.w.Event(key.FocusEvent{Focus: false})
|
w.w.Event(key.FocusEvent{Focus: false})
|
||||||
|
case windows.WM_NCHITTEST:
|
||||||
|
if w.config.Decorated || w.config.Mode != Windowed {
|
||||||
|
// Let the system handle it.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x, y := coordsFromlParam(lParam)
|
||||||
|
np := windows.Point{X: int32(x), Y: int32(y)}
|
||||||
|
windows.ScreenToClient(w.hwnd, &np)
|
||||||
|
return w.hitTest(int(np.X), int(np.Y))
|
||||||
case windows.WM_MOUSEMOVE:
|
case windows.WM_MOUSEMOVE:
|
||||||
x, y := coordsFromlParam(lParam)
|
x, y := coordsFromlParam(lParam)
|
||||||
p := f32.Point{X: float32(x), Y: float32(y)}
|
p := f32.Point{X: float32(x), Y: float32(y)}
|
||||||
@@ -411,6 +426,37 @@ func getModifiers() key.Modifiers {
|
|||||||
return kmods
|
return kmods
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hitTest returns the non-client area hit by the point, needed to
|
||||||
|
// process WM_NCHITTEST.
|
||||||
|
func (w *window) hitTest(x, y int) uintptr {
|
||||||
|
top := y <= w.borderSize.Y
|
||||||
|
bottom := y >= w.config.Size.Y-w.borderSize.Y
|
||||||
|
left := x <= w.borderSize.X
|
||||||
|
right := x >= w.config.Size.X-w.borderSize.X
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
fallthrough
|
||||||
|
case !top && !bottom && !left && !right:
|
||||||
|
return windows.HTCLIENT
|
||||||
|
case top && left:
|
||||||
|
return windows.HTTOPLEFT
|
||||||
|
case top && right:
|
||||||
|
return windows.HTTOPRIGHT
|
||||||
|
case bottom && left:
|
||||||
|
return windows.HTBOTTOMLEFT
|
||||||
|
case bottom && right:
|
||||||
|
return windows.HTBOTTOMRIGHT
|
||||||
|
case top:
|
||||||
|
return windows.HTTOP
|
||||||
|
case bottom:
|
||||||
|
return windows.HTBOTTOM
|
||||||
|
case left:
|
||||||
|
return windows.HTLEFT
|
||||||
|
case right:
|
||||||
|
return windows.HTRIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr, kmods key.Modifiers) {
|
func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr, kmods key.Modifiers) {
|
||||||
var typ pointer.Type
|
var typ pointer.Type
|
||||||
if press {
|
if press {
|
||||||
|
|||||||
Reference in New Issue
Block a user