xref: /haiku/src/servers/app/drawing/interface/remote/RemoteEventStream.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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