* 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
+6 -1
View File
@@ -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
+17 -13
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*
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();
+3 -1
View File
@@ -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;
+28 -4
View File
@@ -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()
{
+4 -1
View File
@@ -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) {}
+3 -4
View File
@@ -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;
}
+10 -6
View File
@@ -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());
}
+1 -6
View File
@@ -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);
}
}