various changes to handling custom cursors:

* all cursors owned by a team are visually different,
  or (iaw) an already existing cursor is reused when
  it is set by the client again
* changed various occurances of cursor data from "int8*"
  to "uint8*"
* ServerCursors also remember the R5 data from which
  they were created
* the reference counting and destruction of
  ServerCursors changed: The cursor knows it is attached
  to a CursorManager and one can simply use
  ServerCursor::Acquire() and Release() and the reference
  counting and everything is being taken care of
* destroying a ViewLayer will now correctly release a set
  ServerCursor
* fixed a race condition when setting a cursor through
  BView::SetViewCursor(): If the client code looks like this:

  BCursor cursor(cursorData);
  someView->SetViewCursor(&cursor, false);

  there is a relatively high chance the BCursor destructor
  told the ServerApp thread to destroy the cursor before
  the ServerWindow thread got to "acquire" the cursor for
  use by the view layer. The very same problem is likely the
  reason that SetViewCursor works to unreliably on R5, even
  when the "sync" flag is set to "true" (although it should
  theoretically work in that case).

all these fixes make WonderBrush work fine again with the
new support of custom cursors.... coded by axeld and myself
(the joys of pair programming :-)



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16521 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2006-02-26 18:15:31 +00:00
parent 2d8561e4c6
commit 588259b66d
15 changed files with 289 additions and 122 deletions
+1
View File
@@ -33,6 +33,7 @@ class BCursor : BArchivable {
int32 fServerToken;
bool fNeedToFree;
mutable bool fPendingViewCursor;
uint32 _reserved[6];
};
+2 -2
View File
@@ -42,7 +42,7 @@ class CursorSet : public BMessage {
status_t Save(const char *path,int32 saveflags=0);
status_t Load(const char *path);
status_t AddCursor(cursor_which which,const BBitmap *cursor, const BPoint &hotspot);
status_t AddCursor(cursor_which which, int8 *data);
status_t AddCursor(cursor_which which, uint8 *data);
void RemoveCursor(cursor_which which);
status_t FindCursor(cursor_which which, BBitmap **cursor, BPoint *hotspot);
status_t FindCursor(cursor_which which, ServerCursor **cursor);
@@ -51,7 +51,7 @@ class CursorSet : public BMessage {
private:
const char *_CursorWhichToString(cursor_which which);
BBitmap *_CursorDataToBitmap(int8 *data);
BBitmap *_CursorDataToBitmap(uint8 *data);
};
#endif // CURSOR_SET_H
+14 -3
View File
@@ -26,7 +26,7 @@ class ServerCursor : public ServerBitmap {
int32 flags, BPoint hotspot,
int32 bytesperrow = -1,
screen_id screen = B_MAIN_SCREEN_ID);
ServerCursor(const int8* cursorDataFromR5);
ServerCursor(const uint8* cursorDataFromR5);
ServerCursor(const uint8* alreadyPaddedData,
uint32 width, uint32 height,
color_space format);
@@ -47,8 +47,16 @@ class ServerCursor : public ServerBitmap {
int32 Token() const
{ return fToken; }
void Acquire() { atomic_add(&fReferenceCount, 1); }
bool Release() { return atomic_add(&fReferenceCount, -1) == 1; }
void Acquire()
{ atomic_add(&fReferenceCount, 1); }
bool Release();
void SetPendingViewCursor(bool pending);
void AttachedToManager(CursorManager* manager);
const uint8* CursorData() const
{ return fCursorData; }
private:
friend class CursorManager;
@@ -56,6 +64,9 @@ class ServerCursor : public ServerBitmap {
BPoint fHotSpot;
team_id fOwningTeam;
int32 fReferenceCount;
uint8* fCursorData;
CursorManager* fManager;
vint32 fPendingViewCursor;
};
#endif // SERVER_CURSOR_H
+4 -1
View File
@@ -31,7 +31,8 @@ const BCursor *B_CURSOR_I_BEAM;
BCursor::BCursor(const void *cursorData)
:
fServerToken(-1),
fNeedToFree(false)
fNeedToFree(false),
fPendingViewCursor(false)
{
const uint8 *data = (const uint8 *)cursorData;
@@ -68,6 +69,7 @@ BCursor::BCursor(BMessage *data)
// undefined on BeOS
fServerToken = -1;
fNeedToFree = false;
fPendingViewCursor = false;
}
@@ -78,6 +80,7 @@ BCursor::~BCursor()
BPrivate::AppServerLink link;
link.StartMessage(AS_DELETE_CURSOR);
link.Attach<int32>(fServerToken);
link.Attach<bool>(fPendingViewCursor);
link.Flush();
}
}
+7 -5
View File
@@ -980,18 +980,20 @@ BView::ResizingMode() const
void
BView::SetViewCursor(const BCursor *cursor, bool sync)
{
if (!cursor)
if (cursor == NULL || fOwner == NULL)
return;
if (!fOwner)
debugger("View method requires owner and doesn't have one");
check_lock();
fOwner->fLink->StartMessage(AS_LAYER_SET_CURSOR);
fOwner->fLink->Attach<int32>(cursor->fServerToken);
if (sync)
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
fOwner->fLink->Flush();
}
+10 -10
View File
@@ -51,7 +51,7 @@ transparent. Transparency only applies to white pixels—black pixels are always
// Impressive ASCII art, eh?
int8 default_cursor_data[] = {
uint8 default_cursor_data[] = {
16,1,0,0,
255,224, // ***********-----
128,16, // *----------*----
@@ -91,56 +91,56 @@ int8 default_cursor_data[] = {
0,0
};
int8 default_text_data[] = {
uint8 default_text_data[] = {
0x10, 0x01, 0x07, 0x07, 0x00, 0x00, 0x06, 0xC0, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x06, 0xC0, 0x00, 0x00, 0x06, 0xC0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80,
0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0,
0x06, 0xC0
};
int8 default_move_data[] = {
uint8 default_move_data[] = {
0x10, 0x01, 0x07, 0x07, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x00, 0x00, 0x10, 0x10, 0x30, 0x18, 0x71, 0x1C, 0x30, 0x18,
0x10, 0x10, 0x00, 0x00, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x07, 0xC0, 0x0F, 0xE0,
0x1F, 0xF0, 0x38, 0x38, 0x7B, 0xBC, 0xFB, 0xBE, 0x7B, 0xBC, 0x38, 0x38, 0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x01, 0x00,
0x00, 0x00
};
int8 default_drag_data[] = {
uint8 default_drag_data[] = {
0x10, 0x01, 0x00, 0x00, 0xFF, 0x00, 0x81, 0x00, 0x82, 0x00, 0x82, 0x00, 0x81, 0xFF, 0x80, 0x81, 0xB0, 0x41, 0xC8, 0x41, 0x04, 0x81,
0x03, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x03, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF,
0x03, 0xFF
};
int8 default_resize_data[] = {
uint8 default_resize_data[] = {
0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x3E, 0x78, 0x1E, 0x70, 0x0E, 0x68, 0x16, 0x44, 0x22, 0x02, 0x40, 0x01, 0x80, 0x01, 0x80,
0x02, 0x40, 0x44, 0x22, 0x68, 0x16, 0x70, 0x0E, 0x78, 0x1E, 0x7C, 0x3E, 0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F,
0xFC, 0x3F, 0xEE, 0x77, 0xC7, 0xE3, 0x03, 0xC0, 0x03, 0xC0, 0xC7, 0xE3, 0xEE, 0x77, 0xFC, 0x3F, 0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F,
0xFE, 0x7F
};
int8 default_resize_ew_data[] = {
uint8 default_resize_ew_data[] = {
0x10, 0x01, 0x07, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x10, 0x31, 0x18, 0x71, 0x1C, 0x71, 0x1C,
0x31, 0x18, 0x11, 0x10, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x80, 0x03, 0x80, 0x0B, 0xA0,
0x1B, 0xB0, 0x3B, 0xB8, 0x7B, 0xBC, 0xFB, 0xBE, 0xFB, 0xBE, 0x7B, 0xBC, 0x3B, 0xB8, 0x1B, 0xB0, 0x0B, 0xA0, 0x03, 0x80, 0x03, 0x80,
0x01, 0x00
};
int8 default_resize_ns_data[] = {
uint8 default_resize_ns_data[] = {
0x10, 0x01, 0x07, 0x07, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x0F, 0xF0,
0x1F, 0xF8, 0x00, 0x00, 0x7F, 0xFE, 0xFF, 0xFF, 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xF8, 0x0F, 0xF0, 0x07, 0xE0, 0x03, 0xC0, 0x01, 0x80,
0x00, 0x00
};
int8 default_resize_nwse_data[] = {
uint8 default_resize_nwse_data[] = {
0x10, 0x01, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x08, 0x1E, 0x10, 0x1C, 0x20, 0x18, 0x40, 0x10, 0x80, 0x01, 0x08,
0x02, 0x18, 0x04, 0x38, 0x08, 0x78, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xCC, 0x3F, 0x9C,
0x3F, 0x38, 0x3E, 0x70, 0x3C, 0xE4, 0x39, 0xCC, 0x33, 0x9C, 0x27, 0x3C, 0x0E, 0x7C, 0x1C, 0xFC, 0x39, 0xFC, 0x33, 0xFC, 0x00, 0x00,
0x00, 0x00
};
int8 default_resize_nesw_data[] = {
uint8 default_resize_nesw_data[] = {
0x10, 0x01, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xF8, 0x08, 0x78, 0x04, 0x38, 0x02, 0x18, 0x01, 0x08, 0x10, 0x80,
0x18, 0x40, 0x1C, 0x20, 0x1E, 0x10, 0x1F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xFC, 0x39, 0xFC,
0x1C, 0xFC, 0x0E, 0x7C, 0x27, 0x3C, 0x33, 0x9C, 0x39, 0xCC, 0x3C, 0xE4, 0x3E, 0x70, 0x3F, 0x38, 0x3F, 0x9C, 0x3F, 0xCC, 0x00, 0x00,
@@ -149,7 +149,7 @@ int8 default_resize_nesw_data[] = {
// known good cursor data for testing rest of system
int8 cross_cursor[] = {16,1,5,5,
uint8 cross_cursor[] = {16,1,5,5,
14,0,4,0,4,0,4,0,128,32,241,224,128,32,4,0,
4,0,4,0,14,0,0,0,0,0,0,0,0,0,0,0,
14,0,4,0,4,0,4,0,128,32,245,224,128,32,4,0,
+9 -9
View File
@@ -3,14 +3,14 @@
#include <SupportDefs.h>
extern int8 default_cursor_data[];
extern int8 default_text_data[];
extern int8 default_move_data[];
extern int8 default_drag_data[];
extern int8 default_resize_data[];
extern int8 default_resize_ew_data[];
extern int8 default_resize_ns_data[];
extern int8 default_resize_nwse_data[];
extern int8 default_resize_nesw_data[];
extern uint8 default_cursor_data[];
extern uint8 default_text_data[];
extern uint8 default_move_data[];
extern uint8 default_drag_data[];
extern uint8 default_resize_data[];
extern uint8 default_resize_ew_data[];
extern uint8 default_resize_ns_data[];
extern uint8 default_resize_nwse_data[];
extern uint8 default_resize_nesw_data[];
#endif
+108 -63
View File
@@ -8,9 +8,11 @@
/** Handles the system's cursor infrastructure */
#include "CursorManager.h"
#include <stdio.h>
#include "CursorData.h"
#include "CursorManager.h"
#include "HaikuSystemCursor.h"
#include "ServerCursor.h"
#include "ServerConfig.h"
@@ -67,72 +69,80 @@ CursorManager::CursorManager()
CursorManager::~CursorManager()
{
for (int32 i = 0; i < fCursorList.CountItems(); i++) {
delete (ServerCursor *)fCursorList.ItemAt(i);
delete (ServerCursor*)fCursorList.ItemAtFast(i);
}
}
ServerCursor*
CursorManager::CreateCursor(team_id clientTeam, const uint8* cursorData)
{
if (!Lock())
return NULL;
ServerCursor* cursor = _FindCursor(clientTeam, cursorData);
if (!cursor) {
cursor = new (nothrow) ServerCursor(cursorData);
if (cursor) {
cursor->SetOwningTeam(clientTeam);
if (AddCursor(cursor) < B_OK) {
delete cursor;
cursor = NULL;
}
}
} else {
cursor->Acquire();
}
Unlock();
return cursor;
}
/*!
\brief Registers a cursor with the manager.
\param sc ServerCursor object to register
\return The token assigned to the cursor or B_ERROR if sc is NULL
\param cursor ServerCursor object to register
\return The token assigned to the cursor or B_ERROR if cursor is NULL
*/
int32
CursorManager::AddCursor(ServerCursor* cursor, int32 token)
{
if (!cursor)
if (!cursor || !Lock())
return B_ERROR;
Lock();
fCursorList.AddItem(cursor);
if (token == -1)
cursor->fToken = fTokenSpace.NewToken(kCursorToken, cursor);
else {
fTokenSpace.SetToken(token, kCursorToken, cursor);
cursor->fToken = token;
if (!fCursorList.AddItem(cursor)) {
Unlock();
return B_ERROR;
}
if (token == -1) {
token = fTokenSpace.NewToken(kCursorToken, cursor);
} else {
fTokenSpace.SetToken(token, kCursorToken, cursor);
}
cursor->fToken = token;
cursor->AttachedToManager(this);
Unlock();
return token;
}
void
CursorManager::_RemoveCursor(ServerCursor* cursor)
{
fCursorList.RemoveItem(cursor);
fTokenSpace.RemoveToken(cursor->fToken);
}
ServerCursor*
CursorManager::_RemoveCursor(int32 index)
{
ServerCursor* cursor = (ServerCursor *)fCursorList.RemoveItem(index);
if (cursor != NULL)
fTokenSpace.RemoveToken(cursor->fToken);
return cursor;
}
/*!
\brief Releases a reference to a cursor
If this was the last reference to this cursor, it will be deleted.
*/
void
CursorManager::ReleaseCursor(ServerCursor* cursor)
CursorManager::RemoveCursor(ServerCursor* cursor)
{
Lock();
if (!Lock())
return;
if (cursor->Release()) {
// this was the last reference, remove the cursor
_RemoveCursor(cursor);
delete cursor;
}
_RemoveCursor(cursor);
Unlock();
}
@@ -145,15 +155,13 @@ CursorManager::ReleaseCursor(ServerCursor* cursor)
void
CursorManager::DeleteCursors(team_id team)
{
Lock();
if (!Lock())
return;
for (int32 index = fCursorList.CountItems(); index-- > 0;) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index);
if (cursor->OwningTeam() != team)
continue;
_RemoveCursor(index);
delete cursor;
ServerCursor *cursor = (ServerCursor*)fCursorList.ItemAtFast(index);
if (cursor->OwningTeam() == team)
cursor->Release();
}
Unlock();
@@ -372,22 +380,6 @@ CursorManager::ChangeCursor(cursor_which which, int32 token)
}
/*!
\brief Internal function which finds the cursor with a particular ID
\param token ID of the cursor to find
\return The cursor or NULL if not found
*/
ServerCursor *
CursorManager::FindCursor(int32 token)
{
ServerCursor* cursor;
if (fTokenSpace.GetToken(token, kCursorToken, (void**)&cursor) == B_OK)
return cursor;
return NULL;
}
//! Sets the cursors to the defaults and saves them to CURSOR_SETTINGS_DIR/"d
void
CursorManager::SetDefaults()
@@ -415,3 +407,56 @@ CursorManager::SetDefaults()
SetCursorSet(string.String());
Unlock();
}
/*!
\brief Internal function which finds the cursor with a particular ID
\param token ID of the cursor to find
\return The cursor or NULL if not found
*/
ServerCursor *
CursorManager::FindCursor(int32 token)
{
ServerCursor* cursor;
if (fTokenSpace.GetToken(token, kCursorToken, (void**)&cursor) == B_OK)
return cursor;
return NULL;
}
ServerCursor *
CursorManager::_FindCursor(team_id clientTeam, const uint8* cursorData)
{
int32 count = fCursorList.CountItems();
for (int32 i = 0; i < count; i++) {
ServerCursor* cursor = (ServerCursor*)fCursorList.ItemAtFast(i);
if (cursor->OwningTeam() == clientTeam
&& cursor->CursorData()
&& memcmp(cursor->CursorData(), cursorData, 68) == 0) {
return cursor;
}
}
return NULL;
}
void
CursorManager::_RemoveCursor(ServerCursor* cursor)
{
fCursorList.RemoveItem(cursor);
fTokenSpace.RemoveToken(cursor->fToken);
}
//ServerCursor*
//CursorManager::_RemoveCursor(int32 index)
//{
// ServerCursor* cursor = (ServerCursor*)fCursorList.RemoveItem(index);
// if (cursor != NULL)
// fTokenSpace.RemoveToken(cursor->fToken);
//
// return cursor;
//}
+8 -2
View File
@@ -33,21 +33,27 @@ class CursorManager : public BLocker {
CursorManager();
virtual ~CursorManager();
ServerCursor* CreateCursor(team_id clientTeam,
const uint8* cursorData);
int32 AddCursor(ServerCursor* cursor, int32 token = -1);
void DeleteCursors(team_id team);
void ReleaseCursor(ServerCursor* cursor);
void RemoveCursor(ServerCursor* cursor);
void SetCursorSet(const char* path);
ServerCursor* GetCursor(cursor_which which);
cursor_which GetCursorWhich();
void ChangeCursor(cursor_which which, int32 token);
void SetDefaults();
ServerCursor* FindCursor(int32 token);
private:
ServerCursor* _FindCursor(team_id cientTeam,
const uint8* cursorData);
void _RemoveCursor(ServerCursor* cursor);
ServerCursor* _RemoveCursor(int32 index);
// ServerCursor* _RemoveCursor(int32 index);
BList fCursorList;
BTokenSpace fTokenSpace;
+2 -2
View File
@@ -119,7 +119,7 @@ CursorSet::AddCursor(cursor_which which, const BBitmap *cursor, const BPoint &ho
function must convert the R5 cursor data into a BBitmap
*/
status_t
CursorSet::AddCursor(cursor_which which, int8 *data)
CursorSet::AddCursor(cursor_which which, uint8 *data)
{
// Convert cursor data to a bitmap because all cursors are internally stored
// as bitmaps
@@ -316,7 +316,7 @@ CursorSet::_CursorWhichToString(cursor_which which)
BBitmaps returned by this function are always in the RGBA32 color space
*/
BBitmap *
CursorSet::_CursorDataToBitmap(int8 *data)
CursorSet::_CursorDataToBitmap(uint8 *data)
{
// 68-byte array used in R5 for holding cursors.
// This API has serious problems and should be deprecated(but supported) in R2
+1 -1
View File
@@ -601,7 +601,7 @@ Desktop::SetCursor(ServerCursor* newCursor)
HWInterface()->SetCursor(newCursor);
if (oldCursor != NULL)
fCursorManager.ReleaseCursor(oldCursor);
oldCursor->Release();
}
+30 -8
View File
@@ -925,19 +925,33 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
// 2) port_id reply port
status_t status = B_ERROR;
int8 cursorData[68];
uint8 cursorData[68];
ServerCursor* cursor = NULL;
// if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
// cursor = new (nothrow) ServerCursor(cursorData);
// if (cursor == NULL)
// status = B_NO_MEMORY;
// }
//
// if (cursor != NULL) {
// cursor->SetOwningTeam(fClientTeam);
// fDesktop->GetCursorManager().AddCursor(cursor);
//
// // Synchronous message - BApplication is waiting on the cursor's ID
// fLink.StartMessage(B_OK);
// fLink.Attach<int32>(cursor->Token());
// } else
// fLink.StartMessage(status);
if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
cursor = new (nothrow) ServerCursor(cursorData);
cursor = fDesktop->GetCursorManager().CreateCursor(fClientTeam,
cursorData);
if (cursor == NULL)
status = B_NO_MEMORY;
}
if (cursor != NULL) {
cursor->SetOwningTeam(fClientTeam);
fDesktop->GetCursorManager().AddCursor(cursor);
// Synchronous message - BApplication is waiting on the cursor's ID
fLink.StartMessage(B_OK);
fLink.Attach<int32>(cursor->Token());
@@ -952,14 +966,22 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
// Attached data:
// 1) int32 token ID of the cursor to delete
int32 token = B_NULL_TOKEN;
int32 token;
bool pendingViewCursor;
link.Read<int32>(&token);
if (link.Read<bool>(&pendingViewCursor) != B_OK)
break;
if (fAppCursor && fAppCursor->Token() == token)
fAppCursor = NULL;
if (ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token))
fDesktop->GetCursorManager().ReleaseCursor(cursor);
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
if (cursor) {
if (pendingViewCursor)
cursor->SetPendingViewCursor(true);
cursor->Release();
}
break;
}
+64 -5
View File
@@ -17,8 +17,12 @@
#include "ServerCursor.h"
#include <new>
#include <stdio.h>
#include "CursorManager.h"
using std::nothrow;
/*!
\brief Constructor
@@ -36,7 +40,10 @@ ServerCursor::ServerCursor(BRect r, color_space format,
: ServerBitmap(r, format, flags, bytesPerRow, screen),
fHotSpot(hotspot),
fOwningTeam(-1),
fReferenceCount(1)
fReferenceCount(1),
fCursorData(NULL),
fManager(NULL),
fPendingViewCursor(0)
{
fHotSpot.ConstrainTo(Bounds());
_AllocateBuffer();
@@ -47,11 +54,14 @@ ServerCursor::ServerCursor(BRect r, color_space format,
\brief Constructor
\param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details
*/
ServerCursor::ServerCursor(const int8* data)
ServerCursor::ServerCursor(const uint8* data)
: ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
fHotSpot(0, 0),
fOwningTeam(-1),
fReferenceCount(1)
fReferenceCount(1),
fCursorData(NULL),
fManager(NULL),
fPendingViewCursor(0)
{
// 68-byte array used in R5 for holding cursors.
// This API has serious problems and should be deprecated(but supported) in R2
@@ -99,6 +109,10 @@ ServerCursor::ServerCursor(const int8* data)
bmppos[i] = ((cursorval != 0) ? black : white) &
((maskval > 0) ? 0xFFFFFFFF : 0x00FFFFFF);
}
fCursorData = new (nothrow) uint8[68];
if (fCursorData)
memcpy(fCursorData, data, 68);
}
} else {
fWidth = 0;
@@ -119,7 +133,10 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData,
: ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
fHotSpot(0, 0),
fOwningTeam(-1),
fReferenceCount(1)
fReferenceCount(1),
fCursorData(NULL),
fManager(NULL),
fPendingViewCursor(0)
{
_AllocateBuffer();
if (Bits())
@@ -135,7 +152,10 @@ ServerCursor::ServerCursor(const ServerCursor* cursor)
: ServerBitmap(cursor),
fHotSpot(0, 0),
fOwningTeam(-1),
fReferenceCount(1)
fReferenceCount(1),
fCursorData(NULL),
fManager(NULL),
fPendingViewCursor(0)
{
// TODO: Hm. I don't move this into the if clause,
// because it might break code elsewhere.
@@ -146,6 +166,11 @@ ServerCursor::ServerCursor(const ServerCursor* cursor)
if (Bits() && cursor->Bits())
memcpy(Bits(), cursor->Bits(), BitsLength());
fHotSpot = cursor->fHotSpot;
if (cursor->fCursorData) {
fCursorData = new (nothrow) uint8[68];
if (fCursorData)
memcpy(fCursorData, cursor->fCursorData, 68);
}
}
}
@@ -168,3 +193,37 @@ ServerCursor::SetHotSpot(BPoint hotSpot)
fHotSpot.ConstrainTo(Bounds());
}
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);
}
delete this;
return true;
}
return false;
}
void
ServerCursor::SetPendingViewCursor(bool pending)
{
atomic_add(&fPendingViewCursor, pending ? 1 : -1);
}
void
ServerCursor::AttachedToManager(CursorManager* manager)
{
fManager = manager;
}
+14 -10
View File
@@ -162,8 +162,6 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
fClientReplyPort(clientPort),
fClientLooperPort(looperPort),
fClientViewsWithInvalidCoords(B_VIEW_RESIZED),
fClientToken(clientToken),
fCurrentLayer(NULL),
@@ -1242,13 +1240,21 @@ ServerWindow::_DispatchViewMessage(int32 code,
{
DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: ViewLayer: %s - NOT IMPLEMENTED\n", Title(), fCurrentLayer->Name()));
int32 token;
if (link.Read<int32>(&token) == B_OK) {
// TODO: this badly needs reference counting
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
fCurrentLayer->SetCursor(cursor);
}
if (link.Read<int32>(&token) != B_OK)
break;
// TODO: if fCurrentLayer is the view under the cursor, the appearance should change immediately!
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
fCurrentLayer->SetCursor(cursor);
if (fWindowLayer->IsFocus()) {
// The cursor might need to be updated now
fDesktop->UnlockSingleWindow();
if (fDesktop->EventDispatcher().ViewUnderMouse(fEventTarget) == fCurrentLayer->Token())
fDesktop->SetCursor(cursor);
fDesktop->LockSingleWindow();
}
break;
}
case AS_LAYER_SET_FLAGS:
@@ -1263,14 +1269,12 @@ ServerWindow::_DispatchViewMessage(int32 code,
case AS_LAYER_HIDE:
{
STRACE(("ServerWindow %s: Message AS_LAYER_HIDE: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
// TODO: test
fCurrentLayer->SetHidden(true);
break;
}
case AS_LAYER_SHOW:
{
STRACE(("ServerWindow %s: Message AS_LAYER_SHOW: ViewLayer: %s\n", Title(), fCurrentLayer->Name()));
// TODO: test
fCurrentLayer->SetHidden(false);
break;
}
+15 -1
View File
@@ -17,6 +17,7 @@
#include "DrawingEngine.h"
#include "ServerApp.h"
#include "ServerBitmap.h"
#include "ServerCursor.h"
#include "ServerPicture.h"
#include "ServerWindow.h"
#include "WindowLayer.h"
@@ -95,6 +96,9 @@ ViewLayer::~ViewLayer()
//
// TODO: Don't know yet if we should also delete fPicture
if (fCursor)
fCursor->Release();
// iterate over children and delete each one
ViewLayer* layer = fFirstChild;
while (layer) {
@@ -890,7 +894,17 @@ ViewLayer::SetEventMask(uint32 eventMask, uint32 options)
void
ViewLayer::SetCursor(ServerCursor *cursor)
{
fCursor = cursor;
if (cursor != fCursor) {
if (fCursor)
fCursor->Release();
fCursor = cursor;
if (fCursor) {
fCursor->Acquire();
fCursor->SetPendingViewCursor(false);
}
}
}