From 195e980ef10d42d13bf8f4360d81eebda3b8417e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 5 Feb 2006 19:43:44 +0000 Subject: [PATCH] * Cursors are now reference counted, so it shouldn't be possible anymore to delete them accidently :) * You should no longer call HWInterface::SetCursor(), but the new Desktop::SetCursor() if you need to change the cursor. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16238 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/servers/app/ServerCursor.h | 7 ++++- src/servers/app/CursorManager.cpp | 30 +++++++++++--------- src/servers/app/CursorManager.h | 4 ++- src/servers/app/Desktop.cpp | 32 +++++++++++++++++++--- src/servers/app/Desktop.h | 5 +++- src/servers/app/ServerApp.cpp | 7 ++--- src/servers/app/ServerCursor.cpp | 16 +++++++---- src/servers/app/WindowLayer.cpp | 7 +---- 8 files changed, 72 insertions(+), 36 deletions(-) diff --git a/headers/private/servers/app/ServerCursor.h b/headers/private/servers/app/ServerCursor.h index bbd5b2fdf8..a775ed0e75 100644 --- a/headers/private/servers/app/ServerCursor.h +++ b/headers/private/servers/app/ServerCursor.h @@ -46,11 +46,16 @@ class ServerCursor : public ServerBitmap { int32 Token() const { return fToken; } + + void Acquire() { atomic_add(&fReferenceCount, 1); } + bool Release() { return atomic_add(&fReferenceCount, -1) == 1; } + private: friend class CursorManager; - + BPoint fHotSpot; team_id fOwningTeam; + int32 fReferenceCount; }; #endif // SERVER_CURSOR_H diff --git a/src/servers/app/CursorManager.cpp b/src/servers/app/CursorManager.cpp index 558887c16e..084648be30 100644 --- a/src/servers/app/CursorManager.cpp +++ b/src/servers/app/CursorManager.cpp @@ -98,6 +98,14 @@ CursorManager::AddCursor(ServerCursor* cursor, int32 token) } +void +CursorManager::_RemoveCursor(ServerCursor* cursor) +{ + fCursorList.RemoveItem(cursor); + fTokenSpace.RemoveToken(cursor->fToken); +} + + ServerCursor* CursorManager::_RemoveCursor(int32 index) { @@ -110,24 +118,20 @@ CursorManager::_RemoveCursor(int32 index) /*! - \brief Removes a cursor from the internal list and deletes it - \param token Token of the cursor to be deleted - - If the cursor is not found, this call does nothing + \brief Releases a reference to a cursor + + If this was the last reference to this cursor, it will be deleted. */ void -CursorManager::DeleteCursor(int32 token) +CursorManager::ReleaseCursor(ServerCursor* cursor) { Lock(); - for (int32 index = 0; index < fCursorList.CountItems(); index++) { - ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index); - - if (cursor && cursor->fToken == token) { - _RemoveCursor(index); - delete cursor; - break; - } + if (cursor->Release()) { + // this was the last reference, remove the cursor + + _RemoveCursor(cursor); + delete cursor; } Unlock(); diff --git a/src/servers/app/CursorManager.h b/src/servers/app/CursorManager.h index 1191bd1397..ce9411ace2 100644 --- a/src/servers/app/CursorManager.h +++ b/src/servers/app/CursorManager.h @@ -34,9 +34,10 @@ class CursorManager : public BLocker { virtual ~CursorManager(); int32 AddCursor(ServerCursor* cursor, int32 token = -1); - void DeleteCursor(int32 token); void DeleteCursors(team_id team); + void ReleaseCursor(ServerCursor* cursor); + void SetCursorSet(const char* path); ServerCursor* GetCursor(cursor_which which); cursor_which GetCursorWhich(); @@ -45,6 +46,7 @@ class CursorManager : public BLocker { ServerCursor* FindCursor(int32 token); private: + void _RemoveCursor(ServerCursor* cursor); ServerCursor* _RemoveCursor(int32 index); BList fCursorList; diff --git a/src/servers/app/Desktop.cpp b/src/servers/app/Desktop.cpp index e841e01522..35b9678a30 100644 --- a/src/servers/app/Desktop.cpp +++ b/src/servers/app/Desktop.cpp @@ -20,6 +20,7 @@ #include "InputManager.h" #include "ServerApp.h" #include "ServerConfig.h" +#include "ServerCursor.h" #include "ServerScreen.h" #include "ServerWindow.h" #include "WindowPrivate.h" @@ -316,10 +317,8 @@ Desktop::Init() fEventDispatcher.SetMouseFilter(new MouseFilter(this)); fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this)); - // take care of setting the default cursor - ServerCursor *cursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT); - if (cursor) - fVirtualScreen.HWInterface()->SetCursor(cursor); + SetCursor(NULL); + // this will set the default cursor fVirtualScreen.HWInterface()->MoveCursorTo(fVirtualScreen.Frame().Width() / 2, fVirtualScreen.Frame().Height() / 2); @@ -564,6 +563,31 @@ Desktop::BroadcastToAllApps(int32 code) } +ServerCursor* +Desktop::Cursor() const +{ + return HWInterface()->Cursor(); +} + + +void +Desktop::SetCursor(ServerCursor* newCursor) +{ + if (newCursor == NULL) + newCursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT); + + ServerCursor* oldCursor = Cursor(); + if (newCursor == oldCursor) + return; + + newCursor->Acquire(); + HWInterface()->SetCursor(newCursor); + + if (oldCursor != NULL) + fCursorManager.ReleaseCursor(oldCursor); +} + + void Desktop::UpdateWorkspaces() { diff --git a/src/servers/app/Desktop.h b/src/servers/app/Desktop.h index 96bea6b2ff..9689d2e2a0 100644 --- a/src/servers/app/Desktop.h +++ b/src/servers/app/Desktop.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005, Haiku. + * Copyright 2001-2006, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -73,6 +73,9 @@ class Desktop : public MessageLooper, public ScreenOwner { CursorManager& GetCursorManager() { return fCursorManager; } + void SetCursor(ServerCursor* cursor); + ServerCursor* Cursor() const; + void ScreenChanged(Screen* screen); void ScreenRemoved(Screen* screen) {} diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index fc051fcefb..593cd28724 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -290,9 +290,7 @@ ServerApp::Activate(bool value) void ServerApp::SetCursor() { - if (fAppCursor != NULL) - fDesktop->HWInterface()->SetCursor(fAppCursor); - + fDesktop->SetCursor(fAppCursor); fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); } @@ -946,7 +944,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) if (fAppCursor && fAppCursor->Token() == token) fAppCursor = NULL; - fDesktop->GetCursorManager().DeleteCursor(token); + if (ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token)) + fDesktop->GetCursorManager().ReleaseCursor(cursor); break; } diff --git a/src/servers/app/ServerCursor.cpp b/src/servers/app/ServerCursor.cpp index 61aa95f811..505afa8d9a 100644 --- a/src/servers/app/ServerCursor.cpp +++ b/src/servers/app/ServerCursor.cpp @@ -35,7 +35,8 @@ ServerCursor::ServerCursor(BRect r, color_space format, screen_id screen) : ServerBitmap(r, format, flags, bytesPerRow, screen), fHotSpot(hotspot), - fOwningTeam(-1) + fOwningTeam(-1), + fReferenceCount(1) { fHotSpot.ConstrainTo(Bounds()); _AllocateBuffer(); @@ -49,7 +50,8 @@ ServerCursor::ServerCursor(BRect r, color_space format, ServerCursor::ServerCursor(const int8* data) : ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0), fHotSpot(0, 0), - fOwningTeam(-1) + fOwningTeam(-1), + fReferenceCount(1) { // 68-byte array used in R5 for holding cursors. // This API has serious problems and should be deprecated(but supported) in R2 @@ -116,7 +118,8 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData, color_space format) : ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0), fHotSpot(0, 0), - fOwningTeam(-1) + fOwningTeam(-1), + fReferenceCount(1) { _AllocateBuffer(); if (Bits()) @@ -131,7 +134,8 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData, ServerCursor::ServerCursor(const ServerCursor* cursor) : ServerBitmap(cursor), fHotSpot(0, 0), - fOwningTeam(-1) + fOwningTeam(-1), + fReferenceCount(1) { // TODO: Hm. I don't move this into the if clause, // because it might break code elsewhere. @@ -158,9 +162,9 @@ ServerCursor::~ServerCursor() \param pt New location of hotspot, constrained to the cursor's boundaries. */ void -ServerCursor::SetHotSpot(BPoint pt) +ServerCursor::SetHotSpot(BPoint hotSpot) { - fHotSpot = pt; + fHotSpot = hotSpot; fHotSpot.ConstrainTo(Bounds()); } diff --git a/src/servers/app/WindowLayer.cpp b/src/servers/app/WindowLayer.cpp index 7a5b610591..dae8e3d479 100644 --- a/src/servers/app/WindowLayer.cpp +++ b/src/servers/app/WindowLayer.cpp @@ -986,17 +986,12 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken, if (IsFocus()) { // TODO: there is more for real cursor support, ie. if a window is closed, // new app cursor shouldn't override view cursor, ... - ServerCursor* currentCursor = fDesktop->HWInterface()->Cursor(); ServerCursor* cursor = ServerWindow()->App()->Cursor(); if (view != NULL && view->Cursor() != NULL) cursor = view->Cursor(); - if (cursor == NULL) - cursor = fDesktop->GetCursorManager().GetCursor(B_CURSOR_DEFAULT); - - if (cursor != currentCursor && cursor != NULL) - fDesktop->HWInterface()->SetCursor(cursor); + fDesktop->SetCursor(cursor); } }