mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-05 20:45:49 +01:00
Two big changes. Pass focus bit into all or and players when focus
not dived and tray or scoreboard focussed. This lets platform decide to display top-level focus via mods to all elements. Second, when moving focus to top level from dived, claim not to have handled the key event (but return true if needs redraw). This allows platform to handle shifting focus without requiring callback (which removed.)
This commit is contained in:
parent
9aa3759761
commit
0d013a0599
7 changed files with 115 additions and 101 deletions
111
common/board.c
111
common/board.c
|
@ -1,6 +1,7 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/*
|
||||
* Copyright 1997 - 2002 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 1997 - 2006 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -121,7 +122,8 @@ static XP_Bool moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey,
|
|||
#endif
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey );
|
||||
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey,
|
||||
XP_Bool* up );
|
||||
static XP_Bool invalFocusOwner( BoardCtxt* board );
|
||||
#endif
|
||||
#ifdef XWFEATURE_SEARCHLIMIT
|
||||
|
@ -2486,30 +2488,32 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|||
#endif /* #ifdef POINTER_SUPPORT */
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
static XP_Key
|
||||
flipKey( BoardCtxt* board, XP_Key key ) {
|
||||
if ( board->isFlipped ) {
|
||||
XP_Key
|
||||
flipKey( XP_Key key, XP_Bool flip ) {
|
||||
XP_Key result = key;
|
||||
if ( flip ) {
|
||||
switch( key ) {
|
||||
case XP_CURSOR_KEY_DOWN:
|
||||
return XP_CURSOR_KEY_RIGHT;
|
||||
result = XP_CURSOR_KEY_RIGHT; break;
|
||||
case XP_CURSOR_KEY_UP:
|
||||
return XP_CURSOR_KEY_LEFT;
|
||||
result = XP_CURSOR_KEY_LEFT; break;
|
||||
case XP_CURSOR_KEY_LEFT:
|
||||
return XP_CURSOR_KEY_UP;
|
||||
result = XP_CURSOR_KEY_UP; break;
|
||||
case XP_CURSOR_KEY_RIGHT:
|
||||
return XP_CURSOR_KEY_DOWN;
|
||||
result = XP_CURSOR_KEY_DOWN; break;
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
return key;
|
||||
return result;
|
||||
} /* flipKey */
|
||||
#endif
|
||||
|
||||
XP_Bool
|
||||
board_handleKey( BoardCtxt* board, XP_Key key )
|
||||
board_handleKey( BoardCtxt* board, XP_Key key, XP_Bool* pHandled )
|
||||
{
|
||||
XP_Bool result = XP_FALSE;
|
||||
XP_Bool redraw = XP_FALSE;
|
||||
XP_Bool handled = XP_FALSE;
|
||||
XP_Bool trayVisible = board->trayVisState == TRAY_REVEALED;
|
||||
XP_Bool gotArrow;
|
||||
|
||||
|
@ -2520,25 +2524,33 @@ board_handleKey( BoardCtxt* board, XP_Key key )
|
|||
case XP_CURSOR_KEY_LEFT:
|
||||
case XP_CURSOR_KEY_RIGHT:
|
||||
if ( board->focusHasDived ) {
|
||||
XP_Bool up = XP_FALSE;
|
||||
if ( board->focussed == OBJ_BOARD ) {
|
||||
result = board_moveCursor( board, flipKey( board, key ) );
|
||||
redraw = board_moveCursor( board,
|
||||
flipKey( key, board->isFlipped ),
|
||||
&up );
|
||||
} else if ( board->focussed == OBJ_SCORE ) {
|
||||
result = moveScoreCursor( board, key );
|
||||
redraw = moveScoreCursor( board, key, &up );
|
||||
} else if ( board->focussed == OBJ_TRAY ) {
|
||||
result = tray_moveCursor( board, key );
|
||||
redraw = tray_moveCursor( board, key, &up );
|
||||
}
|
||||
} else if ( board->focussed != OBJ_NONE ) {
|
||||
if ( up ) {
|
||||
invalFocusOwner( board );
|
||||
shiftFocusUp( board, key );
|
||||
result = XP_TRUE;
|
||||
board->focusHasDived = XP_FALSE;
|
||||
invalFocusOwner( board );
|
||||
} else {
|
||||
handled = XP_TRUE;
|
||||
}
|
||||
} else {
|
||||
/* Do nothing. We don't handle transition among top-level
|
||||
focussed objects. Platform must. */
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case XP_CURSOR_KEY_DEL:
|
||||
if ( trayVisible ) {
|
||||
replaceLastTile( board );
|
||||
result = XP_TRUE;
|
||||
handled = redraw = replaceLastTile( board );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2548,35 +2560,37 @@ board_handleKey( BoardCtxt* board, XP_Key key )
|
|||
invalFocusOwner( board );
|
||||
board->focusHasDived = XP_FALSE;
|
||||
invalFocusOwner( board );
|
||||
result = XP_TRUE;
|
||||
handled = redraw = XP_TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case XP_RETURN_KEY:
|
||||
if ( board->focusHasDived ) {
|
||||
result = XP_TRUE; /* even if don't draw, we handle it!! */
|
||||
handled = XP_TRUE; /* even if don't draw, we handle it!! */
|
||||
if ( board->focussed == OBJ_TRAY ) {
|
||||
if ( trayVisible ) {
|
||||
(void)tray_keyAction( board );
|
||||
redraw = tray_keyAction( board );
|
||||
} else {
|
||||
(void)askRevealTray( board );
|
||||
redraw = askRevealTray( board );
|
||||
}
|
||||
} else if ( board->focussed == OBJ_BOARD ) {
|
||||
/* mimic pen-down/pen-up on cursor */
|
||||
if ( trayVisible ) {
|
||||
BdCursorLoc loc = board->bdCursor[board->selPlayer];
|
||||
(void)handleActionInCell( board, loc.col, loc.row );
|
||||
redraw = handleActionInCell( board, loc.col, loc.row );
|
||||
} else {
|
||||
askRevealTray( board );
|
||||
redraw = askRevealTray( board );
|
||||
}
|
||||
} else if ( board->focussed == OBJ_SCORE ) {
|
||||
/* tap on what's already selected: reveal tray, etc. */
|
||||
board_selectPlayer( board, board->scoreCursorLoc );
|
||||
redraw = XP_TRUE; /* must assume */
|
||||
}
|
||||
} else if ( board->focussed != OBJ_NONE ) {
|
||||
redraw = invalFocusOwner( board );
|
||||
board->focusHasDived = XP_TRUE;
|
||||
board_invalAll( board ); /* just want to inval borders! */
|
||||
result = XP_TRUE;
|
||||
redraw = invalFocusOwner( board );
|
||||
handled = XP_TRUE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -2584,14 +2598,18 @@ board_handleKey( BoardCtxt* board, XP_Key key )
|
|||
default:
|
||||
XP_ASSERT( key >= XP_KEY_LAST );
|
||||
|
||||
result = trayVisible && moveKeyTileToBoard( board, key, &gotArrow );
|
||||
handled = redraw = trayVisible
|
||||
&& moveKeyTileToBoard( board, key, &gotArrow );
|
||||
|
||||
if ( result && gotArrow && !advanceArrow( board ) ) {
|
||||
if ( handled && gotArrow && !advanceArrow( board ) ) {
|
||||
setArrowVisible( board, XP_FALSE );
|
||||
}
|
||||
} /* switch */
|
||||
|
||||
return result;
|
||||
if ( !!pHandled ) {
|
||||
*pHandled = handled;
|
||||
}
|
||||
return redraw;
|
||||
} /* board_handleKey */
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
|
@ -2690,21 +2708,6 @@ board_toggle_arrowDir( BoardCtxt* board )
|
|||
}
|
||||
} /* board_toggle_cursorDir */
|
||||
|
||||
void
|
||||
shiftFocusUp( BoardCtxt* board, XP_Key key )
|
||||
{
|
||||
BoardObjectType next = OBJ_NONE;
|
||||
XP_ASSERT( board->focussed != OBJ_NONE );
|
||||
util_notifyFocusChange( board->util, board->focussed, key, &next );
|
||||
|
||||
if ( board->focussed != next ) {
|
||||
(void)board_focusChanged( board, board->focussed, XP_FALSE );
|
||||
|
||||
board->focusHasDived = XP_FALSE;
|
||||
|
||||
(void)board_focusChanged( board, next, XP_TRUE );
|
||||
}
|
||||
}
|
||||
#endif /* KEYBOARD_NAV */
|
||||
|
||||
static XP_Bool
|
||||
|
@ -2720,8 +2723,8 @@ advanceArrow( BoardCtxt* board )
|
|||
|
||||
static XP_Bool
|
||||
figureNextLoc( BoardCtxt* board, XP_Key cursorKey,
|
||||
XP_Bool XP_UNUSED_KEYBOARD_NAV(canShiftFocus),
|
||||
XP_Bool inclPending, XP_U16* colP, XP_U16* rowP )
|
||||
XP_Bool inclPending, XP_U16* colP, XP_U16* rowP,
|
||||
XP_Bool* pUp )
|
||||
{
|
||||
XP_S16 max;
|
||||
XP_S16* useWhat;
|
||||
|
@ -2772,9 +2775,8 @@ figureNextLoc( BoardCtxt* board, XP_Key cursorKey,
|
|||
for ( ; ; ) {
|
||||
if ( *useWhat == end ) {
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( canShiftFocus ) {
|
||||
shiftFocusUp( board, cursorKey );
|
||||
result = XP_TRUE;
|
||||
if ( !!pUp ) {
|
||||
*pUp = XP_TRUE;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -2798,7 +2800,7 @@ board_moveArrow( BoardCtxt* board, XP_Key cursorKey )
|
|||
|
||||
setArrowVisible( board, XP_TRUE );
|
||||
(void)getArrow( board, &col, &row );
|
||||
changed = figureNextLoc( board, cursorKey, XP_FALSE, XP_TRUE, &col, &row );
|
||||
changed = figureNextLoc( board, cursorKey, XP_TRUE, &col, &row, NULL );
|
||||
if ( changed ) {
|
||||
(void)setArrow( board, col, row );
|
||||
}
|
||||
|
@ -2807,15 +2809,14 @@ board_moveArrow( BoardCtxt* board, XP_Key cursorKey )
|
|||
|
||||
#ifdef KEYBOARD_NAV
|
||||
static XP_Bool
|
||||
board_moveCursor( BoardCtxt* board, XP_Key cursorKey )
|
||||
board_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool* up )
|
||||
{
|
||||
BdCursorLoc loc = board->bdCursor[board->selPlayer];
|
||||
XP_U16 col = loc.col;
|
||||
XP_U16 row = loc.row;
|
||||
XP_Bool changed;
|
||||
|
||||
changed = figureNextLoc( board, cursorKey, XP_TRUE, XP_FALSE,
|
||||
&col, &row );
|
||||
changed = figureNextLoc( board, cursorKey, XP_FALSE, &col, &row, up );
|
||||
if ( changed ) {
|
||||
invalCell( board, loc.col, loc.row );
|
||||
invalCell( board, col, row );
|
||||
|
|
|
@ -121,7 +121,7 @@ XP_Bool board_handlePenMove( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|||
XP_Bool board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
||||
#endif
|
||||
|
||||
XP_Bool board_handleKey( BoardCtxt* board, XP_Key key );
|
||||
XP_Bool board_handleKey( BoardCtxt* board, XP_Key key, XP_Bool* handled );
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
/* void board_focusChange( BoardCtxt* board ); */
|
||||
|
|
|
@ -198,7 +198,8 @@ XP_Bool rectsIntersect( XP_Rect* rect1, XP_Rect* rect2 );
|
|||
void board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer );
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey );
|
||||
XP_Key flipKey( XP_Key key, XP_Bool flip );
|
||||
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool* up );
|
||||
XP_Bool tray_keyAction( BoardCtxt* board );
|
||||
DrawFocusState dfsFor( BoardCtxt* board, BoardObjectType obj );
|
||||
void shiftFocusUp( BoardCtxt* board, XP_Key key );
|
||||
|
|
|
@ -74,12 +74,6 @@ drawScoreBoard( BoardCtxt* board )
|
|||
cursorIndex = board->scoreCursorLoc;
|
||||
}
|
||||
}
|
||||
|
||||
/* XP_Bool focusAll = (board->focussed == OBJ_SCORE) */
|
||||
/* && !board->focusHasDived; */
|
||||
/* XP_S16 cursorIndex = ( (board->focussed == OBJ_SCORE) */
|
||||
/* && board->focusHasDived ) ? */
|
||||
/* board->scoreCursorLoc : -1; */
|
||||
#endif
|
||||
draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers,
|
||||
dfsFor( board, OBJ_SCORE ) );
|
||||
|
@ -285,30 +279,40 @@ handlePenUpScore( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool
|
||||
moveScoreCursor( BoardCtxt* board, XP_Key key )
|
||||
moveScoreCursor( BoardCtxt* board, XP_Key key, XP_Bool* pUp )
|
||||
{
|
||||
XP_Bool result = XP_TRUE;
|
||||
XP_U16 nPlayers = board->gi->nPlayers;
|
||||
XP_S16 scoreCursorLoc = board->scoreCursorLoc;
|
||||
XP_Bool up = XP_FALSE;
|
||||
|
||||
/* Depending on scoreboard layout, keys move cursor or leave. */
|
||||
key = flipKey( key, board->scoreSplitHor );
|
||||
|
||||
switch ( key ) {
|
||||
case XP_CURSOR_KEY_DOWN:
|
||||
case XP_CURSOR_KEY_RIGHT:
|
||||
++scoreCursorLoc;
|
||||
break;
|
||||
case XP_CURSOR_KEY_RIGHT:
|
||||
up = XP_TRUE;
|
||||
break;
|
||||
case XP_CURSOR_KEY_UP:
|
||||
case XP_CURSOR_KEY_LEFT:
|
||||
--scoreCursorLoc;
|
||||
break;
|
||||
case XP_CURSOR_KEY_LEFT:
|
||||
up = XP_TRUE;
|
||||
break;
|
||||
default:
|
||||
result = XP_FALSE;
|
||||
}
|
||||
if ( scoreCursorLoc < 0 || scoreCursorLoc >= nPlayers ) {
|
||||
shiftFocusUp( board, key );
|
||||
if ( !up && ((scoreCursorLoc < 0) || (scoreCursorLoc >= nPlayers)) ) {
|
||||
up = XP_TRUE;
|
||||
} else {
|
||||
board->scoreCursorLoc = scoreCursorLoc;
|
||||
}
|
||||
board->scoreBoardInvalid = XP_TRUE;
|
||||
}
|
||||
|
||||
*pUp = up;
|
||||
|
||||
return result;
|
||||
} /* moveScoreCursor */
|
||||
|
|
|
@ -31,7 +31,7 @@ XP_Bool handlePenUpScore( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|||
#endif
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool moveScoreCursor( BoardCtxt* board, XP_Key key );
|
||||
XP_Bool moveScoreCursor( BoardCtxt* board, XP_Key key, XP_Bool* up );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -111,12 +111,13 @@ drawTray( BoardCtxt* board )
|
|||
if ( draw_trayBegin( board->draw, &board->trayBounds, turn,
|
||||
dfsFor( board, OBJ_TRAY ) ) ) {
|
||||
DictionaryCtxt* dictionary = model_getDictionary( board->model );
|
||||
XP_S16 cursorIndex = -1;
|
||||
XP_S16 cursorBits = 0;
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( board->focusHasDived && board->focussed == OBJ_TRAY ) {
|
||||
TileBit cursorLoc = 1 << board->trayCursorLoc[turn];
|
||||
if ( !!cursorLoc ) {
|
||||
cursorIndex = indexForBits( cursorLoc );
|
||||
if ( board->focussed == OBJ_TRAY ) {
|
||||
if ( board->focusHasDived ) {
|
||||
cursorBits = 1 << board->trayCursorLoc[turn];
|
||||
} else {
|
||||
cursorBits = ALLTILES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -139,12 +140,13 @@ drawTray( BoardCtxt* board )
|
|||
erasing */
|
||||
for ( i = MAX_TRAY_TILES - 1; i >= 0; --i ) {
|
||||
CellFlags flags = CELL_NONE;
|
||||
XP_U16 mask = 1 << i;
|
||||
|
||||
if ( (board->trayInvalBits & (1 << i)) == 0 ) {
|
||||
if ( (board->trayInvalBits & mask) == 0 ) {
|
||||
continue;
|
||||
}
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( cursorIndex == i ) {
|
||||
if ( (cursorBits & mask) != 0 ) {
|
||||
flags |= CELL_ISCURSOR;
|
||||
}
|
||||
#endif
|
||||
|
@ -200,11 +202,13 @@ drawTray( BoardCtxt* board )
|
|||
board->dividerInvalid = XP_FALSE;
|
||||
}
|
||||
|
||||
drawPendingScore( board, cursorIndex == MAX_TRAY_TILES - 1 );
|
||||
drawPendingScore( board,
|
||||
(cursorBits & (1<<(MAX_TRAY_TILES-1))) != 0 );
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( cursorIndex >= 0 ) {
|
||||
figureTrayTileRect( board, cursorIndex, &tileRect );
|
||||
if ( (cursorBits != 0) && (cursorBits != ALLTILES) ) {
|
||||
figureTrayTileRect( board, indexForBits(cursorBits),
|
||||
&tileRect );
|
||||
draw_drawCursor( board->draw, OBJ_TRAY, &tileRect );
|
||||
}
|
||||
#endif
|
||||
|
@ -634,26 +638,34 @@ board_juggleTray( BoardCtxt* board )
|
|||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool
|
||||
tray_moveCursor( BoardCtxt* board, XP_Key cursorKey )
|
||||
tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool* up )
|
||||
{
|
||||
XP_Bool result;
|
||||
XP_U16 selPlayer = board->selPlayer;
|
||||
|
||||
if ( cursorKey == XP_CURSOR_KEY_UP ) {
|
||||
result = board_moveDivider( board, XP_FALSE );
|
||||
} else if ( cursorKey == XP_CURSOR_KEY_DOWN ) {
|
||||
result = board_moveDivider( board, XP_TRUE );
|
||||
} else {
|
||||
XP_S16 pos;
|
||||
|
||||
switch (cursorKey ) {
|
||||
case XP_CURSOR_KEY_UP:
|
||||
case XP_CURSOR_KEY_DOWN:
|
||||
*up = XP_TRUE;
|
||||
/* moving the divider needs to be hard to do accidentally since it
|
||||
confuses users when juggle and hint stop working. But all things
|
||||
must be possible via keyboard on devices that don't have
|
||||
touchscreens. Probably need a new keytype XP_CURSOR_KEY_ALTDOWN
|
||||
etc. */
|
||||
/* result = board_moveDivider( board, XP_FALSE ); */
|
||||
/* result = board_moveDivider( board, XP_TRUE ); */
|
||||
break;
|
||||
case XP_CURSOR_KEY_RIGHT:
|
||||
case XP_CURSOR_KEY_LEFT:
|
||||
board_invalTrayTiles( board, 1 << board->trayCursorLoc[selPlayer] );
|
||||
|
||||
pos = board->trayCursorLoc[selPlayer];
|
||||
/* Loop in order to skip all empty tile slots but one */
|
||||
for ( ; ; ) {
|
||||
pos += cursorKey == XP_CURSOR_KEY_RIGHT ? 1 : -1;
|
||||
pos += (cursorKey == XP_CURSOR_KEY_RIGHT ? 1 : -1);
|
||||
if ( pos < 0 || pos >= MAX_TRAY_TILES ) {
|
||||
shiftFocusUp( board, cursorKey );
|
||||
*up = XP_TRUE;
|
||||
} else {
|
||||
/* Revisit this when able to never draw the cursor in a place
|
||||
this won't allow it, e.g. when the tiles move after a
|
||||
|
@ -672,6 +684,10 @@ tray_moveCursor( BoardCtxt* board, XP_Key cursorKey )
|
|||
}
|
||||
board_invalTrayTiles( board, 1 << board->trayCursorLoc[selPlayer] );
|
||||
result = XP_TRUE;
|
||||
break;
|
||||
default:
|
||||
XP_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -156,10 +156,6 @@ typedef struct UtilVtable {
|
|||
void (*m_util_engineStopping)( XW_UtilCtxt* uc );
|
||||
#endif
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
void (*m_util_notifyFocusChange)( XW_UtilCtxt* uc, BoardObjectType cur,
|
||||
XP_Key key, BoardObjectType* next );
|
||||
#endif
|
||||
} UtilVtable;
|
||||
|
||||
|
||||
|
@ -246,8 +242,4 @@ struct XW_UtilCtxt {
|
|||
# define util_engineStopping( uc )
|
||||
# endif
|
||||
|
||||
# ifdef KEYBOARD_NAV
|
||||
# define util_notifyFocusChange( uc, c, k, n ) \
|
||||
(uc)->vtable->m_util_notifyFocusChange((uc),(c),(k),(n))
|
||||
# endif
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue