diff --git a/area.go b/area.go index 9e76f7f..f1ca850 100644 --- a/area.go +++ b/area.go @@ -52,13 +52,15 @@ type AreaHandler interface { // Mouse is called when the Area receives a mouse event. // You are allowed to do nothing in this handler (to ignore mouse events). // See MouseEvent for details. - Mouse(e MouseEvent) + // If repaint is true, the Area is marked as needing to be redrawn. + Mouse(e MouseEvent) (repaint bool) // Key is called when the Area receives a keyboard event. - // You are allowed to do nothing except return false in this handler (to ignore keyboard events). - // Do not do nothing but return true; this may have unintended consequences. + // You are allowed to do nothing except return false for handled in this handler (to ignore keyboard events). + // Do not do nothing but return true for handled; this may have unintended consequences. // See KeyEvent for details. - Key(e KeyEvent) bool + // If repaint is true, the Area is marked as needing to be redrawn. + Key(e KeyEvent) (handled bool, repaint bool) } // MouseEvent contains all the information for a mous event sent by Area.Mouse. @@ -116,16 +118,17 @@ func (e MouseEvent) HeldBits() (h uintptr) { // // When you are finished processing the incoming event, // return whether or not you did something in response -// to the given keystroke from your Key() implementation. -// If you send false, you indicate that you did not handle -// the keypress, and that the system should handle it instead. -// (Some systems will stop processing the keyboard event at all -// if you return true unconditionally, which may result in unwanted -// behavior like global task-switching keystrokes not being processed.) +// to the given keystroke as the handled return of your +// AreaHandler's Key() implementation. If you send false, +// you indicate that you did not handle the keypress, and that +// the system should handle it instead. (Some systems will stop +// processing the keyboard event at all if you return true +// unconditionally, which may result in unwanted behavior like +// global task-switching keystrokes not being processed.) // // If a key is pressed that is not supported by ASCII, ExtKey, // or Modifiers, no KeyEvent will be produced, and package -// ui will act as if false was returned. +// ui will act as if false was returned for handled. type KeyEvent struct { // ASCII is a byte representing the character pressed. // Despite my best efforts, this cannot be trivialized diff --git a/area_unix.go b/area_unix.go index 57f9b71..b4a7600 100644 --- a/area_unix.go +++ b/area_unix.go @@ -103,7 +103,7 @@ func makeModifiers(state C.guint, m Modifiers) Modifiers { } // shared code for finishing up and sending a mouse event -func finishMouseEvent(data C.gpointer, me MouseEvent, mb uint, x C.gdouble, y C.gdouble, state C.guint, gdkwindow *C.GdkWindow) { +func finishMouseEvent(widget *C.GtkWidget, data C.gpointer, me MouseEvent, mb uint, x C.gdouble, y C.gdouble, state C.guint, gdkwindow *C.GdkWindow) { s := (*sysData)(unsafe.Pointer(data)) state = translateModifiers(state, gdkwindow) me.Modifiers = makeModifiers(state, 0) @@ -125,7 +125,10 @@ func finishMouseEvent(data C.gpointer, me MouseEvent, mb uint, x C.gdouble, y C. me.Held = append(me.Held, 5) } me.Pos = image.Pt(int(x), int(y)) - s.handler.Mouse(me) + repaint := s.handler.Mouse(me) + if repaint { + C.gtk_widget_queue_draw(widget) + } } //export our_area_button_press_event_callback @@ -143,7 +146,7 @@ func our_area_button_press_event_callback(widget *C.GtkWidget, event *C.GdkEvent default: // ignore triple-clicks and beyond; we don't handle those return C.FALSE // TODO really false? } - finishMouseEvent(data, me, me.Down, e.x, e.y, e.state, e.window) + finishMouseEvent(widget, data, me, me.Down, e.x, e.y, e.state, e.window) return C.FALSE // TODO really false? } @@ -156,7 +159,7 @@ func our_area_button_release_event_callback(widget *C.GtkWidget, event *C.GdkEve // GDK button ID == our button ID Up: uint(e.button), } - finishMouseEvent(data, me, me.Up, e.x, e.y, e.state, e.window) + finishMouseEvent(widget, data, me, me.Up, e.x, e.y, e.state, e.window) return C.FALSE // TODO really false? } @@ -166,14 +169,14 @@ var area_button_release_event_callback = C.GCallback(C.our_area_button_release_e func our_area_motion_notify_event_callback(widget *C.GtkWidget, event *C.GdkEvent, data C.gpointer) C.gboolean { e := (*C.GdkEventMotion)(unsafe.Pointer(event)) me := MouseEvent{} - finishMouseEvent(data, me, 0, e.x, e.y, e.state, e.window) + finishMouseEvent(widget, data, me, 0, e.x, e.y, e.state, e.window) return C.FALSE // TODO really false? } var area_motion_notify_event_callback = C.GCallback(C.our_area_motion_notify_event_callback) // shared code for doing a key event -func doKeyEvent(event *C.GdkEvent, data C.gpointer, up bool) bool { +func doKeyEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.gpointer, up bool) bool { var ke KeyEvent e := (*C.GdkEventKey)(unsafe.Pointer(event)) @@ -202,7 +205,11 @@ fmt.Println("$$", up, e.hardware_keycode) state := translateModifiers(e.state, e.window) ke.Modifiers = makeModifiers(state, ke.Modifiers) ke.Up = up - return s.handler.Key(ke) + handled, repaint := s.handler.Key(ke) + if repaint { + C.gtk_widget_queue_draw(widget) + } + return handled } //export our_area_key_press_event_callback @@ -218,7 +225,7 @@ func our_area_key_press_event_callback(widget *C.GtkWidget, event *C.GdkEvent, d fmt.Printf("%d/GDK_KEY_a:\n", C.GDK_KEY_a) pk(C.GDK_KEY_a, e.window) */ - ret := doKeyEvent(event, data, false) + ret := doKeyEvent(widget, event, data, false) _ = ret return C.FALSE // TODO really false? should probably return !ret (since true indicates stop processing) } @@ -227,7 +234,7 @@ var area_key_press_event_callback = C.GCallback(C.our_area_key_press_event_callb //export our_area_key_release_event_callback func our_area_key_release_event_callback(widget *C.GtkWidget, event *C.GdkEvent, data C.gpointer) C.gboolean { - ret := doKeyEvent(event, data, true) + ret := doKeyEvent(widget, event, data, true) _ = ret return C.FALSE // TODO really false? should probably return !ret (since true indicates stop processing) } diff --git a/area_windows.go b/area_windows.go index 3559bd4..49a2a11 100644 --- a/area_windows.go +++ b/area_windows.go @@ -329,6 +329,7 @@ func getModifiers() (m Modifiers) { return m } +// TODO mark repaint func areaMouseEvent(s *sysData, button uint, up bool, count uint, wparam _WPARAM, lparam _LPARAM) { var me MouseEvent @@ -403,6 +404,7 @@ func areaWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lPara areaMouseEvent(s, 3, true, 0, wParam, lParam) return 0 // TODO XBUTTONs? + // TODO mark repaint in key events default: r1, _, _ := defWindowProc.Call( uintptr(hwnd), diff --git a/test/kbtest.go b/test/kbtest.go index 0a21954..d6fa7c1 100644 --- a/test/kbtest.go +++ b/test/kbtest.go @@ -34,7 +34,9 @@ func (a *keyboardArea) Paint(cliprect image.Rectangle) *image.NRGBA { return a.kbd.SubImage(cliprect).(*image.NRGBA) } -func (a *keyboardArea) Mouse(MouseEvent) {} +func (a *keyboardArea) Mouse(MouseEvent) (repaint bool) { + return false +} func markkey(dest *image.NRGBA, keypt image.Point, m Modifiers) { xr := keyrect(m).Add(keypt) @@ -42,7 +44,7 @@ func markkey(dest *image.NRGBA, keypt image.Point, m Modifiers) { draw.Draw(dest, xr, xi, image.ZP, draw.Over) } -func (a *keyboardArea) Key(e KeyEvent) bool { +func (a *keyboardArea) Key(e KeyEvent) (handled bool, repaint bool) { a.lock.Lock() defer a.lock.Unlock() @@ -68,9 +70,9 @@ func (a *keyboardArea) Key(e KeyEvent) bool { // markkey(a.kbd, modpoints[Super], m &^ Super) // } default: - return false + return false, false } - return true + return true, true } var doKeyboard = flag.Bool("kb", false, "run keyboard test") diff --git a/test/main.go b/test/main.go index 60108ab..1e2b465 100644 --- a/test/main.go +++ b/test/main.go @@ -131,13 +131,14 @@ func (a *areaHandler) Paint(rect image.Rectangle) *image.NRGBA { */ return a.img.SubImage(rect).(*image.NRGBA) } -func (a *areaHandler) Mouse(e MouseEvent) { - fmt.Printf("%#v\n", e) -} -func (a *areaHandler) Key(e KeyEvent) bool { +func (a *areaHandler) Mouse(e MouseEvent) bool { fmt.Printf("%#v\n", e) return false } +func (a *areaHandler) Key(e KeyEvent) (bool, bool) { + fmt.Printf("%#v\n", e) + return false, false +} var doArea = flag.Bool("area", false, "run area test instead (overrides -kb)") func areaTest() {