diff --git a/devel.but b/devel.but index afc7fb1..65c1571 100644 --- a/devel.but +++ b/devel.but @@ -3291,8 +3291,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 *handled); +\c int midend_process_key(midend *me, int x, int y, int button) 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 @@ -3330,16 +3329,33 @@ Calling this function is very likely to result in calls back to the front end's drawing API and/or \cw{activate_timer()} (\k{frontend-activate-timer}). -The return value from \cw{midend_process_key()} is \cw{true} unless -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. +The return value from \cw{midend_process_key()} is one of the +following constants: -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. +\dt \cw{PKR_QUIT} + +\dd Means that 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{PKR_QUIT} return. + +\dt \cw{PKR_SOME_EFFECT} + +\dd The keypress had some other effect, either in the mid-end or in +the puzzle itself. + +\dt \cw{PKR_NO_EFFECT} + +\dd The keypress had no effect, but might have had an effect in +slightly different circumstances. For instance it requested a move +that wasn't possible. + +\dt \cw{PKR_UNUSED} + +\dd The key was one that neither the mid-end nor the back-end has any +use for at all. + +A front end might respond to the last value by passing the key on to +something else that might be interested in 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 diff --git a/emcc.c b/emcc.c index 60ef8c8..7d7a09b 100644 --- a/emcc.c +++ b/emcc.c @@ -295,7 +295,7 @@ bool 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, &handled); + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; post_move(); return handled; } @@ -306,7 +306,7 @@ bool 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, &handled); + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; post_move(); return handled; } @@ -317,7 +317,7 @@ bool mousemove(int x, int y, int buttons) buttons & 4 ? RIGHT_DRAG : LEFT_DRAG); bool handled; - midend_process_key(me, x, y, button, &handled); + handled = midend_process_key(me, x, y, button) != PKR_UNUSED; post_move(); return handled; } @@ -335,7 +335,7 @@ bool key(int keycode, const char *key, const char *chr, int location, #define DOM_KEY_LOCATION_RIGHT 2 #define DOM_KEY_LOCATION_NUMPAD 3 int keyevent = -1; - bool handled; + int process_key_result; if (!strnullcmp(key, "Backspace") || !strnullcmp(key, "Delete") || !strnullcmp(key, "Del")) @@ -422,9 +422,16 @@ bool key(int keycode, const char *key, const char *chr, int location, if (ctrl) keyevent |= MOD_CTRL; if (location == DOM_KEY_LOCATION_NUMPAD) keyevent |= MOD_NUM_KEYPAD; - midend_process_key(me, 0, 0, keyevent, &handled); + process_key_result = midend_process_key(me, 0, 0, keyevent); post_move(); - return handled; + /* + * Treat Backspace specially because that's expected on KaiOS. + * https://developer.kaiostech.com/docs/design-guide/key + */ + if (process_key_result == PKR_NO_EFFECT && + !strnullcmp(key, "Backspace")) + return false; + return process_key_result != PKR_UNUSED; } return false; /* Event not handled, because we don't even recognise it. */ } @@ -839,7 +846,7 @@ void command(int n) post_move(); break; case 5: /* New Game */ - midend_process_key(me, 0, 0, UI_NEWGAME, NULL); + midend_process_key(me, 0, 0, UI_NEWGAME); post_move(); js_focus_canvas(); break; @@ -849,12 +856,12 @@ void command(int n) js_focus_canvas(); break; case 7: /* Undo */ - midend_process_key(me, 0, 0, UI_UNDO, NULL); + midend_process_key(me, 0, 0, UI_UNDO); post_move(); js_focus_canvas(); break; case 8: /* Redo */ - midend_process_key(me, 0, 0, UI_REDO, NULL); + midend_process_key(me, 0, 0, UI_REDO); post_move(); js_focus_canvas(); break; diff --git a/gtk.c b/gtk.c index 1c96270..035a300 100644 --- a/gtk.c +++ b/gtk.c @@ -1547,7 +1547,7 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) keyval = -1; if (keyval >= 0 && - !midend_process_key(fe->me, 0, 0, keyval, NULL)) + midend_process_key(fe->me, 0, 0, keyval) == PKR_QUIT) gtk_widget_destroy(fe->window); return true; @@ -1581,8 +1581,8 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, if (event->type == GDK_BUTTON_RELEASE && button >= LEFT_BUTTON) button += LEFT_RELEASE - LEFT_BUTTON; - if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button, NULL)) + if (midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button) == PKR_QUIT) gtk_widget_destroy(fe->window); return true; @@ -1606,8 +1606,8 @@ static gint motion_event(GtkWidget *widget, GdkEventMotion *event, else return false; /* don't even know what button! */ - if (!midend_process_key(fe->me, event->x - fe->ox, - event->y - fe->oy, button, NULL)) + if (midend_process_key(fe->me, event->x - fe->ox, + event->y - fe->oy, button) == PKR_QUIT) gtk_widget_destroy(fe->window); #if GTK_CHECK_VERSION(2,12,0) gdk_event_request_motions(event); @@ -2210,7 +2210,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, NULL)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) gtk_widget_destroy(fe->window); } @@ -4377,7 +4377,7 @@ int main(int argc, char **argv) if (redo_proportion) { /* Start a redo. */ - midend_process_key(fe->me, 0, 0, 'r', NULL); + midend_process_key(fe->me, 0, 0, 'r'); /* And freeze the timer at the specified position. */ midend_freeze_timer(fe->me, redo_proportion); } diff --git a/midend.c b/midend.c index 1064af3..f9ebf77 100644 --- a/midend.c +++ b/midend.c @@ -973,13 +973,13 @@ void midend_restart_game(midend *me) midend_set_timer(me); } -static bool midend_really_process_key(midend *me, int x, int y, int button, - bool *handled) +static int midend_really_process_key(midend *me, int x, int y, int button) { game_state *oldstate = me->ourgame->dup_game(me->states[me->statepos - 1].state); int type = MOVE; - bool gottype = false, ret = true; + bool gottype = false; + int ret = PKR_NO_EFFECT; float anim_time; game_state *s; char *movestr = NULL; @@ -995,7 +995,7 @@ static bool midend_really_process_key(midend *me, int x, int y, int button, button == '\x0E' || button == UI_NEWGAME) { midend_new_game(me); midend_redraw(me); - *handled = true; + ret = PKR_SOME_EFFECT; goto done; /* never animate */ } else if ((me->one_key_shortcuts && (button=='u' || button=='U')) || button == '*' || button == '\x1A' || button == '\x1F' || @@ -1005,30 +1005,32 @@ static bool midend_really_process_key(midend *me, int x, int y, int button, gottype = true; if (!midend_undo(me)) goto done; - *handled = true; + ret = PKR_SOME_EFFECT; } else if ((me->one_key_shortcuts && (button=='r' || button=='R')) || button == '#' || button == '\x12' || button == '\x19' || button == UI_REDO) { midend_stop_anim(me); if (!midend_redo(me)) goto done; - *handled = true; + ret = PKR_SOME_EFFECT; } else if ((button == '\x13' || button == UI_SOLVE) && me->ourgame->can_solve) { - *handled = true; + ret = PKR_SOME_EFFECT; if (midend_solve(me)) goto done; } else if ((me->one_key_shortcuts && (button=='q' || button=='Q')) || button == '\x11' || button == UI_QUIT) { - ret = false; - *handled = true; + ret = PKR_QUIT; goto done; - } else + } else { + ret = PKR_UNUSED; goto done; + } } else if (movestr == MOVE_NO_EFFECT) { + ret = PKR_NO_EFFECT; goto done; } else { - *handled = true; + ret = PKR_SOME_EFFECT; if (movestr == MOVE_UI_UPDATE) s = me->states[me->statepos-1].state; else { @@ -1099,12 +1101,10 @@ 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 *handled) +int midend_process_key(midend *me, int x, int y, int button) { - bool ret = true, dummy_handled; + int ret = PKR_UNUSED, ret2; - if (handled == NULL) handled = &dummy_handled; - *handled = false; /* * Harmonise mouse drag and release messages. * @@ -1206,9 +1206,10 @@ bool midend_process_key(midend *me, int x, int y, int button, bool *handled) /* * Fabricate a button-up for the previously pressed button. */ - ret = ret && midend_really_process_key + ret2 = midend_really_process_key (me, x, y, (me->pressed_mouse_button + - (LEFT_RELEASE - LEFT_BUTTON)), handled); + (LEFT_RELEASE - LEFT_BUTTON))); + ret = min(ret, ret2); } /* Canonicalise CTRL+ASCII. */ @@ -1243,7 +1244,8 @@ bool midend_process_key(midend *me, int x, int y, int button, bool *handled) /* * Now send on the event we originally received. */ - ret = ret && midend_really_process_key(me, x, y, button, handled); + ret2 = midend_really_process_key(me, x, y, button); + ret = min(ret, ret2); /* * And update the currently pressed button. diff --git a/nestedvm.c b/nestedvm.c index 11be3b8..0a9fdbc 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, NULL)) + midend_process_key(fe->me, x - fe->ox, y - fe->oy, keyval) == PKR_QUIT) 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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_NEWGAME) == PKR_QUIT) 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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_UNDO) == PKR_QUIT) 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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_REDO) == PKR_QUIT) 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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_QUIT) == PKR_QUIT) return 42; return 0; } diff --git a/osx.m b/osx.m index 81d18c5..60299c9 100644 --- a/osx.m +++ b/osx.m @@ -767,13 +767,13 @@ struct frontend { - (void)processButton:(int)b x:(int)x y:(int)y { - if (!midend_process_key(me, x, fe.h - 1 - y, b, NULL)) + if (midend_process_key(me, x, fe.h - 1 - y, b) == PKR_QUIT) [self close]; } - (void)processKey:(int)b { - if (!midend_process_key(me, -1, -1, b, NULL)) + if (midend_process_key(me, -1, -1, b) == PKR_QUIT) [self close]; } diff --git a/puzzles.h b/puzzles.h index 25df27b..f057c21 100644 --- a/puzzles.h +++ b/puzzles.h @@ -320,7 +320,8 @@ 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 *handled); +enum { PKR_QUIT = 0, PKR_SOME_EFFECT, PKR_NO_EFFECT, PKR_UNUSED }; +int midend_process_key(midend *me, int x, int y, int button); key_label *midend_request_keys(midend *me, int *nkeys); const char *midend_current_key_label(midend *me, int button); void midend_force_redraw(midend *me); diff --git a/windows.c b/windows.c index 52b2ac3..5273e17 100644 --- a/windows.c +++ b/windows.c @@ -2678,18 +2678,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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_NEWGAME) == PKR_QUIT) 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, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_UNDO) == PKR_QUIT) PostQuitMessage(0); break; case IDM_REDO: - if (!midend_process_key(fe->me, 0, 0, UI_REDO, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_REDO) == PKR_QUIT) PostQuitMessage(0); break; case IDM_COPY: @@ -2711,7 +2711,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; case IDM_QUIT: - if (!midend_process_key(fe->me, 0, 0, UI_QUIT, NULL)) + if (midend_process_key(fe->me, 0, 0, UI_QUIT) == PKR_QUIT) PostQuitMessage(0); break; case IDM_CONFIG: @@ -2998,7 +2998,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } if (key != -1) { - if (!midend_process_key(fe->me, 0, 0, key, NULL)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) PostQuitMessage(0); } else { MSG m; @@ -3028,10 +3028,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else button = LEFT_BUTTON; - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button, NULL)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); SetCapture(hwnd); @@ -3055,10 +3055,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else button = LEFT_RELEASE; - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button, NULL)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); ReleaseCapture(); @@ -3075,10 +3075,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, else button = LEFT_DRAG; - if (!midend_process_key(fe->me, - (signed short)LOWORD(lParam) - fe->bitmapPosition.left, - (signed short)HIWORD(lParam) - fe->bitmapPosition.top, - button, NULL)) + if (midend_process_key(fe->me, + (signed short)LOWORD(lParam) - fe->bitmapPosition.left, + (signed short)HIWORD(lParam) - fe->bitmapPosition.top, + button) == PKR_QUIT) PostQuitMessage(0); } break; @@ -3092,7 +3092,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, NULL)) + if (midend_process_key(fe->me, 0, 0, key) == PKR_QUIT) PostQuitMessage(0); } return 0;