mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-29 08:34:37 +01:00
Use new keydown/up APIs from linux, and add key support and drawing
changes to implement keyboard navigation/focus in gtk port.
This commit is contained in:
parent
bce76a3d34
commit
23fcaa65ab
6 changed files with 172 additions and 74 deletions
|
@ -340,8 +340,8 @@ handleSpace( CursesAppGlobals* globals )
|
|||
XP_Bool handled;
|
||||
checkAssignFocus( globals->cGlobals.game.board );
|
||||
|
||||
globals->doDraw = board_handleKey( globals->cGlobals.game.board,
|
||||
XP_RAISEFOCUS_KEY, &handled );
|
||||
globals->doDraw = board_handleKeyUp( globals->cGlobals.game.board,
|
||||
XP_RAISEFOCUS_KEY, &handled );
|
||||
return XP_TRUE;
|
||||
} /* handleSpace */
|
||||
|
||||
|
@ -349,8 +349,8 @@ static XP_Bool
|
|||
handleRet( CursesAppGlobals* globals )
|
||||
{
|
||||
XP_Bool handled;
|
||||
globals->doDraw = board_handleKey( globals->cGlobals.game.board,
|
||||
XP_RETURN_KEY, &handled );
|
||||
globals->doDraw = board_handleKeyUp( globals->cGlobals.game.board,
|
||||
XP_RETURN_KEY, &handled );
|
||||
return XP_TRUE;
|
||||
} /* handleRet */
|
||||
|
||||
|
@ -437,8 +437,8 @@ static XP_Bool
|
|||
handleBackspace( CursesAppGlobals* globals )
|
||||
{
|
||||
XP_Bool handled;
|
||||
globals->doDraw = board_handleKey( globals->cGlobals.game.board,
|
||||
XP_CURSOR_KEY_DEL, &handled );
|
||||
globals->doDraw = board_handleKeyUp( globals->cGlobals.game.board,
|
||||
XP_CURSOR_KEY_DEL, &handled );
|
||||
return XP_TRUE;
|
||||
} /* handleBackspace */
|
||||
|
||||
|
@ -482,46 +482,6 @@ MenuList sharedMenuList[] = {
|
|||
};
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
static XP_Bool
|
||||
shiftFocus( CursesAppGlobals* globals, XP_Key key )
|
||||
{
|
||||
BoardCtxt* board = globals->cGlobals.game.board;
|
||||
XP_Bool handled = XP_FALSE;
|
||||
|
||||
do { /* allow break */
|
||||
XP_Bool forward;
|
||||
BoardObjectType nxt;
|
||||
|
||||
if ( key == XP_CURSOR_KEY_DOWN || key == XP_CURSOR_KEY_RIGHT ) {
|
||||
forward = XP_TRUE;
|
||||
} else if ( key == XP_CURSOR_KEY_UP || key == XP_CURSOR_KEY_LEFT ) {
|
||||
forward = XP_FALSE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
switch( board_getFocusOwner( board ) ) {
|
||||
case OBJ_NONE:
|
||||
XP_ASSERT( 0 ); /* not in curses anyway */
|
||||
break;
|
||||
case OBJ_SCORE:
|
||||
nxt = forward ? OBJ_TRAY : OBJ_BOARD;
|
||||
break;
|
||||
case OBJ_BOARD:
|
||||
nxt = forward ? OBJ_SCORE : OBJ_TRAY;
|
||||
break;
|
||||
case OBJ_TRAY:
|
||||
nxt = forward ? OBJ_BOARD : OBJ_SCORE;
|
||||
break;
|
||||
}
|
||||
handled = board_focusChanged( board, nxt, XP_TRUE );
|
||||
if ( handled ) {
|
||||
changeMenuForFocus( globals, nxt );
|
||||
}
|
||||
} while ( 0 );
|
||||
return handled;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
handleFocusKey( CursesAppGlobals* globals, XP_Key key )
|
||||
{
|
||||
|
@ -530,9 +490,14 @@ handleFocusKey( CursesAppGlobals* globals, XP_Key key )
|
|||
|
||||
checkAssignFocus( globals->cGlobals.game.board );
|
||||
|
||||
draw = board_handleKey( globals->cGlobals.game.board, key, &handled );
|
||||
draw = board_handleKeyUp( globals->cGlobals.game.board, key, &handled );
|
||||
if ( !handled ) {
|
||||
draw = shiftFocus( globals, key ) || draw;
|
||||
BoardObjectType nxt;
|
||||
BoardObjectType order[] = { OBJ_BOARD, OBJ_SCORE, OBJ_TRAY };
|
||||
draw = linShiftFocus( &globals->cGlobals, key, order, &nxt ) || draw;
|
||||
if ( nxt != OBJ_NONE ) {
|
||||
changeMenuForFocus( globals, nxt );
|
||||
}
|
||||
}
|
||||
|
||||
globals->doDraw = draw || globals->doDraw;
|
||||
|
@ -1037,8 +1002,8 @@ passKeyToBoard( CursesAppGlobals* globals, char ch )
|
|||
XP_Bool handled = ch >= 'a' && ch <= 'z';
|
||||
if ( handled ) {
|
||||
ch += 'A' - 'a';
|
||||
globals->doDraw = board_handleKey( globals->cGlobals.game.board,
|
||||
ch, NULL );
|
||||
globals->doDraw = board_handleKeyUp( globals->cGlobals.game.board,
|
||||
ch, NULL );
|
||||
}
|
||||
return handled;
|
||||
} /* passKeyToBoard */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*- mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/* -*- mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
||||
/*
|
||||
* Copyright 1997-2005 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||
* Copyright 1997-2007 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
|
||||
|
@ -256,12 +256,38 @@ gtk_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* XP_UNUSED(dict),
|
|||
} /* draw_finish */
|
||||
|
||||
static void
|
||||
gtk_draw_objFinished( DrawCtx* XP_UNUSED(p_dctx),
|
||||
BoardObjectType XP_UNUSED(typ),
|
||||
const XP_Rect* XP_UNUSED(rect),
|
||||
DrawFocusState XP_UNUSED(dfs) )
|
||||
drawFocusFrame( GtkDrawCtx* dctx, const XP_Rect* r )
|
||||
{
|
||||
// GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
XP_Rect rectInset = *r;
|
||||
XP_U16 i;
|
||||
XP_U16 targetDim;
|
||||
|
||||
targetDim = XP_MIN( rectInset.width, rectInset.height );
|
||||
targetDim >>= 1;
|
||||
|
||||
gdk_gc_set_foreground( dctx->drawGC, &dctx->black );
|
||||
|
||||
for ( i = 0; i < 5; ++i ) {
|
||||
insetRect( &rectInset, 1 );
|
||||
if ( rectInset.width < targetDim || rectInset.height < targetDim ) {
|
||||
break;
|
||||
}
|
||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
||||
dctx->drawGC,
|
||||
FALSE,
|
||||
rectInset.left, rectInset.top,
|
||||
rectInset.width+1, rectInset.height+1 );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_draw_objFinished( DrawCtx* p_dctx, BoardObjectType XP_UNUSED(typ),
|
||||
const XP_Rect* rect, DrawFocusState dfs )
|
||||
{
|
||||
if ( dfs == DFS_TOP ) {
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
drawFocusFrame( dctx, rect );
|
||||
}
|
||||
} /* draw_finished */
|
||||
|
||||
static void
|
||||
|
@ -378,6 +404,10 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
|
|||
|
||||
drawHintBorders( dctx, rect, hintAtts );
|
||||
|
||||
if ( (flags & CELL_ISCURSOR) != 0 ) {
|
||||
drawFocusFrame( dctx, rect );
|
||||
}
|
||||
|
||||
return XP_TRUE;
|
||||
} /* gtk_draw_drawCell */
|
||||
|
||||
|
@ -404,12 +434,14 @@ gtk_draw_invertCell( DrawCtx* XP_UNUSED(p_dctx),
|
|||
|
||||
static XP_Bool
|
||||
gtk_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect, XP_U16 owner,
|
||||
DrawFocusState XP_UNUSED(dfs) )
|
||||
DrawFocusState dfs )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
XP_Rect clip = *rect;
|
||||
insetRect( &clip, -1 );
|
||||
dctx->trayOwner = owner;
|
||||
dctx->topFocus = dfs == DFS_TOP;
|
||||
|
||||
/* gdk_gc_set_clip_rectangle( dctx->drawGC, (GdkRectangle*)&clip ); */
|
||||
return XP_TRUE;
|
||||
} /* gtk_draw_trayBegin */
|
||||
|
@ -476,11 +508,16 @@ gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
|||
insetR.width, insetR.height);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !dctx->topFocus && (flags & CELL_ISCURSOR) != 0 ) {
|
||||
drawFocusFrame( dctx, rect );
|
||||
}
|
||||
|
||||
} /* gtk_draw_drawTile */
|
||||
|
||||
static void
|
||||
gtk_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||
CellFlags XP_UNUSED(flags) )
|
||||
CellFlags flags )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
XP_Rect r = *rect;
|
||||
|
@ -502,6 +539,10 @@ gtk_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
draw_string_at( dctx, dctx->layout[LAYOUT_LARGE], "?",
|
||||
&r, XP_GTK_JUST_CENTER,
|
||||
&dctx->playerColors[dctx->trayOwner], NULL );
|
||||
|
||||
if ( !dctx->topFocus && (flags & CELL_ISCURSOR) != 0 ) {
|
||||
drawFocusFrame( dctx, rect );
|
||||
}
|
||||
} /* gtk_draw_drawTileBack */
|
||||
|
||||
static void
|
||||
|
@ -577,12 +618,13 @@ gtk_draw_drawBoardArrow( DrawCtx* p_dctx, const XP_Rect* rectP,
|
|||
static void
|
||||
gtk_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||
XP_U16 XP_UNUSED(numPlayers),
|
||||
DrawFocusState XP_UNUSED(dfs) )
|
||||
DrawFocusState dfs )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
|
||||
/* gdk_gc_set_clip_rectangle( dctx->drawGC, (GdkRectangle*)rect ); */
|
||||
eraseRect( dctx, rect );
|
||||
dctx->topFocus = dfs == DFS_TOP;
|
||||
} /* gtk_draw_scoreBegin */
|
||||
|
||||
static void
|
||||
|
@ -702,12 +744,16 @@ gtk_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], scoreBuf,
|
||||
rInner, XP_GTK_JUST_CENTER,
|
||||
&dctx->playerColors[dsi->playerNum], NULL );
|
||||
|
||||
if ( !dctx->topFocus && ((dsi->flags & CELL_ISCURSOR) != 0) ) {
|
||||
drawFocusFrame( dctx, rOuter );
|
||||
}
|
||||
} /* gtk_draw_score_drawPlayer */
|
||||
|
||||
static void
|
||||
gtk_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||
XP_S16 score, XP_U16 XP_UNUSED(playerNum),
|
||||
CellFlags XP_UNUSED(flags) )
|
||||
CellFlags flags )
|
||||
{
|
||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||
char buf[5];
|
||||
|
@ -733,6 +779,10 @@ gtk_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
draw_string_at( dctx, dctx->layout[LAYOUT_SMALL], buf,
|
||||
&localR, XP_GTK_JUST_BOTTOMRIGHT,
|
||||
&dctx->black, NULL );
|
||||
|
||||
if ( !dctx->topFocus && (flags & CELL_ISCURSOR) != 0 ) {
|
||||
drawFocusFrame( dctx, rect );
|
||||
}
|
||||
} /* gtk_draw_score_pendingScore */
|
||||
|
||||
static void
|
||||
|
|
|
@ -153,17 +153,20 @@ button_release_event( GtkWidget* XP_UNUSED(widget), GdkEventMotion *event,
|
|||
return 1;
|
||||
} /* button_release_event */
|
||||
|
||||
static gint
|
||||
key_release_event( GtkWidget* XP_UNUSED(widget), GdkEventKey* event,
|
||||
GtkAppGlobals* globals )
|
||||
static XP_Key
|
||||
evtToXPKey( GdkEventKey* event, XP_Bool* movesCursorP )
|
||||
{
|
||||
XP_Key xpkey = XP_KEY_NONE;
|
||||
XP_Bool movesCursor = XP_FALSE;
|
||||
guint keyval = event->keyval;
|
||||
|
||||
XP_LOGF( "got key 0x%x", keyval );
|
||||
|
||||
switch( keyval ) {
|
||||
switch( keyval ) {
|
||||
case GDK_Return:
|
||||
xpkey = XP_RETURN_KEY;
|
||||
break;
|
||||
case GDK_space:
|
||||
xpkey = XP_RAISEFOCUS_KEY;
|
||||
break;
|
||||
|
||||
case GDK_Left:
|
||||
xpkey = XP_CURSOR_KEY_LEFT;
|
||||
|
@ -191,16 +194,43 @@ key_release_event( GtkWidget* XP_UNUSED(widget), GdkEventKey* event,
|
|||
xpkey = toupper(keyval);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
*movesCursorP = movesCursor;
|
||||
return xpkey;
|
||||
} /* evtToXPKey */
|
||||
|
||||
static gint
|
||||
key_press_event( GtkWidget* XP_UNUSED(widget), GdkEventKey* event,
|
||||
GtkAppGlobals* globals )
|
||||
{
|
||||
XP_Bool handled = XP_FALSE;
|
||||
XP_Bool movesCursor;
|
||||
XP_Key xpkey = evtToXPKey( event, &movesCursor );
|
||||
if ( xpkey != XP_KEY_NONE ) {
|
||||
if ( board_handleKeyDown( globals->cGlobals.game.board, xpkey,
|
||||
&handled ) ) {
|
||||
board_draw( globals->cGlobals.game.board );
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static gint
|
||||
key_release_event( GtkWidget* XP_UNUSED(widget), GdkEventKey* event,
|
||||
GtkAppGlobals* globals )
|
||||
{
|
||||
XP_Bool handled = XP_FALSE;
|
||||
XP_Bool movesCursor;
|
||||
XP_Key xpkey = evtToXPKey( event, &movesCursor );
|
||||
|
||||
if ( xpkey != XP_KEY_NONE ) {
|
||||
XP_Bool handled;
|
||||
XP_Bool draw;
|
||||
draw = board_handleKey( globals->cGlobals.game.board, xpkey, &handled );
|
||||
draw = board_handleKeyUp( globals->cGlobals.game.board, xpkey, &handled );
|
||||
|
||||
if ( movesCursor || !handled ) {
|
||||
XP_LOGF( "need to handle focus shift" );
|
||||
if ( movesCursor && !handled ) {
|
||||
BoardObjectType order[] = { OBJ_SCORE, OBJ_BOARD, OBJ_TRAY };
|
||||
draw = linShiftFocus( &globals->cGlobals, xpkey, order,
|
||||
NULL ) || draw;
|
||||
}
|
||||
|
||||
if ( draw ) {
|
||||
|
@ -208,7 +238,7 @@ key_release_event( GtkWidget* XP_UNUSED(widget), GdkEventKey* event,
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return handled? 1 : 0; /* gtk will do something with the key if 0 returned */
|
||||
} /* key_release_event */
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
|
@ -1134,7 +1164,7 @@ pentimer_idle_func( gpointer data )
|
|||
GtkAppGlobals* globals = (GtkAppGlobals*)data;
|
||||
struct timeval tv;
|
||||
XP_Bool callAgain = XP_TRUE;
|
||||
|
||||
|
||||
gettimeofday( &tv, NULL );
|
||||
|
||||
if ( (tv.tv_usec - globals->penTv.tv_usec) >= globals->penTimerInterval) {
|
||||
|
@ -1788,6 +1818,8 @@ gtkmain( LaunchParams* params, int argc, char *argv[] )
|
|||
g_signal_connect( GTK_OBJECT(drawing_area), "button_release_event",
|
||||
G_CALLBACK(button_release_event), &globals );
|
||||
|
||||
g_signal_connect( GTK_OBJECT(window), "key_press_event",
|
||||
G_CALLBACK(key_press_event), &globals );
|
||||
g_signal_connect( GTK_OBJECT(window), "key_release_event",
|
||||
G_CALLBACK(key_release_event), &globals );
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ typedef struct GtkDrawCtx {
|
|||
PangoLayout* layout[LAYOUT_NLAYOUTS];
|
||||
|
||||
XP_U16 trayOwner;
|
||||
XP_Bool topFocus;
|
||||
} GtkDrawCtx;
|
||||
|
||||
typedef struct ClientStreamRec {
|
||||
|
|
|
@ -286,6 +286,50 @@ usage( char* appName, char* msg )
|
|||
exit(1);
|
||||
} /* usage */
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool
|
||||
linShiftFocus( CommonGlobals* cGlobals, XP_Key key, const BoardObjectType* order,
|
||||
BoardObjectType* nxtP )
|
||||
{
|
||||
BoardCtxt* board = cGlobals->game.board;
|
||||
XP_Bool handled = XP_FALSE;
|
||||
BoardObjectType nxt = OBJ_NONE;
|
||||
BoardObjectType cur;
|
||||
XP_U16 i, curIndex;
|
||||
|
||||
cur = board_getFocusOwner( board );
|
||||
if ( cur == OBJ_NONE ) {
|
||||
cur = order[0];
|
||||
}
|
||||
for ( i = 0; i < 3; ++i ) {
|
||||
if ( cur == order[i] ) {
|
||||
curIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
XP_ASSERT( curIndex < 3 );
|
||||
|
||||
curIndex += 3;
|
||||
if ( key == XP_CURSOR_KEY_DOWN || key == XP_CURSOR_KEY_RIGHT ) {
|
||||
++curIndex;
|
||||
} else if ( key == XP_CURSOR_KEY_UP || key == XP_CURSOR_KEY_LEFT ) {
|
||||
--curIndex;
|
||||
} else {
|
||||
XP_ASSERT(0);
|
||||
}
|
||||
curIndex %= 3;
|
||||
|
||||
nxt = order[curIndex];
|
||||
handled = board_focusChanged( board, nxt, XP_TRUE );
|
||||
|
||||
if ( !!nxtP ) {
|
||||
*nxtP = nxt;
|
||||
}
|
||||
|
||||
return handled;
|
||||
} /* linShiftFocus */
|
||||
#endif
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
static int
|
||||
linux_init_relay_socket( CommonGlobals* cGlobals )
|
||||
|
|
|
@ -53,4 +53,10 @@ XP_UCHAR* strFromStream( XWStreamCtxt* stream );
|
|||
void catGameHistory( CommonGlobals* cGlobals );
|
||||
void catOnClose( XWStreamCtxt* stream, void* closure );
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
XP_Bool linShiftFocus( CommonGlobals* cGlobals, XP_Key key,
|
||||
const BoardObjectType* order,
|
||||
BoardObjectType* nxtP );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue