diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 24478de94..6fb236f15 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -1022,14 +1022,15 @@ invalCellsWithTiles( BoardCtxt* board ) return board->needsDrawing; } /* invalCellsWithTiles */ -void +XP_Bool checkScrollCell( void* p_board, XP_U16 col, XP_U16 row ) { BoardCtxt* board = (BoardCtxt*)p_board; XP_Rect rect; + XP_Bool moved = XP_FALSE; if ( board->boardObscuresTray && board->trayVisState != TRAY_HIDDEN ) { - + /* call getCellRect until the cell's on the board. */ while ( !getCellRect( board, col, row, &rect ) ) { XP_U16 oldOffset = board_getYOffset( board ); if ( rect.top < board->boardBounds.top ) { @@ -1041,8 +1042,10 @@ checkScrollCell( void* p_board, XP_U16 col, XP_U16 row ) XP_ASSERT( 0 ); } board_setYOffset( board, oldOffset ); + moved = XP_TRUE; } } + return moved; } /* checkScrollCell */ /* if any of a blank's neighbors is invalid, so must the blank become (since @@ -1111,8 +1114,8 @@ scrollIfCan( BoardCtxt* board ) if ( scrolled ) { /* inval the rows that have been scrolled into view. I'm cheating - making the client figure the inval rect, but Palm's the only - client now and it does it so well.... */ + making the client figure the inval rect, but Palm's the first + client and it does it so well.... */ invalCellsUnderRect( board, &scrollR ); } else { board_invalAll( board ); @@ -1782,7 +1785,6 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks ) } else if ( dict_faceIsBitmap( dict, tile ) ) { bitmap = dict_getFaceBitmap( dict, tile, XP_FALSE ); XP_ASSERT( !!bitmap ); - textP = (XP_UCHAR*)NULL; } else { (void)dict_tilesToString( dict, &tile, 1, ch, sizeof(ch) ); textP = ch; diff --git a/xwords4/common/boardp.h b/xwords4/common/boardp.h index 56abc654a..26ef5d062 100644 --- a/xwords4/common/boardp.h +++ b/xwords4/common/boardp.h @@ -241,7 +241,7 @@ XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank, XP_UCHAR* buf, XP_U16 len ); XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ); -void checkScrollCell( void* p_board, XP_U16 col, XP_U16 row ); +XP_Bool checkScrollCell( void* p_board, XP_U16 col, XP_U16 row ); #ifdef KEYBOARD_NAV XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, diff --git a/xwords4/common/dragdrpp.c b/xwords4/common/dragdrpp.c index 1353b4df2..be7771d5b 100644 --- a/xwords4/common/dragdrpp.c +++ b/xwords4/common/dragdrpp.c @@ -411,18 +411,15 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, (void)coordToCell( board, xx, yy, &newInfo.u.board.col, &newInfo.u.board.row ); moving = (newInfo.u.board.col != ds->cur.u.board.col) - || (newInfo.u.board.row != ds->cur.u.board.row); - if ( moving ) { - checkScrollCell( board, newInfo.u.board.col, newInfo.u.board.row ); - } - moving = moving || (OBJ_TRAY == ds->cur.obj); + || (newInfo.u.board.row != ds->cur.u.board.row) + || (OBJ_TRAY == ds->cur.obj); } else if ( newInfo.obj == OBJ_TRAY ) { XP_Bool onDivider; XP_S16 index = pointToTileIndex( board, xx, yy, &onDivider ); if ( !onDivider ) { - if ( index < 0 ) { /* negative means onto empty part of tray. - Force left. */ + if ( index < 0 ) { /* negative means onto empty part of + tray. Force left. */ index = model_getNumTilesInTray( board->model, board->selPlayer ); if ( OBJ_TRAY == ds->start.obj ) { @@ -438,16 +435,28 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy, } if ( moving ) { - if ( ds->dtype == DT_TILE ) { - invalDragObjRange( board, &ds->cur, &newInfo ); + + /* This little hack lets us inval twice using the same code but + only in the case where scrolling moves tiles. At a minimum + it's necessary to inval the old position before a scroll and + the new after. Otherwise if the platform scrolls by + bit-blitting the dragged object will be scrolled before it's + invalidated. */ + do { + if ( ds->dtype == DT_TILE ) { + invalDragObjRange( board, &ds->cur, &newInfo ); #ifdef XWFEATURE_SEARCHLIMIT - } else if ( ds->dtype == DT_HINTRGN ) { - invalHintRectDiffs( board, &ds->cur, &newInfo ); - if ( !ds->didMove ) { /* first time through */ - invalCurHintRect( board, board->selPlayer ); - } + } else if ( ds->dtype == DT_HINTRGN ) { + invalHintRectDiffs( board, &ds->cur, &newInfo ); + if ( !ds->didMove ) { /* first time through */ + invalCurHintRect( board, board->selPlayer ); + } #endif - } + } + } while ( (newInfo.obj == OBJ_BOARD) + && checkScrollCell( board, newInfo.u.board.col, + newInfo.u.board.row ) ); + XP_MEMCPY( &ds->cur, &newInfo, sizeof(ds->cur) ); } }