Some work on the input_server:
* Rewrote event handling: instead of writing every single device message to the event port, they are just queued in a list, and the event loop is only notified if necessary (ie. if a notification has been sent already, new events are just queued up until the input_server found the time to process them). * This also fixed a big memory leak: every message processed by EnqueueDeviceMessage() (IOW every key or mouse event) was leaked! * no longer abuses gInputMethodListLocker to lock the method event queue (it now uses the standard event queue lock). * removed the completely superfluous, weird and decelerating event caching mechanism * tried to find a better distribution of work between _SanitizeEvents(), _MethodizeEvents(), and _DispatchEvents(). * HandleSetMousePosition() now only does what it's supposed to do (this currently causes the mouse to jump at the start, though). * now uses the "Message4" for message sending if available. * fixed "kb_mouse_settings.h" to include all headers it needs. * some more cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14966 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,41 +1,34 @@
|
|||||||
//
|
/*
|
||||||
// kb_mouse_settings.h
|
* Copyright 2001-2005, Haiku, Inc. All Rights Reserved.
|
||||||
//
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _KB_MOUSE_SETTINGS_H
|
#ifndef _KB_MOUSE_SETTINGS_H
|
||||||
#define _KB_MOUSE_SETTINGS_H
|
#define _KB_MOUSE_SETTINGS_H
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#include <InterfaceDefs.h>
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bigtime_t key_repeat_delay;
|
bigtime_t key_repeat_delay;
|
||||||
int32 key_repeat_rate;
|
int32 key_repeat_rate;
|
||||||
} kb_settings;
|
} kb_settings;
|
||||||
|
|
||||||
#define kb_settings_file "Keyboard_settings"
|
#define kb_settings_file "Keyboard_settings"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int32 accel_factor;
|
int32 accel_factor;
|
||||||
int32 speed;
|
int32 speed;
|
||||||
} mouse_accel;
|
} mouse_accel;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32 type;
|
int32 type;
|
||||||
mouse_map map;
|
mouse_map map;
|
||||||
mouse_accel accel;
|
mouse_accel accel;
|
||||||
bigtime_t click_speed;
|
bigtime_t click_speed;
|
||||||
} mouse_settings;
|
} mouse_settings;
|
||||||
|
|
||||||
#define mouse_settings_file "Mouse_settings"
|
#define mouse_settings_file "Mouse_settings"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#endif /* _KB_MOUSE_SETTINGS_H */
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
/*
|
||||||
//
|
* Copyright 2004-2005, Haiku, Inc. All Rights Reserved.
|
||||||
// Copyright (c) 2004, Haiku
|
* Distributed under the terms of the MIT License.
|
||||||
//
|
*
|
||||||
// This software is part of the Haiku distribution and is covered
|
* Authors:
|
||||||
// by the Haiku license.
|
* Jérôme Duval
|
||||||
//
|
*/
|
||||||
//
|
|
||||||
// File: BottomlineWindow.cpp
|
|
||||||
// Author: Jérôme Duval
|
|
||||||
// Description: Input server bottomline window
|
|
||||||
// Created : January 24, 2005
|
|
||||||
//
|
|
||||||
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|
||||||
|
|
||||||
#include "BottomlineWindow.h"
|
#include "BottomlineWindow.h"
|
||||||
#include "InputServer.h"
|
|
||||||
#include "WindowPrivate.h"
|
#include "WindowPrivate.h"
|
||||||
|
|
||||||
BottomlineWindow::BottomlineWindow(const BFont *font)
|
#include <TextView.h>
|
||||||
: BWindow(BRect(0,0,350,16), "",
|
|
||||||
kLeftTitledWindowLook,
|
|
||||||
B_FLOATING_ALL_WINDOW_FEEL,
|
BottomlineWindow::BottomlineWindow()
|
||||||
B_NOT_V_RESIZABLE | B_NOT_CLOSABLE |
|
: BWindow(BRect(0, 0, 350, 16), "",
|
||||||
B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AVOID_FOCUS |
|
kLeftTitledWindowLook,
|
||||||
B_WILL_ACCEPT_FIRST_CLICK)
|
B_FLOATING_ALL_WINDOW_FEEL,
|
||||||
|
B_NOT_V_RESIZABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE
|
||||||
|
| B_AVOID_FOCUS | B_WILL_ACCEPT_FIRST_CLICK)
|
||||||
{
|
{
|
||||||
BRect textRect = Bounds();
|
BRect textRect = Bounds();
|
||||||
textRect.OffsetTo(B_ORIGIN);
|
textRect.OffsetTo(B_ORIGIN);
|
||||||
textRect.InsetBy(2,2);
|
textRect.InsetBy(2,2);
|
||||||
fTextView = new BTextView(Bounds(), "", textRect, font, NULL, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS);
|
fTextView = new BTextView(Bounds(), "", textRect, be_plain_font,
|
||||||
|
NULL, B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS);
|
||||||
AddChild(fTextView);
|
AddChild(fTextView);
|
||||||
|
|
||||||
fTextView->SetText("");
|
fTextView->SetText("");
|
||||||
@@ -73,45 +69,43 @@ BottomlineWindow::QuitRequested()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BottomlineWindow::HandleInputMethodEvent(BMessage *msg, BList *list)
|
BottomlineWindow::HandleInputMethodEvent(BMessage* event, EventList& newEvents)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
PostMessage(msg, fTextView);
|
PostMessage(event, fTextView);
|
||||||
|
|
||||||
int32 opcode = -1;
|
const char* string;
|
||||||
const char* string = NULL;
|
bool confirmed;
|
||||||
|
int32 opcode;
|
||||||
msg->FindInt32("be:opcode", &opcode);
|
if (event->FindInt32("be:opcode", &opcode) != B_OK
|
||||||
msg->FindString("be:string", &string);
|
|| opcode != B_INPUT_METHOD_CHANGED
|
||||||
|
|| event->FindBool("be:confirmed", &confirmed) != B_OK
|
||||||
|
|| !confirmed
|
||||||
|
|| event->FindString("be:string", &string) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
SERIAL_PRINT(("IME : %i, %s\n", opcode, string));
|
SERIAL_PRINT(("IME : %i, %s\n", opcode, string));
|
||||||
if (opcode != B_INPUT_METHOD_CHANGED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool confirmed = false;
|
|
||||||
if ((msg->FindBool("be:confirmed", &confirmed) != B_OK)
|
|
||||||
|| !confirmed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SERIAL_PRINT(("IME : confirmed\n"));
|
SERIAL_PRINT(("IME : confirmed\n"));
|
||||||
|
|
||||||
if (string != NULL) {
|
|
||||||
int32 offset = 0;
|
|
||||||
int32 length = strlen(string);
|
|
||||||
int32 next_offset = 0;
|
|
||||||
|
|
||||||
while (offset < length) {
|
int32 length = strlen(string);
|
||||||
for (++next_offset; (string[next_offset] & 0xC0) == 0x80; ++next_offset)
|
int32 offset = 0;
|
||||||
;
|
int32 nextOffset = 0;
|
||||||
|
|
||||||
BMessage *newmsg = new BMessage(B_KEY_DOWN);
|
while (offset < length) {
|
||||||
newmsg->AddInt32("key", 0);
|
// this is supposed to go to the next UTF-8 character
|
||||||
newmsg->AddInt64("when", system_time());
|
for (++nextOffset; (string[nextOffset] & 0xC0) == 0x80; ++nextOffset)
|
||||||
newmsg->AddData("bytes", B_STRING_TYPE, string + offset, next_offset - offset);
|
;
|
||||||
list->AddItem(newmsg);
|
|
||||||
offset = next_offset;
|
BMessage *newEvent = new BMessage(B_KEY_DOWN);
|
||||||
|
if (newEvent != NULL) {
|
||||||
|
newEvent->AddInt32("key", 0);
|
||||||
|
newEvent->AddInt64("when", system_time());
|
||||||
|
newEvent->AddData("bytes", B_STRING_TYPE, string + offset, nextOffset - offset);
|
||||||
|
newEvents.AddItem(newEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offset = nextOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,34 @@
|
|||||||
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
/*
|
||||||
//
|
* Copyright 2004-2005, Haiku, Inc. All Rights Reserved.
|
||||||
// Copyright (c) 2005, Haiku
|
* Distributed under the terms of the MIT License.
|
||||||
//
|
*
|
||||||
// This software is part of the Haiku distribution and is covered
|
* Authors:
|
||||||
// by the Haiku license.
|
* Jérôme Duval
|
||||||
//
|
*/
|
||||||
//
|
#ifndef BOTTOMLINE_WINDOW_H
|
||||||
// File: TMWindow.h
|
#define BOTTOMLINE_WINDOW_H
|
||||||
// Author: Jérôme Duval
|
|
||||||
// Description: Input server bottomline window
|
|
||||||
// Created : January 24, 2005
|
|
||||||
//
|
|
||||||
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
|
|
||||||
|
|
||||||
#ifndef BOTTOMLINEWINDOW_H
|
|
||||||
#define BOTTOMLINEWINDOW_H
|
#include "InputServer.h"
|
||||||
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <TextView.h>
|
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
class BottomlineWindow : public BWindow
|
class BTextView;
|
||||||
{
|
|
||||||
public:
|
|
||||||
BottomlineWindow(const BFont *font);
|
|
||||||
~BottomlineWindow();
|
|
||||||
|
|
||||||
void MessageReceived(BMessage *msg);
|
|
||||||
virtual bool QuitRequested();
|
|
||||||
|
|
||||||
void HandleInputMethodEvent(BMessage *msg, BList *list);
|
|
||||||
//private:
|
class BottomlineWindow : public BWindow {
|
||||||
BTextView *fTextView;
|
public:
|
||||||
|
BottomlineWindow();
|
||||||
|
virtual ~BottomlineWindow();
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
|
void HandleInputMethodEvent(BMessage* event, EventList& newEvents);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BTextView *fTextView;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // BOTTOMLINE_WINDOW_H
|
||||||
#endif //BOTTOMLINEWINDOW_H
|
|
||||||
|
|||||||
+417
-397
@@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
#include "InputServer.h"
|
#include "InputServer.h"
|
||||||
#include "InputServerTypes.h"
|
#include "InputServerTypes.h"
|
||||||
|
#include "BottomlineWindow.h"
|
||||||
#include "kb_mouse_driver.h"
|
#include "kb_mouse_driver.h"
|
||||||
#include "MethodReplicant.h"
|
#include "MethodReplicant.h"
|
||||||
|
|
||||||
#include <AppServerLink.h>
|
#include <AppServerLink.h>
|
||||||
|
#include <MessagePrivate.h>
|
||||||
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Deskbar.h>
|
#include <Deskbar.h>
|
||||||
@@ -38,11 +40,11 @@
|
|||||||
// received from app_server when screen res changed, but could be sent to too.
|
// received from app_server when screen res changed, but could be sent to too.
|
||||||
|
|
||||||
|
|
||||||
#ifdef COMPILE_FOR_R5
|
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
extern "C" status_t _kget_safemode_option_(const char *parameter,
|
extern "C" status_t _kern_get_safemode_option(const char *parameter,
|
||||||
char *buffer, size_t *_bufferSize);
|
char *buffer, size_t *_bufferSize);
|
||||||
#else
|
#else
|
||||||
extern "C" status_t _kern_get_safemode_option(const char *parameter,
|
extern "C" status_t _kget_safemode_option_(const char *parameter,
|
||||||
char *buffer, size_t *_bufferSize);
|
char *buffer, size_t *_bufferSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -140,8 +142,8 @@ InputServer::InputServer()
|
|||||||
fInputDeviceListLocker("input server device list"),
|
fInputDeviceListLocker("input server device list"),
|
||||||
fChars(NULL),
|
fChars(NULL),
|
||||||
fScreen(B_MAIN_SCREEN_ID),
|
fScreen(B_MAIN_SCREEN_ID),
|
||||||
fBLWindow(NULL),
|
fInputMethodWindow(NULL),
|
||||||
fIMAware(false),
|
fInputMethodAware(false),
|
||||||
fCursorSem(-1),
|
fCursorSem(-1),
|
||||||
fAppServerPort(-1),
|
fAppServerPort(-1),
|
||||||
fCursorArea(-1)
|
fCursorArea(-1)
|
||||||
@@ -154,15 +156,15 @@ InputServer::InputServer()
|
|||||||
CALLED();
|
CALLED();
|
||||||
gInputServer = this;
|
gInputServer = this;
|
||||||
|
|
||||||
EventLoop();
|
_StartEventLoop();
|
||||||
|
|
||||||
char parameter[32];
|
char parameter[32];
|
||||||
size_t parameterLength = sizeof(parameter);
|
size_t parameterLength = sizeof(parameter);
|
||||||
|
|
||||||
#ifdef COMPILE_FOR_R5
|
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
if (_kget_safemode_option_(B_SAFEMODE_SAFE_MODE, parameter, ¶meterLength) == B_OK)
|
|
||||||
#else
|
|
||||||
if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, ¶meterLength) == B_OK)
|
if (_kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, parameter, ¶meterLength) == B_OK)
|
||||||
|
#else
|
||||||
|
if (_kget_safemode_option_(B_SAFEMODE_SAFE_MODE, parameter, ¶meterLength) == B_OK)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
|
if (!strcasecmp(parameter, "enabled") || !strcasecmp(parameter, "on")
|
||||||
@@ -760,79 +762,25 @@ InputServer::HandleGetSetMouseSpeed(BMessage* message, BMessage* reply)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InputServer::HandleSetMousePosition(BMessage* message, BMessage* outbound)
|
InputServer::HandleSetMousePosition(BMessage* message, BMessage* reply)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
// this assumes that both supplied pointers are identical
|
BPoint where;
|
||||||
|
if (message->FindPoint("where", &where) != B_OK)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
ASSERT(outbound == message);
|
// create a new event for this and enqueue it to the event list just like any other
|
||||||
|
|
||||||
int32 xValue, yValue;
|
BMessage* event = new BMessage(B_MOUSE_MOVED);
|
||||||
|
if (event == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
switch (message->what) {
|
event->AddPoint("where", where);
|
||||||
case B_MOUSE_MOVED:
|
event->AddBool("be:set_mouse", true);
|
||||||
case B_MOUSE_DOWN:
|
if (EnqueueDeviceMessage(event) != B_OK) {
|
||||||
case B_MOUSE_UP:
|
delete event;
|
||||||
case FAST_MOUSE_MOVED:
|
return B_NO_MEMORY;
|
||||||
// get point and button from msg
|
|
||||||
if ((outbound->FindInt32("x", &xValue) == B_OK)
|
|
||||||
&& (outbound->FindInt32("y", &yValue) == B_OK)) {
|
|
||||||
fMousePos.x += xValue;
|
|
||||||
fMousePos.y -= yValue;
|
|
||||||
fMousePos.ConstrainTo(fFrame);
|
|
||||||
outbound->RemoveName("x");
|
|
||||||
outbound->RemoveName("y");
|
|
||||||
outbound->AddPoint("where", fMousePos);
|
|
||||||
outbound->AddInt32("modifiers", fKeyInfo.modifiers);
|
|
||||||
PRINT(("new position : %f, %f, %ld, %ld\n", fMousePos.x, fMousePos.y, xValue, yValue));
|
|
||||||
} else if (outbound->FindPoint("where", &fMousePos) == B_OK) {
|
|
||||||
outbound->RemoveName("where");
|
|
||||||
fMousePos.ConstrainTo(fFrame);
|
|
||||||
outbound->AddPoint("where", fMousePos);
|
|
||||||
outbound->AddInt32("modifiers", fKeyInfo.modifiers);
|
|
||||||
PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fCursorBuffer) {
|
|
||||||
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
|
||||||
fCursorBuffer[0] = (0x3 << 30L)
|
|
||||||
| ((uint32)fMousePos.x & 0x7fff) << 15
|
|
||||||
| ((uint32)fMousePos.y & 0x7fff);
|
|
||||||
|
|
||||||
PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
|
|
||||||
release_sem(fCursorSem);
|
|
||||||
#else
|
|
||||||
atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
|
|
||||||
| ((uint32)fMousePos.y & 0xffff));
|
|
||||||
if (atomic_or(&fCursorBuffer->read, 1) == 0)
|
|
||||||
release_sem_etc(fCursorSem, 0, B_RELEASE_ALL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// some Key Down and up codes ..
|
|
||||||
case B_KEY_DOWN:
|
|
||||||
case B_KEY_UP:
|
|
||||||
case B_UNMAPPED_KEY_DOWN:
|
|
||||||
case B_UNMAPPED_KEY_UP:
|
|
||||||
case B_MODIFIERS_CHANGED:
|
|
||||||
{
|
|
||||||
ssize_t size = 0;
|
|
||||||
uint8 *data = NULL;
|
|
||||||
outbound->FindInt32("modifiers", (int32*)&fKeyInfo.modifiers);
|
|
||||||
if (outbound->FindData("states", B_UINT8_TYPE,
|
|
||||||
(const void**)&data, &size) == B_OK
|
|
||||||
&& size == (ssize_t)sizeof(fKeyInfo.key_states)) {
|
|
||||||
PRINT(("updated keyinfo\n"));
|
|
||||||
memcpy(fKeyInfo.key_states, data, size);
|
|
||||||
}
|
|
||||||
PRINT(("keyinfo %ld %ld\n", size, (ssize_t)sizeof(fKeyInfo.key_states)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -938,34 +886,41 @@ InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
|
|||||||
|
|
||||||
if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
|
if (message->what == IS_FOCUS_IM_AWARE_VIEW) {
|
||||||
PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
|
PRINT(("HandleFocusUnfocusIMAwareView : entering\n"));
|
||||||
fIMAware = true;
|
fInputMethodAware = true;
|
||||||
} else {
|
} else {
|
||||||
PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
|
PRINT(("HandleFocusUnfocusIMAwareView : leaving\n"));
|
||||||
fIMAware = false;
|
fInputMethodAware = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Enqueues the message into the event queue.
|
||||||
|
* The message must only be deleted in case this method returns an error.
|
||||||
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InputServer::EnqueueDeviceMessage(BMessage* message)
|
InputServer::EnqueueDeviceMessage(BMessage* message)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
// TODO: message is not deleted???
|
BAutolock _(fEventQueueLock);
|
||||||
// TODO: why use ports for in-house messaging???
|
if (!fEventQueue.AddItem(message))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
ssize_t length = message->FlattenedSize();
|
if (fEventQueue.CountItems() == 1) {
|
||||||
char buffer[length];
|
// notify event loop only if we haven't already done so
|
||||||
status_t err;
|
write_port_etc(fEventLooperPort, 1, NULL, 0, B_RELATIVE_TIMEOUT, 0);
|
||||||
if ((err = message->Flatten(buffer,length)) < B_OK)
|
}
|
||||||
return err;
|
return B_OK;
|
||||||
|
|
||||||
return write_port(fEventLooperPort, 0, buffer, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Enqueues the message into the method queue.
|
||||||
|
* The message must only be deleted in case this method returns an error.
|
||||||
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
InputServer::EnqueueMethodMessage(BMessage* message)
|
InputServer::EnqueueMethodMessage(BMessage* message)
|
||||||
{
|
{
|
||||||
@@ -981,27 +936,14 @@ InputServer::EnqueueMethodMessage(BMessage* message)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LockMethodQueue();
|
BAutolock _(fEventQueueLock);
|
||||||
fMethodQueue.AddItem(message);
|
if (!fMethodQueue.AddItem(message))
|
||||||
UnlockMethodQueue();
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
|
if (fMethodQueue.CountItems() == 1) {
|
||||||
return B_OK;
|
// notify event loop only if we haven't already done so
|
||||||
}
|
write_port_etc(fEventLooperPort, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
status_t
|
|
||||||
InputServer::UnlockMethodQueue()
|
|
||||||
{
|
|
||||||
gInputMethodListLocker.Unlock();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
InputServer::LockMethodQueue()
|
|
||||||
{
|
|
||||||
gInputMethodListLocker.Lock();
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,7 +951,7 @@ InputServer::LockMethodQueue()
|
|||||||
status_t
|
status_t
|
||||||
InputServer::SetNextMethod(bool direction)
|
InputServer::SetNextMethod(bool direction)
|
||||||
{
|
{
|
||||||
LockMethodQueue();
|
gInputMethodListLocker.Lock();
|
||||||
|
|
||||||
int32 index = gInputMethodList.IndexOf(fActiveMethod);
|
int32 index = gInputMethodList.IndexOf(fActiveMethod);
|
||||||
index += (direction ? 1 : -1);
|
index += (direction ? 1 : -1);
|
||||||
@@ -1026,7 +968,7 @@ InputServer::SetNextMethod(bool direction)
|
|||||||
|
|
||||||
SetActiveMethod(method);
|
SetActiveMethod(method);
|
||||||
|
|
||||||
UnlockMethodQueue();
|
gInputMethodListLocker.Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,31 +1001,6 @@ InputServer::SetMethodReplicant(const BMessenger* messenger)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
InputServer::EventLoop()
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
fEventLooperPort = create_port(100, "input server event loop");
|
|
||||||
if (fEventLooperPort < 0) {
|
|
||||||
PRINTERR(("InputServer: create_port error: (0x%x) %s\n",
|
|
||||||
fEventLooperPort, strerror(fEventLooperPort)));
|
|
||||||
return fEventLooperPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_id thread = spawn_thread(_PortWatcher, "_input_server_event_loop_",
|
|
||||||
B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
|
|
||||||
if (thread < B_OK || resume_thread(thread) < B_OK) {
|
|
||||||
if (thread >= B_OK)
|
|
||||||
kill_thread(thread);
|
|
||||||
delete_port(fEventLooperPort);
|
|
||||||
fEventLooperPort = -1;
|
|
||||||
return thread < B_OK ? thread : B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InputServer::EventLoopRunning()
|
InputServer::EventLoopRunning()
|
||||||
{
|
{
|
||||||
@@ -1091,241 +1008,6 @@ InputServer::EventLoopRunning()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputServer::DispatchEvents(BList* eventList)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
CacheEvents(eventList);
|
|
||||||
|
|
||||||
if (fEventsCache.CountItems() > 0) {
|
|
||||||
BMessage* event;
|
|
||||||
|
|
||||||
for (int32 i = 0; NULL != (event = (BMessage *)fEventsCache.ItemAt(i)); i++) {
|
|
||||||
// now we must send each event to the app_server
|
|
||||||
if (event->what == B_INPUT_METHOD_EVENT && !fIMAware) {
|
|
||||||
SERIAL_PRINT(("IME received\n"));
|
|
||||||
int32 opcode = -1;
|
|
||||||
event->FindInt32("be:opcode", &opcode);
|
|
||||||
BList events;
|
|
||||||
if (!fBLWindow && opcode == B_INPUT_METHOD_STARTED)
|
|
||||||
fBLWindow = new BottomlineWindow(be_plain_font);
|
|
||||||
|
|
||||||
if (fBLWindow) {
|
|
||||||
fBLWindow->HandleInputMethodEvent(event, &events);
|
|
||||||
|
|
||||||
if (!events.IsEmpty()) {
|
|
||||||
fBLWindow->PostMessage(B_QUIT_REQUESTED);
|
|
||||||
fBLWindow = NULL;
|
|
||||||
|
|
||||||
fEventsCache.AddList(&events);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
DispatchEvent(event);
|
|
||||||
|
|
||||||
delete event;
|
|
||||||
}
|
|
||||||
|
|
||||||
fEventsCache.MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
InputServer::DispatchEvent(BMessage* message)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
switch (message->what) {
|
|
||||||
case B_KEY_DOWN:
|
|
||||||
case B_KEY_UP:
|
|
||||||
case B_UNMAPPED_KEY_UP:
|
|
||||||
case B_UNMAPPED_KEY_DOWN: {
|
|
||||||
uint32 modifiers;
|
|
||||||
ssize_t size;
|
|
||||||
uint8 *data;
|
|
||||||
if (message->FindData("states", B_UINT8_TYPE, (const void**)&data, &size) != B_OK)
|
|
||||||
message->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states, 16);
|
|
||||||
if (message->FindInt32("modifiers", (int32*)&modifiers) != B_OK)
|
|
||||||
message->AddInt32("modifiers", fKeyInfo.modifiers);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t length = message->FlattenedSize();
|
|
||||||
char buffer[length];
|
|
||||||
status_t err;
|
|
||||||
if ((err = message->Flatten(buffer,length)) < B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
if (fAppServerPort > 0)
|
|
||||||
write_port(fAppServerPort, 0, buffer, length);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputServer::CacheEvents(BList* eventsToCache)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
SanitizeEvents(eventsToCache);
|
|
||||||
MethodizeEvents(eventsToCache, true);
|
|
||||||
FilterEvents(eventsToCache);
|
|
||||||
|
|
||||||
fEventsCache.AddList(eventsToCache);
|
|
||||||
eventsToCache->MakeEmpty();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const BList*
|
|
||||||
InputServer::GetNextEvents(BList *)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** This method applies all defined filters to each event in the
|
|
||||||
* supplied list. The supplied list is modified to reflect the
|
|
||||||
* output of the filters.
|
|
||||||
* The method returns true if the filters were applied to all
|
|
||||||
* events without error and false otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputServer::FilterEvents(BList* eventsToFilter)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
if (NULL == eventsToFilter)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
BInputServerFilter* currentFilter;
|
|
||||||
int32 filterIndex = 0;
|
|
||||||
|
|
||||||
while ((currentFilter = (BInputServerFilter*)gInputFilterList.ItemAt(filterIndex)) != NULL) {
|
|
||||||
// Apply the current filter to all available event messages.
|
|
||||||
int32 eventIndex = 0;
|
|
||||||
BMessage *currentEvent;
|
|
||||||
while ((currentEvent = (BMessage*)eventsToFilter->ItemAt(eventIndex)) != NULL) {
|
|
||||||
// Storage for new event messages generated by the filter.
|
|
||||||
BList outList;
|
|
||||||
|
|
||||||
// Apply the current filter to the current event message.
|
|
||||||
PRINT(("InputServer::FilterEvents Filter called\n"));
|
|
||||||
filter_result result = currentFilter->Filter(currentEvent, &outList);
|
|
||||||
|
|
||||||
if (result == B_SKIP_MESSAGE) {
|
|
||||||
// Use the result in out_list (if any); ignore current message.
|
|
||||||
eventsToFilter->RemoveItem(eventIndex);
|
|
||||||
eventsToFilter->AddList(&outList, eventIndex);
|
|
||||||
eventIndex += outList.CountItems();
|
|
||||||
|
|
||||||
// NOTE: eventsToFilter now owns outList's items.
|
|
||||||
} else {
|
|
||||||
// Free resources associated with items in outList.
|
|
||||||
void* outItem;
|
|
||||||
for (int32 i = 0; (outItem = outList.ItemAt(i)) != NULL; i++) {
|
|
||||||
delete (BMessage*)outItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == B_DISPATCH_MESSAGE) {
|
|
||||||
// Use the result in current_message; ignore outList.
|
|
||||||
eventIndex++;
|
|
||||||
} else {
|
|
||||||
// Error
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filterIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputServer::SanitizeEvents(BList* events)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
int32 index = 0;
|
|
||||||
BMessage *event;
|
|
||||||
PRINT(("SanitizeEvents: %ld \n", events->CountItems()));
|
|
||||||
while ((event = (BMessage*)events->ItemAt(index)) != NULL) {
|
|
||||||
PRINT(("SanitizeEvents: what:%lx\n", event->what));
|
|
||||||
switch (event->what) {
|
|
||||||
case B_KEY_DOWN:
|
|
||||||
case B_UNMAPPED_KEY_DOWN:
|
|
||||||
// we scan for Alt+Space key down events which means we change to next input method
|
|
||||||
// Note : Shift+Alt+Space key allows to change to the previous input method
|
|
||||||
|
|
||||||
PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
|
|
||||||
fKeyInfo.key_states[KEY_Spacebar >> 3]));
|
|
||||||
|
|
||||||
if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
|
|
||||||
&& (fKeyInfo.key_states[KEY_Spacebar >> 3]
|
|
||||||
& (1 << (7 - (KEY_Spacebar % 8))))) {
|
|
||||||
SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
|
|
||||||
|
|
||||||
// this event isn't sent to the user
|
|
||||||
events->RemoveItem(index);
|
|
||||||
delete event;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputServer::MethodizeEvents(BList* events, bool)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
if (fActiveMethod) {
|
|
||||||
BList newList;
|
|
||||||
newList.AddList(&fMethodQueue);
|
|
||||||
fMethodQueue.MakeEmpty();
|
|
||||||
|
|
||||||
for (int32 i=0; i<events->CountItems(); i++) {
|
|
||||||
BMessage *item = (BMessage *)events->ItemAt(i);
|
|
||||||
BList filterList;
|
|
||||||
filter_result result = fActiveMethod->Filter(item, &filterList);
|
|
||||||
switch (result) {
|
|
||||||
case B_SKIP_MESSAGE:
|
|
||||||
delete item;
|
|
||||||
case B_DISPATCH_MESSAGE:
|
|
||||||
if (filterList.CountItems() > 0) {
|
|
||||||
newList.AddList(&filterList);
|
|
||||||
delete item;
|
|
||||||
} else
|
|
||||||
newList.AddItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
newList.AddList(&fMethodQueue);
|
|
||||||
fMethodQueue.MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
events->MakeEmpty();
|
|
||||||
events->AddList(&newList);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** The fInputDeviceListLocker must be locked when calling this function */
|
/** The fInputDeviceListLocker must be locked when calling this function */
|
||||||
|
|
||||||
InputDeviceListItem*
|
InputDeviceListItem*
|
||||||
@@ -1571,20 +1253,45 @@ InputServer::SafeMode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
status_t
|
||||||
InputServer::_PortWatcher(void* arg)
|
InputServer::_StartEventLoop()
|
||||||
{
|
{
|
||||||
InputServer* self = (InputServer*)arg;
|
CALLED();
|
||||||
self->_WatchPort();
|
fEventLooperPort = create_port(100, "input server events");
|
||||||
|
if (fEventLooperPort < 0) {
|
||||||
|
PRINTERR(("InputServer: create_port error: (0x%x) %s\n",
|
||||||
|
fEventLooperPort, strerror(fEventLooperPort)));
|
||||||
|
return fEventLooperPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_id thread = spawn_thread(_EventLooper, "_input_server_event_loop_",
|
||||||
|
B_REAL_TIME_DISPLAY_PRIORITY + 3, this);
|
||||||
|
if (thread < B_OK || resume_thread(thread) < B_OK) {
|
||||||
|
if (thread >= B_OK)
|
||||||
|
kill_thread(thread);
|
||||||
|
delete_port(fEventLooperPort);
|
||||||
|
fEventLooperPort = -1;
|
||||||
|
return thread < B_OK ? thread : B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
InputServer::_WatchPort()
|
InputServer::_EventLooper(void* arg)
|
||||||
{
|
{
|
||||||
while (true) {
|
InputServer* self = (InputServer*)arg;
|
||||||
|
self->_EventLoop();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
InputServer::_EventLoop()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
// Block until we find the size of the next message
|
// Block until we find the size of the next message
|
||||||
ssize_t length = port_buffer_size(fEventLooperPort);
|
ssize_t length = port_buffer_size(fEventLooperPort);
|
||||||
if (length < B_OK) {
|
if (length < B_OK) {
|
||||||
@@ -1606,40 +1313,353 @@ InputServer::_WatchPort()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length == 0) {
|
EventList events;
|
||||||
BList list;
|
if (fEventQueueLock.Lock()) {
|
||||||
DispatchEvents(&list);
|
// move the items to our own list to block the event queue as short as possible
|
||||||
continue;
|
events.AddList(&fEventQueue);
|
||||||
|
fEventQueue.MakeEmpty();
|
||||||
|
fEventQueueLock.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
BMessage* event = new BMessage;
|
if (length > 0) {
|
||||||
|
BMessage* event = new BMessage;
|
||||||
|
|
||||||
if ((err = event->Unflatten(buffer)) < 0) {
|
if ((err = event->Unflatten(buffer)) < 0) {
|
||||||
PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
|
PRINTERR(("[InputServer] Unflatten() error: (0x%lx) %s\n", err, strerror(err)));
|
||||||
delete event;
|
delete event;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
|
events.AddItem(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is where the message should be processed.
|
// This is where the message should be processed.
|
||||||
|
|
||||||
// here we test for a message coming from app_server, screen resolution change could have happened
|
if (_SanitizeEvents(events)
|
||||||
if (event->what == FAST_MOUSE_MOVED) {
|
&& _MethodizeEvents(events)
|
||||||
BRect frame = fScreen.Frame();
|
&& _FilterEvents(events))
|
||||||
if (frame != fFrame) {
|
_DispatchEvents(events);
|
||||||
fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width();
|
}
|
||||||
fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height();
|
}
|
||||||
fFrame = frame;
|
|
||||||
|
|
||||||
|
/** Frees events from unwanted fields, adds missing fields, and removes
|
||||||
|
* unwanted events altogether.
|
||||||
|
* As a side effect, it will also update the internal mouse states.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
InputServer::_SanitizeEvents(EventList& events)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
int32 index = 0;
|
||||||
|
BMessage *event;
|
||||||
|
|
||||||
|
while ((event = (BMessage*)events.ItemAt(index)) != NULL) {
|
||||||
|
switch (event->what) {
|
||||||
|
case FAST_MOUSE_MOVED:
|
||||||
|
{
|
||||||
|
// here we test for a message coming from app_server,
|
||||||
|
// screen resolution change could have happened
|
||||||
|
BRect frame = fScreen.Frame();
|
||||||
|
if (frame != fFrame) {
|
||||||
|
fMousePos.x = fMousePos.x * frame.Width() / fFrame.Width();
|
||||||
|
fMousePos.y = fMousePos.y * frame.Height() / fFrame.Height();
|
||||||
|
fFrame = frame;
|
||||||
|
} else {
|
||||||
|
// TODO: discard event
|
||||||
|
}
|
||||||
|
|
||||||
|
event->what = B_MOUSE_MOVED;
|
||||||
|
event->AddPoint("where", fMousePos);
|
||||||
|
// supposed to fall through
|
||||||
}
|
}
|
||||||
|
case B_MOUSE_MOVED:
|
||||||
|
case B_MOUSE_DOWN:
|
||||||
|
{
|
||||||
|
int32 buttons;
|
||||||
|
if (event->FindInt32("buttons", &buttons) != B_OK)
|
||||||
|
event->AddInt32("buttons", 0);
|
||||||
|
|
||||||
|
// supposed to fall through
|
||||||
|
}
|
||||||
|
case B_MOUSE_UP:
|
||||||
|
{
|
||||||
|
BPoint where;
|
||||||
|
int32 x, y;
|
||||||
|
|
||||||
|
if (event->FindInt32("x", &x) == B_OK
|
||||||
|
&& event->FindInt32("y", &y) == B_OK) {
|
||||||
|
fMousePos.x += x;
|
||||||
|
fMousePos.y -= y;
|
||||||
|
fMousePos.ConstrainTo(fFrame);
|
||||||
|
|
||||||
|
event->RemoveName("x");
|
||||||
|
event->RemoveName("y");
|
||||||
|
event->AddPoint("where", fMousePos);
|
||||||
|
|
||||||
|
PRINT(("new position: %f, %f, %ld, %ld\n",
|
||||||
|
fMousePos.x, fMousePos.y, xValue, yValue));
|
||||||
|
} else if (event->FindPoint("where", &where) == B_OK) {
|
||||||
|
fMousePos = where;
|
||||||
|
fMousePos.ConstrainTo(fFrame);
|
||||||
|
|
||||||
|
event->ReplacePoint("where", fMousePos);
|
||||||
|
PRINT(("new position : %f, %f\n", fMousePos.x, fMousePos.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
event->AddInt32("modifiers", fKeyInfo.modifiers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case B_KEY_DOWN:
|
||||||
|
case B_UNMAPPED_KEY_DOWN:
|
||||||
|
if (fActiveMethod == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// we scan for Alt+Space key down events which means we change
|
||||||
|
// to next input method
|
||||||
|
// (pressing "shift" will let us switch to the previous method)
|
||||||
|
|
||||||
|
PRINT(("SanitizeEvents: %lx, %lx\n", fKeyInfo.modifiers,
|
||||||
|
fKeyInfo.key_states[KEY_Spacebar >> 3]));
|
||||||
|
|
||||||
|
if ((fKeyInfo.modifiers & B_COMMAND_KEY) != 0
|
||||||
|
&& (fKeyInfo.key_states[KEY_Spacebar >> 3]
|
||||||
|
& (1 << (7 - (KEY_Spacebar % 8))))) {
|
||||||
|
SetNextMethod(!fKeyInfo.modifiers & B_SHIFT_KEY);
|
||||||
|
|
||||||
|
// this event isn't sent to the user
|
||||||
|
events.RemoveItemAt(index);
|
||||||
|
delete event;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleSetMousePosition(event, event);
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
BList list;
|
return true;
|
||||||
list.AddItem(event);
|
}
|
||||||
DispatchEvents(&list);
|
|
||||||
|
|
||||||
PRINT(("Event written to port\n"));
|
|
||||||
|
/** Applies the filters of the active input method to the
|
||||||
|
* incoming events. It will also move the events in the method
|
||||||
|
* queue to the event list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
InputServer::_MethodizeEvents(EventList& events)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
if (fActiveMethod == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int32 count = events.CountItems();
|
||||||
|
for (int32 i = 0; i < count;) {
|
||||||
|
_FilterEvent(fActiveMethod, events, i, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fInputMethodAware) {
|
||||||
|
// special handling for non-input-method-aware views
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BMessage* event = events.ItemAt(i);
|
||||||
|
|
||||||
|
if (event->what != B_INPUT_METHOD_EVENT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SERIAL_PRINT(("IME received\n"));
|
||||||
|
|
||||||
|
int32 opcode;
|
||||||
|
if (fInputMethodWindow == NULL
|
||||||
|
&& event->FindInt32("be:opcode", &opcode) == B_OK
|
||||||
|
&& opcode == B_INPUT_METHOD_STARTED)
|
||||||
|
fInputMethodWindow = new (nothrow) BottomlineWindow();
|
||||||
|
|
||||||
|
if (fInputMethodWindow != NULL) {
|
||||||
|
EventList newEvents;
|
||||||
|
fInputMethodWindow->HandleInputMethodEvent(event, newEvents);
|
||||||
|
|
||||||
|
if (!newEvents.IsEmpty()) {
|
||||||
|
fInputMethodWindow->PostMessage(B_QUIT_REQUESTED);
|
||||||
|
fInputMethodWindow = NULL;
|
||||||
|
|
||||||
|
// replace event with new events (but don't scan them again
|
||||||
|
// for input method messages)
|
||||||
|
events.RemoveItemAt(i);
|
||||||
|
delete event;
|
||||||
|
|
||||||
|
events.AddList(&newEvents, i);
|
||||||
|
i += newEvents.CountItems() - 1;
|
||||||
|
count = events.CountItems();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move the method events into the event queue - they are not
|
||||||
|
// "methodized" either
|
||||||
|
BAutolock _(fEventQueueLock);
|
||||||
|
events.AddList(&fMethodQueue);
|
||||||
|
fMethodQueue.MakeEmpty();
|
||||||
|
|
||||||
|
return events.CountItems() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** This method applies all defined filters to each event in the
|
||||||
|
* supplied list. The supplied list is modified to reflect the
|
||||||
|
* output of the filters.
|
||||||
|
* The method returns true if the filters were applied to all
|
||||||
|
* events without error and false otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
InputServer::_FilterEvents(EventList& events)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
BAutolock _(gInputFilterListLocker);
|
||||||
|
|
||||||
|
int32 count = gInputFilterList.CountItems();
|
||||||
|
int32 eventCount = events.CountItems();
|
||||||
|
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BInputServerFilter* filter = (BInputServerFilter*)gInputFilterList.ItemAt(i);
|
||||||
|
|
||||||
|
// Apply the current filter to all available event messages.
|
||||||
|
|
||||||
|
for (int32 eventIndex = 0; eventIndex < eventCount;) {
|
||||||
|
_FilterEvent(filter, events, eventIndex, eventCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eventCount != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
InputServer::_DispatchEvents(EventList& events)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
int32 count = events.CountItems();
|
||||||
|
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BMessage* event = events.ItemAt(i);
|
||||||
|
|
||||||
|
// now we must send each event to the app_server
|
||||||
|
_DispatchEvent(event);
|
||||||
|
delete event;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Applies the given filter to the event list.
|
||||||
|
* For your convenience, it also alters the \a index and \a count arguments
|
||||||
|
* ready for the next call to this method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
InputServer::_FilterEvent(BInputServerFilter* filter, EventList& events,
|
||||||
|
int32& index, int32& count)
|
||||||
|
{
|
||||||
|
BMessage* event = events.ItemAt(index);
|
||||||
|
|
||||||
|
BList newEvents;
|
||||||
|
filter_result result = filter->Filter(event, &newEvents);
|
||||||
|
|
||||||
|
if (result == B_SKIP_MESSAGE || newEvents.CountItems() > 0) {
|
||||||
|
// we no longer need the current event
|
||||||
|
events.RemoveItemAt(index);
|
||||||
|
delete event;
|
||||||
|
|
||||||
|
if (result == B_DISPATCH_MESSAGE) {
|
||||||
|
// add the new events - but don't methodize them again
|
||||||
|
events.AsBList()->AddList(&newEvents, index);
|
||||||
|
index += newEvents.CountItems();
|
||||||
|
count = events.CountItems();
|
||||||
|
} else
|
||||||
|
count--;
|
||||||
|
} else
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
InputServer::_DispatchEvent(BMessage* event)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
switch (event->what) {
|
||||||
|
case B_MOUSE_MOVED:
|
||||||
|
case B_MOUSE_DOWN:
|
||||||
|
case B_MOUSE_UP:
|
||||||
|
if (fCursorBuffer) {
|
||||||
|
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
|
||||||
|
fCursorBuffer[0] = (0x3 << 30L)
|
||||||
|
| ((uint32)fMousePos.x & 0x7fff) << 15
|
||||||
|
| ((uint32)fMousePos.y & 0x7fff);
|
||||||
|
|
||||||
|
PRINT(("released cursorSem with value : %08lx\n", fCursorBuffer[0]));
|
||||||
|
release_sem(fCursorSem);
|
||||||
|
#else
|
||||||
|
atomic_set((int32*)&fCursorBuffer->pos, (uint32)fMousePos.x << 16UL
|
||||||
|
| ((uint32)fMousePos.y & 0xffff));
|
||||||
|
if (atomic_or(&fCursorBuffer->read, 1) == 0)
|
||||||
|
release_sem_etc(fCursorSem, 0, B_RELEASE_ALL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_KEY_DOWN:
|
||||||
|
case B_KEY_UP:
|
||||||
|
case B_UNMAPPED_KEY_DOWN:
|
||||||
|
case B_UNMAPPED_KEY_UP:
|
||||||
|
case B_MODIFIERS_CHANGED:
|
||||||
|
{
|
||||||
|
// update or add modifiers
|
||||||
|
uint32 modifiers;
|
||||||
|
if (event->FindInt32("modifiers", (int32*)&modifiers) == B_OK)
|
||||||
|
fKeyInfo.modifiers = modifiers;
|
||||||
|
else
|
||||||
|
event->AddInt32("modifiers", fKeyInfo.modifiers);
|
||||||
|
|
||||||
|
// update or add key states
|
||||||
|
const uint8 *data;
|
||||||
|
ssize_t size;
|
||||||
|
if (event->FindData("states", B_UINT8_TYPE,
|
||||||
|
(const void**)&data, &size) == B_OK) {
|
||||||
|
PRINT(("updated keyinfo\n"));
|
||||||
|
if (size == sizeof(fKeyInfo.key_states))
|
||||||
|
memcpy(fKeyInfo.key_states, data, size);
|
||||||
|
} else {
|
||||||
|
event->AddData("states", B_UINT8_TYPE, fKeyInfo.key_states,
|
||||||
|
sizeof(fKeyInfo.key_states));
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT(("keyinfo %ld %ld\n", size, (ssize_t)sizeof(fKeyInfo.key_states)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(HAIKU_TARGET_PLATFORM_HAIKU) && defined(USING_MESSAGE4)
|
||||||
|
BMessenger reply;
|
||||||
|
BMessage::Private messagePrivate(event);
|
||||||
|
return messagePrivate.SendMessage(fAppServerPort, 0, true, 0, false, reply);
|
||||||
|
#else
|
||||||
|
ssize_t length = event->FlattenedSize();
|
||||||
|
char buffer[length];
|
||||||
|
status_t err;
|
||||||
|
if ((err = event->Flatten(buffer,length)) < B_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return write_port(fAppServerPort, 0, buffer, length);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "AddOnManager.h"
|
#include "AddOnManager.h"
|
||||||
#include "BottomlineWindow.h"
|
|
||||||
#include "DeviceManager.h"
|
#include "DeviceManager.h"
|
||||||
#include "KeyboardSettings.h"
|
#include "KeyboardSettings.h"
|
||||||
#include "MouseSettings.h"
|
#include "MouseSettings.h"
|
||||||
@@ -23,6 +22,7 @@
|
|||||||
#include <InterfaceDefs.h>
|
#include <InterfaceDefs.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
#include <Screen.h>
|
#include <Screen.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
@@ -35,6 +35,10 @@
|
|||||||
#define INPUTSERVER_SIGNATURE "application/x-vnd.Be-input_server"
|
#define INPUTSERVER_SIGNATURE "application/x-vnd.Be-input_server"
|
||||||
// use this when target should replace R5 input_server
|
// use this when target should replace R5 input_server
|
||||||
|
|
||||||
|
typedef BObjectList<BMessage> EventList;
|
||||||
|
|
||||||
|
class BottomlineWindow;
|
||||||
|
|
||||||
class InputDeviceListItem {
|
class InputDeviceListItem {
|
||||||
public:
|
public:
|
||||||
InputDeviceListItem(BInputServerDevice& serverDevice, input_device_ref& device);
|
InputDeviceListItem(BInputServerDevice& serverDevice, input_device_ref& device);
|
||||||
@@ -87,14 +91,12 @@ class _BMethodAddOn_ {
|
|||||||
BMessenger fMessenger;
|
BMessenger fMessenger;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class KeymapMethod : public BInputServerMethod {
|
class KeymapMethod : public BInputServerMethod {
|
||||||
public:
|
public:
|
||||||
KeymapMethod();
|
KeymapMethod();
|
||||||
~KeymapMethod();
|
~KeymapMethod();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class InputServer : public BApplication {
|
class InputServer : public BApplication {
|
||||||
public:
|
public:
|
||||||
InputServer();
|
InputServer();
|
||||||
@@ -125,23 +127,12 @@ class InputServer : public BApplication {
|
|||||||
|
|
||||||
status_t EnqueueDeviceMessage(BMessage* message);
|
status_t EnqueueDeviceMessage(BMessage* message);
|
||||||
status_t EnqueueMethodMessage(BMessage* message);
|
status_t EnqueueMethodMessage(BMessage* message);
|
||||||
status_t UnlockMethodQueue();
|
|
||||||
status_t LockMethodQueue();
|
|
||||||
status_t SetNextMethod(bool direction);
|
status_t SetNextMethod(bool direction);
|
||||||
void SetActiveMethod(BInputServerMethod* method);
|
void SetActiveMethod(BInputServerMethod* method);
|
||||||
const BMessenger* MethodReplicant();
|
const BMessenger* MethodReplicant();
|
||||||
void SetMethodReplicant(const BMessenger *replicant);
|
void SetMethodReplicant(const BMessenger *replicant);
|
||||||
status_t EventLoop();
|
|
||||||
bool EventLoopRunning();
|
bool EventLoopRunning();
|
||||||
|
|
||||||
bool DispatchEvents(BList* eventList);
|
|
||||||
status_t DispatchEvent(BMessage* event);
|
|
||||||
bool CacheEvents(BList* eventList);
|
|
||||||
const BList* GetNextEvents(BList*);
|
|
||||||
bool FilterEvents(BList* eventList);
|
|
||||||
bool SanitizeEvents(BList* eventList);
|
|
||||||
bool MethodizeEvents(BList* eventList, bool);
|
|
||||||
|
|
||||||
status_t GetDeviceInfo(const char* name, input_device_type *_type,
|
status_t GetDeviceInfo(const char* name, input_device_type *_type,
|
||||||
bool *_isRunning = NULL);
|
bool *_isRunning = NULL);
|
||||||
status_t UnregisterDevices(BInputServerDevice& serverDevice,
|
status_t UnregisterDevices(BInputServerDevice& serverDevice,
|
||||||
@@ -180,13 +171,22 @@ class InputServer : public BApplication {
|
|||||||
status_t _LoadSystemKeymap();
|
status_t _LoadSystemKeymap();
|
||||||
void _InitKeyboardMouseStates();
|
void _InitKeyboardMouseStates();
|
||||||
|
|
||||||
|
status_t _StartEventLoop();
|
||||||
|
void _EventLoop();
|
||||||
|
static status_t _EventLooper(void *arg);
|
||||||
|
|
||||||
|
bool _SanitizeEvents(EventList& events);
|
||||||
|
bool _MethodizeEvents(EventList& events);
|
||||||
|
bool _FilterEvents(EventList& events);
|
||||||
|
void _DispatchEvents(EventList& events);
|
||||||
|
|
||||||
|
void _FilterEvent(BInputServerFilter* filter, EventList& events,
|
||||||
|
int32& index, int32& count);
|
||||||
|
status_t _DispatchEvent(BMessage* event);
|
||||||
|
|
||||||
status_t _AcquireInput(BMessage& message, BMessage& reply);
|
status_t _AcquireInput(BMessage& message, BMessage& reply);
|
||||||
void _ReleaseInput(BMessage* message);
|
void _ReleaseInput(BMessage* message);
|
||||||
|
|
||||||
void _WatchPort();
|
|
||||||
|
|
||||||
static int32 _PortWatcher(void *arg);
|
|
||||||
// static bool doStartStopDevice(void*, void*);
|
|
||||||
InputDeviceListItem* _FindInputDeviceListItem(BInputServerDevice& device);
|
InputDeviceListItem* _FindInputDeviceListItem(BInputServerDevice& device);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -199,8 +199,8 @@ class InputServer : public BApplication {
|
|||||||
BList fInputDeviceList;
|
BList fInputDeviceList;
|
||||||
BLocker fInputDeviceListLocker;
|
BLocker fInputDeviceListLocker;
|
||||||
|
|
||||||
KeyboardSettings fKeyboardSettings;
|
KeyboardSettings fKeyboardSettings;
|
||||||
MouseSettings fMouseSettings;
|
MouseSettings fMouseSettings;
|
||||||
|
|
||||||
BPoint fMousePos; // current mouse position
|
BPoint fMousePos; // current mouse position
|
||||||
key_info fKeyInfo; // current key info
|
key_info fKeyInfo; // current key info
|
||||||
@@ -212,16 +212,17 @@ class InputServer : public BApplication {
|
|||||||
|
|
||||||
AddOnManager* fAddOnManager;
|
AddOnManager* fAddOnManager;
|
||||||
|
|
||||||
BList fEventsCache;
|
|
||||||
|
|
||||||
BScreen fScreen;
|
BScreen fScreen;
|
||||||
BRect fFrame;
|
BRect fFrame;
|
||||||
|
|
||||||
|
BLocker fEventQueueLock;
|
||||||
|
EventList fEventQueue;
|
||||||
|
|
||||||
BInputServerMethod* fActiveMethod;
|
BInputServerMethod* fActiveMethod;
|
||||||
BList fMethodQueue;
|
EventList fMethodQueue;
|
||||||
const BMessenger* fReplicantMessenger;
|
const BMessenger* fReplicantMessenger;
|
||||||
BottomlineWindow* fBLWindow;
|
BottomlineWindow* fInputMethodWindow;
|
||||||
bool fIMAware;
|
bool fInputMethodAware;
|
||||||
|
|
||||||
sem_id fCursorSem;
|
sem_id fCursorSem;
|
||||||
port_id fAppServerPort;
|
port_id fAppServerPort;
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ SEARCH on US-International.keymap
|
|||||||
|
|
||||||
AddResources input_server : input_server.rdef ;
|
AddResources input_server : input_server.rdef ;
|
||||||
|
|
||||||
UsePrivateHeaders app ;
|
UsePrivateHeaders app input interface shared storage ;
|
||||||
UsePrivateHeaders input ;
|
|
||||||
UsePrivateHeaders interface ;
|
|
||||||
UsePrivateHeaders storage ;
|
|
||||||
|
|
||||||
|
|
||||||
SubDirC++Flags -DADD_ON_STABLE_SECONDS=1 ; # for AddOnMonitorHandler.cpp
|
SubDirC++Flags -DADD_ON_STABLE_SECONDS=1 ; # for AddOnMonitorHandler.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user