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
BCursor(const void * cursorData)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
BCursor(BCursorID id)61 BCursor::BCursor(BCursorID id)
62 :
63 fServerToken(id),
64 fNeedToFree(false)
65 {
66 }
67
68
BCursor(const BCursor & other)69 BCursor::BCursor(const BCursor& other)
70 :
71 fServerToken(-1),
72 fNeedToFree(false)
73 {
74 *this = other;
75 }
76
77
BCursor(BMessage * data)78 BCursor::BCursor(BMessage *data)
79 {
80 // undefined on BeOS
81 fServerToken = -1;
82 fNeedToFree = false;
83 }
84
85
BCursor(const BBitmap * bitmap,const BPoint & hotspot)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
~BCursor()122 BCursor::~BCursor()
123 {
124 _FreeCursorData();
125 }
126
127
128 status_t
InitCheck() const129 BCursor::InitCheck() const
130 {
131 return fServerToken >= 0 ? B_OK : fServerToken;
132 }
133
134
135 status_t
Archive(BMessage * into,bool deep) const136 BCursor::Archive(BMessage *into, bool deep) const
137 {
138 // not implemented on BeOS
139 return B_OK;
140 }
141
142
143 BArchivable *
Instantiate(BMessage * data)144 BCursor::Instantiate(BMessage *data)
145 {
146 // not implemented on BeOS
147 return NULL;
148 }
149
150
151 BCursor&
operator =(const BCursor & other)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
operator ==(const BCursor & other) const179 BCursor::operator==(const BCursor& other) const
180 {
181 return fServerToken == other.fServerToken;
182 }
183
184
185 bool
operator !=(const BCursor & other) const186 BCursor::operator!=(const BCursor& other) const
187 {
188 return fServerToken != other.fServerToken;
189 }
190
191
192 status_t
Perform(perform_code d,void * arg)193 BCursor::Perform(perform_code d, void *arg)
194 {
195 return B_OK;
196 }
197
198
_ReservedCursor1()199 void BCursor::_ReservedCursor1() {}
_ReservedCursor2()200 void BCursor::_ReservedCursor2() {}
_ReservedCursor3()201 void BCursor::_ReservedCursor3() {}
_ReservedCursor4()202 void BCursor::_ReservedCursor4() {}
203
204
205 void
_FreeCursorData()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