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:
@@ -33,6 +33,7 @@ class BCursor : BArchivable {
|
||||
|
||||
int32 fServerToken;
|
||||
bool fNeedToFree;
|
||||
mutable bool fPendingViewCursor;
|
||||
|
||||
uint32 _reserved[6];
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -601,7 +601,7 @@ Desktop::SetCursor(ServerCursor* newCursor)
|
||||
HWInterface()->SetCursor(newCursor);
|
||||
|
||||
if (oldCursor != NULL)
|
||||
fCursorManager.ReleaseCursor(oldCursor);
|
||||
oldCursor->Release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user