From 2a2d0f1d10ac5233bd429637c3867ade4381be4f Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Fri, 14 Aug 2009 20:38:35 +0000 Subject: [PATCH] After a B_DIRECT_STOP notification, the app_server could trigger a B_DIRECT_MODIFY with, for example, B_CLIPPING_MODIFIED. This was ignored, though. Now we combine this notification with the next ones, so that on B_DIRECT_START, the client is informed of all the things which have changed. Chart was relying on receiving the B_CLIPPING_MODIFIED notification to exclude some stars from being erased, in case the window went offscreen. Anyway, the net result is that Chart doesn't crash now, and we follow more closely the original BDirectWindow protocol. Fixed ticket #1939. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32392 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/ServerWindow.cpp | 49 +++++++++++++++++++++++++------- src/servers/app/ServerWindow.h | 2 +- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 29d94ea383..d9d75b9776 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -120,6 +120,24 @@ static profile sRedrawProcessingTime; #endif +// TODO: Move to another file +struct BufferState { + BufferState(const direct_buffer_state &state) + : fState(state) + { + } + direct_buffer_state Action() const + { + return (direct_buffer_state)(fState & B_DIRECT_MODE_MASK); + } + direct_buffer_state Reason() const + { + return (direct_buffer_state)(fState & ~B_DIRECT_MODE_MASK); + } + direct_buffer_state fState; +}; + + class DirectWindowData { public: DirectWindowData(); @@ -131,8 +149,8 @@ public: status_t SyncronizeWithClient(); bool SetState(const direct_buffer_state &bufferState, - const direct_driver_state &driverState); - + const direct_driver_state &driverState); + BRect old_window_frame; direct_buffer_info *buffer_info; @@ -140,6 +158,7 @@ private: sem_id fSem; sem_id fAcknowledgeSem; area_id fBufferArea; + direct_buffer_state fPreviousState; }; @@ -148,7 +167,8 @@ DirectWindowData::DirectWindowData() buffer_info(NULL), fSem(-1), fAcknowledgeSem(-1), - fBufferArea(-1) + fBufferArea(-1), + fPreviousState(B_DIRECT_STOP) { fBufferArea = create_area("direct area", (void **)&buffer_info, B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_WRITE); @@ -219,22 +239,31 @@ bool DirectWindowData::SetState(const direct_buffer_state &bufferState, const direct_driver_state &driverState) { + BufferState inputState(bufferState); + BufferState currentState(buffer_info->buffer_state); // Don't issue a DirectConnected() notification // if the connection is stopped, and we are called - // with bufferState == B_DIRECT_MODIFY. - if ((buffer_info->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP - && (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START) + // with bufferState == B_DIRECT_MODIFY, but save the reason + // and combine it for next time we are called with B_DIRECT_START + if (currentState.Action() == B_DIRECT_STOP + && inputState.Action() != B_DIRECT_START) { + fPreviousState = (direct_buffer_state)(fPreviousState + | inputState.Reason()); return false; - - if (bufferState != -1) - buffer_info->buffer_state = bufferState; + } + + buffer_info->buffer_state = (direct_buffer_state)(bufferState + | BufferState(fPreviousState).Reason()); + + fPreviousState = B_DIRECT_STOP; + if (driverState != -1) buffer_info->driver_state = driverState; return true; } - + // #pragma mark - diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index 0d48f65d15..50a16993e3 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -90,7 +90,7 @@ public: // related thread/team_id(s). inline team_id ClientTeam() const { return fClientTeam; } - void HandleDirectConnection(int32 bufferState = -1, + void HandleDirectConnection(int32 bufferState, int32 driverState = -1); inline int32 ClientToken() const { return fClientToken; }