xref: /haiku/src/kits/app/Cursor.cpp (revision b5efad4eae1a0754ce3e4eb87458279e81f61f61)
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 	int32 size = bitmap->BitsLength();
100 	BRect bounds = bitmap->Bounds();
101 	color_space colorspace = bitmap->ColorSpace();
102 	void* bits = bitmap->Bits();
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<int32>(size);
110 	link.Attach<BRect>(bounds);
111 	link.Attach<color_space>(colorspace);
112 	link.Attach<BPoint>(hotspot);
113 	link.Attach(bits, size);
114 
115 	status_t status;
116 	if (link.FlushWithReply(status) == B_OK) {
117 		if (status == B_OK) {
118 			link.Read<int32>(&fServerToken);
119 			fNeedToFree = true;
120 		} else
121 			fServerToken = status;
122 	}
123 }
124 
125 
126 BCursor::~BCursor()
127 {
128 	_FreeCursorData();
129 }
130 
131 
132 status_t
133 BCursor::InitCheck() const
134 {
135 	return fServerToken >= 0 ? B_OK : fServerToken;
136 }
137 
138 
139 status_t
140 BCursor::Archive(BMessage *into, bool deep) const
141 {
142 	// not implemented on BeOS
143 	return B_OK;
144 }
145 
146 
147 BArchivable	*
148 BCursor::Instantiate(BMessage *data)
149 {
150 	// not implemented on BeOS
151 	return NULL;
152 }
153 
154 
155 BCursor&
156 BCursor::operator=(const BCursor& other)
157 {
158 	if (&other != this && other != *this) {
159 		_FreeCursorData();
160 
161 		fServerToken = other.fServerToken;
162 		fNeedToFree = other.fNeedToFree;
163 
164 		if (fNeedToFree) {
165 			// Tell app_server that there is another reference for this
166 			// cursor data!
167 			BPrivate::AppServerLink link;
168 			link.StartMessage(AS_REFERENCE_CURSOR);
169 			link.Attach<int32>(fServerToken);
170 		}
171 	}
172 	return *this;
173 }
174 
175 
176 bool
177 BCursor::operator==(const BCursor& other) const
178 {
179 	return fServerToken == other.fServerToken;
180 }
181 
182 
183 bool
184 BCursor::operator!=(const BCursor& other) const
185 {
186 	return fServerToken != other.fServerToken;
187 }
188 
189 
190 status_t
191 BCursor::Perform(perform_code d, void *arg)
192 {
193 	return B_OK;
194 }
195 
196 
197 void BCursor::_ReservedCursor1() {}
198 void BCursor::_ReservedCursor2() {}
199 void BCursor::_ReservedCursor3() {}
200 void BCursor::_ReservedCursor4() {}
201 
202 
203 void
204 BCursor::_FreeCursorData()
205 {
206 	// Notify server to deallocate server-side objects for this cursor
207 	if (fNeedToFree) {
208 		BPrivate::AppServerLink link;
209 		link.StartMessage(AS_DELETE_CURSOR);
210 		link.Attach<int32>(fServerToken);
211 		link.Flush();
212 	}
213 }
214 
215