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
@@ -364,7 +364,8 @@ get_short_name(const char *longName)
KeyboardInputDevice::KeyboardInputDevice() KeyboardInputDevice::KeyboardInputDevice()
: fTMWindow(NULL) :
fTMWindow(NULL)
{ {
#if DEBUG #if DEBUG
if (sLogFile == NULL) if (sLogFile == NULL)
@@ -523,7 +524,7 @@ KeyboardInputDevice::Control(const char *name, void *cookie,
} }
status_t status_t
KeyboardInputDevice::_HandleMonitor(BMessage *message) KeyboardInputDevice::_HandleMonitor(BMessage *message)
{ {
CALLED(); CALLED();
@@ -572,11 +573,7 @@ KeyboardInputDevice::_AddDevice(const char *path)
if (device == NULL) if (device == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
device->fd = -1;
device->device_watcher = -1;
device->active = false;
device->owner = this; device->owner = this;
device->isAT = strstr(device->path, "keyboard/at") != NULL;
input_device_ref *devices[2]; input_device_ref *devices[2];
devices[0] = &device->device_ref; 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 /*static*/ int32
KeyboardInputDevice::_DeviceWatcher(void *arg) KeyboardInputDevice::_DeviceWatcher(void *arg)
{ {
@@ -652,7 +619,6 @@ KeyboardInputDevice::_DeviceWatcher(void *arg)
Keymap* keymap = &owner->fKeymap; Keymap* keymap = &owner->fKeymap;
uint32 lastKeyCode = 0; uint32 lastKeyCode = 0;
uint32 repeatCount = 1; uint32 repeatCount = 1;
bool inlineStarted = false;
uint8 states[16]; uint8 states[16];
memset(states, 0, sizeof(states)); memset(states, 0, sizeof(states));
@@ -808,28 +774,29 @@ KeyboardInputDevice::_DeviceWatcher(void *arg)
delete[] rawString; delete[] rawString;
if (isKeyDown && !modifiers && activeDeadKey != 0 && inlineStarted) { if (isKeyDown && !modifiers && activeDeadKey != 0
&& device->input_method_started) {
// a dead key was completed // a dead key was completed
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string, true, device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
msg); string, true, msg);
} else if (owner->EnqueueMessage(msg) != B_OK) } else if (owner->EnqueueMessage(msg) != B_OK)
delete msg; delete msg;
} else if (isKeyDown) { } else if (isKeyDown) {
// start of a dead key // 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; char *string = NULL;
int32 numBytes = 0; int32 numBytes = 0;
keymap->GetChars(keycode, device->modifiers, 0, &string, &numBytes); keymap->GetChars(keycode, device->modifiers, 0, &string, &numBytes);
if (owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK) if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
inlineStarted = true; device->input_method_started = true;
} }
} }
if (!isKeyDown && !modifiers) { if (!isKeyDown && !modifiers) {
if (activeDeadKey != 0) { if (activeDeadKey != 0) {
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED); device->EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
inlineStarted = false; device->input_method_started = false;
} }
activeDeadKey = newDeadKey; activeDeadKey = newDeadKey;
@@ -883,17 +850,79 @@ KeyboardInputDevice::_SetLeds(keyboard_device *device)
keyboard_device::keyboard_device(const char *path) 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); strcpy(this->path, path);
device_ref.name = get_short_name(path); device_ref.name = get_short_name(path);
device_ref.type = B_KEYBOARD_DEVICE; device_ref.type = B_KEYBOARD_DEVICE;
device_ref.cookie = this; 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() keyboard_device::~keyboard_device()
{ {
free(device_ref.name); 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;
} }
@@ -10,6 +10,7 @@
#include "TMWindow.h" #include "TMWindow.h"
#include "kb_mouse_settings.h" #include "kb_mouse_settings.h"
#include <Handler.h>
#include <InputServerDevice.h> #include <InputServerDevice.h>
#include <List.h> #include <List.h>
@@ -18,10 +19,14 @@
class KeyboardInputDevice; class KeyboardInputDevice;
struct keyboard_device { struct keyboard_device : public BHandler {
keyboard_device(const char *path); 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; KeyboardInputDevice *owner;
input_device_ref device_ref; input_device_ref device_ref;
char path[B_PATH_NAME_LENGTH]; char path[B_PATH_NAME_LENGTH];
@@ -30,6 +35,7 @@ struct keyboard_device {
kb_settings settings; kb_settings settings;
volatile bool active; volatile bool active;
bool isAT; bool isAT;
volatile bool input_method_started;
uint32 modifiers; uint32 modifiers;
}; };
@@ -61,9 +67,6 @@ class KeyboardInputDevice : public BInputServerDevice {
status_t _AddDevice(const char *path); status_t _AddDevice(const char *path);
status_t _RemoveDevice(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); static int32 _DeviceWatcher(void *arg);
void _SetLeds(keyboard_device *device); void _SetLeds(keyboard_device *device);