* Copyright 2009, Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "RemoteEventStream.h"
#include "RemoteMessage.h"
#include "StreamingRingBuffer.h"
#include <Autolock.h>
#include <new>
RemoteEventStream::RemoteEventStream()
:
fEventList(10),
fEventListLocker("remote event list"),
fEventNotification(-1),
fWaitingOnEvent(false),
fLatestMouseMovedEvent(NULL),
fMousePosition(0, 0),
fMouseButtons(0),
fModifiers(0)
{
fEventNotification = create_sem(0, "remote event notification");
}
RemoteEventStream::~RemoteEventStream()
{
delete_sem(fEventNotification);
}
void
RemoteEventStream::UpdateScreenBounds(BRect bounds)
{
}
bool
RemoteEventStream::GetNextEvent(BMessage** _event)
{
BAutolock lock(fEventListLocker);
while (fEventList.CountItems() == 0) {
fWaitingOnEvent = true;
lock.Unlock();
status_t result;
do {
result = acquire_sem(fEventNotification);
} while (result == B_INTERRUPTED);
lock.Lock();
if (!lock.IsLocked())
return false;
}
*_event = fEventList.RemoveItemAt(0);
return true;
}
status_t
RemoteEventStream::InsertEvent(BMessage* event)
{
BAutolock lock(fEventListLocker);
if (!lock.IsLocked())
return B_ERROR;
if (!fEventList.AddItem(event))
return B_ERROR;
if (event->what == B_MOUSE_MOVED)
fLatestMouseMovedEvent = event;
return B_OK;
}
BMessage*
RemoteEventStream::PeekLatestMouseMoved()
{
return fLatestMouseMovedEvent;
}
bool
RemoteEventStream::EventReceived(RemoteMessage& message)
{
uint16 code = message.Code();
uint32 what = 0;
switch (code) {
case RP_MOUSE_MOVED:
what = B_MOUSE_MOVED;
break;
case RP_MOUSE_DOWN:
what = B_MOUSE_DOWN;
break;
case RP_MOUSE_UP:
what = B_MOUSE_UP;
break;
case RP_MOUSE_WHEEL_CHANGED:
what = B_MOUSE_WHEEL_CHANGED;
break;
case RP_KEY_DOWN:
what = B_KEY_DOWN;
break;
case RP_KEY_UP:
what = B_KEY_UP;
break;
case RP_MODIFIERS_CHANGED:
what = B_MODIFIERS_CHANGED;
break;
}
if (what == 0)
return false;
BMessage* event = new BMessage(what);
if (event == NULL)
return false;
event->AddInt64("when", system_time());
switch (code) {
case RP_MOUSE_MOVED:
case RP_MOUSE_DOWN:
case RP_MOUSE_UP:
{
message.Read(fMousePosition);
if (code != RP_MOUSE_MOVED)
message.Read(fMouseButtons);
event->AddPoint("where", fMousePosition);
event->AddInt32("buttons", fMouseButtons);
event->AddInt32("modifiers", fModifiers);
if (code == RP_MOUSE_DOWN) {
int32 clicks;
if (message.Read(clicks) == B_OK)
event->AddInt32("clicks", clicks);
}
if (code == RP_MOUSE_MOVED)
fLatestMouseMovedEvent = event;
break;
}
case RP_MOUSE_WHEEL_CHANGED:
{
float xDelta, yDelta;
message.Read(xDelta);
message.Read(yDelta);
event->AddFloat("be:wheel_delta_x", xDelta);
event->AddFloat("be:wheel_delta_y", yDelta);
break;
}
case RP_KEY_DOWN:
case RP_KEY_UP:
{
int32 numBytes;
if (message.Read(numBytes) != B_OK)
break;
if (numBytes > 1000)
break;
char* bytes = (char*)malloc(numBytes + 1);
if (bytes == NULL)
break;
if (message.ReadList(bytes, numBytes) != B_OK) {
free(bytes);
break;
}
for (int32 i = 0; i < numBytes; i++)
event->AddInt8("byte", (int8)bytes[i]);
bytes[numBytes] = 0;
event->AddData("bytes", B_STRING_TYPE, bytes, numBytes + 1, false);
event->AddInt32("modifiers", fModifiers);
int32 rawChar;
if (message.Read(rawChar) == B_OK)
event->AddInt32("raw_char", rawChar);
int32 key;
if (message.Read(key) == B_OK)
event->AddInt32("key", key);
free(bytes);
break;
}
case RP_MODIFIERS_CHANGED:
{
event->AddInt32("be:old_modifiers", fModifiers);
message.Read(fModifiers);
event->AddInt32("modifiers", fModifiers);
break;
}
}
BAutolock lock(fEventListLocker);
fEventList.AddItem(event);
if (fWaitingOnEvent) {
fWaitingOnEvent = false;
lock.Unlock();
release_sem(fEventNotification);
}
return true;
}