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