2 * Copyright 2005, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
10 #include "EventStream.h"
12 #include <InputServerTypes.h>
13 #include <ServerProtocol.h>
14 #include <shared_cursor_area.h>
23 EventStream::EventStream()
28 EventStream::~EventStream()
34 EventStream::SupportsCursorThread() const
41 EventStream::GetNextCursorPosition(BPoint
& where
, bigtime_t timeout
)
50 InputServerStream::InputServerStream(BMessenger
& messenger
)
52 fInputServer(messenger
),
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
);
66 if (messenger
.SendMessage(&message
, &reply
) != B_OK
)
69 if (reply
.FindInt32("event port", &fPort
) != B_OK
)
71 if (reply
.FindInt32("cursor semaphore", &fCursorSemaphore
) != B_OK
)
72 fCursorSemaphore
= -1;
77 InputServerStream::InputServerStream()
81 fLatestMouseMoved(NULL
)
83 fPort
= find_port(SERVER_INPUT_PORT
);
88 InputServerStream::~InputServerStream()
90 delete_area(fCursorArea
);
95 InputServerStream::IsValid()
98 if (fPort
< B_OK
|| get_port_info(fPort
, &portInfo
) != B_OK
)
106 InputServerStream::SendQuit()
109 write_port(fPort
, 'quit', NULL
, 0);
110 release_sem(fCursorSemaphore
);
115 InputServerStream::UpdateScreenBounds(BRect bounds
)
117 BMessage
update(IS_SCREEN_BOUNDS_UPDATED
);
118 update
.AddRect("screen_bounds", bounds
);
120 fInputServer
.SendMessage(&update
);
125 InputServerStream::GetNextEvent(BMessage
** _event
)
127 while (fEvents
.IsEmpty()) {
128 // wait for new events
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
142 int32 count
= port_count(fPort
);
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();
163 InputServerStream::GetNextCursorPosition(BPoint
&where
, bigtime_t timeout
)
168 status
= acquire_sem_etc(fCursorSemaphore
, 1, B_RELATIVE_TIMEOUT
,
170 } while (status
== B_INTERRUPTED
);
172 if (status
== B_TIMED_OUT
)
175 if (status
== B_BAD_SEM_ID
) {
176 // the semaphore is no longer valid - the input_server must have died
177 fCursorSemaphore
= -1;
181 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
182 uint32 pos
= atomic_get((int32
*)&fCursorBuffer
->pos
);
184 uint32 pos
= fCursorBuffer
->pos
;
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
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
)
212 // If the port is full, we obviously don't care to report this, as we
213 // already placed our message.
219 InputServerStream::PeekLatestMouseMoved()
221 return fLatestMouseMoved
;
226 InputServerStream::_MessageFromPort(BMessage
** _message
, bigtime_t timeout
)
228 uint8
*buffer
= NULL
;
231 // read message from port
234 bufferSize
= port_buffer_size_etc(fPort
, B_RELATIVE_TIMEOUT
, timeout
);
235 } while (bufferSize
== B_INTERRUPTED
);
237 if (bufferSize
< B_OK
)
240 if (bufferSize
> 0) {
241 buffer
= new (std::nothrow
) uint8
[bufferSize
];
247 bufferSize
= read_port_etc(fPort
, &code
, buffer
, bufferSize
,
248 B_RELATIVE_TIMEOUT
, 0);
249 if (bufferSize
< B_OK
) {
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
);
269 if (buffer
== NULL
) {
274 status_t status
= message
->Unflatten((const char*)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
);