summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-08-21 05:37:24 -0400
committerPietro Gagliardi <[email protected]>2014-08-21 05:37:24 -0400
commite5c74b832be68fdbefb9c7527c2367dba1cec7a8 (patch)
treebff78082b8666a04ce42b815b11a65ddee77821d
parentf3ca234dda0c34c2bd11acee414111d1c745422d (diff)
Changed AreaHandler.Key() to return a boolean value indicating if the event was handled; implemented this on Windows. It does sledgehammer some edge cases I wanted to avoid, but it also avoids fussing about scrolling and focus and what not.
-rw-r--r--redo/area.go8
-rw-r--r--redo/area_windows.c17
-rw-r--r--redo/area_windows.go10
-rw-r--r--redo/uitask_windows.c26
-rw-r--r--redo/winapi_windows.h2
-rw-r--r--redo/zz_test.go10
6 files changed, 47 insertions, 26 deletions
diff --git a/redo/area.go b/redo/area.go
index b4b2f78..75f47b2 100644
--- a/redo/area.go
+++ b/redo/area.go
@@ -74,10 +74,10 @@ type AreaHandler interface {
Mouse(e MouseEvent)
// Key is called when the Area receives a keyboard event.
- // You are allowed to do nothing in this handler (to ignore keyboard events).
+ // Return true to indicate that you handled the event; return false to indicate that you did not and let the system handle the event.
+ // You are allowed to do nothing in this handler (to ignore keyboard events); in this case, return false.
// See KeyEvent for details.
- // After handling the key event, package ui will decide whether to perform platform-dependent event chain continuation based on that platform's designated action (so it is not possible to override global key events, such as Alt-Tab, this way).
- Key(e KeyEvent)
+ Key(e KeyEvent) (handled bool)
}
// MouseEvent contains all the information for a mous event sent by Area.Mouse.
@@ -140,7 +140,7 @@ func (e MouseEvent) HeldBits() (h uintptr) {
// on US English QWERTY keyboards; see Key for details.
//
// If a key is pressed that is not supported by Key, ExtKey,
-// or Modifiers, no KeyEvent will be produced.
+// or Modifiers, no KeyEvent will be produced and package ui will behave as if false was returned from the event handler.
type KeyEvent struct {
// Key is a byte representing a character pressed
// in the typewriter section of the keyboard.
diff --git a/redo/area_windows.c b/redo/area_windows.c
index e9ded14..ce538db 100644
--- a/redo/area_windows.c
+++ b/redo/area_windows.c
@@ -380,19 +380,10 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
heldButtons = (uintptr_t) GET_KEYSTATE_WPARAM(wParam);
areaMouseEvent(hwnd, data, which, TRUE, heldButtons, lParam);
return TRUE;
- case WM_KEYDOWN:
- areaKeyEvent(data, FALSE, wParam, lParam);
- return 0;
- case WM_KEYUP:
- areaKeyEvent(data, TRUE, wParam, lParam);
- return 0;
- // Alt+[anything] and F10 send these instead and require us to return to DefWindowProc() so global keystrokes such as Alt+Tab can be processed
- case WM_SYSKEYDOWN:
- areaKeyEvent(data, FALSE, wParam, lParam);
- return DefWindowProcW(hwnd, uMsg, wParam, lParam);
- case WM_SYSKEYUP:
- areaKeyEvent(data, TRUE, wParam, lParam);
- return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+ case msgAreaKeyDown:
+ return (LRESULT) areaKeyEvent(data, FALSE, wParam, lParam);
+ case msgAreaKeyUp:
+ return (LRESULT) areaKeyEvent(data, TRUE, wParam, lParam);
case msgAreaSizeChanged:
adjustAreaScrollbars(hwnd, data);
repaintArea(hwnd); // this calls for an update
diff --git a/redo/area_windows.go b/redo/area_windows.go
index 05f0274..877f8b6 100644
--- a/redo/area_windows.go
+++ b/redo/area_windows.go
@@ -152,7 +152,7 @@ func finishAreaMouseEvent(data unsafe.Pointer, cbutton C.DWORD, up C.BOOL, heldB
}
//export areaKeyEvent
-func areaKeyEvent(data unsafe.Pointer, up C.BOOL, wParam C.WPARAM, lParam C.LPARAM) {
+func areaKeyEvent(data unsafe.Pointer, up C.BOOL, wParam C.WPARAM, lParam C.LPARAM) C.BOOL {
var ke KeyEvent
a := (*area)(data)
@@ -180,10 +180,14 @@ func areaKeyEvent(data unsafe.Pointer, up C.BOOL, wParam C.WPARAM, lParam C.LPAR
ke.ExtKey = xke.ExtKey
} else if ke.Modifiers == 0 {
// no key, extkey, or modifiers; do nothing
- return
+ return C.FALSE
}
ke.Up = up != C.FALSE
- a.handler.Key(ke)
+ handled := a.handler.Key(ke)
+ if handled {
+ return C.TRUE
+ }
+ return C.FALSE
}
// all mappings come from GLFW - https://github.com/glfw/glfw/blob/master/src/win32_window.c#L152
diff --git a/redo/uitask_windows.c b/redo/uitask_windows.c
index 5dad117..25f7da9 100644
--- a/redo/uitask_windows.c
+++ b/redo/uitask_windows.c
@@ -8,9 +8,31 @@
// this also assumes WC_TABCONTROL is longer than areaWindowClass
#define NCLASSNAME (sizeof WC_TABCONTROL / sizeof WC_TABCONTROL[0])
-void uimsgloop_area(MSG *msg)
+void uimsgloop_area(HWND active, HWND focus, MSG *msg)
{
+ MSG copy;
+
+ copy = *msg;
+ switch (copy.message) {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN: // Alt+[anything] and F10 send these instead
+ copy.message = msgAreaKeyDown;
+ break;
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ copy.message = msgAreaKeyUp;
+ break;
+ default:
+ goto notkey;
+ }
+ // if we handled the key, don't do the default behavior
// don't call TranslateMessage(); we do our own keyboard handling
+ if (DispatchMessage(&copy) != FALSE)
+ return;
+ // TODO move this under notkey?
+ if (IsDialogMessage(active, msg) != 0)
+ return;
+notkey:
DispatchMessage(msg);
}
@@ -70,7 +92,7 @@ void uimsgloop(void)
if (GetClassNameW(focus, classchk, NCLASSNAME) == 0)
xpanic("error getting name of focused window class for Area check", GetLastError());
if (wcscmp(classchk, areaWindowClass) == 0) {
- uimsgloop_area(&msg);
+ uimsgloop_area(active, focus, &msg);
continue;
} else if (wcscmp(classchk, WC_TABCONTROL) == 0) {
uimsgloop_tab(active, focus, &msg);
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 5787331..c11dc7c 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -34,6 +34,8 @@ enum {
msgTabCurrentTabHasChildren,
msgBeginModal,
msgEndModal,
+ msgAreaKeyDown,
+ msgAreaKeyUp,
};
// uitask_windows.c
diff --git a/redo/zz_test.go b/redo/zz_test.go
index f3392ad..e8ccead 100644
--- a/redo/zz_test.go
+++ b/redo/zz_test.go
@@ -63,14 +63,16 @@ type testwin struct {
wsmall Window
}
-type areaHandler struct{}
+type areaHandler struct {
+ handled bool
+}
func (a *areaHandler) Paint(r image.Rectangle) *image.RGBA {
i := image.NewRGBA(r)
draw.Draw(i, r, &image.Uniform{color.RGBA{128,0,128,255}}, image.ZP, draw.Src)
return i
}
func (a *areaHandler) Mouse(me MouseEvent) { fmt.Printf("%#v\n", me) }
-func (a *areaHandler) Key(ke KeyEvent) { fmt.Printf("%#v %q\n", ke, ke.Key) }
+func (a *areaHandler) Key(ke KeyEvent) bool { fmt.Printf("%#v %q\n", ke, ke.Key); return a.handled }
func (tw *testwin) addfe() {
tw.festart = NewButton("Start")
@@ -169,7 +171,7 @@ func (tw *testwin) make(done chan struct{}) {
tw.nt.Append("Tab 2", Space())
tw.t.Append("Tab", tw.nt)
tw.t.Append("Space", Space())
- tw.a = NewArea(200, 200, &areaHandler{})
+ tw.a = NewArea(200, 200, &areaHandler{false})
tw.t.Append("Area", tw.a)
tw.spw = NewHorizontalStack(
NewButton("hello"),
@@ -233,7 +235,7 @@ func (tw *testwin) make(done chan struct{}) {
NewVerticalStack(
NewButton("Small"),
NewButton("Small 2"),
- NewArea(200, 200, &areaHandler{})))
+ NewArea(200, 200, &areaHandler{true})))
tw.wsmall.Show()
}
}