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