diff --git a/headers/os/app/Cursor.h b/headers/os/app/Cursor.h index 257cee3f41..e51ef49a26 100644 --- a/headers/os/app/Cursor.h +++ b/headers/os/app/Cursor.h @@ -41,8 +41,9 @@ private: int32 fServerToken; bool fNeedToFree; - mutable bool fPendingViewCursor; + bool _reservedWasPendingViewCursor; + // Probably bogus because of padding. uint32 _reserved[6]; }; diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index e6da9c1025..28edc04838 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -61,6 +61,7 @@ enum { // Cursor commands AS_SET_CURSOR, + AS_SET_VIEW_CURSOR, AS_SHOW_CURSOR, AS_HIDE_CURSOR, @@ -258,7 +259,6 @@ enum { AS_VIEW_SET_ORIGIN, AS_VIEW_GET_ORIGIN, AS_VIEW_RESIZE_MODE, - AS_VIEW_SET_CURSOR, AS_VIEW_BEGIN_RECT_TRACK, AS_VIEW_END_RECT_TRACK, AS_VIEW_DRAG_RECT, diff --git a/headers/private/app/ServerProtocolStructs.h b/headers/private/app/ServerProtocolStructs.h index 01e1a126e4..12f70a1b8a 100644 --- a/headers/private/app/ServerProtocolStructs.h +++ b/headers/private/app/ServerProtocolStructs.h @@ -55,6 +55,7 @@ struct ViewDragImageInfo { struct ViewSetViewCursorInfo { int32 cursorToken; + int32 viewToken; bool sync; }; diff --git a/src/kits/app/Cursor.cpp b/src/kits/app/Cursor.cpp index 90883d2dc2..b58d1e6111 100644 --- a/src/kits/app/Cursor.cpp +++ b/src/kits/app/Cursor.cpp @@ -30,8 +30,7 @@ const BCursor *B_CURSOR_I_BEAM; BCursor::BCursor(const void *cursorData) : fServerToken(-1), - fNeedToFree(false), - fPendingViewCursor(false) + fNeedToFree(false) { const uint8 *data = (const uint8 *)cursorData; @@ -66,8 +65,7 @@ BCursor::BCursor(const void *cursorData) BCursor::BCursor(const BCursor& other) : fServerToken(-1), - fNeedToFree(false), - fPendingViewCursor(false) + fNeedToFree(false) { *this = other; } @@ -78,7 +76,6 @@ BCursor::BCursor(BMessage *data) // undefined on BeOS fServerToken = -1; fNeedToFree = false; - fPendingViewCursor = false; } @@ -112,7 +109,6 @@ BCursor::operator=(const BCursor& other) fServerToken = other.fServerToken; fNeedToFree = other.fNeedToFree; - fPendingViewCursor = false; if (fNeedToFree) { // Tell app_server that there is another reference for this @@ -161,7 +157,6 @@ BCursor::_FreeCursorData() BPrivate::AppServerLink link; link.StartMessage(AS_DELETE_CURSOR); link.Attach(fServerToken); - link.Attach(fPendingViewCursor); link.Flush(); } } diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index df3d651da9..9e4b93f744 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -996,26 +996,21 @@ BView::SetViewCursor(const BCursor *cursor, bool sync) if (cursor == NULL || fOwner == NULL) return; - _CheckLockAndSwitchCurrent(); + _CheckLock(); - fOwner->fLink->StartMessage(AS_VIEW_SET_CURSOR); ViewSetViewCursorInfo info; info.cursorToken = cursor->fServerToken; + info.viewToken = _get_object_token_(this); // TODO: Use server_token! info.sync = sync; - fOwner->fLink->Attach(info); - if (!sync) { - cursor->fPendingViewCursor = true; - // this avoids a race condition in case the cursor is - // immediately deleted after this call, as the deletion - // is handled by the application, not the window - } else { - // make sure the server has processed the - // message and "acquired" the cursor in - // the window thread before returning from - // this function + BPrivate::AppServerLink link; + link.StartMessage(AS_SET_VIEW_CURSOR); + link.Attach(info); + + if (sync) { + // Make sure the server has processed the message. int32 code; - fOwner->fLink->FlushWithReply(code); + link.FlushWithReply(code); } } @@ -3911,6 +3906,7 @@ BView::_RemoveSelf() if (owner != NULL && !fTopLevelView) { // the top level view is deleted by the app_server automatically owner->fLink->StartMessage(AS_VIEW_DELETE); + // TODO: Use server_token owner->fLink->Attach(_get_object_token_(this)); } @@ -4250,7 +4246,7 @@ BView::MessageReceived(BMessage* msg) if (err == B_OK) { if (newHiddenState == true) Hide(); - else + else Show(); } } @@ -4906,6 +4902,7 @@ BView::_CreateSelf() else fOwner->fLink->StartMessage(AS_VIEW_CREATE); + // TODO: Use server_token fOwner->fLink->Attach(_get_object_token_(this)); fOwner->fLink->AttachString(Name()); fOwner->fLink->Attach(Frame()); @@ -4919,6 +4916,7 @@ BView::_CreateSelf() if (fTopLevelView) fOwner->fLink->Attach(B_NULL_TOKEN); else + // TODO: Use server_token fOwner->fLink->Attach(_get_object_token_(fParent)); fOwner->fLink->Flush(); @@ -5127,6 +5125,7 @@ BView::_Detach() if (fOwner->fLastMouseMovedView == this) fOwner->fLastMouseMovedView = NULL; + // TODO: Use server_token if (fOwner->fLastViewToken == _get_object_token_(this)) fOwner->fLastViewToken = B_NULL_TOKEN; @@ -5344,6 +5343,7 @@ BView::_CheckLock() const void BView::_SwitchServerCurrentView() const { + // TODO: Use server_token int32 serverToken = _get_object_token_(this); if (fOwner->fLastViewToken != serverToken) { diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 03feba160a..697a386eff 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -45,6 +45,7 @@ string_for_message_code(uint32 code, BString& string) // Cursor commands case AS_SET_CURSOR: string = "AS_SET_CURSOR"; break; + case AS_SET_VIEW_CURSOR: string = "AS_SET_VIEW_CURSOR"; break; case AS_SHOW_CURSOR: string = "AS_SHOW_CURSOR"; break; case AS_HIDE_CURSOR: string = "AS_HIDE_CURSOR"; break; @@ -52,6 +53,7 @@ string_for_message_code(uint32 code, BString& string) case AS_QUERY_CURSOR_HIDDEN: string = "AS_QUERY_CURSOR_HIDDEN"; break; case AS_CREATE_CURSOR: string = "AS_CREATE_CURSOR"; break; + case AS_REFERENCE_CURSOR: string = "AS_REFERENCE_CURSOR"; break; case AS_DELETE_CURSOR: string = "AS_DELETE_CURSOR"; break; case AS_BEGIN_RECT_TRACKING: string = "AS_BEGIN_RECT_TRACKING"; break; @@ -64,7 +66,7 @@ string_for_message_code(uint32 code, BString& string) case AS_QUIT_WINDOW: string = "AS_QUIT_WINDOW"; break; case AS_SEND_BEHIND: string = "AS_SEND_BEHIND"; break; case AS_SET_LOOK: string = "AS_SET_LOOK"; break; - case AS_SET_FEEL: string = "AS_SET_FEEL"; break; + case AS_SET_FEEL: string = "AS_SET_FEEL"; break; case AS_SET_FLAGS: string = "AS_SET_FLAGS"; break; case AS_DISABLE_UPDATES: string = "AS_DISABLE_UPDATES"; break; case AS_ENABLE_UPDATES: string = "AS_ENABLE_UPDATES"; break; @@ -140,7 +142,7 @@ string_for_message_code(uint32 code, BString& string) case AS_GET_ACCELERANT_INFO: string = "AS_GET_ACCELERANT_INFO"; break; case AS_GET_MONITOR_INFO: string = "AS_GET_MONITOR_INFO"; break; case AS_GET_FRAME_BUFFER_CONFIG: string = "AS_GET_FRAME_BUFFER_CONFIG"; break; - + case AS_SET_DPMS: string = "AS_SET_DPMS"; break; case AS_GET_DPMS_STATE: string = "AS_GET_DPMS_STATE"; break; case AS_GET_DPMS_CAPABILITIES: string = "AS_GET_DPMS_CAPABILITIES"; break; @@ -174,7 +176,7 @@ string_for_message_code(uint32 code, BString& string) case AS_GET_DECORATOR_SETTINGS: string = "AS_GET_DECORATOR_SETTINGS"; break; case AS_GET_SHOW_ALL_DRAGGERS: string = "AS_GET_SHOW_ALL_DRAGGERS"; break; case AS_SET_SHOW_ALL_DRAGGERS: string = "AS_SET_SHOW_ALL_DRAGGERS"; break; - + // Subpixel antialiasing & hinting case AS_SET_SUBPIXEL_ANTIALIASING: string = "AS_SET_SUBPIXEL_ANTIALIASING"; break; case AS_GET_SUBPIXEL_ANTIALIASING: string = "AS_GET_SUBPIXEL_ANTIALIASING"; break; @@ -240,7 +242,6 @@ string_for_message_code(uint32 code, BString& string) case AS_VIEW_SET_ORIGIN: string = "AS_VIEW_SET_ORIGIN"; break; case AS_VIEW_GET_ORIGIN: string = "AS_VIEW_GET_ORIGIN"; break; case AS_VIEW_RESIZE_MODE: string = "AS_VIEW_RESIZE_MODE"; break; - case AS_VIEW_SET_CURSOR: string = "AS_VIEW_SET_CURSOR"; break; case AS_VIEW_BEGIN_RECT_TRACK: string = "AS_VIEW_BEGIN_RECT_TRACK"; break; case AS_VIEW_END_RECT_TRACK: string = "AS_VIEW_END_RECT_TRACK"; break; case AS_VIEW_DRAG_RECT: string = "AS_VIEW_DRAG_RECT"; break; @@ -296,7 +297,7 @@ string_for_message_code(uint32 code, BString& string) // BDirectWindow codes case AS_DIRECT_WINDOW_GET_SYNC_DATA: string = "AS_DIRECT_WINDOW_GET_SYNC_DATA"; break; case AS_DIRECT_WINDOW_SET_FULLSCREEN: string = "AS_DIRECT_WINDOW_SET_FULLSCREEN"; break; - + default: string << "unkown code: " << code; break; diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 4d532ef107..96424923e6 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -300,7 +300,17 @@ ServerApp::Activate(bool value) void ServerApp::SetCurrentCursor(ServerCursor* cursor) { + if (fViewCursor == cursor) + return; + + if (fViewCursor) + fViewCursor->Release(); + fViewCursor = cursor; + + if (fViewCursor) + fViewCursor->Acquire(); + fDesktop->SetCursor(CurrentCursor()); } @@ -910,6 +920,63 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) } break; } + case AS_SET_VIEW_CURSOR: + { + STRACE(("ServerApp %s: AS_SET_VIEW_CURSOR:\n", Signature())); + + ViewSetViewCursorInfo info; + if (link.Read(&info) != B_OK) + break; + + if (fDesktop->GetCursorManager().Lock()) { + ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor( + info.cursorToken); + // If we found a cursor, make sure it doesn't go away. + if (cursor != NULL) + cursor->Acquire(); + + fDesktop->GetCursorManager().Unlock(); + + if (cursor != NULL) { + // We need to acquire the write lock here, since we cannot + // afford that the window thread to which the view belongs + // is running and messing with that same view. + fDesktop->LockAllWindows(); + + // Find the corresponding view by the given token. It's ok + // if this view does not exist anymore, since it may have + // already be deleted in the window thread before this + // message got here. + View* view; + if (fViewTokens.GetToken(info.viewToken, B_HANDLER_TOKEN, + (void**)&view) == B_OK) { + // Set the cursor on the view. + view->SetCursor(cursor); + + // The cursor might need to be updated now. + Window* window = view->Window(); + if (window != NULL && window->IsFocus()) { + if (fDesktop->ViewUnderMouse(window) + == view->Token()) { + SetCurrentCursor(cursor); + } + } + } + + fDesktop->UnlockAllWindows(); + + // Release the temporary reference. + cursor->Release(); + } + } + + if (info.sync) { + // sync the client (it can now delete the cursor) + fLink.StartMessage(B_OK); + fLink.Flush(); + } + break; + } case AS_CREATE_CURSOR: { STRACE(("ServerApp %s: Create Cursor\n", Signature())); @@ -981,9 +1048,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) // Attached data: // 1) int32 token ID of the cursor to delete int32 token; - bool pendingViewCursor; - link.Read(&token); - if (link.Read(&pendingViewCursor) != B_OK) + if (link.Read(&token) != B_OK) break; if (!fDesktop->GetCursorManager().Lock()) @@ -991,12 +1056,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token); - if (cursor != NULL) { - if (pendingViewCursor) - cursor->SetPendingViewCursor(true); - + if (cursor != NULL) cursor->Release(); - } + fDesktop->GetCursorManager().Unlock(); break; diff --git a/src/servers/app/ServerCursor.cpp b/src/servers/app/ServerCursor.cpp index c23a6e68ac..735db850bf 100644 --- a/src/servers/app/ServerCursor.cpp +++ b/src/servers/app/ServerCursor.cpp @@ -10,7 +10,7 @@ /*! Although descended from ServerBitmaps, ServerCursors are not handled by - the BitmapManager - they are allocated like any other object. Unlike BeOS + the BitmapManager - they are allocated like any other object. Unlike BeOS R5, cursors can be any size or color space, and this class accomodates and expands the R5 API. */ @@ -33,19 +33,17 @@ using std::nothrow; \param flags ServerBitmap flags. See Bitmap.h. \param hotspot Hotspot of the cursor \param bytesperline Bytes per row for the cursor. See ServerBitmap::ServerBitmap() - + */ -ServerCursor::ServerCursor(BRect r, color_space format, - int32 flags, BPoint hotspot, - int32 bytesPerRow, - screen_id screen) - : ServerBitmap(r, format, flags, bytesPerRow, screen), - fHotSpot(hotspot), - fOwningTeam(-1), - fReferenceCount(1), - fCursorData(NULL), - fManager(NULL), - fPendingViewCursor(0) +ServerCursor::ServerCursor(BRect r, color_space format, int32 flags, + BPoint hotspot, int32 bytesPerRow, screen_id screen) + : + ServerBitmap(r, format, flags, bytesPerRow, screen), + fHotSpot(hotspot), + fOwningTeam(-1), + fReferenceCount(1), + fCursorData(NULL), + fManager(NULL) { fHotSpot.ConstrainTo(Bounds()); _AllocateBuffer(); @@ -57,13 +55,13 @@ ServerCursor::ServerCursor(BRect r, color_space format, \param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details */ ServerCursor::ServerCursor(const uint8* data) - : ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0), - fHotSpot(0, 0), - fOwningTeam(-1), - fReferenceCount(1), - fCursorData(NULL), - fManager(NULL), - fPendingViewCursor(0) + : + ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0), + fHotSpot(0, 0), + fOwningTeam(-1), + fReferenceCount(1), + fCursorData(NULL), + fManager(NULL) { // 68-byte array used in R5 for holding cursors. // This API has serious problems and should be deprecated(but supported) in R2 @@ -72,7 +70,7 @@ ServerCursor::ServerCursor(const uint8* data) // to RGBA32 (little endian). Eventually, there will be support for 16 and // 8-bit depths // NOTE: review this once we have working PPC graphics cards (big endian). - if (data) { + if (data) { _AllocateBuffer(); uint8* buffer = Bits(); if (!buffer) @@ -123,17 +121,16 @@ ServerCursor::ServerCursor(const uint8* data) \param data Pointer to bitmap data in memory, the padding bytes should be contained when format less than 32 bpp. */ -ServerCursor::ServerCursor(const uint8* alreadyPaddedData, - uint32 width, uint32 height, - color_space format) - : ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0), - fHotSpot(0, 0), - fOwningTeam(-1), - fReferenceCount(1), - fCursorData(NULL), - fManager(NULL), - fPendingViewCursor(0) -{ +ServerCursor::ServerCursor(const uint8* alreadyPaddedData, uint32 width, + uint32 height, color_space format) + : + ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0), + fHotSpot(0, 0), + fOwningTeam(-1), + fReferenceCount(1), + fCursorData(NULL), + fManager(NULL) +{ _AllocateBuffer(); if (Bits()) memcpy(Bits(), alreadyPaddedData, BitsLength()); @@ -145,19 +142,19 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData, \param cursor cursor to copy */ ServerCursor::ServerCursor(const ServerCursor* cursor) - : ServerBitmap(cursor), - fHotSpot(0, 0), - fOwningTeam(-1), - fReferenceCount(1), - fCursorData(NULL), - fManager(NULL), - fPendingViewCursor(0) + : + ServerBitmap(cursor), + fHotSpot(0, 0), + fOwningTeam(-1), + fReferenceCount(1), + fCursorData(NULL), + fManager(NULL) { // TODO: Hm. I don't move this into the if clause, // because it might break code elsewhere. _AllocateBuffer(); - if (cursor) { + if (cursor) { if (Bits() && cursor->Bits()) memcpy(Bits(), cursor->Bits(), BitsLength()); fHotSpot = cursor->fHotSpot; @@ -193,11 +190,6 @@ bool ServerCursor::Release() { if (atomic_add(&fReferenceCount, -1) == 1) { - if (fPendingViewCursor > 0) { - // There is a SetViewCursor() waiting to be carried out - return false; - } - if (fManager && !fManager->RemoveCursor(this)) return false; @@ -208,13 +200,6 @@ ServerCursor::Release() } -void -ServerCursor::SetPendingViewCursor(bool pending) -{ - atomic_add(&fPendingViewCursor, pending ? 1 : -1); -} - - void ServerCursor::AttachedToManager(CursorManager* manager) { diff --git a/src/servers/app/ServerCursor.h b/src/servers/app/ServerCursor.h index 4014d5fa90..40ac712205 100644 --- a/src/servers/app/ServerCursor.h +++ b/src/servers/app/ServerCursor.h @@ -52,8 +52,6 @@ class ServerCursor : public ServerBitmap { bool Release(); int32 ReferenceCount() { return fReferenceCount; } - void SetPendingViewCursor(bool pending); - void AttachedToManager(CursorManager* manager); const uint8* CursorData() const @@ -67,7 +65,6 @@ class ServerCursor : public ServerBitmap { vint32 fReferenceCount; uint8* fCursorData; CursorManager* fManager; - vint32 fPendingViewCursor; }; diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index de28b5b3e5..84aa5639e2 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -1539,37 +1539,6 @@ fDesktop->LockSingleWindow(); fCurrentView->SetResizeMode(resizeMode); break; } - case AS_VIEW_SET_CURSOR: - { - DTRACE(("ServerWindow %s: Message AS_VIEW_CURSOR: View: %s\n", - Title(), fCurrentView->Name())); - - ViewSetViewCursorInfo info; - if (link.Read(&info) != B_OK) - break; - - if (!fDesktop->GetCursorManager().Lock()) - break; - - ServerCursor* cursor - = fDesktop->GetCursorManager().FindCursor(info.cursorToken); - fCurrentView->SetCursor(cursor); - - fDesktop->GetCursorManager().Unlock(); - - if (fWindow->IsFocus()) { - // The cursor might need to be updated now - if (fDesktop->ViewUnderMouse(fWindow) == fCurrentView->Token()) - fServerApp->SetCurrentCursor(cursor); - } - if (info.sync) { - // sync the client (it can now delete the cursor) - fLink.StartMessage(B_OK); - fLink.Flush(); - } - - break; - } case AS_VIEW_SET_FLAGS: { uint32 flags; diff --git a/src/servers/app/View.cpp b/src/servers/app/View.cpp index 6fdcb3fa45..503d433723 100644 --- a/src/servers/app/View.cpp +++ b/src/servers/app/View.cpp @@ -1291,10 +1291,8 @@ View::SetCursor(ServerCursor *cursor) fCursor = cursor; - if (fCursor) { + if (fCursor) fCursor->Acquire(); - fCursor->SetPendingViewCursor(false); - } }