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.
*/
#include "KeyboardInputDevice.h"
#include "kb_mouse_driver.h"
#include <Application.h>
#include <Directory.h>
#include <Entry.h>
#include <NodeMonitor.h>
@@ -404,7 +406,7 @@ KeyboardInputDevice::SystemShuttingDown()
status_t
KeyboardInputDevice::InitFromSettings(void *cookie, uint32 opcode)
KeyboardInputDevice::_InitFromSettings(void *cookie, uint32 opcode)
{
CALLED();
@@ -431,7 +433,7 @@ KeyboardInputDevice::InitFromSettings(void *cookie, uint32 opcode)
|| opcode == B_KEY_LOCKS_CHANGED) {
fKeymap.LoadCurrent();
device->modifiers = fKeymap.Locks();
SetLeds(device);
_SetLeds(device);
}
return B_OK;
@@ -443,7 +445,7 @@ KeyboardInputDevice::InitCheck()
{
CALLED();
// TODO: this doesn't belong here!
RecursiveScan(kKeyboardDevicesDirectory);
_RecursiveScan(kKeyboardDevicesDirectory);
return B_OK;
}
@@ -460,13 +462,13 @@ KeyboardInputDevice::Start(const char *name, void *cookie)
return B_ERROR;
}
InitFromSettings(device);
_InitFromSettings(device);
char threadName[B_OS_NAME_LENGTH];
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", name);
device->active = true;
device->device_watcher = spawn_thread(DeviceWatcher, threadName,
device->device_watcher = spawn_thread(_DeviceWatcher, threadName,
kKeyboardThreadPriority, device);
if (device->device_watcher < B_OK)
return device->device_watcher;
@@ -512,17 +514,17 @@ KeyboardInputDevice::Control(const char *name, void *cookie,
LOG("Control(%s, code: %lu)\n", name, command);
if (command == B_NODE_MONITOR)
HandleMonitor(message);
_HandleMonitor(message);
else if (command >= B_KEY_MAP_CHANGED
&& command <= B_KEY_REPEAT_RATE_CHANGED) {
InitFromSettings(cookie, command);
_InitFromSettings(cookie, command);
}
return B_OK;
}
status_t
KeyboardInputDevice::HandleMonitor(BMessage *message)
KeyboardInputDevice::_HandleMonitor(BMessage *message)
{
CALLED();
int32 opcode = 0;
@@ -554,16 +556,16 @@ KeyboardInputDevice::HandleMonitor(BMessage *message)
return status;
if (opcode == B_ENTRY_CREATED)
AddDevice(path.Path());
_AddDevice(path.Path());
else
RemoveDevice(path.Path());
_RemoveDevice(path.Path());
return status;
}
status_t
KeyboardInputDevice::AddDevice(const char *path)
KeyboardInputDevice::_AddDevice(const char *path)
{
CALLED();
keyboard_device *device = new (std::nothrow) keyboard_device(path);
@@ -587,7 +589,7 @@ KeyboardInputDevice::AddDevice(const char *path)
status_t
KeyboardInputDevice::RemoveDevice(const char *path)
KeyboardInputDevice::_RemoveDevice(const char *path)
{
CALLED();
keyboard_device *device;
@@ -609,24 +611,56 @@ KeyboardInputDevice::RemoveDevice(const char *path)
}
int32
KeyboardInputDevice::DeviceWatcher(void *arg)
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)
{
CALLED();
keyboard_device *dev = (keyboard_device *)arg;
keyboard_device* device = (keyboard_device *)arg;
KeyboardInputDevice* owner = device->owner;
uint8 buffer[16];
uint8 activeDeadKey = 0;
Keymap *keymap = &dev->owner->fKeymap;
Keymap* keymap = &owner->fKeymap;
uint32 lastKeyCode = 0;
uint32 repeatCount = 1;
bool inlineStarted = false;
uint8 states[16];
memset(states, 0, sizeof(states));
LOG("%s\n", __PRETTY_FUNCTION__);
while (dev->active) {
if (ioctl(dev->fd, KB_READ, &buffer) != B_OK)
while (device->active) {
if (ioctl(device->fd, KB_READ, &buffer) != B_OK)
return 0;
uint32 keycode = 0;
@@ -635,7 +669,7 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
LOG("KB_READ :");
if (dev->isAT) {
if (device->isAT) {
at_kbd_io *at_kbd = (at_kbd_io *)buffer;
if (at_kbd->scancode > 0)
keycode = kATKeycodeMap[at_kbd->scancode-1];
@@ -685,14 +719,14 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
LOG("TeamMonitor called\n");
// show the team monitor
if (dev->owner->fTMWindow == NULL)
dev->owner->fTMWindow = new (std::nothrow) TMWindow();
if (owner->fTMWindow == NULL)
owner->fTMWindow = new (std::nothrow) TMWindow();
if (dev->owner->fTMWindow != NULL) {
dev->owner->fTMWindow->Enable();
if (owner->fTMWindow != NULL) {
owner->fTMWindow->Enable();
// 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");
}
}
@@ -707,42 +741,33 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
msg->AddInt64("when", timestamp);
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)))
|| (isKeyDown && !(dev->modifiers & modifiers)))
dev->modifiers |= modifiers;
|| (isKeyDown && !(device->modifiers & modifiers)))
device->modifiers |= modifiers;
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);
if (dev->owner->EnqueueMessage(msg)!=B_OK)
if (owner->EnqueueMessage(msg)!=B_OK)
delete msg;
if (modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))
dev->owner->SetLeds(dev);
owner->_SetLeds(device);
}
uint8 newDeadKey = 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) {
keymap->GetChars(keycode, dev->modifiers, activeDeadKey, &str, &numBytes);
keymap->GetChars(keycode, 0, 0, &str2, &numBytes2);
}
#endif
// 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);
char *string = NULL, *rawString = NULL;
int32 numBytes = 0, rawNumBytes = 0;
keymap->GetChars(keycode, device->modifiers, activeDeadKey, &string, &numBytes);
keymap->GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
BMessage *msg = new BMessage;
if (msg == NULL)
@@ -755,20 +780,20 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
msg->AddInt64("when", timestamp);
msg->AddInt32("key", keycode);
msg->AddInt32("modifiers", dev->modifiers);
msg->AddInt32("modifiers", device->modifiers);
msg->AddData("states", B_UINT8_TYPE, states, 16);
if (numBytes > 0) {
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) {
numBytes2 = 1;
delete[] str2;
str2 = str;
if (rawNumBytes <= 0) {
rawNumBytes = 1;
delete[] rawString;
rawString = string;
} else
delete[] str;
delete[] string;
if (isKeyDown && lastKeyCode == keycode) {
repeatCount++;
@@ -776,19 +801,39 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
} else
repeatCount = 1;
} else
delete[] str;
delete[] string;
if (numBytes2 > 0)
msg->AddInt32("raw_char", (uint32)((uint8)str2[0] & 0x7f));
if (rawNumBytes > 0)
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;
} 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;
}
lastKeyCode = keycode;
}
@@ -798,7 +843,7 @@ KeyboardInputDevice::DeviceWatcher(void *arg)
void
KeyboardInputDevice::RecursiveScan(const char *directory)
KeyboardInputDevice::_RecursiveScan(const char *directory)
{
CALLED();
BEntry entry;
@@ -807,15 +852,15 @@ KeyboardInputDevice::RecursiveScan(const char *directory)
BPath path;
entry.GetPath(&path);
if (entry.IsDirectory())
RecursiveScan(path.Path());
_RecursiveScan(path.Path());
else
AddDevice(path.Path());
_AddDevice(path.Path());
}
}
void
KeyboardInputDevice::SetLeds(keyboard_device *device)
KeyboardInputDevice::_SetLeds(keyboard_device *device)
{
if (device->fd < 0)
return;
@@ -834,6 +879,9 @@ KeyboardInputDevice::SetLeds(keyboard_device *device)
}
// #pragma mark -
keyboard_device::keyboard_device(const char *path)
{
// todo: initialize other members
@@ -1,38 +1,20 @@
/*****************************************************************************/
// Keyboard input server device addon
// Written by Jérôme Duval
//
// KeyboardInputDevice.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
/*
* Copyright 2004-2006, Jérôme Duval. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef KEYBOARD_INPUT_DEVICE_H
#define KEYBOARD_INPUT_DEVICE_H
#include "Keymap.h"
#include "TMWindow.h"
#include "kb_mouse_settings.h"
#include <InputServerDevice.h>
#include <List.h>
#include <stdio.h>
#include "kb_mouse_settings.h"
class KeyboardInputDevice;
@@ -53,37 +35,42 @@ struct keyboard_device {
class KeyboardInputDevice : public BInputServerDevice {
public:
KeyboardInputDevice();
~KeyboardInputDevice();
virtual status_t InitCheck();
virtual status_t Start(const char *name, void *cookie);
virtual status_t Stop(const char *name, void *cookie);
virtual status_t Control(const char *name, void *cookie,
uint32 command, BMessage *message);
virtual status_t SystemShuttingDown();
public:
KeyboardInputDevice();
~KeyboardInputDevice();
virtual status_t InitCheck();
virtual status_t Start(const char *name, void *cookie);
virtual status_t Stop(const char *name, void *cookie);
virtual status_t Control(const char *name, void *cookie,
uint32 command, BMessage *message);
virtual status_t SystemShuttingDown();
#ifdef DEBUG
static FILE *sLogFile;
static FILE *sLogFile;
#endif
private:
status_t HandleMonitor(BMessage *message);
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);
static int32 DeviceWatcher(void *arg);
void SetLeds(keyboard_device *device);
BList fDevices;
Keymap fKeymap;
TMWindow *fTMWindow;
private:
status_t _HandleMonitor(BMessage *message);
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 _EnqueueInlineInputMethod(int32 opcode, const char* string = NULL,
bool confirmed = false, BMessage* keyDown = NULL);
static int32 _DeviceWatcher(void *arg);
void _SetLeds(keyboard_device *device);
BList fDevices;
Keymap fKeymap;
TMWindow *fTMWindow;
};
extern "C" BInputServerDevice *instantiate_input_device();
@@ -99,5 +86,4 @@ extern "C" BInputServerDevice *instantiate_input_device();
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
#endif
#endif // KEYBOARD_INPUT_DEVICE_H