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