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