xref: /haiku/src/kits/app/Cursor.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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 
27 const BCursor *B_CURSOR_SYSTEM_DEFAULT;
28 const BCursor *B_CURSOR_I_BEAM;
29 	// these are initialized in BApplication::InitData()
30 
31 BCursor::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 
66 BCursor::BCursor(BCursorID id)
67 	:
68 	fServerToken(id),
69 	fNeedToFree(false)
70 {
71 }
72 
73 
74 BCursor::BCursor(const BCursor& other)
75 	:
76 	fServerToken(-1),
77 	fNeedToFree(false)
78 {
79 	*this = other;
80 }
81 
82 
83 BCursor::BCursor(BMessage *data)
84 {
85 	// undefined on BeOS
86 	fServerToken = -1;
87 	fNeedToFree = false;
88 }
89 
90 
91 BCursor::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 
127 BCursor::~BCursor()
128 {
129 	_FreeCursorData();
130 }
131 
132 
133 status_t
134 BCursor::InitCheck() const
135 {
136 	return fServerToken >= 0 ? B_OK : fServerToken;
137 }
138 
139 
140 status_t
141 BCursor::Archive(BMessage *into, bool deep) const
142 {
143 	// not implemented on BeOS
144 	return B_OK;
145 }
146 
147 
148 BArchivable	*
149 BCursor::Instantiate(BMessage *data)
150 {
151 	// not implemented on BeOS
152 	return NULL;
153 }
154 
155 
156 BCursor&
157 BCursor::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 
177 bool
178 BCursor::operator==(const BCursor& other) const
179 {
180 	return fServerToken == other.fServerToken;
181 }
182 
183 
184 bool
185 BCursor::operator!=(const BCursor& other) const
186 {
187 	return fServerToken != other.fServerToken;
188 }
189 
190 
191 status_t
192 BCursor::Perform(perform_code d, void *arg)
193 {
194 	return B_OK;
195 }
196 
197 
198 void BCursor::_ReservedCursor1() {}
199 void BCursor::_ReservedCursor2() {}
200 void BCursor::_ReservedCursor3() {}
201 void BCursor::_ReservedCursor4() {}
202 
203 
204 void
205 BCursor::_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