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;
} /* 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;

View file

@ -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,

View file

@ -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) );
}
}