* 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
This commit is contained in:
Axel Dörfler
2006-02-05 19:43:44 +00:00
parent aa1f543799
commit 195e980ef1
8 changed files with 72 additions and 36 deletions
@@ -46,11 +46,16 @@ class ServerCursor : public ServerBitmap {
int32 Token() const int32 Token() const
{ return fToken; } { return fToken; }
void Acquire() { atomic_add(&fReferenceCount, 1); }
bool Release() { return atomic_add(&fReferenceCount, -1) == 1; }
private: private:
friend class CursorManager; friend class CursorManager;
BPoint fHotSpot; BPoint fHotSpot;
team_id fOwningTeam; team_id fOwningTeam;
int32 fReferenceCount;
}; };
#endif // SERVER_CURSOR_H #endif // SERVER_CURSOR_H
+15 -11
View File
@@ -98,6 +98,14 @@ CursorManager::AddCursor(ServerCursor* cursor, int32 token)
} }
void
CursorManager::_RemoveCursor(ServerCursor* cursor)
{
fCursorList.RemoveItem(cursor);
fTokenSpace.RemoveToken(cursor->fToken);
}
ServerCursor* ServerCursor*
CursorManager::_RemoveCursor(int32 index) CursorManager::_RemoveCursor(int32 index)
{ {
@@ -110,24 +118,20 @@ CursorManager::_RemoveCursor(int32 index)
/*! /*!
\brief Removes a cursor from the internal list and deletes it \brief Releases a reference to a cursor
\param token Token of the cursor to be deleted
If the cursor is not found, this call does nothing If this was the last reference to this cursor, it will be deleted.
*/ */
void void
CursorManager::DeleteCursor(int32 token) CursorManager::ReleaseCursor(ServerCursor* cursor)
{ {
Lock(); Lock();
for (int32 index = 0; index < fCursorList.CountItems(); index++) { if (cursor->Release()) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index); // this was the last reference, remove the cursor
if (cursor && cursor->fToken == token) { _RemoveCursor(cursor);
_RemoveCursor(index); delete cursor;
delete cursor;
break;
}
} }
Unlock(); Unlock();
+3 -1
View File
@@ -34,9 +34,10 @@ class CursorManager : public BLocker {
virtual ~CursorManager(); virtual ~CursorManager();
int32 AddCursor(ServerCursor* cursor, int32 token = -1); int32 AddCursor(ServerCursor* cursor, int32 token = -1);
void DeleteCursor(int32 token);
void DeleteCursors(team_id team); void DeleteCursors(team_id team);
void ReleaseCursor(ServerCursor* cursor);
void SetCursorSet(const char* path); void SetCursorSet(const char* path);
ServerCursor* GetCursor(cursor_which which); ServerCursor* GetCursor(cursor_which which);
cursor_which GetCursorWhich(); cursor_which GetCursorWhich();
@@ -45,6 +46,7 @@ class CursorManager : public BLocker {
ServerCursor* FindCursor(int32 token); ServerCursor* FindCursor(int32 token);
private: private:
void _RemoveCursor(ServerCursor* cursor);
ServerCursor* _RemoveCursor(int32 index); ServerCursor* _RemoveCursor(int32 index);
BList fCursorList; BList fCursorList;
+28 -4
View File
@@ -20,6 +20,7 @@
#include "InputManager.h" #include "InputManager.h"
#include "ServerApp.h" #include "ServerApp.h"
#include "ServerConfig.h" #include "ServerConfig.h"
#include "ServerCursor.h"
#include "ServerScreen.h" #include "ServerScreen.h"
#include "ServerWindow.h" #include "ServerWindow.h"
#include "WindowPrivate.h" #include "WindowPrivate.h"
@@ -316,10 +317,8 @@ Desktop::Init()
fEventDispatcher.SetMouseFilter(new MouseFilter(this)); fEventDispatcher.SetMouseFilter(new MouseFilter(this));
fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this)); fEventDispatcher.SetKeyboardFilter(new KeyboardFilter(this));
// take care of setting the default cursor SetCursor(NULL);
ServerCursor *cursor = fCursorManager.GetCursor(B_CURSOR_DEFAULT); // this will set the default cursor
if (cursor)
fVirtualScreen.HWInterface()->SetCursor(cursor);
fVirtualScreen.HWInterface()->MoveCursorTo(fVirtualScreen.Frame().Width() / 2, fVirtualScreen.HWInterface()->MoveCursorTo(fVirtualScreen.Frame().Width() / 2,
fVirtualScreen.Frame().Height() / 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 void
Desktop::UpdateWorkspaces() Desktop::UpdateWorkspaces()
{ {
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2005, Haiku. * Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -73,6 +73,9 @@ class Desktop : public MessageLooper, public ScreenOwner {
CursorManager& GetCursorManager() { return fCursorManager; } CursorManager& GetCursorManager() { return fCursorManager; }
void SetCursor(ServerCursor* cursor);
ServerCursor* Cursor() const;
void ScreenChanged(Screen* screen); void ScreenChanged(Screen* screen);
void ScreenRemoved(Screen* screen) {} void ScreenRemoved(Screen* screen) {}
+3 -4
View File
@@ -290,9 +290,7 @@ ServerApp::Activate(bool value)
void void
ServerApp::SetCursor() ServerApp::SetCursor()
{ {
if (fAppCursor != NULL) fDesktop->SetCursor(fAppCursor);
fDesktop->HWInterface()->SetCursor(fAppCursor);
fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0); fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
} }
@@ -946,7 +944,8 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
if (fAppCursor && fAppCursor->Token() == token) if (fAppCursor && fAppCursor->Token() == token)
fAppCursor = NULL; fAppCursor = NULL;
fDesktop->GetCursorManager().DeleteCursor(token); if (ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token))
fDesktop->GetCursorManager().ReleaseCursor(cursor);
break; break;
} }
+10 -6
View File
@@ -35,7 +35,8 @@ ServerCursor::ServerCursor(BRect r, color_space format,
screen_id screen) screen_id screen)
: ServerBitmap(r, format, flags, bytesPerRow, screen), : ServerBitmap(r, format, flags, bytesPerRow, screen),
fHotSpot(hotspot), fHotSpot(hotspot),
fOwningTeam(-1) fOwningTeam(-1),
fReferenceCount(1)
{ {
fHotSpot.ConstrainTo(Bounds()); fHotSpot.ConstrainTo(Bounds());
_AllocateBuffer(); _AllocateBuffer();
@@ -49,7 +50,8 @@ ServerCursor::ServerCursor(BRect r, color_space format,
ServerCursor::ServerCursor(const int8* data) ServerCursor::ServerCursor(const int8* data)
: ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0), : ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
fHotSpot(0, 0), fHotSpot(0, 0),
fOwningTeam(-1) fOwningTeam(-1),
fReferenceCount(1)
{ {
// 68-byte array used in R5 for holding cursors. // 68-byte array used in R5 for holding cursors.
// This API has serious problems and should be deprecated(but supported) in R2 // 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) color_space format)
: ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0), : ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
fHotSpot(0, 0), fHotSpot(0, 0),
fOwningTeam(-1) fOwningTeam(-1),
fReferenceCount(1)
{ {
_AllocateBuffer(); _AllocateBuffer();
if (Bits()) if (Bits())
@@ -131,7 +134,8 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData,
ServerCursor::ServerCursor(const ServerCursor* cursor) ServerCursor::ServerCursor(const ServerCursor* cursor)
: ServerBitmap(cursor), : ServerBitmap(cursor),
fHotSpot(0, 0), fHotSpot(0, 0),
fOwningTeam(-1) fOwningTeam(-1),
fReferenceCount(1)
{ {
// TODO: Hm. I don't move this into the if clause, // TODO: Hm. I don't move this into the if clause,
// because it might break code elsewhere. // because it might break code elsewhere.
@@ -158,9 +162,9 @@ ServerCursor::~ServerCursor()
\param pt New location of hotspot, constrained to the cursor's boundaries. \param pt New location of hotspot, constrained to the cursor's boundaries.
*/ */
void void
ServerCursor::SetHotSpot(BPoint pt) ServerCursor::SetHotSpot(BPoint hotSpot)
{ {
fHotSpot = pt; fHotSpot = hotSpot;
fHotSpot.ConstrainTo(Bounds()); fHotSpot.ConstrainTo(Bounds());
} }
+1 -6
View File
@@ -986,17 +986,12 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken,
if (IsFocus()) { if (IsFocus()) {
// TODO: there is more for real cursor support, ie. if a window is closed, // TODO: there is more for real cursor support, ie. if a window is closed,
// new app cursor shouldn't override view cursor, ... // new app cursor shouldn't override view cursor, ...
ServerCursor* currentCursor = fDesktop->HWInterface()->Cursor();
ServerCursor* cursor = ServerWindow()->App()->Cursor(); ServerCursor* cursor = ServerWindow()->App()->Cursor();
if (view != NULL && view->Cursor() != NULL) if (view != NULL && view->Cursor() != NULL)
cursor = view->Cursor(); cursor = view->Cursor();
if (cursor == NULL) fDesktop->SetCursor(cursor);
cursor = fDesktop->GetCursorManager().GetCursor(B_CURSOR_DEFAULT);
if (cursor != currentCursor && cursor != NULL)
fDesktop->HWInterface()->SetCursor(cursor);
} }
} }