diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 6aab7422c..1ade81c48 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -2995,7 +2995,8 @@ penMoved( const BoardCtxt* board, XP_U16 curCol, XP_U16 curRow ) } static XP_Bool -handlePenUpInternal( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool isPen ) +handlePenUpInternal( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool isPen, + XP_Bool altDown ) { XP_Bool draw = XP_FALSE; XP_Bool dragged = XP_FALSE; @@ -3027,7 +3028,7 @@ handlePenUpInternal( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool isPen ) switch( onWhich ) { case OBJ_SCORE: if ( prevObj == OBJ_SCORE ) { - draw = handlePenUpScore( board, xx, yy ) || draw; + draw = handlePenUpScore( board, xx, yy, altDown ) || draw; } break; case OBJ_BOARD: @@ -3066,7 +3067,7 @@ handlePenUpInternal( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool isPen ) XP_Bool board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y ) { - return handlePenUpInternal( board, x, y, XP_TRUE ); + return handlePenUpInternal( board, x, y, XP_TRUE, XP_FALSE ); } XP_Bool @@ -3207,15 +3208,15 @@ board_handleKeyDown( BoardCtxt* XP_UNUSED_KEYBOARD_NAV(board), { XP_Bool draw = XP_FALSE; #ifdef KEYBOARD_NAV - XP_U16 x, y; + XP_U16 xx, yy; board->srcIsPen = XP_FALSE; *pHandled = XP_FALSE; - if ( key == XP_RETURN_KEY ) { - if ( focusToCoords( board, &x, &y ) ) { - draw = handleLikeDown( board, board->focussed, x, y ); + if ( key == XP_RETURN_KEY || key == XP_ALTRETURN_KEY ) { + if ( focusToCoords( board, &xx, &yy ) ) { + draw = handleLikeDown( board, board->focussed, xx, yy ); *pHandled = draw; } } else if ( board->focussed != OBJ_NONE ) { @@ -3276,13 +3277,15 @@ board_handleKeyUp( BoardCtxt* board, XP_Key key, XP_Bool* pHandled ) break; case XP_RETURN_KEY: + case XP_ALTRETURN_KEY: { + XP_Bool altDown = XP_ALTRETURN_KEY == key; if ( unhideFocus( board ) ) { handled = XP_TRUE; } else if ( board->focussed != OBJ_NONE ) { if ( board->focusHasDived ) { XP_U16 xx, yy; if ( focusToCoords( board, &xx, &yy ) ) { - redraw = handlePenUpInternal( board, xx, yy, XP_FALSE ); + redraw = handlePenUpInternal( board, xx, yy, XP_FALSE, altDown ); handled = XP_TRUE; } } else { @@ -3292,6 +3295,7 @@ board_handleKeyUp( BoardCtxt* board, XP_Key key, XP_Bool* pHandled ) handled = XP_TRUE; } } + } break; #endif diff --git a/xwords4/common/board.h b/xwords4/common/board.h index 476c5af89..6d9e59858 100644 --- a/xwords4/common/board.h +++ b/xwords4/common/board.h @@ -50,6 +50,7 @@ typedef enum { XP_CURSOR_KEY_DEL, XP_RAISEFOCUS_KEY, XP_RETURN_KEY, + XP_ALTRETURN_KEY, XP_KEY_LAST } XP_Key; diff --git a/xwords4/common/scorebdp.c b/xwords4/common/scorebdp.c index 2979c4f22..45be5af02 100644 --- a/xwords4/common/scorebdp.c +++ b/xwords4/common/scorebdp.c @@ -411,7 +411,7 @@ figureScoreRectTapped( const BoardCtxt* board, XP_U16 xx, XP_U16 yy ) */ #if defined POINTER_SUPPORT || defined KEYBOARD_NAV XP_Bool -handlePenUpScore( BoardCtxt* board, XP_U16 xx, XP_U16 yy ) +handlePenUpScore( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool altDown ) { XP_Bool result = XP_TRUE; @@ -421,10 +421,10 @@ handlePenUpScore( BoardCtxt* board, XP_U16 xx, XP_U16 yy ) util_remSelected( board->util ); } else if ( --rectNum >= 0 ) { XP_Bool canSwitch = board->gameOver || board->allowPeek; - if ( canSwitch ) { - board_selectPlayer( board, rectNum, XP_TRUE ); - } else { + if ( altDown || !canSwitch ) { penTimerFiredScore( board ); + } else { + board_selectPlayer( board, rectNum, XP_TRUE ); } } else { result = XP_FALSE; diff --git a/xwords4/common/scorebdp.h b/xwords4/common/scorebdp.h index 084d788f5..0cb6d89f0 100644 --- a/xwords4/common/scorebdp.h +++ b/xwords4/common/scorebdp.h @@ -28,7 +28,7 @@ void drawTimer( BoardCtxt* board ); void penTimerFiredScore( const BoardCtxt* board ); #if defined POINTER_SUPPORT || defined KEYBOARD_NAV -XP_Bool handlePenUpScore( BoardCtxt* board, XP_U16 x, XP_U16 y ); +XP_Bool handlePenUpScore( BoardCtxt* board, XP_U16 xx, XP_U16 yy, XP_Bool altDown ); #endif diff --git a/xwords4/linux/cursesboard.c b/xwords4/linux/cursesboard.c index 17499b6c3..5f143a013 100644 --- a/xwords4/linux/cursesboard.c +++ b/xwords4/linux/cursesboard.c @@ -168,7 +168,7 @@ const MenuList g_allMenuList[] = { { handleDown, "Down", "K", 'K' }, { handleClose, "Close", "W", 'W' }, { handleSpace, "Raise focus", "", ' ' }, - { handleRet, "Click/tap", "", '\r' }, + { handleRet, "Tap", "<[alt-]ret>", '\r' }, { handleShowVals, "Tile values", "T", 'T' }, }; @@ -1307,13 +1307,15 @@ handleSpace( void* closure, int XP_UNUSED(key) ) } /* handleSpace */ static bool -handleRet( void* closure, int XP_UNUSED(key) ) +handleRet( void* closure, int key ) { CursesBoardGlobals* bGlobals = (CursesBoardGlobals*)closure; BoardCtxt* board = bGlobals->cGlobals.game.board; XP_Bool handled; - (void)board_handleKey( board, XP_RETURN_KEY, &handled ); - board_draw( board ); + XP_Key xpKey = (key & ALT_BIT) == 0 ? XP_RETURN_KEY : XP_ALTRETURN_KEY; + if ( board_handleKey( board, xpKey, &handled ) ) { + board_draw( board ); + } return XP_TRUE; } /* handleRet */ diff --git a/xwords4/linux/cursesmenu.c b/xwords4/linux/cursesmenu.c index 890359be8..528e23b49 100644 --- a/xwords4/linux/cursesmenu.c +++ b/xwords4/linux/cursesmenu.c @@ -29,8 +29,12 @@ struct CursesMenuState { WINDOW* menuWin; GSList* menuLists; + bool altPressed; }; +static bool handleKeyEvent( CursesMenuState* state, char ch, bool altPressed ); + + static gboolean handle_stdin( GIOChannel* XP_UNUSED_DBG(source), GIOCondition condition, gpointer data ) @@ -42,7 +46,15 @@ handle_stdin( GIOChannel* XP_UNUSED_DBG(source), GIOCondition condition, #endif CursesMenuState* state = (CursesMenuState*)data; int ch = wgetch( state->menuWin ); - cmenu_handleKeyEvent( state, ch ); + // Alt (at least pressed with ) comes in as a separate keypress + // immediately before. So don't distribute it, but instead OR a + // special bit into the key sent out. + if ( ch == 0x1b ) { + state->altPressed = true; + } else { + handleKeyEvent( state, ch, state->altPressed ); + state->altPressed = false; + } } return TRUE; } @@ -154,8 +166,8 @@ cmenu_removeMenus( CursesMenuState* state, ... ) cmenu_draw( state ); } -bool -cmenu_handleKeyEvent( CursesMenuState* state, char ch ) +static bool +handleKeyEvent( CursesMenuState* state, char ch, bool altPressed ) { bool result = false; for ( GSList* iter = state->menuLists; !!iter; iter = iter->next ) { @@ -163,9 +175,11 @@ cmenu_handleKeyEvent( CursesMenuState* state, char ch ) if ( PUSH_TOKEN == elem ) { break; } + + int altBit = altPressed ? ALT_BIT : 0; for ( const MenuList* list = elem->list; !!list->handler; ++list ) { if ( list->key == ch ) { - result = (*list->handler)(elem->closure, ch); + result = (*list->handler)(elem->closure, ch | altBit); goto done; } } diff --git a/xwords4/linux/cursesmenu.h b/xwords4/linux/cursesmenu.h index 397db0dfa..22fbb50a7 100644 --- a/xwords4/linux/cursesmenu.h +++ b/xwords4/linux/cursesmenu.h @@ -30,6 +30,8 @@ # define BOARD_OFFSET 1 #endif +#define ALT_BIT (1 << 8) /* ORd into key when alt key was down */ + typedef bool (*CursesMenuHandler)( void* closure, int key ); typedef struct MenuList { CursesMenuHandler handler; @@ -49,6 +51,5 @@ void cmenu_addMenus( CursesMenuState* state, void* closure, ... ); void cmenu_push( CursesMenuState* state, void* closure, ... ); void cmenu_pop( CursesMenuState* state ); void cmenu_removeMenus( CursesMenuState* state, ... ); -bool cmenu_handleKeyEvent( CursesMenuState* state, char ch ); #endif