usb_ecm: Use the current configuration instead of a fixed one.
[haiku.git] / src / servers / app / EventStream.cpp
blob964326231978cee59a111a4d22b6a278eb9ebcc3
1 /*
2 * Copyright 2005, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
10 #include "EventStream.h"
12 #include <InputServerTypes.h>
13 #include <ServerProtocol.h>
14 #include <shared_cursor_area.h>
16 #include <AppMisc.h>
18 #include <new>
19 #include <stdio.h>
20 #include <string.h>
23 EventStream::EventStream()
28 EventStream::~EventStream()
33 bool
34 EventStream::SupportsCursorThread() const
36 return false;
40 status_t
41 EventStream::GetNextCursorPosition(BPoint& where, bigtime_t timeout)
43 return B_ERROR;
47 // #pragma mark -
50 InputServerStream::InputServerStream(BMessenger& messenger)
52 fInputServer(messenger),
53 fPort(-1),
54 fQuitting(false),
55 fLatestMouseMoved(NULL)
57 BMessage message(IS_ACQUIRE_INPUT);
58 message.AddInt32("remote team", BPrivate::current_team());
60 fCursorArea = create_area("shared cursor", (void **)&fCursorBuffer, B_ANY_ADDRESS,
61 B_PAGE_SIZE, B_LAZY_LOCK, B_READ_AREA | B_WRITE_AREA);
62 if (fCursorArea >= B_OK)
63 message.AddInt32("cursor area", fCursorArea);
65 BMessage reply;
66 if (messenger.SendMessage(&message, &reply) != B_OK)
67 return;
69 if (reply.FindInt32("event port", &fPort) != B_OK)
70 fPort = -1;
71 if (reply.FindInt32("cursor semaphore", &fCursorSemaphore) != B_OK)
72 fCursorSemaphore = -1;
76 #if TEST_MODE
77 InputServerStream::InputServerStream()
79 fQuitting(false),
80 fCursorSemaphore(-1),
81 fLatestMouseMoved(NULL)
83 fPort = find_port(SERVER_INPUT_PORT);
85 #endif
88 InputServerStream::~InputServerStream()
90 delete_area(fCursorArea);
94 bool
95 InputServerStream::IsValid()
97 port_info portInfo;
98 if (fPort < B_OK || get_port_info(fPort, &portInfo) != B_OK)
99 return false;
101 return true;
105 void
106 InputServerStream::SendQuit()
108 fQuitting = true;
109 write_port(fPort, 'quit', NULL, 0);
110 release_sem(fCursorSemaphore);
114 void
115 InputServerStream::UpdateScreenBounds(BRect bounds)
117 BMessage update(IS_SCREEN_BOUNDS_UPDATED);
118 update.AddRect("screen_bounds", bounds);
120 fInputServer.SendMessage(&update);
124 bool
125 InputServerStream::GetNextEvent(BMessage** _event)
127 while (fEvents.IsEmpty()) {
128 // wait for new events
129 BMessage* event;
130 status_t status = _MessageFromPort(&event);
131 if (status == B_OK) {
132 if (event->what == B_MOUSE_MOVED)
133 fLatestMouseMoved = event;
135 fEvents.AddMessage(event);
136 } else if (status == B_BAD_PORT_ID) {
137 // our port got deleted - the input_server must have died
138 fPort = -1;
139 return false;
142 int32 count = port_count(fPort);
143 if (count > 0) {
144 // empty port queue completely while we're at it
145 for (int32 i = 0; i < count; i++) {
146 if (_MessageFromPort(&event, 0) == B_OK) {
147 if (event->what == B_MOUSE_MOVED)
148 fLatestMouseMoved = event;
149 fEvents.AddMessage(event);
155 // there are items in our list, so just work through them
157 *_event = fEvents.NextMessage();
158 return true;
162 status_t
163 InputServerStream::GetNextCursorPosition(BPoint &where, bigtime_t timeout)
165 status_t status;
167 do {
168 status = acquire_sem_etc(fCursorSemaphore, 1, B_RELATIVE_TIMEOUT,
169 timeout);
170 } while (status == B_INTERRUPTED);
172 if (status == B_TIMED_OUT)
173 return status;
175 if (status == B_BAD_SEM_ID) {
176 // the semaphore is no longer valid - the input_server must have died
177 fCursorSemaphore = -1;
178 return B_ERROR;
181 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
182 uint32 pos = atomic_get((int32*)&fCursorBuffer->pos);
183 #else
184 uint32 pos = fCursorBuffer->pos;
185 #endif
187 where.x = pos >> 16UL;
188 where.y = pos & 0xffff;
190 atomic_and(&fCursorBuffer->read, 0);
191 // this tells the input_server that we've read the
192 // cursor position and want to be notified if updated
194 if (fQuitting) {
195 fQuitting = false;
196 return B_ERROR;
199 return B_OK;
203 status_t
204 InputServerStream::InsertEvent(BMessage* event)
206 fEvents.AddMessage(event);
207 status_t status = write_port_etc(fPort, 'insm', NULL, 0, B_RELATIVE_TIMEOUT,
209 if (status == B_BAD_PORT_ID)
210 return status;
212 // If the port is full, we obviously don't care to report this, as we
213 // already placed our message.
214 return B_OK;
218 BMessage*
219 InputServerStream::PeekLatestMouseMoved()
221 return fLatestMouseMoved;
225 status_t
226 InputServerStream::_MessageFromPort(BMessage** _message, bigtime_t timeout)
228 uint8 *buffer = NULL;
229 ssize_t bufferSize;
231 // read message from port
233 do {
234 bufferSize = port_buffer_size_etc(fPort, B_RELATIVE_TIMEOUT, timeout);
235 } while (bufferSize == B_INTERRUPTED);
237 if (bufferSize < B_OK)
238 return bufferSize;
240 if (bufferSize > 0) {
241 buffer = new (std::nothrow) uint8[bufferSize];
242 if (buffer == NULL)
243 return B_NO_MEMORY;
246 int32 code;
247 bufferSize = read_port_etc(fPort, &code, buffer, bufferSize,
248 B_RELATIVE_TIMEOUT, 0);
249 if (bufferSize < B_OK) {
250 delete[] buffer;
251 return bufferSize;
254 if (code == 'quit') {
255 // this will cause GetNextEvent() to return false
256 return B_BAD_PORT_ID;
258 if (code == 'insm') {
259 // a message has been inserted into our queue
260 return B_INTERRUPTED;
263 // we have the message, now let's unflatten it
265 BMessage* message = new BMessage(code);
266 if (message == NULL)
267 return B_NO_MEMORY;
269 if (buffer == NULL) {
270 *_message = message;
271 return B_OK;
274 status_t status = message->Unflatten((const char*)buffer);
275 delete[] buffer;
277 if (status != B_OK) {
278 printf("Unflatten event failed: %s, port message code was: %" B_PRId32
279 " - %c%c%c%c\n", strerror(status), code, (int8)(code >> 24),
280 (int8)(code >> 16), (int8)(code >> 8), (int8)code);
281 delete message;
282 return status;
285 *_message = message;
286 return B_OK;