1/*
2 * Copyright 2001-2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Frans van Nispen (xlr8@tref.nl)
7 *		Gabe Yoder (gyoder@stny.rr.com)
8 *		Axel D��rfler, axeld@pinc-software.de
9 */
10
11/**	BCursor describes a view-wide or application-wide cursor. */
12
13/**
14	@note:	As BeOS only supports 16x16 monochrome cursors, and I would like
15			to see a nice shadowes one, we will need to extend this one.
16 */
17
18
19#include <AppDefs.h>
20#include <Bitmap.h>
21#include <Cursor.h>
22
23#include <AppServerLink.h>
24#include <ServerProtocol.h>
25
26
27const BCursor *B_CURSOR_SYSTEM_DEFAULT;
28const BCursor *B_CURSOR_I_BEAM;
29	// these are initialized in BApplication::InitData()
30
31BCursor::BCursor(const void *cursorData)
32	:
33	fServerToken(-1),
34	fNeedToFree(false)
35{
36	const uint8 *data = (const uint8 *)cursorData;
37
38	if (data == B_HAND_CURSOR || data == B_I_BEAM_CURSOR) {
39		// just use the default cursors from the app_server
40		fServerToken = data == B_HAND_CURSOR ?
41			B_CURSOR_ID_SYSTEM_DEFAULT : B_CURSOR_ID_I_BEAM;
42		return;
43	}
44
45	// Create a new cursor in the app_server
46
47	if (data == NULL
48		|| data[0] != 16	// size
49		|| data[1] != 1		// depth
50		|| data[2] >= 16 || data[3] >= 16)	// hot-spot
51		return;
52
53	// Send data directly to server
54	BPrivate::AppServerLink link;
55	link.StartMessage(AS_CREATE_CURSOR);
56	link.Attach(cursorData, 68);
57
58	status_t status;
59	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
60		link.Read<int32>(&fServerToken);
61		fNeedToFree = true;
62	}
63}
64
65
66BCursor::BCursor(BCursorID id)
67	:
68	fServerToken(id),
69	fNeedToFree(false)
70{
71}
72
73
74BCursor::BCursor(const BCursor& other)
75	:
76	fServerToken(-1),
77	fNeedToFree(false)
78{
79	*this = other;
80}
81
82
83BCursor::BCursor(BMessage *data)
84{
85	// undefined on BeOS
86	fServerToken = -1;
87	fNeedToFree = false;
88}
89
90
91BCursor::BCursor(const BBitmap* bitmap, const BPoint& hotspot)
92	:
93	fServerToken(-1),
94	fNeedToFree(false)
95{
96	if (bitmap == NULL)
97		return;
98
99	BRect bounds = bitmap->Bounds();
100	color_space colorspace = bitmap->ColorSpace();
101	void* bits = bitmap->Bits();
102	int32 size = bitmap->BitsLength();
103	if (bits == NULL || size <= 0)
104		return;
105
106	// Send data directly to server
107	BPrivate::AppServerLink link;
108	link.StartMessage(AS_CREATE_CURSOR_BITMAP);
109	link.Attach<BRect>(bounds);
110	link.Attach<BPoint>(hotspot);
111	link.Attach<color_space>(colorspace);
112	link.Attach<int32>(bitmap->BytesPerRow());
113	link.Attach<int32>(size);
114	link.Attach(bits, size);
115
116	status_t status;
117	if (link.FlushWithReply(status) == B_OK) {
118		if (status == B_OK) {
119			link.Read<int32>(&fServerToken);
120			fNeedToFree = true;
121		} else
122			fServerToken = status;
123	}
124}
125
126
127BCursor::~BCursor()
128{
129	_FreeCursorData();
130}
131
132
133status_t
134BCursor::InitCheck() const
135{
136	return fServerToken >= 0 ? B_OK : fServerToken;
137}
138
139
140status_t
141BCursor::Archive(BMessage *into, bool deep) const
142{
143	// not implemented on BeOS
144	return B_OK;
145}
146
147
148BArchivable	*
149BCursor::Instantiate(BMessage *data)
150{
151	// not implemented on BeOS
152	return NULL;
153}
154
155
156BCursor&
157BCursor::operator=(const BCursor& other)
158{
159	if (&other != this && other != *this) {
160		_FreeCursorData();
161
162		fServerToken = other.fServerToken;
163		fNeedToFree = other.fNeedToFree;
164
165		if (fNeedToFree) {
166			// Tell app_server that there is another reference for this
167			// cursor data!
168			BPrivate::AppServerLink link;
169			link.StartMessage(AS_REFERENCE_CURSOR);
170			link.Attach<int32>(fServerToken);
171		}
172	}
173	return *this;
174}
175
176
177bool
178BCursor::operator==(const BCursor& other) const
179{
180	return fServerToken == other.fServerToken;
181}
182
183
184bool
185BCursor::operator!=(const BCursor& other) const
186{
187	return fServerToken != other.fServerToken;
188}
189
190
191status_t
192BCursor::Perform(perform_code d, void *arg)
193{
194	return B_OK;
195}
196
197
198void BCursor::_ReservedCursor1() {}
199void BCursor::_ReservedCursor2() {}
200void BCursor::_ReservedCursor3() {}
201void BCursor::_ReservedCursor4() {}
202
203
204void
205BCursor::_FreeCursorData()
206{
207	// Notify server to deallocate server-side objects for this cursor
208	if (fNeedToFree) {
209		BPrivate::AppServerLink link;
210		link.StartMessage(AS_DELETE_CURSOR);
211		link.Attach<int32>(fServerToken);
212		link.Flush();
213	}
214}
215
216