ref: 1547154efbfcf0bd8f6fc4f91fe99c26371fe0ee
parent: 87e98e67158326a7dd94fd8fa255e3695898ecf3
author: Ben Harris <bjh21@bjh21.me.uk>
date: Wed Jun 7 19:03:30 EDT 2023
Expose the NO_EFFECT/UNUSED distinction through midend_process_key() This removed the "handled" pointer and instead extends the existing boolean return value (quit or don't quit) into an enumeration. One of the values still quits the program, but now there are different values for keys that had an effect, had no effect, and are not used by the puzzle at all. The mapping from interpret_move results to process_key results is roughly: move string -> PKR_SOME_EFFECT MOVE_UI_UPDATE -> PKR_SOME_EFFECT MOVE_NO_EFFECT -> PKR_NO_EFFECT MOVE_UNUSED -> PKR_UNUSED The mid-end can also generate results internally, and is the only place that PKR_QUIT can arise. For compatibility, PKR_QUIT is zero, so anything expecting a false return value to mean quit will be unsurprised. The other values are ordered so that lower values indicate a greater amount of handling of the key.
--- a/devel.but
+++ b/devel.but
@@ -3291,8 +3291,7 @@
\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 @@
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
--- a/emcc.c
+++ b/emcc.c
@@ -295,7 +295,7 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 @@
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;
--- a/gtk.c
+++ b/gtk.c
@@ -1547,7 +1547,7 @@
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 @@
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 @@
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 @@
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 @@
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);
}
--- a/midend.c
+++ b/midend.c
@@ -973,13 +973,13 @@
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 @@
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,7 +1005,7 @@
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) {
@@ -1012,23 +1012,25 @@
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 @@
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 @@
/*
* 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 @@
/*
* 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.
--- a/nestedvm.c
+++ b/nestedvm.c
@@ -206,7 +206,7 @@
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 @@
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_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_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_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;
}
--- a/osx.m
+++ b/osx.m
@@ -767,13 +767,13 @@
- (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];
}
--- a/puzzles.h
+++ b/puzzles.h
@@ -320,7 +320,8 @@
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);
--- a/windows.c
+++ b/windows.c
@@ -2678,7 +2678,7 @@
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:
@@ -2685,11 +2685,11 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
(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;