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 char* bytes = (char*)malloc(numBytes + 1); 173 if (bytes == NULL) 174 break; 175 176 if (message.ReadList(bytes, numBytes) != B_OK) { 177 free(bytes); 178 break; 179 } 180 181 for (int32 i = 0; i < numBytes; i++) 182 event->AddInt8("byte", (int8)bytes[i]); 183 184 bytes[numBytes] = 0; 185 event->AddData("bytes", B_STRING_TYPE, bytes, numBytes + 1, false); 186 event->AddInt32("modifiers", fModifiers); 187 188 int32 rawChar; 189 if (message.Read(rawChar) == B_OK) 190 event->AddInt32("raw_char", rawChar); 191 192 int32 key; 193 if (message.Read(key) == B_OK) 194 event->AddInt32("key", key); 195 196 free(bytes); 197 break; 198 } 199 200 case RP_MODIFIERS_CHANGED: 201 { 202 event->AddInt32("be:old_modifiers", fModifiers); 203 message.Read(fModifiers); 204 event->AddInt32("modifiers", fModifiers); 205 break; 206 } 207 } 208 209 BAutolock lock(fEventListLocker); 210 fEventList.AddItem(event); 211 if (fWaitingOnEvent) { 212 fWaitingOnEvent = false; 213 lock.Unlock(); 214 release_sem(fEventNotification); 215 } 216 217 return true; 218 } 219