1 /* 2 * Copyright 2009, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include "RemoteEventStream.h" 10 11 #include "RemoteMessage.h" 12 #include "StreamingRingBuffer.h" 13 14 #include <Autolock.h> 15 16 #include <new> 17 18 19 RemoteEventStream::RemoteEventStream() 20 : 21 fEventList(10, true), 22 fEventListLocker("remote event list"), 23 fEventNotification(-1), 24 fWaitingOnEvent(false), 25 fLatestMouseMovedEvent(NULL), 26 fMousePosition(0, 0), 27 fMouseButtons(0), 28 fModifiers(0) 29 { 30 fEventNotification = create_sem(0, "remote event notification"); 31 } 32 33 34 RemoteEventStream::~RemoteEventStream() 35 { 36 delete_sem(fEventNotification); 37 } 38 39 40 void 41 RemoteEventStream::UpdateScreenBounds(BRect bounds) 42 { 43 } 44 45 46 bool 47 RemoteEventStream::GetNextEvent(BMessage** _event) 48 { 49 BAutolock lock(fEventListLocker); 50 while (fEventList.CountItems() == 0) { 51 fWaitingOnEvent = true; 52 lock.Unlock(); 53 54 status_t result; 55 do { 56 result = acquire_sem(fEventNotification); 57 } while (result == B_INTERRUPTED); 58 59 lock.Lock(); 60 if (!lock.IsLocked()) 61 return false; 62 } 63 64 *_event = fEventList.RemoveItemAt(0); 65 return true; 66 } 67 68 69 status_t 70 RemoteEventStream::InsertEvent(BMessage* event) 71 { 72 BAutolock lock(fEventListLocker); 73 if (!lock.IsLocked()) 74 return B_ERROR; 75 76 if (!fEventList.AddItem(event)) 77 return B_ERROR; 78 79 if (event->what == B_MOUSE_MOVED) 80 fLatestMouseMovedEvent = event; 81 82 return B_OK; 83 } 84 85 86 BMessage* 87 RemoteEventStream::PeekLatestMouseMoved() 88 { 89 return fLatestMouseMovedEvent; 90 } 91 92 93 bool 94 RemoteEventStream::EventReceived(RemoteMessage& message) 95 { 96 uint16 code = message.Code(); 97 uint32 what = 0; 98 switch (code) { 99 case RP_MOUSE_MOVED: 100 what = B_MOUSE_MOVED; 101 break; 102 case RP_MOUSE_DOWN: 103 what = B_MOUSE_DOWN; 104 break; 105 case RP_MOUSE_UP: 106 what = B_MOUSE_UP; 107 break; 108 case RP_MOUSE_WHEEL_CHANGED: 109 what = B_MOUSE_WHEEL_CHANGED; 110 break; 111 case RP_KEY_DOWN: 112 what = B_KEY_DOWN; 113 break; 114 case RP_KEY_UP: 115 what = B_KEY_UP; 116 break; 117 case RP_MODIFIERS_CHANGED: 118 what = B_MODIFIERS_CHANGED; 119 break; 120 } 121 122 if (what == 0) 123 return false; 124 125 BMessage* event = new BMessage(what); 126 if (event == NULL) 127 return false; 128 129 event->AddInt64("when", system_time()); 130 131 switch (code) { 132 case RP_MOUSE_MOVED: 133 case RP_MOUSE_DOWN: 134 case RP_MOUSE_UP: 135 { 136 message.Read(fMousePosition); 137 if (code != RP_MOUSE_MOVED) 138 message.Read(fMouseButtons); 139 140 event->AddPoint("where", fMousePosition); 141 event->AddInt32("buttons", fMouseButtons); 142 event->AddInt32("modifiers", fModifiers); 143 144 if (code == RP_MOUSE_DOWN) { 145 int32 clicks; 146 if (message.Read(clicks) == B_OK) 147 event->AddInt32("clicks", clicks); 148 } 149 150 if (code == RP_MOUSE_MOVED) 151 fLatestMouseMovedEvent = event; 152 break; 153 } 154 155 case RP_MOUSE_WHEEL_CHANGED: 156 { 157 float xDelta, yDelta; 158 message.Read(xDelta); 159 message.Read(yDelta); 160 event->AddFloat("be:wheel_delta_x", xDelta); 161 event->AddFloat("be:wheel_delta_y", yDelta); 162 break; 163 } 164 165 case RP_KEY_DOWN: 166 case RP_KEY_UP: 167 { 168 int32 numBytes; 169 if (message.Read(numBytes) != B_OK) 170 break; 171 172 if (numBytes > 1000) 173 break; 174 175 char* bytes = (char*)malloc(numBytes + 1); 176 if (bytes == NULL) 177 break; 178 179 if (message.ReadList(bytes, numBytes) != B_OK) { 180 free(bytes); 181 break; 182 } 183 184 for (int32 i = 0; i < numBytes; i++) 185 event->AddInt8("byte", (int8)bytes[i]); 186 187 bytes[numBytes] = 0; 188 event->AddData("bytes", B_STRING_TYPE, bytes, numBytes + 1, false); 189 event->AddInt32("modifiers", fModifiers); 190 191 int32 rawChar; 192 if (message.Read(rawChar) == B_OK) 193 event->AddInt32("raw_char", rawChar); 194 195 int32 key; 196 if (message.Read(key) == B_OK) 197 event->AddInt32("key", key); 198 199 free(bytes); 200 break; 201 } 202 203 case RP_MODIFIERS_CHANGED: 204 { 205 event->AddInt32("be:old_modifiers", fModifiers); 206 message.Read(fModifiers); 207 event->AddInt32("modifiers", fModifiers); 208 break; 209 } 210 } 211 212 BAutolock lock(fEventListLocker); 213 fEventList.AddItem(event); 214 if (fWaitingOnEvent) { 215 fWaitingOnEvent = false; 216 lock.Unlock(); 217 release_sem(fEventNotification); 218 } 219 220 return true; 221 } 222