diff --git a/devel.but b/devel.but index 9f734e1..e6e34cf 100644 --- a/devel.but +++ b/devel.but @@ -3131,7 +3131,7 @@ call to this function. Some back ends require that \cw{midend_size()} \H{midend-process-key} \cw{midend_process_key()} -\c bool midend_process_key(midend *me, int x, int y, int button); +\c bool midend_process_key(midend *me, int x, int y, int button, bool *handled); The front end calls this function to report a mouse or keyboard event. The parameters \c{x} and \c{y} are identical to the ones passed to the @@ -3173,6 +3173,12 @@ the effect of the keypress was to request termination of the program. A front end should shut down the puzzle in response to a \cw{false} return. +If the front end passes in a non-NULL pointer in \c{handled}, the +mid-end will set \cw{*handled} to \cw{true} if it or the backend does +something in response to the keypress. A front end can use this to +decide whether to pass the keypress on to anything else that might +want to do something in response to it. + The following additional values of \c{button} are permitted to be passed to this function by the front end, but are never passed on to the back end. They indicate front-end specific UI operations, such as diff --git a/emcc.c b/emcc.c index c223b14..450bbad 100644 --- a/emcc.c +++ b/emcc.c @@ -250,7 +250,7 @@ void mousedown(int x, int y, int button) { button = (button == 0 ? LEFT_BUTTON : button == 1 ? MIDDLE_BUTTON : RIGHT_BUTTON); - midend_process_key(me, x, y, button); + midend_process_key(me, x, y, button, NULL); update_undo_redo(); } @@ -258,7 +258,7 @@ void mouseup(int x, int y, int button) { button = (button == 0 ? LEFT_RELEASE : button == 1 ? MIDDLE_RELEASE : RIGHT_RELEASE); - midend_process_key(me, x, y, button); + midend_process_key(me, x, y, button, NULL); update_undo_redo(); } @@ -266,7 +266,7 @@ void mousemove(int x, int y, int buttons) { int button = (buttons & 2 ? MIDDLE_DRAG : buttons & 4 ? RIGHT_DRAG : LEFT_DRAG); - midend_process_key(me, x, y, button); + midend_process_key(me, x, y, button, NULL); update_undo_redo(); } @@ -379,7 +379,7 @@ bool key(int keycode, const char *key, const char *chr, int location, location == DOM_KEY_LOCATION_NUMPAD) keyevent |= MOD_NUM_KEYPAD; - midend_process_key(me, 0, 0, keyevent); + midend_process_key(me, 0, 0, keyevent, NULL); update_undo_redo(); return true; /* We've probably handled the event. */ } @@ -792,7 +792,7 @@ void command(int n) update_undo_redo(); break; case 5: /* New Game */ - midend_process_key(me, 0, 0, UI_NEWGAME); + midend_process_key(me, 0, 0, UI_NEWGAME, NULL); update_undo_redo(); js_focus_canvas(); break; @@ -802,12 +802,12 @@ void command(int n) js_focus_canvas(); break; case 7: /* Undo */ - midend_process_key(me, 0, 0, UI_UNDO); + midend_process_key(me, 0, 0, UI_UNDO, NULL); update_undo_redo(); js_focus_canvas(); break; case 8: /* Redo */ - midend_process_key(me, 0, 0, UI_REDO); + midend_process_key(me, 0, 0, UI_REDO, NULL); update_undo_redo(); js_focus_canvas(); break; diff --git a/gtk.c b/gtk.c index 3ded45a..c4c3a5c 100644 --- a/gtk.c +++ b/gtk.c @@ -1533,7 +1533,7 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) keyval = -1; if (keyval >= 0 && - !midend_process_key(fe->me, 0, 0, keyval)) + !midend_process_key(fe->me, 0, 0, keyval, NULL)) gtk_widget_destroy(fe->window); return true; @@ -1568,7 +1568,7 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, button += LEFT_RELEASE - LEFT_BUTTON; if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button)) + event->y - fe->oy, button, NULL)) gtk_widget_destroy(fe->window); return true; @@ -1593,7 +1593,7 @@ static gint motion_event(GtkWidget *widget, GdkEventMotion *event, return false; /* don't even know what button! */ if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button)) + event->y - fe->oy, button, NULL)) gtk_widget_destroy(fe->window); #if GTK_CHECK_VERSION(2,12,0) gdk_event_request_motions(event); @@ -2188,7 +2188,7 @@ static void menu_key_event(GtkMenuItem *menuitem, gpointer data) frontend *fe = (frontend *)data; int key = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "user-data")); - if (!midend_process_key(fe->me, 0, 0, key)) + if (!midend_process_key(fe->me, 0, 0, key, NULL)) gtk_widget_destroy(fe->window); } @@ -4130,7 +4130,7 @@ int main(int argc, char **argv) if (redo_proportion) { /* Start a redo. */ - midend_process_key(fe->me, 0, 0, 'r'); + midend_process_key(fe->me, 0, 0, 'r', NULL); /* And freeze the timer at the specified position. */ midend_freeze_timer(fe->me, redo_proportion); } diff --git a/midend.c b/midend.c index a8f9cf3..8e63eb7 100644 --- a/midend.c +++ b/midend.c @@ -935,7 +935,8 @@ void midend_restart_game(midend *me) midend_set_timer(me); } -static bool midend_really_process_key(midend *me, int x, int y, int button) +static bool midend_really_process_key(midend *me, int x, int y, int button, + bool *handled) { game_state *oldstate = me->ourgame->dup_game(me->states[me->statepos - 1].state); @@ -956,6 +957,7 @@ static bool midend_really_process_key(midend *me, int x, int y, int button) button == UI_NEWGAME) { midend_new_game(me); midend_redraw(me); + *handled = true; goto done; /* never animate */ } else if (button == 'u' || button == 'U' || button == '\x1A' || button == '\x1F' || @@ -965,23 +967,28 @@ static bool midend_really_process_key(midend *me, int x, int y, int button) gottype = true; if (!midend_undo(me)) goto done; + *handled = true; } else if (button == 'r' || button == 'R' || button == '\x12' || button == '\x19' || button == UI_REDO) { midend_stop_anim(me); if (!midend_redo(me)) goto done; + *handled = true; } else if ((button == '\x13' || button == UI_SOLVE) && me->ourgame->can_solve) { + *handled = true; if (midend_solve(me)) goto done; } else if (button == 'q' || button == 'Q' || button == '\x11' || button == UI_QUIT) { ret = false; + *handled = true; goto done; } else goto done; } else { + *handled = true; if (movestr == UI_UPDATE) s = me->states[me->statepos-1].state; else { @@ -1052,10 +1059,12 @@ static bool midend_really_process_key(midend *me, int x, int y, int button) return ret; } -bool midend_process_key(midend *me, int x, int y, int button) +bool midend_process_key(midend *me, int x, int y, int button, bool *handled) { - bool ret = true; + bool ret = true, dummy_handled; + if (handled == NULL) handled = &dummy_handled; + *handled = false; /* * Harmonise mouse drag and release messages. * @@ -1155,7 +1164,7 @@ bool midend_process_key(midend *me, int x, int y, int button) */ ret = ret && midend_really_process_key (me, x, y, (me->pressed_mouse_button + - (LEFT_RELEASE - LEFT_BUTTON))); + (LEFT_RELEASE - LEFT_BUTTON)), handled); } /* @@ -1178,7 +1187,7 @@ bool midend_process_key(midend *me, int x, int y, int button) /* * Now send on the event we originally received. */ - ret = ret && midend_really_process_key(me, x, y, button); + ret = ret && midend_really_process_key(me, x, y, button, handled); /* * And update the currently pressed button. diff --git a/nestedvm.c b/nestedvm.c index ec633d3..11be3b8 100644 --- a/nestedvm.c +++ b/nestedvm.c @@ -206,7 +206,7 @@ int jcallback_key_event(int x, int y, int keyval) if (fe->ox == -1) return 1; if (keyval >= 0 && - !midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval)) + !midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval, NULL)) return 42; return 1; } @@ -323,7 +323,7 @@ static bool get_config(frontend *fe, int which) int jcallback_newgame_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME)) + if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME, NULL)) return 42; return 0; } @@ -331,7 +331,7 @@ int jcallback_newgame_event(void) int jcallback_undo_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_UNDO)) + if (!midend_process_key(fe->me, 0, 0, UI_UNDO, NULL)) return 42; return 0; } @@ -339,7 +339,7 @@ int jcallback_undo_event(void) int jcallback_redo_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_REDO)) + if (!midend_process_key(fe->me, 0, 0, UI_REDO, NULL)) return 42; return 0; } @@ -347,7 +347,7 @@ int jcallback_redo_event(void) int jcallback_quit_event(void) { frontend *fe = (frontend *)_fe; - if (!midend_process_key(fe->me, 0, 0, UI_QUIT)) + if (!midend_process_key(fe->me, 0, 0, UI_QUIT, NULL)) return 42; return 0; } diff --git a/osx.m b/osx.m index 646cffc..d18aeec 100644 --- a/osx.m +++ b/osx.m @@ -632,13 +632,13 @@ struct frontend { - (void)processButton:(int)b x:(int)x y:(int)y { - if (!midend_process_key(me, x, fe.h - 1 - y, b)) + if (!midend_process_key(me, x, fe.h - 1 - y, b, NULL)) [self close]; } - (void)processKey:(int)b { - if (!midend_process_key(me, -1, -1, b)) + if (!midend_process_key(me, -1, -1, b, NULL)) [self close]; } diff --git a/puzzles.h b/puzzles.h index 1d4dd33..b476dee 100644 --- a/puzzles.h +++ b/puzzles.h @@ -305,7 +305,7 @@ void midend_reset_tilesize(midend *me); void midend_new_game(midend *me); void midend_restart_game(midend *me); void midend_stop_anim(midend *me); -bool midend_process_key(midend *me, int x, int y, int button); +bool midend_process_key(midend *me, int x, int y, int button, bool *handled); key_label *midend_request_keys(midend *me, int *nkeys); void midend_force_redraw(midend *me); void midend_redraw(midend *me); diff --git a/windows.c b/windows.c index e58a150..e4942f4 100644 --- a/windows.c +++ b/windows.c @@ -2530,18 +2530,18 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, cmd = wParam & ~0xF; /* low 4 bits reserved to Windows */ switch (cmd) { case IDM_NEW: - if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME)) + if (!midend_process_key(fe->me, 0, 0, UI_NEWGAME, NULL)) PostQuitMessage(0); break; case IDM_RESTART: midend_restart_game(fe->me); break; case IDM_UNDO: - if (!midend_process_key(fe->me, 0, 0, UI_UNDO)) + if (!midend_process_key(fe->me, 0, 0, UI_UNDO, NULL)) PostQuitMessage(0); break; case IDM_REDO: - if (!midend_process_key(fe->me, 0, 0, UI_REDO)) + if (!midend_process_key(fe->me, 0, 0, UI_REDO, NULL)) PostQuitMessage(0); break; case IDM_COPY: @@ -2563,7 +2563,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; case IDM_QUIT: - if (!midend_process_key(fe->me, 0, 0, UI_QUIT)) + if (!midend_process_key(fe->me, 0, 0, UI_QUIT, NULL)) PostQuitMessage(0); break; case IDM_CONFIG: @@ -2833,7 +2833,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } if (key != -1) { - if (!midend_process_key(fe->me, 0, 0, key)) + if (!midend_process_key(fe->me, 0, 0, key, NULL)) PostQuitMessage(0); } else { MSG m; @@ -2866,7 +2866,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (!midend_process_key(fe->me, (signed short)LOWORD(lParam) - fe->bitmapPosition.left, (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + button, NULL)) PostQuitMessage(0); SetCapture(hwnd); @@ -2893,7 +2893,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (!midend_process_key(fe->me, (signed short)LOWORD(lParam) - fe->bitmapPosition.left, (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + button, NULL)) PostQuitMessage(0); ReleaseCapture(); @@ -2913,7 +2913,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (!midend_process_key(fe->me, (signed short)LOWORD(lParam) - fe->bitmapPosition.left, (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button)) + button, NULL)) PostQuitMessage(0); } break; @@ -2927,7 +2927,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, (keystate[VK_CONTROL] & 0x80)) key = UI_REDO; } - if (!midend_process_key(fe->me, 0, 0, key)) + if (!midend_process_key(fe->me, 0, 0, key, NULL)) PostQuitMessage(0); } return 0;