xref: /haiku/src/servers/app/ServerCursor.cpp (revision ba499cdc3336fb89429027418871bf263f1f5e14)
1 /*
2  * Copyright 2001-2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Stephan Aßmus <superstippi@gmx.de>
8  *		Axel Dörfler, axeld@pinc-software.de
9  */
10 
11 /*!
12 	Although descended from ServerBitmaps, ServerCursors are not handled by
13 	the BitmapManager - they are allocated like any other object. Unlike BeOS
14 	R5, cursors can be any size or color space, and this class accomodates and
15 	expands the R5 API.
16 */
17 
18 #include "CursorManager.h"
19 #include "ServerCursor.h"
20 
21 #include <ByteOrder.h>
22 
23 #include <new>
24 #include <stdio.h>
25 
26 
27 using std::nothrow;
28 
29 /*!
30 	\brief Constructor
31 	\param r Size of the cursor
32 	\param cspace Color space of the cursor
33 	\param flags ServerBitmap flags. See Bitmap.h.
34 	\param hotspot Hotspot of the cursor
35 	\param bytesperline Bytes per row for the cursor. See ServerBitmap::ServerBitmap()
36 
37 */
38 ServerCursor::ServerCursor(BRect r, color_space format,
39 						   int32 flags, BPoint hotspot,
40 						   int32 bytesPerRow,
41 						   screen_id screen)
42 	: ServerBitmap(r, format, flags, bytesPerRow, screen),
43 	  fHotSpot(hotspot),
44 	  fOwningTeam(-1),
45 	  fReferenceCount(1),
46 	  fCursorData(NULL),
47 	  fManager(NULL),
48 	  fPendingViewCursor(0)
49 {
50 	fHotSpot.ConstrainTo(Bounds());
51 	_AllocateBuffer();
52 }
53 
54 
55 /*!
56 	\brief Constructor
57 	\param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details
58 */
59 ServerCursor::ServerCursor(const uint8* data)
60 	: ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
61 	  fHotSpot(0, 0),
62 	  fOwningTeam(-1),
63 	  fReferenceCount(1),
64 	  fCursorData(NULL),
65 	  fManager(NULL),
66 	  fPendingViewCursor(0)
67 {
68 	// 68-byte array used in R5 for holding cursors.
69 	// This API has serious problems and should be deprecated(but supported) in R2
70 
71 	// Now that we have all the setup, we're going to map (for now) the cursor
72 	// to RGBA32 (little endian). Eventually, there will be support for 16 and
73 	// 8-bit depths
74 	// NOTE: review this once we have working PPC graphics cards (big endian).
75 	if (data) {
76 		_AllocateBuffer();
77 		uint8* buffer = Bits();
78 		if (!buffer)
79 			return;
80 
81 		uint16* cursorBits = (uint16*)(data + 4);
82 		uint16* transparencyBits = (uint16*)(data + 36);
83 		fHotSpot.Set(data[3], data[2]);
84 
85 		// for each row in the cursor data
86 		for (int32 j = 0; j < 16; j++) {
87 			uint32* bits = (uint32*)(buffer + (j * BytesPerRow()));
88 
89 			// On intel, our bytes end up swapped, so we must swap them back
90 			uint16 cursorLine = __swap_int16(cursorBits[j]);
91 			uint16 transparencyLine = __swap_int16(transparencyBits[j]);
92 
93 			uint16 mask = 1 << 15;
94 
95 			// for each column in each row of cursor data
96 			for (int32 i = 0; i < 16; i++, mask >>= 1) {
97 				// Get the values and dump them to the bitmap
98 				if (cursorLine & mask)
99 					bits[i] = 0xff000000; // black
100 				else if (transparencyLine & mask)
101 					bits[i] = 0xffffffff; // white
102 				else
103 					bits[i] = 0x00000000; // transparent
104 			}
105 		}
106 
107 		// remember cursor data for later
108 		fCursorData = new (nothrow) uint8[68];
109 		if (fCursorData)
110 			memcpy(fCursorData, data, 68);
111 
112 	} else {
113 		fWidth = 0;
114 		fHeight = 0;
115 		fBytesPerRow = 0;
116 		fSpace = B_NO_COLOR_SPACE;
117 	}
118 }
119 
120 
121 /*!
122 	\brief Constructor
123 	\param data Pointer to bitmap data in memory,
124 	the padding bytes should be contained when format less than 32 bpp.
125 */
126 ServerCursor::ServerCursor(const uint8* alreadyPaddedData,
127 						   uint32 width, uint32 height,
128 						   color_space format)
129 	: ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
130 	  fHotSpot(0, 0),
131 	  fOwningTeam(-1),
132 	  fReferenceCount(1),
133 	  fCursorData(NULL),
134 	  fManager(NULL),
135 	  fPendingViewCursor(0)
136 {
137 	_AllocateBuffer();
138 	if (Bits())
139 		memcpy(Bits(), alreadyPaddedData, BitsLength());
140 }
141 
142 
143 /*!
144 	\brief Copy constructor
145 	\param cursor cursor to copy
146 */
147 ServerCursor::ServerCursor(const ServerCursor* cursor)
148 	: ServerBitmap(cursor),
149 	  fHotSpot(0, 0),
150 	  fOwningTeam(-1),
151 	  fReferenceCount(1),
152 	  fCursorData(NULL),
153 	  fManager(NULL),
154 	  fPendingViewCursor(0)
155 {
156 	// TODO: Hm. I don't move this into the if clause,
157 	// because it might break code elsewhere.
158 	_AllocateBuffer();
159 
160 	if (cursor) {
161 		if (Bits() && cursor->Bits())
162 			memcpy(Bits(), cursor->Bits(), BitsLength());
163 		fHotSpot = cursor->fHotSpot;
164 		if (cursor->fCursorData) {
165 			fCursorData = new (nothrow) uint8[68];
166 			if (fCursorData)
167 				memcpy(fCursorData, cursor->fCursorData, 68);
168 		}
169 	}
170 }
171 
172 
173 //!	Frees the heap space allocated for the cursor's image data
174 ServerCursor::~ServerCursor()
175 {
176 }
177 
178 
179 /*!
180 	\brief Sets the cursor's hotspot
181 	\param pt New location of hotspot, constrained to the cursor's boundaries.
182 */
183 void
184 ServerCursor::SetHotSpot(BPoint hotSpot)
185 {
186 	fHotSpot = hotSpot;
187 	fHotSpot.ConstrainTo(Bounds());
188 }
189 
190 
191 bool
192 ServerCursor::Release()
193 {
194 	if (atomic_add(&fReferenceCount, -1) == 1) {
195 		if (fPendingViewCursor > 0) {
196 			// There is a SetViewCursor() waiting to be carried out
197 			return false;
198 		}
199 
200 		if (fManager && !fManager->RemoveCursor(this))
201 			return false;
202 
203 		delete this;
204 		return true;
205 	}
206 	return false;
207 }
208 
209 
210 void
211 ServerCursor::SetPendingViewCursor(bool pending)
212 {
213 	atomic_add(&fPendingViewCursor, pending ? 1 : -1);
214 }
215 
216 
217 void
218 ServerCursor::AttachedToManager(CursorManager* manager)
219 {
220 	fManager = manager;
221 }
222 
223