2006-02-05 21:14:14 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2003-01-13 01:51:01 +03:00
|
|
|
#include "ServerCursor.h"
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2006-02-26 21:15:31 +03:00
|
|
|
#include <new>
|
2003-02-22 23:23:22 +03:00
|
|
|
#include <stdio.h>
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2006-02-26 21:15:31 +03:00
|
|
|
#include "CursorManager.h"
|
|
|
|
|
|
|
|
using std::nothrow;
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-01-18 23:32:45 +03:00
|
|
|
/*!
|
|
|
|
\brief Constructor
|
2003-01-20 02:04:58 +03:00
|
|
|
\param r Size of the cursor
|
|
|
|
\param cspace Color space of the cursor
|
|
|
|
\param flags ServerBitmap flags. See Bitmap.h.
|
|
|
|
\param hotspot Hotspot of the cursor
|
|
|
|
\param bytesperline Bytes per row for the cursor. See ServerBitmap::ServerBitmap()
|
2003-01-18 23:32:45 +03:00
|
|
|
|
|
|
|
*/
|
2005-04-14 04:04:26 +04:00
|
|
|
ServerCursor::ServerCursor(BRect r, color_space format,
|
|
|
|
int32 flags, BPoint hotspot,
|
|
|
|
int32 bytesPerRow,
|
|
|
|
screen_id screen)
|
|
|
|
: ServerBitmap(r, format, flags, bytesPerRow, screen),
|
|
|
|
fHotSpot(hotspot),
|
2006-02-05 22:43:44 +03:00
|
|
|
fOwningTeam(-1),
|
2006-02-26 21:15:31 +03:00
|
|
|
fReferenceCount(1),
|
|
|
|
fCursorData(NULL),
|
|
|
|
fManager(NULL),
|
|
|
|
fPendingViewCursor(0)
|
2003-01-13 01:51:01 +03:00
|
|
|
{
|
2004-09-21 02:50:02 +04:00
|
|
|
fHotSpot.ConstrainTo(Bounds());
|
2003-01-13 01:51:01 +03:00
|
|
|
_AllocateBuffer();
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-01-18 23:32:45 +03:00
|
|
|
/*!
|
|
|
|
\brief Constructor
|
2005-04-14 04:04:26 +04:00
|
|
|
\param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details
|
2003-01-18 23:32:45 +03:00
|
|
|
*/
|
2006-02-26 21:15:31 +03:00
|
|
|
ServerCursor::ServerCursor(const uint8* data)
|
2005-04-14 04:04:26 +04:00
|
|
|
: ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
|
|
|
|
fHotSpot(0, 0),
|
2006-02-05 22:43:44 +03:00
|
|
|
fOwningTeam(-1),
|
2006-02-26 21:15:31 +03:00
|
|
|
fReferenceCount(1),
|
|
|
|
fCursorData(NULL),
|
|
|
|
fManager(NULL),
|
|
|
|
fPendingViewCursor(0)
|
2003-01-13 01:51:01 +03:00
|
|
|
{
|
|
|
|
// 68-byte array used in R5 for holding cursors.
|
|
|
|
// This API has serious problems and should be deprecated(but supported) in R2
|
|
|
|
|
|
|
|
// Now that we have all the setup, we're going to map (for now) the cursor
|
|
|
|
// to RGBA32. Eventually, there will be support for 16 and 8-bit depths
|
2005-04-14 04:04:26 +04:00
|
|
|
if (data) {
|
2003-01-13 01:51:01 +03:00
|
|
|
_AllocateBuffer();
|
2005-04-14 04:04:26 +04:00
|
|
|
uint8* buffer = Bits();
|
|
|
|
if (!buffer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fInitialized = true;
|
|
|
|
uint32 black = 0xFF000000;
|
|
|
|
uint32 white = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
uint16* cursorpos = (uint16*)(data + 4);
|
|
|
|
uint16* maskpos = (uint16*)(data + 36);
|
|
|
|
fHotSpot.Set(data[3], data[2]);
|
|
|
|
|
|
|
|
uint32* bmppos;
|
|
|
|
uint16 cursorflip;
|
|
|
|
uint16 maskflip;
|
|
|
|
uint16 cursorval;
|
|
|
|
uint16 maskval;
|
|
|
|
uint16 powval;
|
|
|
|
|
2003-01-13 01:51:01 +03:00
|
|
|
// for each row in the cursor data
|
2005-04-14 04:04:26 +04:00
|
|
|
for (int32 j = 0; j < 16; j++) {
|
|
|
|
bmppos = (uint32*)(buffer + (j * BytesPerRow()));
|
2003-01-13 01:51:01 +03:00
|
|
|
|
|
|
|
// On intel, our bytes end up swapped, so we must swap them back
|
2005-04-14 04:04:26 +04:00
|
|
|
cursorflip = (cursorpos[j] & 0xFF) << 8;
|
2003-01-13 01:51:01 +03:00
|
|
|
cursorflip |= (cursorpos[j] & 0xFF00) >> 8;
|
2003-02-22 23:23:22 +03:00
|
|
|
|
2005-04-14 04:04:26 +04:00
|
|
|
maskflip = (maskpos[j] & 0xFF) << 8;
|
2003-01-13 01:51:01 +03:00
|
|
|
maskflip |= (maskpos[j] & 0xFF00) >> 8;
|
|
|
|
|
|
|
|
// for each column in each row of cursor data
|
2005-04-14 04:04:26 +04:00
|
|
|
for (int32 i = 0; i < 16; i++) {
|
2003-01-13 01:51:01 +03:00
|
|
|
// Get the values and dump them to the bitmap
|
2005-04-14 04:04:26 +04:00
|
|
|
powval = 1 << (15 - i);
|
|
|
|
cursorval = cursorflip & powval;
|
|
|
|
maskval = maskflip & powval;
|
2006-02-27 14:43:10 +03:00
|
|
|
bmppos[i] = maskval > 0 ? (cursorval != 0 ? black : white)
|
|
|
|
: 0x00000000;
|
2003-01-13 01:51:01 +03:00
|
|
|
}
|
|
|
|
}
|
2006-02-27 14:43:10 +03:00
|
|
|
|
|
|
|
// remember cursor data for later
|
|
|
|
fCursorData = new (nothrow) uint8[68];
|
|
|
|
if (fCursorData)
|
|
|
|
memcpy(fCursorData, data, 68);
|
|
|
|
|
2005-04-14 04:04:26 +04:00
|
|
|
} else {
|
|
|
|
fWidth = 0;
|
|
|
|
fHeight = 0;
|
|
|
|
fBytesPerRow = 0;
|
|
|
|
fSpace = B_NO_COLOR_SPACE;
|
2003-01-13 01:51:01 +03:00
|
|
|
}
|
2005-04-14 04:04:26 +04:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2005-04-14 04:04:26 +04:00
|
|
|
/*!
|
|
|
|
\brief Constructor
|
2006-02-27 14:43:10 +03:00
|
|
|
\param data Pointer to bitmap data in memory,
|
|
|
|
the padding bytes should be contained when format less than 32 bpp.
|
2005-04-14 04:04:26 +04:00
|
|
|
*/
|
|
|
|
ServerCursor::ServerCursor(const uint8* alreadyPaddedData,
|
|
|
|
uint32 width, uint32 height,
|
|
|
|
color_space format)
|
|
|
|
: ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
|
|
|
|
fHotSpot(0, 0),
|
2006-02-05 22:43:44 +03:00
|
|
|
fOwningTeam(-1),
|
2006-02-26 21:15:31 +03:00
|
|
|
fReferenceCount(1),
|
|
|
|
fCursorData(NULL),
|
|
|
|
fManager(NULL),
|
|
|
|
fPendingViewCursor(0)
|
2005-04-14 04:04:26 +04:00
|
|
|
{
|
|
|
|
_AllocateBuffer();
|
|
|
|
if (Bits())
|
|
|
|
memcpy(Bits(), alreadyPaddedData, BitsLength());
|
2003-01-13 01:51:01 +03:00
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-01-18 23:32:45 +03:00
|
|
|
/*!
|
|
|
|
\brief Copy constructor
|
2003-01-20 02:04:58 +03:00
|
|
|
\param cursor cursor to copy
|
2003-01-18 23:32:45 +03:00
|
|
|
*/
|
2005-04-14 04:04:26 +04:00
|
|
|
ServerCursor::ServerCursor(const ServerCursor* cursor)
|
|
|
|
: ServerBitmap(cursor),
|
|
|
|
fHotSpot(0, 0),
|
2006-02-05 22:43:44 +03:00
|
|
|
fOwningTeam(-1),
|
2006-02-26 21:15:31 +03:00
|
|
|
fReferenceCount(1),
|
|
|
|
fCursorData(NULL),
|
|
|
|
fManager(NULL),
|
|
|
|
fPendingViewCursor(0)
|
2003-01-13 01:51:01 +03:00
|
|
|
{
|
2005-04-14 04:04:26 +04:00
|
|
|
// TODO: Hm. I don't move this into the if clause,
|
|
|
|
// because it might break code elsewhere.
|
2003-01-13 01:51:01 +03:00
|
|
|
_AllocateBuffer();
|
|
|
|
|
2005-04-14 04:04:26 +04:00
|
|
|
if (cursor) {
|
|
|
|
fInitialized = true;
|
|
|
|
if (Bits() && cursor->Bits())
|
|
|
|
memcpy(Bits(), cursor->Bits(), BitsLength());
|
|
|
|
fHotSpot = cursor->fHotSpot;
|
2006-02-26 21:15:31 +03:00
|
|
|
if (cursor->fCursorData) {
|
|
|
|
fCursorData = new (nothrow) uint8[68];
|
|
|
|
if (fCursorData)
|
|
|
|
memcpy(fCursorData, cursor->fCursorData, 68);
|
|
|
|
}
|
2003-01-13 01:51:01 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-01-18 23:32:45 +03:00
|
|
|
//! Frees the heap space allocated for the cursor's image data
|
2005-04-14 04:04:26 +04:00
|
|
|
ServerCursor::~ServerCursor()
|
2003-01-13 01:51:01 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-02-05 21:14:14 +03:00
|
|
|
|
2003-01-18 23:32:45 +03:00
|
|
|
/*!
|
|
|
|
\brief Sets the cursor's hotspot
|
2003-01-20 02:04:58 +03:00
|
|
|
\param pt New location of hotspot, constrained to the cursor's boundaries.
|
2003-01-18 23:32:45 +03:00
|
|
|
*/
|
2005-04-14 04:04:26 +04:00
|
|
|
void
|
2006-02-05 22:43:44 +03:00
|
|
|
ServerCursor::SetHotSpot(BPoint hotSpot)
|
2003-01-13 01:51:01 +03:00
|
|
|
{
|
2006-02-05 22:43:44 +03:00
|
|
|
fHotSpot = hotSpot;
|
2004-09-21 02:50:02 +04:00
|
|
|
fHotSpot.ConstrainTo(Bounds());
|
2003-01-13 01:51:01 +03:00
|
|
|
}
|
2003-02-24 18:47:06 +03:00
|
|
|
|
2006-02-26 21:15:31 +03:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|