Sorry for the confusing patch...
* Made KeyboardInputDevice more similar to MouseInputDevice, the object to
track individual keyboards has become the class KeyboardDevice. Moved
much functionality that used to be in KeyboardInputDevice into
KeyboardDevice.
Functionally, it should still be the same, but there are two important
changes:
- Each KeyboardDevice now has it's own Keymap. At first, it is not
visible by the user, since all KeyboardDevices still adopt the keymap
if the user reconfigures it. But it will make it easier to assign
individual keymaps to each attached keyboard (and perhaps associate them
with a vendor/product or some other means). The more immediate side effect
is that there is no longer a confusion about the keyboard locks. If
you press NumLock on your external keyboard, it will no longer enable
NumLock on your notebooks internal keyboard.
- KeyboardDevice now has a Stop() method, which it will call in it's
destructor. This will make sure that the control thread is cleanly
exited and does not end up invoking methods on a deleted object.
* Rewrote the tracing implementation in MouseInputDevice.cpp. At least it
helped track me down the following problem:
* Both KeyboardDevice and MouseDevice now set fActive to "false" *before*
closing the device. Since the control threads run at high priority, chances
are high that rescheduling happens as soon as the device unblocks in
ioctl() and returns an error. In that case, the control threads would
check fActive and it would still be "true" and the whole idea of bailing
out because we're already in Stop() would not work, causing a double free
in the end.
All of this is nice and more correct, but input_server is still crashing
when restarting it via "input_server -q"... :-(
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28352 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -371,242 +371,195 @@ get_short_name(const char* longName)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
KeyboardInputDevice::KeyboardInputDevice()
|
KeyboardDevice::KeyboardDevice(KeyboardInputDevice* owner, const char* path)
|
||||||
:
|
: BHandler("keyboard device"),
|
||||||
fDevices(2, true),
|
fOwner(owner),
|
||||||
fTeamMonitorWindow(NULL),
|
fFD(-1),
|
||||||
|
fThread(-1),
|
||||||
|
fActive(false),
|
||||||
|
fInputMethodStarted(false),
|
||||||
fKeymapLock("keymap lock")
|
fKeymapLock("keymap lock")
|
||||||
{
|
{
|
||||||
CALLED();
|
strcpy(fPath, path);
|
||||||
|
fDeviceRef.name = get_short_name(path);
|
||||||
|
fDeviceRef.type = B_KEYBOARD_DEVICE;
|
||||||
|
fDeviceRef.cookie = this;
|
||||||
|
|
||||||
StartMonitoringDevice(kKeyboardDevicesDirectory);
|
fIsAT = strstr(path, "keyboard/at") != NULL;
|
||||||
_RecursiveScan(kKeyboardDevicesDirectory);
|
|
||||||
|
if (be_app->Lock()) {
|
||||||
|
be_app->AddHandler(this);
|
||||||
|
be_app->Unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KeyboardInputDevice::~KeyboardInputDevice()
|
KeyboardDevice::~KeyboardDevice()
|
||||||
{
|
{
|
||||||
CALLED();
|
if (fActive)
|
||||||
StopMonitoringDevice(kKeyboardDevicesDirectory);
|
Stop();
|
||||||
|
|
||||||
|
free(fDeviceRef.name);
|
||||||
|
|
||||||
|
if (be_app->Lock()) {
|
||||||
|
be_app->RemoveHandler(this);
|
||||||
|
be_app->Unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::SystemShuttingDown()
|
KeyboardDevice::EnqueueInlineInputMethod(int32 opcode,
|
||||||
|
const char* string, bool confirmed, BMessage* keyDown)
|
||||||
{
|
{
|
||||||
CALLED();
|
BMessage* message = new BMessage(B_INPUT_METHOD_EVENT);
|
||||||
if (fTeamMonitorWindow)
|
if (message == NULL)
|
||||||
fTeamMonitorWindow->PostMessage(SYSTEM_SHUTTING_DOWN);
|
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 = fOwner->EnqueueMessage(message);
|
||||||
|
if (status != B_OK)
|
||||||
|
delete message;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyboardDevice::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)
|
||||||
|
fInputMethodStarted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardDevice::Start()
|
||||||
|
{
|
||||||
|
if ((fFD = open(fPath, O_RDWR)) < B_OK) {
|
||||||
|
fprintf(stderr, "error when opening %s: %s\n", fPath, strerror(errno));
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitFromSettings();
|
||||||
|
|
||||||
|
char threadName[B_OS_NAME_LENGTH];
|
||||||
|
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||||
|
|
||||||
|
fActive = true;
|
||||||
|
fThread = spawn_thread(_ThreadEntry, threadName,
|
||||||
|
kKeyboardThreadPriority, this);
|
||||||
|
if (fThread < B_OK)
|
||||||
|
return fThread;
|
||||||
|
|
||||||
|
resume_thread(fThread);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyboardDevice::Stop()
|
||||||
|
{
|
||||||
|
fActive = false;
|
||||||
|
|
||||||
|
close(fFD);
|
||||||
|
fFD = -1;
|
||||||
|
|
||||||
|
if (fThread >= 0) {
|
||||||
|
suspend_thread(fThread);
|
||||||
|
resume_thread(fThread);
|
||||||
|
status_t dummy;
|
||||||
|
wait_for_thread(fThread, &dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::_InitFromSettings(void* cookie, uint32 opcode)
|
KeyboardDevice::InitFromSettings(uint32 opcode)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
keyboard_device* device = (keyboard_device*)cookie;
|
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
||||||
if (get_key_repeat_rate(&device->settings.key_repeat_rate) != B_OK)
|
if (get_key_repeat_rate(&fSettings.key_repeat_rate) != B_OK)
|
||||||
LOG_ERR("error when get_key_repeat_rate\n");
|
LOG_ERR("error when get_key_repeat_rate\n");
|
||||||
else if (ioctl(device->fd, KB_SET_KEY_REPEAT_RATE,
|
else if (ioctl(fFD, KB_SET_KEY_REPEAT_RATE,
|
||||||
&device->settings.key_repeat_rate) != B_OK)
|
&fSettings.key_repeat_rate) != B_OK)
|
||||||
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", device->fd);
|
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", fFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
||||||
if (get_key_repeat_delay(&device->settings.key_repeat_delay) != B_OK)
|
if (get_key_repeat_delay(&fSettings.key_repeat_delay) != B_OK)
|
||||||
LOG_ERR("error when get_key_repeat_delay\n");
|
LOG_ERR("error when get_key_repeat_delay\n");
|
||||||
else if (ioctl(device->fd, KB_SET_KEY_REPEAT_DELAY,
|
else if (ioctl(fFD, KB_SET_KEY_REPEAT_DELAY,
|
||||||
&device->settings.key_repeat_delay) != B_OK)
|
&fSettings.key_repeat_delay) != B_OK)
|
||||||
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", device->fd);
|
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", fFD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
||||||
|| opcode == B_KEY_LOCKS_CHANGED) {
|
|| opcode == B_KEY_LOCKS_CHANGED) {
|
||||||
BAutolock lock(fKeymapLock);
|
BAutolock lock(fKeymapLock);
|
||||||
fKeymap.LoadCurrent();
|
fKeymap.LoadCurrent();
|
||||||
device->modifiers = fKeymap.Locks();
|
fModifiers = fKeymap.Locks();
|
||||||
_SetLeds(device);
|
UpdateLEDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
KeyboardInputDevice::InitCheck()
|
KeyboardDevice::UpdateLEDs()
|
||||||
{
|
{
|
||||||
CALLED();
|
if (fFD < 0)
|
||||||
return BInputServerDevice::InitCheck();
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
|
uint32 locks = fModifiers;
|
||||||
|
char lockIO[3];
|
||||||
|
memset(lockIO, 0, sizeof(lockIO));
|
||||||
|
if (locks & B_NUM_LOCK)
|
||||||
|
lockIO[0] = 1;
|
||||||
|
if (locks & B_CAPS_LOCK)
|
||||||
|
lockIO[1] = 1;
|
||||||
|
if (locks & B_SCROLL_LOCK)
|
||||||
|
lockIO[2] = 1;
|
||||||
|
|
||||||
status_t
|
ioctl(fFD, KB_SET_LEDS, &lockIO);
|
||||||
KeyboardInputDevice::Start(const char* name, void* cookie)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
keyboard_device* device = (keyboard_device*)cookie;
|
|
||||||
|
|
||||||
if ((device->fd = open(device->path, O_RDWR)) < B_OK) {
|
|
||||||
fprintf(stderr, "error when opening %s: %s\n", device->path, strerror(errno));
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
_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,
|
|
||||||
kKeyboardThreadPriority, device);
|
|
||||||
if (device->device_watcher < B_OK)
|
|
||||||
return device->device_watcher;
|
|
||||||
|
|
||||||
resume_thread(device->device_watcher);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardInputDevice::Stop(const char* name, void* cookie)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
keyboard_device* device = (keyboard_device*)cookie;
|
|
||||||
|
|
||||||
LOG("Stop(%s)\n", name);
|
|
||||||
|
|
||||||
close(device->fd);
|
|
||||||
device->fd = -1;
|
|
||||||
|
|
||||||
device->active = false;
|
|
||||||
if (device->device_watcher >= 0) {
|
|
||||||
suspend_thread(device->device_watcher);
|
|
||||||
resume_thread(device->device_watcher);
|
|
||||||
status_t dummy;
|
|
||||||
wait_for_thread(device->device_watcher, &dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fTeamMonitorWindow) {
|
|
||||||
fTeamMonitorWindow->PostMessage(B_QUIT_REQUESTED);
|
|
||||||
fTeamMonitorWindow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardInputDevice::Control(const char* name, void* cookie,
|
|
||||||
uint32 command, BMessage* message)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
LOG("Control(%s, code: %lu)\n", name, command);
|
|
||||||
|
|
||||||
if (command == B_NODE_MONITOR)
|
|
||||||
_HandleMonitor(message);
|
|
||||||
else if (command >= B_KEY_MAP_CHANGED
|
|
||||||
&& command <= B_KEY_REPEAT_RATE_CHANGED) {
|
|
||||||
_InitFromSettings(cookie, command);
|
|
||||||
}
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardInputDevice::_HandleMonitor(BMessage* message)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
const char* path;
|
|
||||||
int32 opcode;
|
|
||||||
if (message->FindInt32("opcode", &opcode) != B_OK
|
|
||||||
|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)
|
|
||||||
|| message->FindString("path", &path) != B_OK)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
if (opcode == B_ENTRY_CREATED)
|
|
||||||
return _AddDevice(path);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
return _RemoveDevice(path);
|
|
||||||
#else
|
|
||||||
// Don't handle B_ENTRY_REMOVED, let the control thread take care of it.
|
|
||||||
return B_OK;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
keyboard_device*
|
|
||||||
KeyboardInputDevice::_FindDevice(const char* path) const
|
|
||||||
{
|
|
||||||
for (int i = fDevices.CountItems() - 1; i >= 0; i--) {
|
|
||||||
keyboard_device* device = fDevices.ItemAt(i);
|
|
||||||
if (strcmp(device->path, path) == 0)
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardInputDevice::_AddDevice(const char* path)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
_RemoveDevice(path);
|
|
||||||
|
|
||||||
keyboard_device* device = new(std::nothrow) keyboard_device(path);
|
|
||||||
if (device == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
device->owner = this;
|
|
||||||
|
|
||||||
input_device_ref* devices[2];
|
|
||||||
devices[0] = &device->device_ref;
|
|
||||||
devices[1] = NULL;
|
|
||||||
|
|
||||||
fDevices.AddItem(device);
|
|
||||||
|
|
||||||
return RegisterDevices(devices);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardInputDevice::_RemoveDevice(const char* path)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
keyboard_device* device = _FindDevice(path);
|
|
||||||
if (device == NULL)
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
input_device_ref* devices[2];
|
|
||||||
devices[0] = &device->device_ref;
|
|
||||||
devices[1] = NULL;
|
|
||||||
|
|
||||||
UnregisterDevices(devices);
|
|
||||||
|
|
||||||
fDevices.RemoveItem(device);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int32
|
/*static*/ int32
|
||||||
KeyboardInputDevice::_DeviceWatcher(void* arg)
|
KeyboardDevice::_ThreadEntry(void* arg)
|
||||||
|
{
|
||||||
|
KeyboardDevice* device = (KeyboardDevice*)arg;
|
||||||
|
return device->_Thread();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
KeyboardDevice::_Thread()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
keyboard_device* device = (keyboard_device*)arg;
|
|
||||||
KeyboardInputDevice* owner = device->owner;
|
|
||||||
uint8 buffer[16];
|
uint8 buffer[16];
|
||||||
uint8 activeDeadKey = 0;
|
uint8 activeDeadKey = 0;
|
||||||
Keymap* keymap = &owner->fKeymap;
|
|
||||||
uint32 lastKeyCode = 0;
|
uint32 lastKeyCode = 0;
|
||||||
uint32 repeatCount = 1;
|
uint32 repeatCount = 1;
|
||||||
uint8 states[16];
|
uint8 states[16];
|
||||||
@@ -616,13 +569,13 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
|
|
||||||
LOG("%s\n", __PRETTY_FUNCTION__);
|
LOG("%s\n", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
while (device->active) {
|
while (fActive) {
|
||||||
if (ioctl(device->fd, KB_READ, &buffer) != B_OK) {
|
if (ioctl(fFD, KB_READ, &buffer) != B_OK) {
|
||||||
if (device->active) {
|
if (fActive) {
|
||||||
device->device_watcher = -1;
|
fThread = -1;
|
||||||
device->owner->_RemoveDevice(device->path);
|
fOwner->_RemoveDevice(fPath);
|
||||||
} else {
|
} else {
|
||||||
// In case active is already false, another thread
|
// In case fActive is already false, another thread
|
||||||
// waits for this thread to quit, and may already hold
|
// waits for this thread to quit, and may already hold
|
||||||
// locks that _RemoveDevice() wants to acquire. In another
|
// locks that _RemoveDevice() wants to acquire. In another
|
||||||
// words, the device is already being removed, so we simply
|
// words, the device is already being removed, so we simply
|
||||||
@@ -638,7 +591,7 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
|
|
||||||
LOG("KB_READ :");
|
LOG("KB_READ :");
|
||||||
|
|
||||||
if (device->isAT) {
|
if (fIsAT) {
|
||||||
at_kbd_io* atKeyboard = (at_kbd_io*)buffer;
|
at_kbd_io* atKeyboard = (at_kbd_io*)buffer;
|
||||||
if (atKeyboard->scancode > 0)
|
if (atKeyboard->scancode > 0)
|
||||||
keycode = kATKeycodeMap[atKeyboard->scancode - 1];
|
keycode = kATKeycodeMap[atKeyboard->scancode - 1];
|
||||||
@@ -687,27 +640,27 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
LOG("TeamMonitor called\n");
|
LOG("TeamMonitor called\n");
|
||||||
|
|
||||||
// show the team monitor
|
// show the team monitor
|
||||||
if (owner->fTeamMonitorWindow == NULL)
|
if (fOwner->fTeamMonitorWindow == NULL)
|
||||||
owner->fTeamMonitorWindow = new(std::nothrow) TeamMonitorWindow();
|
fOwner->fTeamMonitorWindow = new(std::nothrow) TeamMonitorWindow();
|
||||||
|
|
||||||
if (owner->fTeamMonitorWindow != NULL)
|
if (fOwner->fTeamMonitorWindow != NULL)
|
||||||
owner->fTeamMonitorWindow->Enable();
|
fOwner->fTeamMonitorWindow->Enable();
|
||||||
|
|
||||||
ctrlAltDelPressed = true;
|
ctrlAltDelPressed = true;
|
||||||
}
|
}
|
||||||
if (ctrlAltDelPressed) {
|
if (ctrlAltDelPressed) {
|
||||||
if (owner->fTeamMonitorWindow != NULL) {
|
if (fOwner->fTeamMonitorWindow != NULL) {
|
||||||
BMessage message(kMsgCtrlAltDelPressed);
|
BMessage message(kMsgCtrlAltDelPressed);
|
||||||
message.AddBool("key down", isKeyDown);
|
message.AddBool("key down", isKeyDown);
|
||||||
owner->fTeamMonitorWindow->PostMessage(&message);
|
fOwner->fTeamMonitorWindow->PostMessage(&message);
|
||||||
}
|
}
|
||||||
if (!isKeyDown)
|
if (!isKeyDown)
|
||||||
ctrlAltDelPressed = false;
|
ctrlAltDelPressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAutolock lock(owner->fKeymapLock);
|
BAutolock lock(fKeymapLock);
|
||||||
|
|
||||||
uint32 modifiers = keymap->Modifier(keycode);
|
uint32 modifiers = fKeymap.Modifier(keycode);
|
||||||
if (modifiers
|
if (modifiers
|
||||||
&& (!(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))
|
&& (!(modifiers & (B_CAPS_LOCK | B_NUM_LOCK | B_SCROLL_LOCK))
|
||||||
|| isKeyDown)) {
|
|| isKeyDown)) {
|
||||||
@@ -717,34 +670,34 @@ 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", device->modifiers);
|
msg->AddInt32("be:old_modifiers", fModifiers);
|
||||||
|
|
||||||
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 && !(device->modifiers & modifiers)))
|
|| (isKeyDown && !(fModifiers & modifiers)))
|
||||||
device->modifiers |= modifiers;
|
fModifiers |= modifiers;
|
||||||
else
|
else
|
||||||
device->modifiers &= ~modifiers;
|
fModifiers &= ~modifiers;
|
||||||
|
|
||||||
msg->AddInt32("modifiers", device->modifiers);
|
msg->AddInt32("modifiers", fModifiers);
|
||||||
msg->AddData("states", B_UINT8_TYPE, states, 16);
|
msg->AddData("states", B_UINT8_TYPE, states, 16);
|
||||||
|
|
||||||
if (owner->EnqueueMessage(msg) != B_OK)
|
if (fOwner->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))
|
||||||
owner->_SetLeds(device);
|
UpdateLEDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 newDeadKey = 0;
|
uint8 newDeadKey = 0;
|
||||||
if (activeDeadKey == 0)
|
if (activeDeadKey == 0)
|
||||||
newDeadKey = keymap->IsDeadKey(keycode, device->modifiers);
|
newDeadKey = fKeymap.IsDeadKey(keycode, fModifiers);
|
||||||
|
|
||||||
if (newDeadKey == 0) {
|
if (newDeadKey == 0) {
|
||||||
char* string = NULL;
|
char* string = NULL;
|
||||||
char* rawString = NULL;
|
char* rawString = NULL;
|
||||||
int32 numBytes = 0, rawNumBytes = 0;
|
int32 numBytes = 0, rawNumBytes = 0;
|
||||||
keymap->GetChars(keycode, device->modifiers, activeDeadKey, &string, &numBytes);
|
fKeymap.GetChars(keycode, fModifiers, activeDeadKey, &string, &numBytes);
|
||||||
keymap->GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
|
fKeymap.GetChars(keycode, 0, 0, &rawString, &rawNumBytes);
|
||||||
|
|
||||||
BMessage* msg = new BMessage;
|
BMessage* msg = new BMessage;
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
@@ -760,7 +713,7 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
|
|
||||||
msg->AddInt64("when", timestamp);
|
msg->AddInt64("when", timestamp);
|
||||||
msg->AddInt32("key", keycode);
|
msg->AddInt32("key", keycode);
|
||||||
msg->AddInt32("modifiers", device->modifiers);
|
msg->AddInt32("modifiers", fModifiers);
|
||||||
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++) {
|
||||||
@@ -789,28 +742,28 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
delete[] rawString;
|
delete[] rawString;
|
||||||
|
|
||||||
if (isKeyDown && !modifiers && activeDeadKey != 0
|
if (isKeyDown && !modifiers && activeDeadKey != 0
|
||||||
&& device->input_method_started) {
|
&& fInputMethodStarted) {
|
||||||
// a dead key was completed
|
// a dead key was completed
|
||||||
device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
||||||
string, true, msg);
|
string, true, msg);
|
||||||
} else if (owner->EnqueueMessage(msg) != B_OK)
|
} else if (fOwner->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 (device->EnqueueInlineInputMethod(B_INPUT_METHOD_STARTED) == B_OK) {
|
if (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);
|
fKeymap.GetChars(keycode, fModifiers, 0, &string, &numBytes);
|
||||||
|
|
||||||
if (device->EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
if (EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
||||||
device->input_method_started = true;
|
fInputMethodStarted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyDown && !modifiers) {
|
if (!isKeyDown && !modifiers) {
|
||||||
if (activeDeadKey != 0) {
|
if (activeDeadKey != 0) {
|
||||||
device->EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
||||||
device->input_method_started = false;
|
fInputMethodStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
activeDeadKey = newDeadKey;
|
activeDeadKey = newDeadKey;
|
||||||
@@ -823,6 +776,174 @@ KeyboardInputDevice::_DeviceWatcher(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
KeyboardInputDevice::KeyboardInputDevice()
|
||||||
|
:
|
||||||
|
fDevices(2, true),
|
||||||
|
fTeamMonitorWindow(NULL)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
StartMonitoringDevice(kKeyboardDevicesDirectory);
|
||||||
|
_RecursiveScan(kKeyboardDevicesDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KeyboardInputDevice::~KeyboardInputDevice()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
if (fTeamMonitorWindow) {
|
||||||
|
fTeamMonitorWindow->PostMessage(B_QUIT_REQUESTED);
|
||||||
|
fTeamMonitorWindow = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
StopMonitoringDevice(kKeyboardDevicesDirectory);
|
||||||
|
fDevices.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::SystemShuttingDown()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
if (fTeamMonitorWindow)
|
||||||
|
fTeamMonitorWindow->PostMessage(SYSTEM_SHUTTING_DOWN);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::InitCheck()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
return BInputServerDevice::InitCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::Start(const char* name, void* cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
|
|
||||||
|
return device->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::Stop(const char* name, void* cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
|
|
||||||
|
LOG("Stop(%s)\n", name);
|
||||||
|
|
||||||
|
device->Stop();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::Control(const char* name, void* cookie,
|
||||||
|
uint32 command, BMessage* message)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
LOG("Control(%s, code: %lu)\n", name, command);
|
||||||
|
|
||||||
|
if (command == B_NODE_MONITOR)
|
||||||
|
_HandleMonitor(message);
|
||||||
|
else if (command >= B_KEY_MAP_CHANGED
|
||||||
|
&& command <= B_KEY_REPEAT_RATE_CHANGED) {
|
||||||
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
|
device->InitFromSettings(command);
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::_HandleMonitor(BMessage* message)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
const char* path;
|
||||||
|
int32 opcode;
|
||||||
|
if (message->FindInt32("opcode", &opcode) != B_OK
|
||||||
|
|| (opcode != B_ENTRY_CREATED && opcode != B_ENTRY_REMOVED)
|
||||||
|
|| message->FindString("path", &path) != B_OK)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (opcode == B_ENTRY_CREATED)
|
||||||
|
return _AddDevice(path);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
return _RemoveDevice(path);
|
||||||
|
#else
|
||||||
|
// Don't handle B_ENTRY_REMOVED, let the control thread take care of it.
|
||||||
|
return B_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
KeyboardDevice*
|
||||||
|
KeyboardInputDevice::_FindDevice(const char* path) const
|
||||||
|
{
|
||||||
|
for (int i = fDevices.CountItems() - 1; i >= 0; i--) {
|
||||||
|
KeyboardDevice* device = fDevices.ItemAt(i);
|
||||||
|
if (strcmp(device->Path(), path) == 0)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::_AddDevice(const char* path)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
_RemoveDevice(path);
|
||||||
|
|
||||||
|
KeyboardDevice* device = new(std::nothrow) KeyboardDevice(this, path);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
input_device_ref* devices[2];
|
||||||
|
devices[0] = device->DeviceRef();
|
||||||
|
devices[1] = NULL;
|
||||||
|
|
||||||
|
fDevices.AddItem(device);
|
||||||
|
|
||||||
|
return RegisterDevices(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardInputDevice::_RemoveDevice(const char* path)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
KeyboardDevice* device = _FindDevice(path);
|
||||||
|
if (device == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
input_device_ref* devices[2];
|
||||||
|
devices[0] = device->DeviceRef();
|
||||||
|
devices[1] = NULL;
|
||||||
|
|
||||||
|
UnregisterDevices(devices);
|
||||||
|
|
||||||
|
fDevices.RemoveItem(device);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
KeyboardInputDevice::_RecursiveScan(const char* directory)
|
KeyboardInputDevice::_RecursiveScan(const char* directory)
|
||||||
{
|
{
|
||||||
@@ -840,103 +961,10 @@ KeyboardInputDevice::_RecursiveScan(const char* directory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
KeyboardInputDevice::_SetLeds(keyboard_device* device)
|
|
||||||
{
|
|
||||||
if (device->fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32 locks = device->modifiers;
|
|
||||||
char lock_io[3];
|
|
||||||
memset(lock_io, 0, sizeof(lock_io));
|
|
||||||
if (locks & B_NUM_LOCK)
|
|
||||||
lock_io[0] = 1;
|
|
||||||
if (locks & B_CAPS_LOCK)
|
|
||||||
lock_io[1] = 1;
|
|
||||||
if (locks & B_SCROLL_LOCK)
|
|
||||||
lock_io[2] = 1;
|
|
||||||
|
|
||||||
ioctl(device->fd, KB_SET_LEDS, &lock_io);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
keyboard_device::keyboard_device(const char* path)
|
|
||||||
: BHandler("keyboard device"),
|
|
||||||
owner(NULL),
|
|
||||||
fd(-1),
|
|
||||||
device_watcher(-1),
|
|
||||||
active(false),
|
|
||||||
input_method_started(false)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,65 +21,77 @@
|
|||||||
|
|
||||||
class KeyboardInputDevice;
|
class KeyboardInputDevice;
|
||||||
|
|
||||||
struct keyboard_device : public BHandler {
|
class KeyboardDevice : public BHandler {
|
||||||
keyboard_device(const char* path);
|
public:
|
||||||
virtual ~keyboard_device();
|
KeyboardDevice(KeyboardInputDevice* owner,
|
||||||
|
const char* path);
|
||||||
|
virtual ~KeyboardDevice();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
status_t EnqueueInlineInputMethod(int32 opcode,
|
status_t EnqueueInlineInputMethod(int32 opcode,
|
||||||
const char* string = NULL,
|
const char* string = NULL,
|
||||||
bool confirmed = false,
|
bool confirmed = false,
|
||||||
BMessage* keyDown = NULL);
|
BMessage* keyDown = NULL);
|
||||||
|
|
||||||
KeyboardInputDevice* owner;
|
status_t Start();
|
||||||
input_device_ref device_ref;
|
void Stop();
|
||||||
char path[B_PATH_NAME_LENGTH];
|
|
||||||
int fd;
|
status_t InitFromSettings(uint32 opcode = 0);
|
||||||
thread_id device_watcher;
|
void UpdateLEDs();
|
||||||
kb_settings settings;
|
|
||||||
volatile bool active;
|
const char* Path() const { return fPath; }
|
||||||
bool isAT;
|
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||||
volatile bool input_method_started;
|
|
||||||
uint32 modifiers;
|
private:
|
||||||
|
static int32 _ThreadEntry(void* arg);
|
||||||
|
int32 _Thread();
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyboardInputDevice* fOwner;
|
||||||
|
input_device_ref fDeviceRef;
|
||||||
|
char fPath[B_PATH_NAME_LENGTH];
|
||||||
|
int fFD;
|
||||||
|
thread_id fThread;
|
||||||
|
kb_settings fSettings;
|
||||||
|
volatile bool fActive;
|
||||||
|
bool fIsAT;
|
||||||
|
volatile bool fInputMethodStarted;
|
||||||
|
uint32 fModifiers;
|
||||||
|
|
||||||
|
Keymap fKeymap;
|
||||||
|
BLocker fKeymapLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class KeyboardInputDevice : public BInputServerDevice {
|
class KeyboardInputDevice : public BInputServerDevice {
|
||||||
public:
|
public:
|
||||||
KeyboardInputDevice();
|
KeyboardInputDevice();
|
||||||
~KeyboardInputDevice();
|
virtual ~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();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct keyboard_device;
|
friend struct KeyboardDevice;
|
||||||
// TODO: needed by the control thread to remove a dead device
|
// TODO: needed by the control thread to remove a dead device
|
||||||
// find a better way...
|
// find a better way...
|
||||||
|
|
||||||
status_t _HandleMonitor(BMessage* message);
|
status_t _HandleMonitor(BMessage* message);
|
||||||
status_t _InitFromSettings(void* cookie, uint32 opcode = 0);
|
void _RecursiveScan(const char* directory);
|
||||||
void _RecursiveScan(const char* directory);
|
|
||||||
|
|
||||||
keyboard_device* _FindDevice(const char* path) const;
|
KeyboardDevice* _FindDevice(const char* path) const;
|
||||||
status_t _AddDevice(const char* path);
|
status_t _AddDevice(const char* path);
|
||||||
status_t _RemoveDevice(const char* path);
|
status_t _RemoveDevice(const char* path);
|
||||||
|
|
||||||
void _SetLeds(keyboard_device* device);
|
BObjectList<KeyboardDevice> fDevices;
|
||||||
|
TeamMonitorWindow* fTeamMonitorWindow;
|
||||||
static int32 _DeviceWatcher(void* arg);
|
|
||||||
|
|
||||||
BObjectList<keyboard_device> fDevices;
|
|
||||||
Keymap fKeymap;
|
|
||||||
TeamMonitorWindow* fTeamMonitorWindow;
|
|
||||||
BLocker fKeymapLock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" BInputServerDevice* instantiate_input_device();
|
extern "C" BInputServerDevice* instantiate_input_device();
|
||||||
|
|||||||
@@ -29,20 +29,68 @@
|
|||||||
#include "kb_mouse_driver.h"
|
#include "kb_mouse_driver.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef TRACE
|
||||||
|
#undef CALLED
|
||||||
//#define TRACE_MOUSE_DEVICE
|
//#define TRACE_MOUSE_DEVICE
|
||||||
#ifdef TRACE_MOUSE_DEVICE
|
#ifdef TRACE_MOUSE_DEVICE
|
||||||
|
|
||||||
|
class FunctionTracer {
|
||||||
|
public:
|
||||||
|
FunctionTracer(const void* pointer, const char* className,
|
||||||
|
const char* functionName,
|
||||||
|
int32& depth)
|
||||||
|
: fFunctionName(),
|
||||||
|
fPrepend(),
|
||||||
|
fFunctionDepth(depth),
|
||||||
|
fPointer(pointer)
|
||||||
|
{
|
||||||
|
fFunctionDepth++;
|
||||||
|
fPrepend.Append(' ', fFunctionDepth * 2);
|
||||||
|
fFunctionName << className << "::" << functionName << "()";
|
||||||
|
|
||||||
|
debug_printf("%p -> %s%s {\n", fPointer, fPrepend.String(),
|
||||||
|
fFunctionName.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
~FunctionTracer()
|
||||||
|
{
|
||||||
|
debug_printf("%p -> %s}\n", fPointer, fPrepend.String());
|
||||||
|
fFunctionDepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fFunctionName;
|
||||||
|
BString fPrepend;
|
||||||
|
int32& fFunctionDepth;
|
||||||
|
const void* fPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int32 sFunctionDepth = -1;
|
||||||
|
# define MD_CALLED(x...) FunctionTracer _ft(this, "MouseDevice", \
|
||||||
|
__FUNCTION__, sFunctionDepth)
|
||||||
|
# define MID_CALLED(x...) FunctionTracer _ft(this, "MouseInputDevice", \
|
||||||
|
__FUNCTION__, sFunctionDepth)
|
||||||
|
# define TRACE(x...) { BString _to; \
|
||||||
|
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
||||||
|
debug_printf("%p -> %s", this, _to.String()); \
|
||||||
|
debug_printf(x); }
|
||||||
# define LOG(text...) debug_printf(text)
|
# define LOG(text...) debug_printf(text)
|
||||||
|
# define LOG_EVENT(text...) do {} while (0)
|
||||||
# define LOG_ERR(text...) LOG(text)
|
# define LOG_ERR(text...) LOG(text)
|
||||||
#else
|
#else
|
||||||
# define LOG(text...) do {} while (0)
|
# define TRACE(x...) do {} while (0)
|
||||||
|
# define MD_CALLED(x...) TRACE(x)
|
||||||
|
# define MID_CALLED(x...) TRACE(x)
|
||||||
|
# define LOG(text...) TRACE(x)
|
||||||
# define LOG_ERR(text...) debug_printf(text)
|
# define LOG_ERR(text...) debug_printf(text)
|
||||||
|
# define LOG_EVENT(text...) TRACE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//#define LOG_DEVICES(text...) debug_printf(text)
|
//#define LOG_DEVICES(text...) debug_printf(text)
|
||||||
#define LOG_DEVICES(text...) LOG(text)
|
#define LOG_DEVICES(text...) LOG(text)
|
||||||
|
|
||||||
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||||
@@ -103,9 +151,12 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath)
|
|||||||
fTarget(target),
|
fTarget(target),
|
||||||
fPath(driverPath),
|
fPath(driverPath),
|
||||||
fDevice(-1),
|
fDevice(-1),
|
||||||
|
fDeviceRemapsButtons(false),
|
||||||
fThread(-1),
|
fThread(-1),
|
||||||
fActive(false)
|
fActive(false)
|
||||||
{
|
{
|
||||||
|
MD_CALLED();
|
||||||
|
|
||||||
fDeviceRef.name = _BuildShortName();
|
fDeviceRef.name = _BuildShortName();
|
||||||
fDeviceRef.type = B_POINTING_DEVICE;
|
fDeviceRef.type = B_POINTING_DEVICE;
|
||||||
fDeviceRef.cookie = this;
|
fDeviceRef.cookie = this;
|
||||||
@@ -115,13 +166,17 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath)
|
|||||||
fSettings.map.button[1] = B_SECONDARY_MOUSE_BUTTON;
|
fSettings.map.button[1] = B_SECONDARY_MOUSE_BUTTON;
|
||||||
fSettings.map.button[2] = B_TERTIARY_MOUSE_BUTTON;
|
fSettings.map.button[2] = B_TERTIARY_MOUSE_BUTTON;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fDeviceRemapsButtons = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MouseDevice::~MouseDevice()
|
MouseDevice::~MouseDevice()
|
||||||
{
|
{
|
||||||
|
MD_CALLED();
|
||||||
|
TRACE("delete\n");
|
||||||
|
|
||||||
|
if (fTarget._HasDevice(this))
|
||||||
|
TRACE("still in the list!\n");
|
||||||
|
|
||||||
if (fActive)
|
if (fActive)
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
@@ -132,6 +187,8 @@ MouseDevice::~MouseDevice()
|
|||||||
status_t
|
status_t
|
||||||
MouseDevice::Start()
|
MouseDevice::Start()
|
||||||
{
|
{
|
||||||
|
MD_CALLED();
|
||||||
|
|
||||||
fDevice = open(fPath.String(), O_RDWR);
|
fDevice = open(fPath.String(), O_RDWR);
|
||||||
if (fDevice < 0)
|
if (fDevice < 0)
|
||||||
return errno;
|
return errno;
|
||||||
@@ -166,12 +223,14 @@ MouseDevice::Start()
|
|||||||
void
|
void
|
||||||
MouseDevice::Stop()
|
MouseDevice::Stop()
|
||||||
{
|
{
|
||||||
close(fDevice);
|
MD_CALLED();
|
||||||
fDevice = -1;
|
|
||||||
|
|
||||||
fActive = false;
|
fActive = false;
|
||||||
// this will stop the thread as soon as it reads the next packet
|
// this will stop the thread as soon as it reads the next packet
|
||||||
|
|
||||||
|
close(fDevice);
|
||||||
|
fDevice = -1;
|
||||||
|
|
||||||
if (fThread >= B_OK) {
|
if (fThread >= B_OK) {
|
||||||
// unblock the thread, which might wait on a semaphore.
|
// unblock the thread, which might wait on a semaphore.
|
||||||
suspend_thread(fThread);
|
suspend_thread(fThread);
|
||||||
@@ -186,7 +245,7 @@ MouseDevice::Stop()
|
|||||||
status_t
|
status_t
|
||||||
MouseDevice::UpdateSettings()
|
MouseDevice::UpdateSettings()
|
||||||
{
|
{
|
||||||
CALLED();
|
MD_CALLED();
|
||||||
|
|
||||||
// retrieve current values
|
// retrieve current values
|
||||||
|
|
||||||
@@ -254,10 +313,10 @@ MouseDevice::_Run()
|
|||||||
int32 deltaX, deltaY;
|
int32 deltaX, deltaY;
|
||||||
_ComputeAcceleration(movements, deltaX, deltaY);
|
_ComputeAcceleration(movements, deltaX, deltaY);
|
||||||
|
|
||||||
LOG("%s: buttons: 0x%lx, x: %ld, y: %ld, clicks:%ld, wheel_x:%ld, wheel_y:%ld\n",
|
LOG_EVENT("%s: buttons: 0x%lx, x: %ld, y: %ld, clicks:%ld, wheel_x:%ld, wheel_y:%ld\n",
|
||||||
fDeviceRef.name, movements.buttons, movements.xdelta, movements.ydelta,
|
fDeviceRef.name, movements.buttons, movements.xdelta, movements.ydelta,
|
||||||
movements.clicks, movements.wheel_xdelta, movements.wheel_ydelta);
|
movements.clicks, movements.wheel_xdelta, movements.wheel_ydelta);
|
||||||
LOG("%s: x: %ld, y: %ld\n", fDeviceRef.name, deltaX, deltaY);
|
LOG_EVENT("%s: x: %ld, y: %ld\n", fDeviceRef.name, deltaX, deltaY);
|
||||||
|
|
||||||
// Send single messages for each event
|
// Send single messages for each event
|
||||||
|
|
||||||
@@ -269,9 +328,9 @@ MouseDevice::_Run()
|
|||||||
if (message != NULL) {
|
if (message != NULL) {
|
||||||
if (pressedButton) {
|
if (pressedButton) {
|
||||||
message->AddInt32("clicks", movements.clicks);
|
message->AddInt32("clicks", movements.clicks);
|
||||||
LOG("B_MOUSE_DOWN\n");
|
LOG_EVENT("B_MOUSE_DOWN\n");
|
||||||
} else
|
} else
|
||||||
LOG("B_MOUSE_UP\n");
|
LOG_EVENT("B_MOUSE_UP\n");
|
||||||
|
|
||||||
fTarget.EnqueueMessage(message);
|
fTarget.EnqueueMessage(message);
|
||||||
lastButtons = movements.buttons;
|
lastButtons = movements.buttons;
|
||||||
@@ -416,7 +475,7 @@ MouseInputDevice::MouseInputDevice()
|
|||||||
:
|
:
|
||||||
fDevices(2, true)
|
fDevices(2, true)
|
||||||
{
|
{
|
||||||
CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
StartMonitoringDevice(kMouseDevicesDirectory);
|
StartMonitoringDevice(kMouseDevicesDirectory);
|
||||||
_RecursiveScan(kMouseDevicesDirectory);
|
_RecursiveScan(kMouseDevicesDirectory);
|
||||||
@@ -425,15 +484,18 @@ MouseInputDevice::MouseInputDevice()
|
|||||||
|
|
||||||
MouseInputDevice::~MouseInputDevice()
|
MouseInputDevice::~MouseInputDevice()
|
||||||
{
|
{
|
||||||
CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
StopMonitoringDevice(kMouseDevicesDirectory);
|
StopMonitoringDevice(kMouseDevicesDirectory);
|
||||||
|
fDevices.MakeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
MouseInputDevice::InitCheck()
|
MouseInputDevice::InitCheck()
|
||||||
{
|
{
|
||||||
CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
return BInputServerDevice::InitCheck();
|
return BInputServerDevice::InitCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +503,8 @@ MouseInputDevice::InitCheck()
|
|||||||
status_t
|
status_t
|
||||||
MouseInputDevice::Start(const char* name, void* cookie)
|
MouseInputDevice::Start(const char* name, void* cookie)
|
||||||
{
|
{
|
||||||
LOG("%s(%s)\n", __PRETTY_FUNCTION__, name);
|
MID_CALLED();
|
||||||
|
|
||||||
MouseDevice* device = (MouseDevice*)cookie;
|
MouseDevice* device = (MouseDevice*)cookie;
|
||||||
|
|
||||||
return device->Start();
|
return device->Start();
|
||||||
@@ -451,10 +514,11 @@ MouseInputDevice::Start(const char* name, void* cookie)
|
|||||||
status_t
|
status_t
|
||||||
MouseInputDevice::Stop(const char* name, void* cookie)
|
MouseInputDevice::Stop(const char* name, void* cookie)
|
||||||
{
|
{
|
||||||
LOG("%s(%s)\n", __PRETTY_FUNCTION__, name);
|
TRACE("%s(%s)\n", __PRETTY_FUNCTION__, name);
|
||||||
MouseDevice* device = (MouseDevice*)cookie;
|
|
||||||
|
|
||||||
|
MouseDevice* device = (MouseDevice*)cookie;
|
||||||
device->Stop();
|
device->Stop();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +527,8 @@ status_t
|
|||||||
MouseInputDevice::Control(const char* name, void* cookie,
|
MouseInputDevice::Control(const char* name, void* cookie,
|
||||||
uint32 command, BMessage* message)
|
uint32 command, BMessage* message)
|
||||||
{
|
{
|
||||||
LOG("%s(%s, code: %lu)\n", __PRETTY_FUNCTION__, name, command);
|
TRACE("%s(%s, code: %lu)\n", __PRETTY_FUNCTION__, name, command);
|
||||||
|
|
||||||
MouseDevice* device = (MouseDevice*)cookie;
|
MouseDevice* device = (MouseDevice*)cookie;
|
||||||
|
|
||||||
if (command == B_NODE_MONITOR)
|
if (command == B_NODE_MONITOR)
|
||||||
@@ -480,7 +545,7 @@ MouseInputDevice::Control(const char* name, void* cookie,
|
|||||||
status_t
|
status_t
|
||||||
MouseInputDevice::_HandleMonitor(BMessage* message)
|
MouseInputDevice::_HandleMonitor(BMessage* message)
|
||||||
{
|
{
|
||||||
CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
int32 opcode;
|
int32 opcode;
|
||||||
@@ -501,78 +566,10 @@ MouseInputDevice::_HandleMonitor(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MouseDevice*
|
|
||||||
MouseInputDevice::_FindDevice(const char* path)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
for (int32 i = fDevices.CountItems() - 1; i >= 0; i--) {
|
|
||||||
MouseDevice* device = fDevices.ItemAt(i);
|
|
||||||
if (strcmp(device->Path(), path) == 0)
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MouseInputDevice::_AddDevice(const char* path)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
_RemoveDevice(path);
|
|
||||||
|
|
||||||
MouseDevice* device = new(std::nothrow) MouseDevice(*this, path);
|
|
||||||
if (!device) {
|
|
||||||
LOG("MouseInputDevice::_AddDevice() - No memory\n");
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fDevices.AddItem(device)) {
|
|
||||||
delete device;
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
input_device_ref* devices[2];
|
|
||||||
devices[0] = device->DeviceRef();
|
|
||||||
devices[1] = NULL;
|
|
||||||
|
|
||||||
LOG_DEVICES("MouseInputDevice::_AddDevice(%s), name: %s\n", path,
|
|
||||||
devices[0]->name);
|
|
||||||
|
|
||||||
return RegisterDevices(devices);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MouseInputDevice::_RemoveDevice(const char* path)
|
|
||||||
{
|
|
||||||
CALLED();
|
|
||||||
|
|
||||||
MouseDevice* device = _FindDevice(path);
|
|
||||||
if (device == NULL)
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
input_device_ref* devices[2];
|
|
||||||
devices[0] = device->DeviceRef();
|
|
||||||
devices[1] = NULL;
|
|
||||||
|
|
||||||
LOG_DEVICES("MouseInputDevice::_RemoveDevice(%s), name: %s\n", path,
|
|
||||||
devices[0]->name);
|
|
||||||
|
|
||||||
UnregisterDevices(devices);
|
|
||||||
|
|
||||||
fDevices.RemoveItem(device);
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MouseInputDevice::_RecursiveScan(const char* directory)
|
MouseInputDevice::_RecursiveScan(const char* directory)
|
||||||
{
|
{
|
||||||
CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
BDirectory dir(directory);
|
BDirectory dir(directory);
|
||||||
@@ -592,3 +589,84 @@ MouseInputDevice::_RecursiveScan(const char* directory)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MouseDevice*
|
||||||
|
MouseInputDevice::_FindDevice(const char* path)
|
||||||
|
{
|
||||||
|
MID_CALLED();
|
||||||
|
|
||||||
|
for (int32 i = fDevices.CountItems() - 1; i >= 0; i--) {
|
||||||
|
MouseDevice* device = fDevices.ItemAt(i);
|
||||||
|
if (strcmp(device->Path(), path) == 0)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::_AddDevice(const char* path)
|
||||||
|
{
|
||||||
|
MID_CALLED();
|
||||||
|
|
||||||
|
_RemoveDevice(path);
|
||||||
|
|
||||||
|
MouseDevice* device = new(std::nothrow) MouseDevice(*this, path);
|
||||||
|
if (!device) {
|
||||||
|
TRACE("No memory\n");
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fDevices.AddItem(device)) {
|
||||||
|
TRACE("No memory in list\n");
|
||||||
|
delete device;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_device_ref* devices[2];
|
||||||
|
devices[0] = device->DeviceRef();
|
||||||
|
devices[1] = NULL;
|
||||||
|
|
||||||
|
TRACE("adding path: %s, name: %s\n", path, devices[0]->name);
|
||||||
|
|
||||||
|
return RegisterDevices(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::_RemoveDevice(const char* path)
|
||||||
|
{
|
||||||
|
MID_CALLED();
|
||||||
|
|
||||||
|
MouseDevice* device = _FindDevice(path);
|
||||||
|
if (device == NULL) {
|
||||||
|
TRACE("%s not found\n", path);
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_device_ref* devices[2];
|
||||||
|
devices[0] = device->DeviceRef();
|
||||||
|
devices[1] = NULL;
|
||||||
|
|
||||||
|
TRACE("removing path: %s, name: %s\n", path, devices[0]->name);
|
||||||
|
|
||||||
|
UnregisterDevices(devices);
|
||||||
|
|
||||||
|
fDevices.RemoveItem(device);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MouseInputDevice::_HasDevice(const MouseDevice* device) const
|
||||||
|
{
|
||||||
|
for (int32 i = fDevices.CountItems() - 1; i >= 0; i--) {
|
||||||
|
if (device == fDevices.ItemAt(i))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ private:
|
|||||||
status_t _AddDevice(const char* path);
|
status_t _AddDevice(const char* path);
|
||||||
status_t _RemoveDevice(const char* path);
|
status_t _RemoveDevice(const char* path);
|
||||||
|
|
||||||
|
bool _HasDevice(const MouseDevice* device) const;
|
||||||
|
|
||||||
|
private:
|
||||||
BObjectList<MouseDevice> fDevices;
|
BObjectList<MouseDevice> fDevices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user