When scrolling in response to a drag, invalidate under the tile both

before and after the scroll.  Otherwise on platforms where scrolling
is via a bitmove the old position gets scrolled away and never redrawn
leaving ghost tile parts lying around.
This commit is contained in:
ehouse 2008-03-15 14:00:05 +00:00
parent ddafe8b97a
commit ffd7dffd27
3 changed files with 32 additions and 21 deletions

View file

@ -1022,14 +1022,15 @@ invalCellsWithTiles( BoardCtxt* board )
return board->needsDrawing; return board->needsDrawing;
} /* invalCellsWithTiles */ } /* invalCellsWithTiles */
void XP_Bool
checkScrollCell( void* p_board, XP_U16 col, XP_U16 row ) checkScrollCell( void* p_board, XP_U16 col, XP_U16 row )
{ {
BoardCtxt* board = (BoardCtxt*)p_board; BoardCtxt* board = (BoardCtxt*)p_board;
XP_Rect rect; XP_Rect rect;
XP_Bool moved = XP_FALSE;
if ( board->boardObscuresTray && board->trayVisState != TRAY_HIDDEN ) { if ( board->boardObscuresTray && board->trayVisState != TRAY_HIDDEN ) {
/* call getCellRect until the cell's on the board. */
while ( !getCellRect( board, col, row, &rect ) ) { while ( !getCellRect( board, col, row, &rect ) ) {
XP_U16 oldOffset = board_getYOffset( board ); XP_U16 oldOffset = board_getYOffset( board );
if ( rect.top < board->boardBounds.top ) { if ( rect.top < board->boardBounds.top ) {
@ -1041,8 +1042,10 @@ checkScrollCell( void* p_board, XP_U16 col, XP_U16 row )
XP_ASSERT( 0 ); XP_ASSERT( 0 );
} }
board_setYOffset( board, oldOffset ); board_setYOffset( board, oldOffset );
moved = XP_TRUE;
} }
} }
return moved;
} /* checkScrollCell */ } /* checkScrollCell */
/* if any of a blank's neighbors is invalid, so must the blank become (since /* if any of a blank's neighbors is invalid, so must the blank become (since
@ -1111,8 +1114,8 @@ scrollIfCan( BoardCtxt* board )
if ( scrolled ) { if ( scrolled ) {
/* inval the rows that have been scrolled into view. I'm cheating /* inval the rows that have been scrolled into view. I'm cheating
making the client figure the inval rect, but Palm's the only making the client figure the inval rect, but Palm's the first
client now and it does it so well.... */ client and it does it so well.... */
invalCellsUnderRect( board, &scrollR ); invalCellsUnderRect( board, &scrollR );
} else { } else {
board_invalAll( board ); 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 ) ) { } else if ( dict_faceIsBitmap( dict, tile ) ) {
bitmap = dict_getFaceBitmap( dict, tile, XP_FALSE ); bitmap = dict_getFaceBitmap( dict, tile, XP_FALSE );
XP_ASSERT( !!bitmap ); XP_ASSERT( !!bitmap );
textP = (XP_UCHAR*)NULL;
} else { } else {
(void)dict_tilesToString( dict, &tile, 1, ch, sizeof(ch) ); (void)dict_tilesToString( dict, &tile, 1, ch, sizeof(ch) );
textP = ch; textP = ch;

View file

@ -241,7 +241,7 @@ XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank,
XP_UCHAR* buf, XP_U16 len ); XP_UCHAR* buf, XP_U16 len );
XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ); 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 #ifdef KEYBOARD_NAV
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey, XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey,

View file

@ -411,18 +411,15 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
(void)coordToCell( board, xx, yy, &newInfo.u.board.col, (void)coordToCell( board, xx, yy, &newInfo.u.board.col,
&newInfo.u.board.row ); &newInfo.u.board.row );
moving = (newInfo.u.board.col != ds->cur.u.board.col) moving = (newInfo.u.board.col != ds->cur.u.board.col)
|| (newInfo.u.board.row != ds->cur.u.board.row); || (newInfo.u.board.row != ds->cur.u.board.row)
if ( moving ) { || (OBJ_TRAY == ds->cur.obj);
checkScrollCell( board, newInfo.u.board.col, newInfo.u.board.row );
}
moving = moving || (OBJ_TRAY == ds->cur.obj);
} else if ( newInfo.obj == OBJ_TRAY ) { } else if ( newInfo.obj == OBJ_TRAY ) {
XP_Bool onDivider; XP_Bool onDivider;
XP_S16 index = pointToTileIndex( board, xx, yy, &onDivider ); XP_S16 index = pointToTileIndex( board, xx, yy, &onDivider );
if ( !onDivider ) { if ( !onDivider ) {
if ( index < 0 ) { /* negative means onto empty part of tray. if ( index < 0 ) { /* negative means onto empty part of
Force left. */ tray. Force left. */
index = model_getNumTilesInTray( board->model, index = model_getNumTilesInTray( board->model,
board->selPlayer ); board->selPlayer );
if ( OBJ_TRAY == ds->start.obj ) { if ( OBJ_TRAY == ds->start.obj ) {
@ -438,16 +435,28 @@ dragDropContinueImpl( BoardCtxt* board, XP_U16 xx, XP_U16 yy,
} }
if ( moving ) { 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 #ifdef XWFEATURE_SEARCHLIMIT
} else if ( ds->dtype == DT_HINTRGN ) { } else if ( ds->dtype == DT_HINTRGN ) {
invalHintRectDiffs( board, &ds->cur, &newInfo ); invalHintRectDiffs( board, &ds->cur, &newInfo );
if ( !ds->didMove ) { /* first time through */ if ( !ds->didMove ) { /* first time through */
invalCurHintRect( board, board->selPlayer ); invalCurHintRect( board, board->selPlayer );
} }
#endif #endif
} }
} while ( (newInfo.obj == OBJ_BOARD)
&& checkScrollCell( board, newInfo.u.board.col,
newInfo.u.board.row ) );
XP_MEMCPY( &ds->cur, &newInfo, sizeof(ds->cur) ); XP_MEMCPY( &ds->cur, &newInfo, sizeof(ds->cur) );
} }
} }