summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-05-23 17:01:56 -0400
committerPietro Gagliardi <[email protected]>2014-05-23 17:01:56 -0400
commit582e3b4644c25c273e790bc646fd5a28c3a9a85c (patch)
treeb6c65b5a959a10ca54d2b6901b92220ea4cb915b
parent92e4d322841a0267605d9f1b25499cdaa0994895 (diff)
Implemented triple-clicks and up on Windows.
-rw-r--r--area_windows.go63
-rw-r--r--events_notdarwin.go2
-rw-r--r--sysdata_windows.go1
3 files changed, 36 insertions, 30 deletions
diff --git a/area_windows.go b/area_windows.go
index b0f8e74..4270046 100644
--- a/area_windows.go
+++ b/area_windows.go
@@ -459,7 +459,18 @@ func getModifiers() (m Modifiers) {
return m
}
-func areaMouseEvent(s *sysData, button uint, up bool, count uint, wparam _WPARAM, lparam _LPARAM) {
+const (
+ _SM_CXDOUBLECLK = 36
+ _SM_CYDOUBLECLK = 37
+)
+
+var (
+ _getMessageTime = user32.NewProc("GetMessageTime")
+ _getDoubleClickTime = user32.NewProc("GetDoubleClickTime")
+ _getSystemMetrics = user32.NewProc("GetSystemMetrics")
+)
+
+func areaMouseEvent(s *sysData, button uint, up bool, wparam _WPARAM, lparam _LPARAM) {
var me MouseEvent
xpos, ypos := getScrollPos(s.hwnd) // mouse coordinates are relative to control; make them relative to Area
@@ -471,9 +482,19 @@ func areaMouseEvent(s *sysData, button uint, up bool, count uint, wparam _WPARAM
}
if up {
me.Up = button
- } else {
+ } else if button != 0 { // don't run the click counter if the mouse was only moved
me.Down = button
- me.Count = count
+ // this returns a LONG, which is int32, but we don't need to worry about the signedness because for the same bit widths and two's complement arithmetic, s1-s2 == u1-u2 if bits(s1)==bits(s2) and bits(u1)==bits(u2) (and Windows requires two's complement: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/27/422551.aspx)
+ // TODO actually will this break with negative numbers on systems where uintptr is 64 bits wide? only if the ABI doesn't sign-extend...
+ time, _, _ := _getMessageTime.Call()
+ // this returns a UINT, which is uint32; don't worry about the smaller size as sign extension won't matter here (see the above)
+ maxTime, _, _ := _getDoubleClickTime.Call()
+ // ignore zero returns and errors; MSDN says zero will be returned on error but that GetLastError() is meaningless
+ // these should be unsigned... TODO MSDN doesn't say and GetSystemMetrics() returns an int (int32)
+ xdist, _, _ := _getSystemMetrics.Call(_SM_CXDOUBLECLK)
+ ydist, _, _ := _getSystemMetrics.Call(_SM_CYDOUBLECLK)
+ me.Count = s.clickCounter.click(button, me.Pos.X, me.Pos.Y,
+ time, maxTime, int(xdist / 2), int(ydist / 2))
}
// though wparam will contain control and shift state, let's use just one function to get modifiers for both keyboard and mouse events; it'll work the same anyway since we have to do this for alt and windows key (super)
me.Modifiers = getModifiers()
@@ -633,46 +654,33 @@ func areaWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lPara
}
return defwndproc()
case _WM_MOUSEMOVE:
- areaMouseEvent(s, 0, false, 0, wParam, lParam)
+ areaMouseEvent(s, 0, false, wParam, lParam)
return 0
case _WM_LBUTTONDOWN:
- areaMouseEvent(s, 1, false, 1, wParam, lParam)
- return 0
- case _WM_LBUTTONDBLCLK:
- areaMouseEvent(s, 1, false, 2, wParam, lParam)
+ areaMouseEvent(s, 1, false, wParam, lParam)
return 0
case _WM_LBUTTONUP:
- areaMouseEvent(s, 1, true, 0, wParam, lParam)
+ areaMouseEvent(s, 1, true, wParam, lParam)
return 0
case _WM_MBUTTONDOWN:
- areaMouseEvent(s, 2, false, 1, wParam, lParam)
- return 0
- case _WM_MBUTTONDBLCLK:
- areaMouseEvent(s, 2, false, 2, wParam, lParam)
+ areaMouseEvent(s, 2, false, wParam, lParam)
return 0
case _WM_MBUTTONUP:
- areaMouseEvent(s, 2, true, 0, wParam, lParam)
+ areaMouseEvent(s, 2, true, wParam, lParam)
return 0
case _WM_RBUTTONDOWN:
- areaMouseEvent(s, 3, false, 1, wParam, lParam)
- return 0
- case _WM_RBUTTONDBLCLK:
- areaMouseEvent(s, 3, false, 2, wParam, lParam)
+ areaMouseEvent(s, 3, false, wParam, lParam)
return 0
case _WM_RBUTTONUP:
- areaMouseEvent(s, 3, true, 0, wParam, lParam)
+ areaMouseEvent(s, 3, true, wParam, lParam)
return 0
case _WM_XBUTTONDOWN:
which := uint((wParam >> 16) & 0xFFFF) + 3 // values start at 1; we want them to start at 4
- areaMouseEvent(s, which, false, 1, wParam, lParam)
+ areaMouseEvent(s, which, false, wParam, lParam)
return _LRESULT(_TRUE) // XBUTTON messages are different!
- case _WM_XBUTTONDBLCLK:
- which := uint((wParam >> 16) & 0xFFFF) + 3
- areaMouseEvent(s, which, false, 2, wParam, lParam)
- return _LRESULT(_TRUE)
case _WM_XBUTTONUP:
which := uint((wParam >> 16) & 0xFFFF) + 3
- areaMouseEvent(s, which, true, 0, wParam, lParam)
+ areaMouseEvent(s, which, true, wParam, lParam)
return _LRESULT(_TRUE)
case _WM_KEYDOWN:
areaKeyEvent(s, false, wParam, lParam)
@@ -710,9 +718,6 @@ func registerAreaWndClass(s *sysData) (newClassName string, err error) {
const (
_CS_HREDRAW = 0x0002
_CS_VREDRAW = 0x0001
-
- // from winuser.h
- _CS_DBLCLKS = 0x0008 // needed to be able to register double-clicks
)
areaWndClassNumLock.Lock()
@@ -721,7 +726,7 @@ func registerAreaWndClass(s *sysData) (newClassName string, err error) {
areaWndClassNumLock.Unlock()
wc := &_WNDCLASS{
- style: _CS_DBLCLKS | _CS_HREDRAW | _CS_VREDRAW,
+ style: _CS_HREDRAW | _CS_VREDRAW, // no CS_DBLCLKS because do that manually
lpszClassName: uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(newClassName))),
lpfnWndProc: syscall.NewCallback(areaWndProc(s)),
hInstance: hInstance,
diff --git a/events_notdarwin.go b/events_notdarwin.go
index a96b835..7ccfcda 100644
--- a/events_notdarwin.go
+++ b/events_notdarwin.go
@@ -55,7 +55,7 @@ func (c *clickCounter) click(button uint, x int, y int, time uintptr, maxTime ui
}
// call this when losing focus, etc.
-func (c *clickCounter reset() {
+func (c *clickCounter) reset() {
c.count = 0
}
diff --git a/sysdata_windows.go b/sysdata_windows.go
index 5bda9c0..1e02936 100644
--- a/sysdata_windows.go
+++ b/sysdata_windows.go
@@ -20,6 +20,7 @@ type sysData struct {
// unlike with GTK+ and Mac OS X, we're responsible for sizing Area properly ourselves
areawidth int
areaheight int
+ clickCounter clickCounter
}
type classData struct {