The keyboard input device is now using the new inline-only input method extension

for dead keys - IOW you'll now see dead keys in BTextViews as you would see real
input methods like canna. Non-input-method-aware views won't see a difference to
the previous behaviour, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19117 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-10-25 11:55:43 +00:00
parent b735e46de3
commit d32e5bae5e
2 changed files with 157 additions and 123 deletions
@@ -3,9 +3,11 @@
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include "KeyboardInputDevice.h" #include "KeyboardInputDevice.h"
#include "kb_mouse_driver.h" #include "kb_mouse_driver.h"
#include <Application.h>
#include <Directory.h> #include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <NodeMonitor.h> #include <NodeMonitor.h>
@@ -404,7 +406,7 @@ KeyboardInputDevice::SystemShuttingDown()
status_t status_t
KeyboardInputDevice::InitFromSettings(void *cookie, uint32 opcode) KeyboardInputDevice::_InitFromSettings(void *cookie, uint32 opcode)
{ {
CALLED(); CALLED();
@@ -431,7 +433,7 @@ KeyboardInputDevice::InitFromSettings(void *cookie, uint32 opcode)
|| opcode == B_KEY_LOCKS_CHANGED) { || opcode == B_KEY_LOCKS_CHANGED) {
fKeymap.LoadCurrent(); fKeymap.LoadCurrent();
device->modifiers = fKeymap.Locks(); device->modifiers = fKeymap.Locks();
SetLeds(device); _SetLeds(device);
} }
return B_OK; return B_OK;
@@ -443,7 +445,7 @@ KeyboardInputDevice::InitCheck()
{ {
CALLED(); CALLED();
// TODO: this doesn't belong here! // TODO: this doesn't belong here!
RecursiveScan(kKeyboardDevicesDirectory); _RecursiveScan(kKeyboardDevicesDirectory);
return B_OK; return B_OK;
} }
@@ -460,13 +462,13 @@ KeyboardInputDevice::Start(const char *name, void *cookie)
return B_ERROR; return B_ERROR;
} }
InitFromSettings(device); _InitFromSettings(device);
char threadName[B_OS_NAME_LENGTH]; char threadName[B_OS_NAME_LENGTH];
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name); snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name);
device->active = true; device->active = true;
device->device_watcher = spawn_thread(DeviceWatcher, threadName, device->device_watcher = spawn_thread(_DeviceWatcher, threadName,
kKeyboardThreadPriority, device); kKeyboardThreadPriority, device);
if (device->device_watcher < B_OK) if (device->device_watcher < B_OK)
return device->device_watcher; return device->device_watcher;
@@ -512,17 +514,17 @@ KeyboardInputDevice::Control(const char *name, void *cookie,
LOG("Control(%s, code: %lu)\n", name, command); LOG("Control(%s, code: %lu)\n", name, command);
if (command == B_NODE_MONITOR) if (command == B_NODE_MONITOR)
HandleMonitor(message); _HandleMonitor(message);
else if (command >= B_KEY_MAP_CHANGED else if (command >= B_KEY_MAP_CHANGED
&& command <= B_KEY_REPEAT_RATE_CHANGED) { && command <= B_KEY_REPEAT_RATE_CHANGED) {
InitFromSettings(cookie, command); _InitFromSettings(cookie, command);
} }
return B_OK; return B_OK;
} }
status_t status_t
KeyboardInputDevice::HandleMonitor(BMessage *message) KeyboardInputDevice::_HandleMonitor(BMessage *message)
{ {
CALLED(); CALLED();
int32 opcode = 0; int32 opcode = 0;
@@ -554,16 +556,16 @@ KeyboardInputDevice::HandleMonitor(BMessage *message)
return status; return status;
if (opcode == B_ENTRY_CREATED) if (opcode == B_ENTRY_CREATED)
AddDevice(path.Path()); _AddDevice(path.Path());
else else
RemoveDevice(path.Path()); _RemoveDevice(path.Path());
return status; return status;
} }
status_t status_t
KeyboardInputDevice::AddDevice(const char *path) KeyboardInputDevice::_AddDevice(const char *path)
{ {
CALLED(); CALLED();
keyboard_device *device = new (std::nothrow) keyboard_device(path); keyboard_device *device = new (std::nothrow) keyboard_device(path);
@@ -587,7 +589,7 @@ KeyboardInputDevice::AddDevice(const char *path)
status_t status_t
KeyboardInputDevice::RemoveDevice(const char *path) KeyboardInputDevice::_RemoveDevice(const char *path)
{ {
CALLED(); CALLED();
keyboard_device *device; keyboard_device *device;
@@ -609,24 +611,56 @@ KeyboardInputDevice::RemoveDevice(const char *path)
} }
int32 status_t
KeyboardInputDevice::DeviceWatcher(void *arg) 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)
{ {
CALLED(); CALLED();
keyboard_device *dev = (keyboard_device *)arg; keyboard_device* device = (keyboard_device *)arg;
KeyboardInputDevice* owner = device->owner;
uint8 buffer[16]; uint8 buffer[16];
uint8 activeDeadKey = 0; uint8 activeDeadKey = 0;
Keymap *keymap = &dev->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));
LOG("%s\n", __PRETTY_FUNCTION__); LOG("%s\n", __PRETTY_FUNCTION__);
while (dev->active) { while (device->active) {
if (ioctl(dev->fd, KB_READ, &buffer) != B_OK) if (ioctl(device->fd, KB_READ, &buffer) != B_OK)
return 0; return 0;
uint32 keycode = 0; uint32 keycode = 0;
@@ -635,7 +669,7 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
LOG("KB_READ :"); LOG("KB_READ :");
if (dev->isAT) { if (device->isAT) {
at_kbd_io *at_kbd = (at_kbd_io *)buffer; at_kbd_io *at_kbd = (at_kbd_io *)buffer;
if (at_kbd->scancode > 0) if (at_kbd->scancode > 0)
keycode = kATKeycodeMap[at_kbd->scancode-1]; keycode = kATKeycodeMap[at_kbd->scancode-1];
@@ -685,14 +719,14 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
LOG("TeamMonitor called\n"); LOG("TeamMonitor called\n");
// show the team monitor // show the team monitor
if (dev->owner->fTMWindow == NULL) if (owner->fTMWindow == NULL)
dev->owner->fTMWindow = new (std::nothrow) TMWindow(); owner->fTMWindow = new (std::nothrow) TMWindow();
if (dev->owner->fTMWindow != NULL) { if (owner->fTMWindow != NULL) {
dev->owner->fTMWindow->Enable(); owner->fTMWindow->Enable();
// cancel timer only for R5 // cancel timer only for R5
if (ioctl(dev->fd, KB_CANCEL_CONTROL_ALT_DEL, NULL) == B_OK) if (ioctl(device->fd, KB_CANCEL_CONTROL_ALT_DEL, NULL) == B_OK)
LOG("KB_CANCEL_CONTROL_ALT_DEL : OK\n"); LOG("KB_CANCEL_CONTROL_ALT_DEL : OK\n");
} }
} }
@@ -707,42 +741,33 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
msg->AddInt64("when", timestamp); msg->AddInt64("when", timestamp);
msg->what = B_MODIFIERS_CHANGED; msg->what = B_MODIFIERS_CHANGED;
msg->AddInt32("be:old_modifiers", dev->modifiers); msg->AddInt32("be:old_modifiers", device->modifiers);
if ((isKeyDown && !(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))) if ((isKeyDown && !(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)))
|| (isKeyDown && !(dev->modifiers & modifiers))) || (isKeyDown && !(device->modifiers & modifiers)))
dev->modifiers |= modifiers; device->modifiers |= modifiers;
else else
dev->modifiers &= ~modifiers; device->modifiers &= ~modifiers;
msg->AddInt32("modifiers", dev->modifiers); msg->AddInt32("modifiers", device->modifiers);
msg->AddData("states", B_UINT8_TYPE, states, 16); msg->AddData("states", B_UINT8_TYPE, states, 16);
if (dev->owner->EnqueueMessage(msg)!=B_OK) if (owner->EnqueueMessage(msg)!=B_OK)
delete msg; delete msg;
if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK)) if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))
dev->owner->SetLeds(dev); owner->_SetLeds(device);
} }
uint8 newDeadKey = 0; uint8 newDeadKey = 0;
if (activeDeadKey == 0) if (activeDeadKey == 0)
newDeadKey = keymap->IsDeadKey(keycode, dev->modifiers); newDeadKey = keymap->IsDeadKey(keycode, device->modifiers);
// new dead key behaviour
#if 0
if (newDeadKey == 0) { if (newDeadKey == 0) {
keymap->GetChars(keycode, dev->modifiers, activeDeadKey, &str, &numBytes); char *string = NULL, *rawString = NULL;
keymap->GetChars(keycode, 0, 0, &str2, &numBytes2); int32 numBytes = 0, rawNumBytes = 0;
} keymap->GetChars(keycode, device->modifiers, activeDeadKey, &string, &numBytes);
#endif keymap->GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
// R5-like dead key behaviour
if (newDeadKey == 0) {
char *str = NULL, *str2 = NULL;
int32 numBytes = 0, numBytes2 = 0;
keymap->GetChars(keycode, dev->modifiers, activeDeadKey, &str, &numBytes);
keymap->GetChars(keycode, 0, 0, &str2, &numBytes2);
BMessage *msg = new BMessage; BMessage *msg = new BMessage;
if (msg == NULL) if (msg == NULL)
@@ -755,20 +780,20 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
msg->AddInt64("when", timestamp); msg->AddInt64("when", timestamp);
msg->AddInt32("key", keycode); msg->AddInt32("key", keycode);
msg->AddInt32("modifiers", dev->modifiers); msg->AddInt32("modifiers", device->modifiers);
msg->AddData("states", B_UINT8_TYPE, states, 16); msg->AddData("states", B_UINT8_TYPE, states, 16);
if (numBytes > 0) { if (numBytes > 0) {
for (int i = 0; i < numBytes; i++) { for (int i = 0; i < numBytes; i++) {
msg->AddInt8("byte", (int8)str[i]); msg->AddInt8("byte", (int8)string[i]);
} }
msg->AddString("bytes", str); msg->AddString("bytes", string);
if (numBytes2 <= 0) { if (rawNumBytes <= 0) {
numBytes2 = 1; rawNumBytes = 1;
delete[] str2; delete[] rawString;
str2 = str; rawString = string;
} else } else
delete[] str; delete[] string;
if (isKeyDown && lastKeyCode == keycode) { if (isKeyDown && lastKeyCode == keycode) {
repeatCount++; repeatCount++;
@@ -776,19 +801,39 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
} else } else
repeatCount = 1; repeatCount = 1;
} else } else
delete[] str; delete[] string;
if (numBytes2 > 0) if (rawNumBytes > 0)
msg->AddInt32("raw_char", (uint32)((uint8)str2[0] & 0x7f)); msg->AddInt32("raw_char", (uint32)((uint8)rawString[0] & 0x7f));
delete[] str2; delete[] rawString;
if (dev->owner->EnqueueMessage(msg) != B_OK) if (isKeyDown && !modifiers && activeDeadKey != 0 && inlineStarted) {
// a dead key was completed
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string, true,
msg);
} else if (owner->EnqueueMessage(msg) != B_OK)
delete msg; delete msg;
} else if (isKeyDown) {
// start of a dead key
if (owner->_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 (!isKeyDown && !modifiers) if (!isKeyDown && !modifiers) {
if (activeDeadKey != 0) {
owner->_EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
inlineStarted = false;
}
activeDeadKey = newDeadKey; activeDeadKey = newDeadKey;
}
lastKeyCode = keycode; lastKeyCode = keycode;
} }
@@ -798,7 +843,7 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
void void
KeyboardInputDevice::RecursiveScan(const char *directory) KeyboardInputDevice::_RecursiveScan(const char *directory)
{ {
CALLED(); CALLED();
BEntry entry; BEntry entry;
@@ -807,15 +852,15 @@ KeyboardInputDevice::RecursiveScan(const char *directory)
BPath path; BPath path;
entry.GetPath(&path); entry.GetPath(&path);
if (entry.IsDirectory()) if (entry.IsDirectory())
RecursiveScan(path.Path()); _RecursiveScan(path.Path());
else else
AddDevice(path.Path()); _AddDevice(path.Path());
} }
} }
void void
KeyboardInputDevice::SetLeds(keyboard_device *device) KeyboardInputDevice::_SetLeds(keyboard_device *device)
{ {
if (device->fd < 0) if (device->fd < 0)
return; return;
@@ -834,6 +879,9 @@ KeyboardInputDevice::SetLeds(keyboard_device *device)
} }
// #pragma mark -
keyboard_device::keyboard_device(const char *path) keyboard_device::keyboard_device(const char *path)
{ {
// todo: initialize other members // todo: initialize other members
@@ -1,38 +1,20 @@
/*****************************************************************************/ /*
// Keyboard input server device addon * Copyright 2004-2006, Jérôme Duval. All rights reserved.
// Written by Jérôme Duval * Distributed under the terms of the MIT License.
// */
// KeyboardInputDevice.h #ifndef KEYBOARD_INPUT_DEVICE_H
// #define KEYBOARD_INPUT_DEVICE_H
// Copyright (c) 2004 Haiku Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/
#ifndef __KEYBOARDINPUTDEVICE_H
#define __KEYBOARDINPUTDEVICE_H
#include "Keymap.h" #include "Keymap.h"
#include "TMWindow.h" #include "TMWindow.h"
#include "kb_mouse_settings.h"
#include <InputServerDevice.h> #include <InputServerDevice.h>
#include <List.h> #include <List.h>
#include <stdio.h> #include <stdio.h>
#include "kb_mouse_settings.h"
class KeyboardInputDevice; class KeyboardInputDevice;
@@ -53,37 +35,42 @@ struct keyboard_device {
class KeyboardInputDevice : public BInputServerDevice { class KeyboardInputDevice : public BInputServerDevice {
public: public:
KeyboardInputDevice(); KeyboardInputDevice();
~KeyboardInputDevice(); ~KeyboardInputDevice();
virtual status_t InitCheck(); virtual status_t InitCheck();
virtual status_t Start(const char *name, void *cookie); virtual status_t Start(const char *name, void *cookie);
virtual status_t Stop(const char *name, void *cookie); virtual status_t Stop(const char *name, void *cookie);
virtual status_t Control(const char *name, void *cookie, virtual status_t Control(const char *name, void *cookie,
uint32 command, BMessage *message); uint32 command, BMessage *message);
virtual status_t SystemShuttingDown(); virtual status_t SystemShuttingDown();
#ifdef DEBUG #ifdef DEBUG
static FILE *sLogFile; static FILE *sLogFile;
#endif #endif
private:
status_t HandleMonitor(BMessage *message); private:
status_t InitFromSettings(void *cookie, uint32 opcode = 0); status_t _HandleMonitor(BMessage *message);
void RecursiveScan(const char *directory); status_t _InitFromSettings(void *cookie, uint32 opcode = 0);
void _RecursiveScan(const char *directory);
status_t AddDevice(const char *path);
status_t RemoveDevice(const char *path); status_t _AddDevice(const char *path);
status_t _RemoveDevice(const char *path);
static int32 DeviceWatcher(void *arg);
status_t _EnqueueInlineInputMethod(int32 opcode, const char* string = NULL,
void SetLeds(keyboard_device *device); bool confirmed = false, BMessage* keyDown = NULL);
BList fDevices; static int32 _DeviceWatcher(void *arg);
Keymap fKeymap;
TMWindow *fTMWindow; void _SetLeds(keyboard_device *device);
BList fDevices;
Keymap fKeymap;
TMWindow *fTMWindow;
}; };
extern "C" BInputServerDevice *instantiate_input_device(); extern "C" BInputServerDevice *instantiate_input_device();
@@ -99,5 +86,4 @@ extern "C" BInputServerDevice *instantiate_input_device();
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__) #define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
#endif #endif // KEYBOARD_INPUT_DEVICE_H