The keyboard_device now also acts as the target for input method messages from

the input method aware view.
This was necessary to support stopping an input method on the fly: if you press
the dead key first, then change to another view and press a key that is changed
by the dead key, the resulting key now reaches its target, and will no longer
be ignored.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19119 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-10-25 12:45:41 +00:00
parent f0cd9e9d87
commit bd50618697
2 changed files with 84 additions and 52 deletions

View File

@ -364,7 +364,8 @@ get_short_name(const char *longName)
KeyboardInputDevice::KeyboardInputDevice()
: fTMWindow(NULL)
:
fTMWindow(NULL)
{
#if DEBUG
if (sLogFile == NULL)
@ -523,7 +524,7 @@ KeyboardInputDevice::Control(const char *name, void *cookie,
}
status_t
status_t
KeyboardInputDevice::_HandleMonitor(BMessage *message)
{
CALLED();
@ -572,11 +573,7 @@ KeyboardInputDevice::_AddDevice(const char *path)
if (device == NULL)
return B_NO_MEMORY;
device->fd = -1;
device->device_watcher = -1;
device->active = false;
device->owner = this;
device->isAT = strstr(device->path, "keyboard/at") != NULL;
input_device_ref *devices[2];
devices[0] = &device->device_ref;
@ -611,36 +608,6 @@ KeyboardInputDevice::_RemoveDevice(const char *path)
}
status_t
KeyboardInputDevice::_EnqueueInlineInputMethod(int32 opcode,
const char* string, bool confirmed, BMessage* keyDown)
{
BMessage* message = new BMessage(B_INPUT_METHOD_EVENT);
if (message == NULL)
return B_NO_MEMORY;
message->AddInt32("be:opcode", opcode);
message->AddBool("be:inline_only", true);
if (string != NULL)
message->AddString("be:string", string);
if (confirmed)
message->AddBool("be:confirmed", true);
if (keyDown)
message->AddMessage("be:translated", keyDown);
if (opcode == B_INPUT_METHOD_STARTED) {
message->AddMessenger("be:reply_to", be_app_messenger);
// we don't really need a real messenger; be_app must be enough
}
status_t status = EnqueueMessage(message);
if (status != B_OK)
delete message;
return status;
}
/*static*/ int32
KeyboardInputDevice::_DeviceWatcher(void *arg)
{
@ -652,7 +619,6 @@ KeyboardInputDevice::_DeviceWatcher(void *arg)
Keymap* keymap = &owner->fKeymap;
uint32 lastKeyCode = 0;
uint32 repeatCount = 1;
bool inlineStarted = false;
uint8 states[16];
memset(states, 0, sizeof(states));
@ -808,28 +774,29 @@ KeyboardInputDevice::_DeviceWatcher(void *arg)
delete[] rawString;
if (isKeyDown && !modifiers && activeDeadKey != 0 && inlineStarted) {
if (isKeyDown && !modifiers && activeDeadKey != 0
&& device->input_method_started) {
// a dead key was completed
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string, true,
msg);
device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
string, true, msg);
} else if (owner->EnqueueMessage(msg) != B_OK)
delete msg;
} else if (isKeyDown) {
// start of a dead key
if (owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) {
if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) {
char *string = NULL;
int32 numBytes = 0;
keymap->GetChars(keycode, device->modifiers, 0, &string, &numBytes);
if (owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
inlineStarted = true;
if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
device->input_method_started = true;
}
}
if (!isKeyDown && !modifiers) {
if (activeDeadKey != 0) {
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
inlineStarted = false;
device->EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
device->input_method_started = false;
}
activeDeadKey = newDeadKey;
@ -883,17 +850,79 @@ KeyboardInputDevice::_SetLeds(keyboard_device *device)
keyboard_device::keyboard_device(const char *path)
: BHandler("keyboard device"),
owner(NULL),
fd(-1),
device_watcher(-1),
active(false),
input_method_started(false)
{
// todo: initialize other members
strcpy(this->path, path);
device_ref.name = get_short_name(path);
device_ref.type = B_KEYBOARD_DEVICE;
device_ref.cookie = this;
isAT = strstr(path, "keyboard/at") != NULL;
if (be_app->Lock()) {
be_app->AddHandler(this);
be_app->Unlock();
}
}
keyboard_device::~keyboard_device()
{
free(device_ref.name);
if (be_app->Lock()) {
be_app->RemoveHandler(this);
be_app->Unlock();
}
}
status_t
keyboard_device::EnqueueInlineInputMethod(int32 opcode,
const char* string, bool confirmed, BMessage* keyDown)
{
BMessage* message = new BMessage(B_INPUT_METHOD_EVENT);
if (message == NULL)
return B_NO_MEMORY;
message->AddInt32("be:opcode", opcode);
message->AddBool("be:inline_only", true);
if (string != NULL)
message->AddString("be:string", string);
if (confirmed)
message->AddBool("be:confirmed", true);
if (keyDown)
message->AddMessage("be:translated", keyDown);
if (opcode == B_INPUT_METHOD_STARTED)
message->AddMessenger("be:reply_to", this);
status_t status = owner->EnqueueMessage(message);
if (status != B_OK)
delete message;
return status;
}
void
keyboard_device::MessageReceived(BMessage *message)
{
if (message->what != B_INPUT_METHOD_EVENT) {
BHandler::MessageReceived(message);
return;
}
int32 opcode;
if (message->FindInt32("be:opcode", &opcode) != B_OK)
return;
if (opcode == B_INPUT_METHOD_STOPPED)
input_method_started = false;
}

View File

@ -10,6 +10,7 @@
#include "TMWindow.h"
#include "kb_mouse_settings.h"
#include <Handler.h>
#include <InputServerDevice.h>
#include <List.h>
@ -18,10 +19,14 @@
class KeyboardInputDevice;
struct keyboard_device {
struct keyboard_device : public BHandler {
keyboard_device(const char *path);
~keyboard_device();
virtual ~keyboard_device();
virtual void MessageReceived(BMessage* message);
status_t EnqueueInlineInputMethod(int32 opcode, const char* string = NULL,
bool confirmed = false, BMessage* keyDown = NULL);
KeyboardInputDevice *owner;
input_device_ref device_ref;
char path[B_PATH_NAME_LENGTH];
@ -30,6 +35,7 @@ struct keyboard_device {
kb_settings settings;
volatile bool active;
bool isAT;
volatile bool input_method_started;
uint32 modifiers;
};
@ -61,9 +67,6 @@ class KeyboardInputDevice : public BInputServerDevice {
status_t _AddDevice(const char *path);
status_t _RemoveDevice(const char *path);
status_t _EnqueueInlineInputMethod(int32 opcode, const char* string = NULL,
bool confirmed = false, BMessage* keyDown = NULL);
static int32 _DeviceWatcher(void *arg);
void _SetLeds(keyboard_device *device);