diff --git a/headers/os/app/Cursor.h b/headers/os/app/Cursor.h index c392305d2a..257cee3f41 100644 --- a/headers/os/app/Cursor.h +++ b/headers/os/app/Cursor.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _CURSOR_H @@ -11,31 +11,39 @@ class BCursor : BArchivable { - public: - BCursor(const void* cursorData); - BCursor(BMessage* data); - virtual ~BCursor(); +public: + BCursor(const void* cursorData); + BCursor(const BCursor& other); + BCursor(BMessage* data); + virtual ~BCursor(); - virtual status_t Archive(BMessage* archive, bool deep = true) const; - static BArchivable* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, + bool deep = true) const; + static BArchivable* Instantiate(BMessage* archive); - private: - virtual status_t Perform(perform_code d, void* arg); + BCursor& operator=(const BCursor& other); + bool operator==(const BCursor& other) const; + bool operator!=(const BCursor& other) const; - virtual void _ReservedCursor1(); - virtual void _ReservedCursor2(); - virtual void _ReservedCursor3(); - virtual void _ReservedCursor4(); +private: + virtual status_t Perform(perform_code d, void* arg); - private: - friend class BApplication; - friend class BView; + virtual void _ReservedCursor1(); + virtual void _ReservedCursor2(); + virtual void _ReservedCursor3(); + virtual void _ReservedCursor4(); - int32 fServerToken; - bool fNeedToFree; - mutable bool fPendingViewCursor; + void _FreeCursorData(); - uint32 _reserved[6]; +private: + friend class BApplication; + friend class BView; + + int32 fServerToken; + bool fNeedToFree; + mutable bool fPendingViewCursor; + + uint32 _reserved[6]; }; #endif // _CURSOR_H diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 89ea027788..e6da9c1025 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -68,6 +68,7 @@ enum { AS_QUERY_CURSOR_HIDDEN, AS_CREATE_CURSOR, + AS_REFERENCE_CURSOR, AS_DELETE_CURSOR, AS_BEGIN_RECT_TRACKING, diff --git a/src/kits/app/Cursor.cpp b/src/kits/app/Cursor.cpp index 320664ed1c..90883d2dc2 100644 --- a/src/kits/app/Cursor.cpp +++ b/src/kits/app/Cursor.cpp @@ -63,6 +63,16 @@ BCursor::BCursor(const void *cursorData) } +BCursor::BCursor(const BCursor& other) + : + fServerToken(-1), + fNeedToFree(false), + fPendingViewCursor(false) +{ + *this = other; +} + + BCursor::BCursor(BMessage *data) { // undefined on BeOS @@ -74,14 +84,7 @@ BCursor::BCursor(BMessage *data) BCursor::~BCursor() { - // Notify server to deallocate server-side objects for this cursor - if (fNeedToFree) { - BPrivate::AppServerLink link; - link.StartMessage(AS_DELETE_CURSOR); - link.Attach(fServerToken); - link.Attach(fPendingViewCursor); - link.Flush(); - } + _FreeCursorData(); } @@ -101,6 +104,42 @@ BCursor::Instantiate(BMessage *data) } +BCursor& +BCursor::operator=(const BCursor& other) +{ + if (&other != this && other != *this) { + _FreeCursorData(); + + fServerToken = other.fServerToken; + fNeedToFree = other.fNeedToFree; + fPendingViewCursor = false; + + if (fNeedToFree) { + // Tell app_server that there is another reference for this + // cursor data! + BPrivate::AppServerLink link; + link.StartMessage(AS_REFERENCE_CURSOR); + link.Attach(fServerToken); + } + } + return *this; +} + + +bool +BCursor::operator==(const BCursor& other) const +{ + return fServerToken == other.fServerToken; +} + + +bool +BCursor::operator!=(const BCursor& other) const +{ + return fServerToken != other.fServerToken; +} + + status_t BCursor::Perform(perform_code d, void *arg) { @@ -112,3 +151,18 @@ void BCursor::_ReservedCursor1() {} void BCursor::_ReservedCursor2() {} void BCursor::_ReservedCursor3() {} void BCursor::_ReservedCursor4() {} + + +void +BCursor::_FreeCursorData() +{ + // Notify server to deallocate server-side objects for this cursor + if (fNeedToFree) { + BPrivate::AppServerLink link; + link.StartMessage(AS_DELETE_CURSOR); + link.Attach(fServerToken); + link.Attach(fPendingViewCursor); + link.Flush(); + } +} + diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 70cea18574..4d532ef107 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -939,7 +939,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) { cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam, - cursorData); + cursorData); if (cursor == NULL) status = B_NO_MEMORY; } @@ -954,6 +954,27 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) fLink.Flush(); break; } + case AS_REFERENCE_CURSOR: + { + STRACE(("ServerApp %s: Reference BCursor\n", Signature())); + // Attached data: + // 1) int32 token ID of the cursor to reference + int32 token; + if (link.Read(&token) != B_OK) + break; + + if (!fDesktop->GetCursorManager().Lock()) + break; + + ServerCursor* cursor + = fDesktop->GetCursorManager().FindCursor(token); + if (cursor != NULL) + cursor->Acquire(); + + fDesktop->GetCursorManager().Unlock(); + + break; + } case AS_DELETE_CURSOR: { STRACE(("ServerApp %s: Delete BCursor\n", Signature())); @@ -968,8 +989,9 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) if (!fDesktop->GetCursorManager().Lock()) break; - ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token); - if (cursor) { + ServerCursor* cursor + = fDesktop->GetCursorManager().FindCursor(token); + if (cursor != NULL) { if (pendingViewCursor) cursor->SetPendingViewCursor(true);