Some work on cursors:

* Fixed a myriad of bugs all over the place, ranging from locking errors to
  deleting objects that don't belong to the one deleting them (hello HWInterface!)
* Almost all ServerWindow cursor stuff was broken; I've replaced all commands
  to set a cursor with a single one AS_SET_CURSOR.
* Renamed some cursor commands.
* Changed the (broken) way ServerApp::fAppCursor was maintained - the application
  cursor is now NULL as long as possible.
* Removed superfluous ServerCursor app signature stuff.
* The BApplication will no longer duplicate the default/I-beam cursors, it will
  just reuse the default ones which now have fixed tokens.
* As a result, changing the cursor is now working as expected, closing bug #102.
* Rewrote Cursor.h, renamed private members to match our style guide.
* Minor cleanup.

What's still left to be done is reference counting the cursor objects to make them
work right and reliable.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16237 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-02-05 18:14:14 +00:00
parent 73b3ea3cd7
commit aa1f543799
18 changed files with 333 additions and 482 deletions

View File

@ -1,82 +1,40 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, OpenBeOS
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Cursor.h
// Author: Frans van Nispen (xlr8@tref.nl)
// Description: BCursor describes a view-wide or application-wide cursor.
//------------------------------------------------------------------------------
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _CURSOR_H
#define _CURSOR_H
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <Archivable.h>
#include <BeBuild.h>
#include <InterfaceDefs.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
// BCursor class ---------------------------------------------------------------
class BCursor : BArchivable {
public:
BCursor(const void* cursorData);
BCursor(BMessage* data);
virtual ~BCursor();
public:
BCursor(const void* cursorData);
BCursor(BMessage* data);
virtual ~BCursor();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* data);
virtual status_t Archive(BMessage* archive, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
// Private or reserved ---------------------------------------------------------
virtual status_t Perform(perform_code d, void* arg);
private:
virtual status_t Perform(perform_code d, void* arg);
private:
virtual void _ReservedCursor1();
virtual void _ReservedCursor2();
virtual void _ReservedCursor3();
virtual void _ReservedCursor4();
virtual void _ReservedCursor1();
virtual void _ReservedCursor2();
virtual void _ReservedCursor3();
virtual void _ReservedCursor4();
private:
friend class BApplication;
friend class BView;
friend class BApplication;
friend class BView;
int32 fServerToken;
bool fNeedToFree;
int32 m_serverToken;
int32 m_needToFree;
uint32 _reserved[6];
uint32 _reserved[6];
};
//------------------------------------------------------------------------------
#endif // _CURSOR_H
/*
* $Log $
*
* $Id $
*
*/

View File

@ -1,13 +1,14 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Jérôme Duval, jerome.duval@free.fr
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef _APP_SERVER_PROTOCOL_H_
#define _APP_SERVER_PROTOCOL_H_
#ifndef APP_SERVER_PROTOCOL_H
#define APP_SERVER_PROTOCOL_H
#include <SupportDefs.h>
@ -54,25 +55,16 @@ enum {
AS_RELEASE_SERVERMEM,
AS_AREA_MESSAGE,
// Cursor definitions
AS_SET_CURSOR_DATA,
AS_SET_CURSOR_BCURSOR,
AS_SET_CURSOR_BBITMAP,
AS_SET_CURSOR_SYSTEM,
AS_SET_SYSCURSOR_DATA,
AS_SET_SYSCURSOR_BCURSOR,
AS_SET_SYSCURSOR_BBITMAP,
AS_SET_SYSCURSOR_DEFAULTS,
AS_GET_SYSCURSOR,
// Cursor commands
AS_SET_CURSOR,
AS_SHOW_CURSOR,
AS_HIDE_CURSOR,
AS_OBSCURE_CURSOR,
AS_QUERY_CURSOR_HIDDEN,
AS_CREATE_BCURSOR,
AS_DELETE_BCURSOR,
AS_CREATE_CURSOR,
AS_DELETE_CURSOR,
AS_BEGIN_RECT_TRACKING,
AS_END_RECT_TRACKING,
@ -260,7 +252,7 @@ enum {
AS_LAYER_SET_ORIGIN,
AS_LAYER_GET_ORIGIN,
AS_LAYER_RESIZE_MODE,
AS_LAYER_CURSOR,
AS_LAYER_SET_CURSOR,
AS_LAYER_BEGIN_RECT_TRACK,
AS_LAYER_END_RECT_TRACK,
AS_LAYER_DRAG_RECT,
@ -320,4 +312,4 @@ enum {
AS_LAST_CODE
};
#endif // _APP_SERVER_PROTOCOL_H_
#endif // APP_SERVER_PROTOCOL_H

View File

@ -1,39 +1,21 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2005, Haiku
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: CursorSet.h
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Description: Private file encapsulating of the Haiku system cursor API
//
//------------------------------------------------------------------------------
#ifndef CURSORSET_H_
#define CURSORSET_H_
/*
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
*/
#ifndef CURSOR_SET_H
#define CURSOR_SET_H
#include <Bitmap.h>
#include <Cursor.h>
#include <Message.h>
typedef enum
{
B_CURSOR_DEFAULT=0,
typedef enum {
B_CURSOR_DEFAULT = 1,
B_CURSOR_TEXT,
B_CURSOR_MOVE,
B_CURSOR_DRAG,
@ -49,15 +31,14 @@ typedef enum
class ServerCursor;
const char *CursorWhichToString(cursor_which which);
BBitmap *CursorDataToBitmap(int8 *data);
/*!
\brief Class to manage system cursor sets
*/
class CursorSet : public BMessage {
public:
CursorSet(const char *name);
public:
CursorSet(const char *name);
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);
@ -67,6 +48,10 @@ public:
status_t FindCursor(cursor_which which, ServerCursor **cursor);
void SetName(const char *name);
const char *GetName(void);
private:
const char *_CursorWhichToString(cursor_which which);
BBitmap *_CursorDataToBitmap(int8 *data);
};
#endif
#endif // CURSOR_SET_H

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -26,51 +26,34 @@ class BitmapManager;
*/
class ServerBitmap {
public:
inline bool IsValid() const
{ return fInitialized; }
void Acquire();
/*!
\brief Returns the area in which the buffer resides
\return
- \c B_ERROR if the buffer is not allocated in an area
- area_id for the buffer
*/
inline area_id Area() const
{ return fArea; }
// Returns the offset of the bitmap in its area
inline int32 AreaOffset() const
{ return fOffset; }
//! Returns the bitmap's buffer
inline uint8* Bits() const
{ return fBuffer; }
inline uint32 BitsLength() const
{ return (uint32)(fBytesPerRow * fHeight); }
inline BRect Bounds() const
{ return BRect(0, 0, fWidth - 1, fHeight - 1); }
//! Returns the number of bytes in each row, including padding
inline int32 BytesPerRow() const
{ return fBytesPerRow; }
inline uint8 BitsPerPixel() const
{ return fBitsPerPixel; }
inline color_space ColorSpace() const
{ return fSpace; }
//! Returns the bitmap's width in pixels per row
inline int32 Width() const
{ return fWidth; }
//! Returns the bitmap's row count
inline int32 Height() const
{ return fHeight; }
inline bool IsValid() const
{ return fInitialized; }
inline int32 BytesPerRow() const
{ return fBytesPerRow; }
inline uint8 BitsPerPixel() const
{ return fBitsPerPixel; }
inline color_space ColorSpace() const
{ return fSpace; }
//! Returns the identifier token for the bitmap
inline int32 Token() const
@ -79,6 +62,8 @@ class ServerBitmap {
//! Does a shallow copy of the bitmap passed to it
inline void ShallowCopy(const ServerBitmap *from);
void PrintToStream();
protected:
friend class BitmapManager;
friend class PicturePlayer;
@ -86,7 +71,7 @@ protected:
ServerBitmap(BRect rect,
color_space space,
int32 flags,
int32 bytesperline = -1,
int32 bytesPerRow = -1,
screen_id screen = B_MAIN_SCREEN_ID);
ServerBitmap(const ServerBitmap* bmp);
virtual ~ServerBitmap();

View File

@ -1,50 +1,25 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: ServerCursor.h
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Glorified ServerBitmap used for cursor work.
//
//------------------------------------------------------------------------------
#ifndef SERVERCURSOR_H_
#define SERVERCURSOR_H_
/*
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef SERVER_CURSOR_H
#define SERVER_CURSOR_H
#include "ServerBitmap.h"
#include <Point.h>
#include <String.h>
#include "ServerBitmap.h"
class ServerApp;
class CursorManager;
/*!
\class ServerCursor ServerCursor.h
\brief Class to handle all cursor capabilities for the system
Although descended from ServerBitmaps, ServerCursors are not handled by
the BitmapManager - they are allocated like any other object. Unlike BeOS
R5, cursors can be any size or color space, and this class accomodates and
expands the R5 API.
*/
class ServerCursor : public ServerBitmap {
public:
ServerCursor(BRect r, color_space space,
@ -64,24 +39,18 @@ class ServerCursor : public ServerBitmap {
BPoint GetHotSpot() const
{ return fHotSpot; }
void SetAppSignature(const char* signature);
const char* GetAppSignature() const
{ return fAppSignature.String(); }
void SetOwningTeam(team_id tid)
{ fOwningTeam = tid; }
team_id OwningTeam() const
{ return fOwningTeam; }
//! Returns the cursor's ID
int32 ID() const
int32 Token() const
{ return fToken; }
private:
friend class CursorManager;
BPoint fHotSpot;
team_id fOwningTeam;
BString fAppSignature;
};
#endif // SERVERCURSOR_H_
#endif // SERVER_CURSOR_H

View File

@ -666,13 +666,11 @@ BApplication::IsCursorHidden() const
void
BApplication::SetCursor(const void *cursor)
BApplication::SetCursor(const void *cursorData)
{
// BeBook sez: If you want to call SetCursor() without forcing an immediate
// sync of the Application Server, you have to use a BCursor.
// By deductive reasoning, this function forces a sync. =)
BCursor Cursor(cursor);
SetCursor(&Cursor, true);
BCursor cursor(cursorData);
SetCursor(&cursor, true);
// forces the cursor to be sync'ed
}
@ -680,14 +678,14 @@ void
BApplication::SetCursor(const BCursor *cursor, bool sync)
{
BPrivate::AppServerLink link;
int32 code = SERVER_FALSE;
link.StartMessage(AS_SET_CURSOR_BCURSOR);
link.StartMessage(AS_SET_CURSOR);
link.Attach<bool>(sync);
link.Attach<int32>(cursor->m_serverToken);
if (sync)
link.Attach<int32>(cursor->fServerToken);
if (sync) {
int32 code;
link.FlushWithReply(code);
else
} else
link.Flush();
}
@ -695,24 +693,16 @@ BApplication::SetCursor(const BCursor *cursor, bool sync)
int32
BApplication::CountWindows() const
{
// BeBook sez: The windows list includes all windows explicitely created by
// the app ... but excludes private windows create by Be
// classes.
// I'm taking this to include private menu windows, thus the incl_menus
// param is false.
return count_windows(false);
// we're ignoring menu windows
}
BWindow *
BApplication::WindowAt(int32 index) const
{
// BeBook sez: The windows list includes all windows explicitely created by
// the app ... but excludes private windows create by Be
// classes.
// I'm taking this to include private menu windows, thus the incl_menus
// param is false.
return window_at(index, false);
// we're ignoring menu windows
}

View File

@ -1,10 +1,11 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Frans van Nispen (xlr8@tref.nl)
* Gabe Yoder (gyoder@stny.rr.com)
* Axel Dörfler, axeld@pinc-software.de
*/
/** BCursor describes a view-wide or application-wide cursor. */
@ -15,8 +16,9 @@
*/
#include <AppDefs.h>
#include <Cursor.h>
#include <CursorSet.h>
#include <AppServerLink.h>
#include <ServerProtocol.h>
@ -27,9 +29,20 @@ const BCursor *B_CURSOR_I_BEAM;
BCursor::BCursor(const void *cursorData)
:
fServerToken(-1),
fNeedToFree(false)
{
int8 *data = (int8 *)cursorData;
m_serverToken = 0;
const uint8 *data = (const uint8 *)cursorData;
if (data == B_HAND_CURSOR || data == B_I_BEAM_CURSOR) {
// just use the default cursors from the app_server
fServerToken = data == B_HAND_CURSOR ?
B_CURSOR_DEFAULT : B_CURSOR_TEXT;
return;
}
// Create a new cursor in the app_server
if (data == NULL
|| data[0] != 16 // size
@ -38,47 +51,50 @@ BCursor::BCursor(const void *cursorData)
return;
// Send data directly to server
BPrivate::AppServerLink serverlink;
int32 code = SERVER_FALSE;
BPrivate::AppServerLink link;
link.StartMessage(AS_CREATE_CURSOR);
link.Attach(cursorData, 68);
serverlink.StartMessage(AS_CREATE_BCURSOR);
serverlink.Attach(cursorData, 68);
serverlink.FlushWithReply(code);
if (code == SERVER_TRUE)
serverlink.Read<int32>(&m_serverToken);
status_t status;
if (link.FlushWithReply(status) == B_OK && status == B_OK) {
link.Read<int32>(&fServerToken);
fNeedToFree = true;
}
}
// undefined on BeOS
BCursor::BCursor(BMessage *data)
{
m_serverToken = 0;
// undefined on BeOS
fServerToken = -1;
fNeedToFree = false;
}
BCursor::~BCursor()
{
// Notify server to deallocate server-side objects for this cursor
BPrivate::AppServerLink serverlink;
serverlink.StartMessage(AS_DELETE_BCURSOR);
serverlink.Attach<int32>(m_serverToken);
serverlink.Flush();
if (fNeedToFree) {
BPrivate::AppServerLink link;
link.StartMessage(AS_DELETE_CURSOR);
link.Attach<int32>(fServerToken);
link.Flush();
}
}
// not implemented on BeOS
status_t BCursor::Archive(BMessage *into, bool deep) const
status_t
BCursor::Archive(BMessage *into, bool deep) const
{
// not implemented on BeOS
return B_OK;
}
// not implemented on BeOS
BArchivable *BCursor::Instantiate(BMessage *data)
BArchivable *
BCursor::Instantiate(BMessage *data)
{
// not implemented on BeOS
return NULL;
}
@ -86,9 +102,6 @@ BArchivable *BCursor::Instantiate(BMessage *data)
status_t
BCursor::Perform(perform_code d, void *arg)
{
/*
printf("perform %d\n", (int)d);
*/
return B_OK;
}

View File

@ -19,6 +19,7 @@ if $(RUN_WITHOUT_APP_SERVER) != 0 {
UsePrivateHeaders shared app interface ;
UsePrivateHeaders [ FDirName kernel util ] ; # For KMessage.h
UsePrivateHeaders [ FDirName servers app ] ;
SetSubDirSupportedPlatforms haiku libbe_test ;

View File

@ -1004,8 +1004,8 @@ BView::SetViewCursor(const BCursor *cursor, bool sync)
check_lock();
fOwner->fLink->StartMessage(AS_LAYER_CURSOR);
fOwner->fLink->Attach<int32>(cursor->m_serverToken);
fOwner->fLink->StartMessage(AS_LAYER_SET_CURSOR);
fOwner->fLink->Attach<int32>(cursor->fServerToken);
if (sync)
fOwner->fLink->Flush();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -9,9 +9,6 @@
/** Handles the system's cursor infrastructure */
#include <Directory.h>
#include <String.h>
#include "CursorData.h"
#include "CursorManager.h"
#include "HaikuSystemCursor.h"
@ -19,10 +16,13 @@
#include "ServerConfig.h"
#include "ServerTokenSpace.h"
#include <Autolock.h>
#include <Directory.h>
#include <String.h>
//! Initializes the CursorManager
CursorManager::CursorManager()
: BLocker("CursorManager")
: BLocker("CursorManager")
{
// Set system cursors to "unassigned"
// ToDo: decide about default cursor
@ -34,11 +34,11 @@ CursorManager::CursorManager()
fDefaultCursor->SetHotSpot(BPoint(1, 0));
#else
fDefaultCursor = new ServerCursor(default_cursor_data);
AddCursor(fDefaultCursor);
#endif
AddCursor(fDefaultCursor, B_CURSOR_DEFAULT);
fTextCursor = new ServerCursor(default_text_data);
AddCursor(fTextCursor);
AddCursor(fTextCursor, B_CURSOR_TEXT);
fMoveCursor = new ServerCursor(default_move_data);
AddCursor(fMoveCursor);
@ -67,16 +67,8 @@ CursorManager::CursorManager()
CursorManager::~CursorManager()
{
for (int32 i = 0; i < fCursorList.CountItems(); i++) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(i);
if (cursor)
delete cursor;
delete (ServerCursor *)fCursorList.ItemAt(i);
}
// Note that it is not necessary to remove and delete the system
// cursors. These cursors are kept in the list with a empty application
// signature so they cannot be removed very easily except via
// SetCursor(cursor_which). At shutdown, they are removed with the
// above loop.
}
@ -86,7 +78,7 @@ CursorManager::~CursorManager()
\return The token assigned to the cursor or B_ERROR if sc is NULL
*/
int32
CursorManager::AddCursor(ServerCursor* cursor)
CursorManager::AddCursor(ServerCursor* cursor, int32 token)
{
if (!cursor)
return B_ERROR;
@ -94,17 +86,32 @@ CursorManager::AddCursor(ServerCursor* cursor)
Lock();
fCursorList.AddItem(cursor);
int32 token = fTokenSpace.NewToken(B_SERVER_TOKEN, cursor);
cursor->fToken = token;
if (token == -1)
cursor->fToken = fTokenSpace.NewToken(kCursorToken, cursor);
else {
fTokenSpace.SetToken(token, kCursorToken, cursor);
cursor->fToken = token;
}
Unlock();
return token;
}
ServerCursor*
CursorManager::_RemoveCursor(int32 index)
{
ServerCursor* cursor = (ServerCursor *)fCursorList.RemoveItem(index);
if (cursor != NULL)
fTokenSpace.RemoveToken(cursor->fToken);
return cursor;
}
/*!
\brief Removes a cursor from the internal list and deletes it
\param token ID value of the cursor to be deleted
\param token Token of the cursor to be deleted
If the cursor is not found, this call does nothing
*/
@ -113,11 +120,11 @@ CursorManager::DeleteCursor(int32 token)
{
Lock();
for (int32 i = 0; i < fCursorList.CountItems(); i++) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(i);
for (int32 index = 0; index < fCursorList.CountItems(); index++) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index);
if (cursor && cursor->fToken == token) {
fCursorList.RemoveItem(i);
_RemoveCursor(index);
delete cursor;
break;
}
@ -132,21 +139,17 @@ CursorManager::DeleteCursor(int32 token)
\param signature Signature to which the cursors belong
*/
void
CursorManager::RemoveAppCursors(team_id team)
CursorManager::DeleteCursors(team_id team)
{
Lock();
int32 index = 0;
while (index < fCursorList.CountItems()) {
for (int32 index = fCursorList.CountItems(); index-- > 0;) {
ServerCursor *cursor = (ServerCursor *)fCursorList.ItemAt(index);
if (!cursor)
break;
if (cursor->OwningTeam() != team)
continue;
if (cursor->OwningTeam() == team) {
fCursorList.RemoveItem(index);
delete cursor;
} else
index++;
_RemoveCursor(index);
delete cursor;
}
Unlock();
@ -165,7 +168,8 @@ CursorManager::RemoveAppCursors(team_id team)
void
CursorManager::SetCursorSet(const char *path)
{
Lock();
BAutolock locker (this);
CursorSet cursorSet(NULL);
if (!path || cursorSet.Load(path) != B_OK)
@ -226,8 +230,6 @@ CursorManager::SetCursorSet(const char *path)
delete fEWCursor;
fEWCursor = cursor;
}
Unlock();
}
@ -240,52 +242,31 @@ CursorManager::SetCursorSet(const char *path)
ServerCursor *
CursorManager::GetCursor(cursor_which which)
{
ServerCursor *cursor = NULL;
Lock();
BAutolock locker(this);
switch (which) {
case B_CURSOR_DEFAULT:
cursor = fDefaultCursor;
break;
return fDefaultCursor;
case B_CURSOR_TEXT:
cursor = fTextCursor;
break;
return fTextCursor;
case B_CURSOR_MOVE:
cursor = fMoveCursor;
break;
return fMoveCursor;
case B_CURSOR_DRAG:
cursor = fDragCursor;
break;
return fDragCursor;
case B_CURSOR_RESIZE:
cursor = fResizeCursor;
break;
return fResizeCursor;
case B_CURSOR_RESIZE_NWSE:
cursor = fNWSECursor;
break;
return fNWSECursor;
case B_CURSOR_RESIZE_NESW:
cursor = fNESWCursor;
break;
return fNESWCursor;
case B_CURSOR_RESIZE_NS:
cursor = fNSCursor;
break;
return fNSCursor;
case B_CURSOR_RESIZE_EW:
cursor = fEWCursor;
break;
return fEWCursor;
default:
break;
return NULL;
}
Unlock();
return cursor;
}
@ -382,9 +363,6 @@ CursorManager::ChangeCursor(cursor_which which, int32 token)
return;
}
if (cursor->GetAppSignature())
cursor->SetAppSignature("");
fCursorList.RemoveItem(cursor);
Unlock();
}
@ -399,7 +377,7 @@ ServerCursor *
CursorManager::FindCursor(int32 token)
{
ServerCursor* cursor;
if (gTokenSpace.GetToken(token, kCursorToken, (void**)&cursor) == B_OK)
if (fTokenSpace.GetToken(token, kCursorToken, (void**)&cursor) == B_OK)
return cursor;
return NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -33,9 +33,9 @@ class CursorManager : public BLocker {
CursorManager();
virtual ~CursorManager();
int32 AddCursor(ServerCursor* cursor);
int32 AddCursor(ServerCursor* cursor, int32 token = -1);
void DeleteCursor(int32 token);
void RemoveAppCursors(team_id team);
void DeleteCursors(team_id team);
void SetCursorSet(const char* path);
ServerCursor* GetCursor(cursor_which which);
@ -45,6 +45,8 @@ class CursorManager : public BLocker {
ServerCursor* FindCursor(int32 token);
private:
ServerCursor* _RemoveCursor(int32 index);
BList fCursorList;
BTokenSpace fTokenSpace;

View File

@ -1,37 +1,21 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: CursorSet.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Description: Private file encapsulating OBOS system cursor API
//
//------------------------------------------------------------------------------
#include <PortLink.h>
/*
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
*/
#include <AppServerLink.h>
#include <CursorSet.h>
#include <PortLink.h>
#include <ServerCursor.h>
#include <ServerProtocol.h>
#include <OS.h>
#include <String.h>
#include <File.h>
#include "CursorSet.h"
#include "ServerCursor.h"
/*!
@ -44,6 +28,7 @@ CursorSet::CursorSet(const char *name)
AddString("name", name ? name : "Untitled");
}
/*!
\brief Saves the data in the cursor set to a file
\param path Path of the file to save to.
@ -54,19 +39,20 @@ CursorSet::CursorSet(const char *name)
- \c other value: See BFile::SetTo and BMessage::Flatten return codes
*/
status_t
CursorSet::Save(const char *path, int32 saveflags)
CursorSet::Save(const char *path, int32 saveFlags)
{
if (!path)
return B_BAD_VALUE;
BFile file;
status_t status = file.SetTo(path, B_READ_WRITE | saveflags);
status_t status = file.SetTo(path, B_READ_WRITE | saveFlags);
if (status != B_OK)
return status;
return Flatten(&file);
}
/*!
\brief Loads the data into the cursor set from a file
\param path Path of the file to load from.
@ -89,6 +75,7 @@ CursorSet::Load(const char *path)
return Unflatten(&file);
}
/*!
\brief Adds the cursor to the set and replaces any existing entry for the given specifier
\param which System cursor specifier defined in CursorSet.h
@ -103,7 +90,7 @@ CursorSet::AddCursor(cursor_which which, const BBitmap *cursor, const BPoint &ho
return B_BAD_VALUE;
// Remove the data if it exists already
RemoveData(CursorWhichToString(which));
RemoveData(_CursorWhichToString(which));
// Actually add the data to our set
BMessage msg((int32)which);
@ -116,11 +103,12 @@ CursorSet::AddCursor(cursor_which which, const BBitmap *cursor, const BPoint &ho
msg.AddInt32("_rowbytes",cursor->BytesPerRow());
msg.AddPoint("hotspot",hotspot);
msg.AddData("_data",B_RAW_TYPE,cursor->Bits(), cursor->BitsLength());
AddMessage(CursorWhichToString(which),&msg);
AddMessage(_CursorWhichToString(which),&msg);
return B_OK;
}
/*!
\brief Adds the cursor to the set and replaces any existing entry for the given specifier
\param which System cursor specifier defined in CursorSet.h
@ -138,7 +126,7 @@ CursorSet::AddCursor(cursor_which which, int8 *data)
if (!data)
return B_BAD_VALUE;
BBitmap *bmp = CursorDataToBitmap(data);
BBitmap *bmp = _CursorDataToBitmap(data);
BPoint pt(data[2],data[3]);
status_t stat = AddCursor(which,bmp,pt);
@ -147,6 +135,7 @@ CursorSet::AddCursor(cursor_which which, int8 *data)
return stat;
}
/*!
\brief Removes the data associated with the specifier from the cursor set
\param which System cursor specifier defined in CursorSet.h
@ -154,9 +143,10 @@ CursorSet::AddCursor(cursor_which which, int8 *data)
void
CursorSet::RemoveCursor(cursor_which which)
{
RemoveData(CursorWhichToString(which));
RemoveData(_CursorWhichToString(which));
}
/*!
\brief Retrieves a cursor from the set.
\param which System cursor specifier defined in CursorSet.h
@ -177,7 +167,7 @@ CursorSet::FindCursor(cursor_which which, BBitmap **cursor, BPoint *hotspot)
return B_BAD_VALUE;
BMessage msg;
if (FindMessage(CursorWhichToString(which), &msg) != B_OK)
if (FindMessage(_CursorWhichToString(which), &msg) != B_OK)
return B_NAME_NOT_FOUND;
const void *buffer;
@ -206,6 +196,7 @@ CursorSet::FindCursor(cursor_which which, BBitmap **cursor, BPoint *hotspot)
return B_ERROR;
}
/*!
\brief Retrieves a cursor from the set.
\param which System cursor specifier defined in CursorSet.h
@ -222,7 +213,7 @@ status_t
CursorSet::FindCursor(cursor_which which, ServerCursor **_cursor)
{
BMessage msg;
if (FindMessage(CursorWhichToString(which), &msg) != B_OK)
if (FindMessage(_CursorWhichToString(which), &msg) != B_OK)
return B_NAME_NOT_FOUND;
const char *className;
@ -250,6 +241,7 @@ CursorSet::FindCursor(cursor_which which, ServerCursor **_cursor)
return B_ERROR;
}
/*!
\brief Returns the name of the set
\return The name of the set
@ -264,6 +256,7 @@ CursorSet::GetName(void)
return NULL;
}
/*!
\brief Renames the cursor set
\param name new name of the set.
@ -287,7 +280,7 @@ CursorSet::SetName(const char *name)
\return Name for the cursor specifier
*/
const char *
CursorWhichToString(cursor_which which)
CursorSet::_CursorWhichToString(cursor_which which)
{
switch (which) {
case B_CURSOR_DEFAULT:
@ -323,7 +316,7 @@ CursorWhichToString(cursor_which which)
BBitmaps returned by this function are always in the RGBA32 color space
*/
BBitmap *
CursorDataToBitmap(int8 *data)
CursorSet::_CursorDataToBitmap(int8 *data)
{
// 68-byte array used in R5 for holding cursors.
// This API has serious problems and should be deprecated(but supported) in R2

View File

@ -118,14 +118,6 @@ ServerApp::ServerApp(Desktop* desktop, port_id clientReplyPort,
BMessenger::Private(fHandlerMessenger).SetTo(fClientTeam,
clientLooperPort, clientToken);
ServerCursor *defaultCursor =
fDesktop->GetCursorManager().GetCursor(B_CURSOR_DEFAULT);
if (defaultCursor) {
fAppCursor = new ServerCursor(defaultCursor);
fAppCursor->SetOwningTeam(fClientTeam);
}
fInitialWorkspace = desktop->CurrentWorkspace();
// TODO: this should probably be retrieved when the app is loaded!
@ -191,7 +183,7 @@ ServerApp::~ServerApp()
delete (ServerPicture*)fPictureList.ItemAtFast(i);
}
fDesktop->GetCursorManager().RemoveAppCursors(fClientTeam);
fDesktop->GetCursorManager().DeleteCursors(fClientTeam);
STRACE(("ServerApp %s::~ServerApp(): Exiting\n", Signature()));
}
@ -298,9 +290,8 @@ ServerApp::Activate(bool value)
void
ServerApp::SetCursor()
{
// TODO: custom cursors cannot be drawn by the HWInterface right now (wrong bitmap format)
// if (fAppCursor)
// fDesktop->HWInterface()->SetCursor(fAppCursor);
if (fAppCursor != NULL)
fDesktop->HWInterface()->SetCursor(fAppCursor);
fDesktop->HWInterface()->SetCursorVisible(fCursorHideLevel == 0);
}
@ -886,95 +877,76 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link)
fLink.Flush();
break;
}
case AS_SET_CURSOR_DATA:
case AS_SET_CURSOR:
{
STRACE(("ServerApp %s: SetCursor via cursor data\n", Signature()));
// Attached data: 68 bytes of fAppCursor data
int8 cursorData[68];
link.Read(cursorData, 68);
// Because we don't want an overaccumulation of these particular
// cursors, we will delete them if there is an existing one. It would
// otherwise be easy to crash the server by calling SetCursor a
// sufficient number of times
if (fAppCursor)
fDesktop->GetCursorManager().DeleteCursor(fAppCursor->ID());
fAppCursor = new ServerCursor(cursorData);
fAppCursor->SetOwningTeam(fClientTeam);
fAppCursor->SetAppSignature(Signature());
// ToDo: These two should probably both be done in Desktop directly
fDesktop->GetCursorManager().AddCursor(fAppCursor);
fDesktop->HWInterface()->SetCursor(fAppCursor);
break;
}
case AS_SET_CURSOR_BCURSOR:
{
STRACE(("ServerApp %s: SetCursor via BCursor\n", Signature()));
STRACE(("ServerApp %s: SetCursor\n", Signature()));
// Attached data:
// 1) bool flag to send a reply
// 2) int32 token ID of the cursor to set
// 3) port_id port to receive a reply. Only exists if the sync flag is true.
bool sync;
int32 ctoken = B_NULL_TOKEN;
link.Read<bool>(&sync);
link.Read<int32>(&ctoken);
int32 token = B_NULL_TOKEN;
ServerCursor *cursor = fDesktop->GetCursorManager().FindCursor(ctoken);
if (cursor)
fDesktop->HWInterface()->SetCursor(cursor);
link.Read<bool>(&sync);
link.Read<int32>(&token);
fAppCursor = fDesktop->GetCursorManager().FindCursor(token);
if (fAppCursor != NULL)
fDesktop->HWInterface()->SetCursor(fAppCursor);
else {
// if there is no new cursor, we just set the default cursor
fDesktop->HWInterface()->SetCursor(fDesktop->GetCursorManager().GetCursor(B_CURSOR_DEFAULT));
}
if (sync) {
// the application is expecting a reply so that it
// knows the cursor shape has truely changed
// The application is expecting a reply
fLink.StartMessage(B_OK);
fLink.Flush();
}
break;
}
case AS_CREATE_BCURSOR:
case AS_CREATE_CURSOR:
{
STRACE(("ServerApp %s: Create BCursor\n", Signature()));
STRACE(("ServerApp %s: Create Cursor\n", Signature()));
// Attached data:
// 1) 68 bytes of fAppCursor data
// 2) port_id reply port
status_t status = B_ERROR;
int8 cursorData[68];
link.Read(cursorData, sizeof(cursorData));
ServerCursor* cursor = NULL;
// Because we don't want an overaccumulation of these particular
// cursors, we will delete them if there is an existing one. It would
// otherwise be easy to crash the server by calling CreateCursor a
// sufficient number of times
if (fAppCursor)
fDesktop->GetCursorManager().DeleteCursor(fAppCursor->ID());
if (link.Read(cursorData, sizeof(cursorData)) >= B_OK) {
cursor = new (nothrow) ServerCursor(cursorData);
if (cursor == NULL)
status = B_NO_MEMORY;
}
fAppCursor = new ServerCursor(cursorData);
fAppCursor->SetOwningTeam(fClientTeam);
fAppCursor->SetAppSignature(Signature());
fDesktop->GetCursorManager().AddCursor(fAppCursor);
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);
// Synchronous message - BApplication is waiting on the cursor's ID
fLink.StartMessage(B_OK);
fLink.Attach<int32>(fAppCursor->ID());
fLink.Flush();
break;
}
case AS_DELETE_BCURSOR:
case AS_DELETE_CURSOR:
{
STRACE(("ServerApp %s: Delete BCursor\n", Signature()));
// Attached data:
// 1) int32 token ID of the cursor to delete
int32 ctoken = B_NULL_TOKEN;
link.Read<int32>(&ctoken);
int32 token = B_NULL_TOKEN;
link.Read<int32>(&token);
if (fAppCursor && fAppCursor->ID() == ctoken)
if (fAppCursor && fAppCursor->Token() == token)
fAppCursor = NULL;
fDesktop->GetCursorManager().DeleteCursor(ctoken);
fDesktop->GetCursorManager().DeleteCursor(token);
break;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2005, Haiku.
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -10,6 +10,7 @@
#include "ServerBitmap.h"
#include <new>
#include <stdio.h>
#include <string.h>
using std::nothrow;
@ -26,7 +27,7 @@ using std::nothrow;
\param screen Screen assigned to the bitmap.
*/
ServerBitmap::ServerBitmap(BRect rect, color_space space,
int32 flags, int32 bytesPerLine,
int32 flags, int32 bytesPerRow,
screen_id screen)
: fInitialized(false),
fArea(B_ERROR),
@ -44,7 +45,7 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space,
fBitsPerPixel(0)
// TODO: what about fToken and fOffset ?!?
{
_HandleSpace(space, bytesPerLine);
_HandleSpace(space, bytesPerRow);
}
@ -244,6 +245,14 @@ ServerBitmap::_HandleSpace(color_space space, int32 bytesPerRow)
}
void
ServerBitmap::PrintToStream()
{
printf("Bitmap@%p: (%ld:%ld), space %ld, bpr %ld, buffer %p\n",
this, fWidth, fHeight, (int32)fSpace, fBytesPerRow, fBuffer);
}
// #pragma mark -

View File

@ -1,32 +1,25 @@
//------------------------------------------------------------------------------
// Copyright (c) 2001-2002, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: ServerCursor.cpp
// Author: DarkWyrm <bpmagic@columbus.rr.com>
// Stephan Aßmus <superstippi@gmx.de>
// Description: Glorified ServerBitmap used for cursor work.
//
//------------------------------------------------------------------------------
/*
* Copyright 2001-2006, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de
*/
/*!
Although descended from ServerBitmaps, ServerCursors are not handled by
the BitmapManager - they are allocated like any other object. Unlike BeOS
R5, cursors can be any size or color space, and this class accomodates and
expands the R5 API.
*/
#include "ServerCursor.h"
#include <stdio.h>
/*!
\brief Constructor
\param r Size of the cursor
@ -48,6 +41,7 @@ ServerCursor::ServerCursor(BRect r, color_space format,
_AllocateBuffer();
}
/*!
\brief Constructor
\param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details
@ -112,6 +106,7 @@ ServerCursor::ServerCursor(const int8* data)
}
}
/*!
\brief Constructor
\param data Pointer to bitmap data in memory, the padding bytes should be contained when format less than 32 bpp.
@ -128,6 +123,7 @@ ServerCursor::ServerCursor(const uint8* alreadyPaddedData,
memcpy(Bits(), alreadyPaddedData, BitsLength());
}
/*!
\brief Copy constructor
\param cursor cursor to copy
@ -149,12 +145,14 @@ ServerCursor::ServerCursor(const ServerCursor* cursor)
}
}
//! Frees the heap space allocated for the cursor's image data
ServerCursor::~ServerCursor()
{
_FreeBuffer();
}
/*!
\brief Sets the cursor's hotspot
\param pt New location of hotspot, constrained to the cursor's boundaries.
@ -166,9 +164,3 @@ ServerCursor::SetHotSpot(BPoint pt)
fHotSpot.ConstrainTo(Bounds());
}
// SetAppSignature
void
ServerCursor::SetAppSignature(const char* signature)
{
fAppSignature.SetTo((signature) ? signature : "");
}

View File

@ -1243,16 +1243,16 @@ ServerWindow::_DispatchViewMessage(int32 code,
fCurrentLayer->SetResizeMode(resizeMode);
break;
}
case AS_LAYER_CURSOR:
case AS_LAYER_SET_CURSOR:
{
DTRACE(("ServerWindow %s: Message AS_LAYER_CURSOR: ViewLayer: %s - NOT IMPLEMENTED\n", Title(), fCurrentLayer->Name()));
int32 token = -1;
link.Read<int32>(&token);
int32 token;
if (link.Read<int32>(&token) == B_OK) {
// TODO: this badly needs reference counting
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
fCurrentLayer->SetCursor(cursor);
}
// TODO: this badly needs reference counting
ServerCursor* cursor = fDesktop->GetCursorManager().FindCursor(token);
fCurrentLayer->SetCursor(cursor);
// TODO: if fCurrentLayer is the view under the cursor, the appearance should change immediately!
break;
}

View File

@ -988,13 +988,15 @@ WindowLayer::MouseMoved(BMessage *msg, BPoint where, int32* _viewToken,
// 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 != currentCursor) {
// TODO: custom cursors cannot be drawn by the HWInterface right now (wrong bitmap format)
// fDesktop->HWInterface()->SetCursor(cursor);
}
if (cursor == NULL)
cursor = fDesktop->GetCursorManager().GetCursor(B_CURSOR_DEFAULT);
if (cursor != currentCursor && cursor != NULL)
fDesktop->HWInterface()->SetCursor(cursor);
}
}

View File

@ -40,8 +40,11 @@ HWInterface::HWInterface(bool doubleBuffered)
HWInterface::~HWInterface()
{
delete fCursorAreaBackup;
delete fCursor;
delete fCursorAndDragBitmap;
// The standard cursor doesn't belong us - the drag bitmap might
if (fCursor != fCursorAndDragBitmap)
delete fCursorAndDragBitmap;
delete fUpdateExecutor;
}
@ -81,17 +84,24 @@ HWInterface::SetCursor(ServerCursor* cursor)
// considered iritating to the user to
// change cursor shapes while something
// is dragged anyways.
// TODO: like a "+" or "-" sign when dragging some files to indicate
// the current drag mode?
WriteUnlock();
return;
}
if (fCursor != cursor) {
BRect oldFrame = _CursorFrame();
delete fCursor;
if (fCursorAndDragBitmap == fCursor) {
// make sure _AdoptDragBitmap doesn't delete a real cursor
fCursorAndDragBitmap = NULL;
}
fCursor = cursor;
Invalidate(oldFrame);
BRect r = _CursorFrame();
_AdoptDragBitmap(fDragBitmap, fDragBitmapOffset);
Invalidate(r);
Invalidate(_CursorFrame());
}
WriteUnlock();
}