Implemented triple-clicks and up on Windows.

This commit is contained in:
Pietro Gagliardi 2014-05-23 17:01:56 -04:00
parent 92e4d32284
commit 582e3b4644
3 changed files with 36 additions and 30 deletions

View File

@ -459,7 +459,18 @@ func getModifiers() (m Modifiers) {
return m 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 var me MouseEvent
xpos, ypos := getScrollPos(s.hwnd) // mouse coordinates are relative to control; make them relative to Area 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 { if up {
me.Up = button me.Up = button
} else { } else if button != 0 { // don't run the click counter if the mouse was only moved
me.Down = button 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) // 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() me.Modifiers = getModifiers()
@ -633,46 +654,33 @@ func areaWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lPara
} }
return defwndproc() return defwndproc()
case _WM_MOUSEMOVE: case _WM_MOUSEMOVE:
areaMouseEvent(s, 0, false, 0, wParam, lParam) areaMouseEvent(s, 0, false, wParam, lParam)
return 0 return 0
case _WM_LBUTTONDOWN: case _WM_LBUTTONDOWN:
areaMouseEvent(s, 1, false, 1, wParam, lParam) areaMouseEvent(s, 1, false, wParam, lParam)
return 0
case _WM_LBUTTONDBLCLK:
areaMouseEvent(s, 1, false, 2, wParam, lParam)
return 0 return 0
case _WM_LBUTTONUP: case _WM_LBUTTONUP:
areaMouseEvent(s, 1, true, 0, wParam, lParam) areaMouseEvent(s, 1, true, wParam, lParam)
return 0 return 0
case _WM_MBUTTONDOWN: case _WM_MBUTTONDOWN:
areaMouseEvent(s, 2, false, 1, wParam, lParam) areaMouseEvent(s, 2, false, wParam, lParam)
return 0
case _WM_MBUTTONDBLCLK:
areaMouseEvent(s, 2, false, 2, wParam, lParam)
return 0 return 0
case _WM_MBUTTONUP: case _WM_MBUTTONUP:
areaMouseEvent(s, 2, true, 0, wParam, lParam) areaMouseEvent(s, 2, true, wParam, lParam)
return 0 return 0
case _WM_RBUTTONDOWN: case _WM_RBUTTONDOWN:
areaMouseEvent(s, 3, false, 1, wParam, lParam) areaMouseEvent(s, 3, false, wParam, lParam)
return 0
case _WM_RBUTTONDBLCLK:
areaMouseEvent(s, 3, false, 2, wParam, lParam)
return 0 return 0
case _WM_RBUTTONUP: case _WM_RBUTTONUP:
areaMouseEvent(s, 3, true, 0, wParam, lParam) areaMouseEvent(s, 3, true, wParam, lParam)
return 0 return 0
case _WM_XBUTTONDOWN: case _WM_XBUTTONDOWN:
which := uint((wParam >> 16) & 0xFFFF) + 3 // values start at 1; we want them to start at 4 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! 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: case _WM_XBUTTONUP:
which := uint((wParam >> 16) & 0xFFFF) + 3 which := uint((wParam >> 16) & 0xFFFF) + 3
areaMouseEvent(s, which, true, 0, wParam, lParam) areaMouseEvent(s, which, true, wParam, lParam)
return _LRESULT(_TRUE) return _LRESULT(_TRUE)
case _WM_KEYDOWN: case _WM_KEYDOWN:
areaKeyEvent(s, false, wParam, lParam) areaKeyEvent(s, false, wParam, lParam)
@ -710,9 +718,6 @@ func registerAreaWndClass(s *sysData) (newClassName string, err error) {
const ( const (
_CS_HREDRAW = 0x0002 _CS_HREDRAW = 0x0002
_CS_VREDRAW = 0x0001 _CS_VREDRAW = 0x0001
// from winuser.h
_CS_DBLCLKS = 0x0008 // needed to be able to register double-clicks
) )
areaWndClassNumLock.Lock() areaWndClassNumLock.Lock()
@ -721,7 +726,7 @@ func registerAreaWndClass(s *sysData) (newClassName string, err error) {
areaWndClassNumLock.Unlock() areaWndClassNumLock.Unlock()
wc := &_WNDCLASS{ 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))), lpszClassName: uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(newClassName))),
lpfnWndProc: syscall.NewCallback(areaWndProc(s)), lpfnWndProc: syscall.NewCallback(areaWndProc(s)),
hInstance: hInstance, hInstance: hInstance,

View File

@ -55,7 +55,7 @@ func (c *clickCounter) click(button uint, x int, y int, time uintptr, maxTime ui
} }
// call this when losing focus, etc. // call this when losing focus, etc.
func (c *clickCounter reset() { func (c *clickCounter) reset() {
c.count = 0 c.count = 0
} }

View File

@ -20,6 +20,7 @@ type sysData struct {
// unlike with GTK+ and Mac OS X, we're responsible for sizing Area properly ourselves // unlike with GTK+ and Mac OS X, we're responsible for sizing Area properly ourselves
areawidth int areawidth int
areaheight int areaheight int
clickCounter clickCounter
} }
type classData struct { type classData struct {