* Cleanup and refactoring, made several Mouse-/Keyboard-/TouchpadDevice
functions private and moved them accordingly in the file. * I forgot to initialize the BObjectList to own the items in TouchpadInputDevice. * Changed the methods that read and apply settings in all three addons to be executed from the control threads only, which fixes race conditions. * The success of opening a device is no longer checked in the Start() method of the *Devices. Instead, the control thread checks the device before it enters the polling loop and cleans up if there was an error. This fixes non-running devices in the input_server because the PS/2 driver publishes devices which is has not checked yet for other reasons. It is important, however, to open() the devices in the Start() hook and not the control thread, otherwise there are unwanted race conditions in case node monitoring events are received more than once for the same device. That's the case for some reason on one of my computers for the AT 0 keyboard. TODO: * Combine the Touchpad and Mouse device addon into one, it's almost the same code except the Touchpad knows more settings and one more control message. * Refactor a common base class for Keyboard and Mouse device addon. * Fix the mouse speed/acceleration. If the speed is lowered from the default in the preflet, the mouse becomes almost unusable. To fix this, the same trick should be used as I used in the touchpad kernel driver, which is to sum up previous mouse moved fractional offsets. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28590 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,16 +26,60 @@
|
|||||||
#include "kb_mouse_driver.h"
|
#include "kb_mouse_driver.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_KEYBOARD_DEVICE
|
#undef TRACE
|
||||||
|
#define TRACE_KEYBOARD_DEVICE
|
||||||
#ifdef TRACE_KEYBOARD_DEVICE
|
#ifdef TRACE_KEYBOARD_DEVICE
|
||||||
# define LOG(text...) debug_printf(text)
|
|
||||||
# define LOG_ERR(text...) LOG(text)
|
|
||||||
#else
|
|
||||||
# define LOG(text...) do {} while (0)
|
|
||||||
# define LOG_ERR(text...) debug_printf(text)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
|
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 KD_CALLED(x...) FunctionTracer _ft(this, "KeyboardDevice", \
|
||||||
|
__FUNCTION__, sFunctionDepth)
|
||||||
|
# define KID_CALLED(x...) FunctionTracer _ft(this, "KeyboardInputDevice", \
|
||||||
|
__FUNCTION__, sFunctionDepth)
|
||||||
|
# define TRACE(x...) { BString _to; \
|
||||||
|
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
||||||
|
debug_printf("%p -> %s", this, _to.String()); \
|
||||||
|
debug_printf(x); }
|
||||||
|
# define LOG_EVENT(text...) do {} while (0)
|
||||||
|
# define LOG_ERR(text...) TRACE(text)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) do {} while (0)
|
||||||
|
# define KD_CALLED(x...) TRACE(x)
|
||||||
|
# define KID_CALLED(x...) TRACE(x)
|
||||||
|
# define LOG_ERR(text...) debug_printf(text)
|
||||||
|
# define LOG_EVENT(text...) TRACE(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const static uint32 kKeyboardThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
const static uint32 kKeyboardThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||||
@@ -346,7 +390,6 @@ instantiate_input_device()
|
|||||||
static char*
|
static char*
|
||||||
get_short_name(const char* longName)
|
get_short_name(const char* longName)
|
||||||
{
|
{
|
||||||
CALLED();
|
|
||||||
BString string(longName);
|
BString string(longName);
|
||||||
BString name;
|
BString name;
|
||||||
|
|
||||||
@@ -379,8 +422,12 @@ KeyboardDevice::KeyboardDevice(KeyboardInputDevice* owner, const char* path)
|
|||||||
fThread(-1),
|
fThread(-1),
|
||||||
fActive(false),
|
fActive(false),
|
||||||
fInputMethodStarted(false),
|
fInputMethodStarted(false),
|
||||||
|
fUpdateSettings(false),
|
||||||
|
fSettingsCommand(0),
|
||||||
fKeymapLock("keymap lock")
|
fKeymapLock("keymap lock")
|
||||||
{
|
{
|
||||||
|
KD_CALLED();
|
||||||
|
|
||||||
strcpy(fPath, path);
|
strcpy(fPath, path);
|
||||||
fDeviceRef.name = get_short_name(path);
|
fDeviceRef.name = get_short_name(path);
|
||||||
fDeviceRef.type = B_KEYBOARD_DEVICE;
|
fDeviceRef.type = B_KEYBOARD_DEVICE;
|
||||||
@@ -397,6 +444,9 @@ KeyboardDevice::KeyboardDevice(KeyboardInputDevice* owner, const char* path)
|
|||||||
|
|
||||||
KeyboardDevice::~KeyboardDevice()
|
KeyboardDevice::~KeyboardDevice()
|
||||||
{
|
{
|
||||||
|
KD_CALLED();
|
||||||
|
TRACE("delete\n");
|
||||||
|
|
||||||
if (fActive)
|
if (fActive)
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
@@ -409,37 +459,11 @@ KeyboardDevice::~KeyboardDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
KeyboardDevice::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 = fOwner->EnqueueMessage(message);
|
|
||||||
if (status != B_OK)
|
|
||||||
delete message;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
KeyboardDevice::MessageReceived(BMessage* message)
|
KeyboardDevice::MessageReceived(BMessage* message)
|
||||||
{
|
{
|
||||||
|
KD_CALLED();
|
||||||
|
|
||||||
if (message->what != B_INPUT_METHOD_EVENT) {
|
if (message->what != B_INPUT_METHOD_EVENT) {
|
||||||
BHandler::MessageReceived(message);
|
BHandler::MessageReceived(message);
|
||||||
return;
|
return;
|
||||||
@@ -457,22 +481,21 @@ KeyboardDevice::MessageReceived(BMessage* message)
|
|||||||
status_t
|
status_t
|
||||||
KeyboardDevice::Start()
|
KeyboardDevice::Start()
|
||||||
{
|
{
|
||||||
if ((fFD = open(fPath, O_RDWR)) < B_OK) {
|
KD_CALLED();
|
||||||
fprintf(stderr, "error when opening %s: %s\n", fPath, strerror(errno));
|
TRACE("name: %s\n", fDeviceRef.name);
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitFromSettings();
|
fFD = open(fPath, O_RDWR);
|
||||||
|
// let the control thread handle any error on opening the device
|
||||||
|
|
||||||
char threadName[B_OS_NAME_LENGTH];
|
char threadName[B_OS_NAME_LENGTH];
|
||||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||||
|
|
||||||
fActive = true;
|
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||||
fThread = spawn_thread(_ThreadEntry, threadName,
|
|
||||||
kKeyboardThreadPriority, this);
|
kKeyboardThreadPriority, this);
|
||||||
if (fThread < B_OK)
|
if (fThread < B_OK)
|
||||||
return fThread;
|
return fThread;
|
||||||
|
|
||||||
|
fActive = true;
|
||||||
resume_thread(fThread);
|
resume_thread(fThread);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -480,6 +503,9 @@ KeyboardDevice::Start()
|
|||||||
void
|
void
|
||||||
KeyboardDevice::Stop()
|
KeyboardDevice::Stop()
|
||||||
{
|
{
|
||||||
|
KD_CALLED();
|
||||||
|
TRACE("name: %s\n", fDeviceRef.name);
|
||||||
|
|
||||||
fActive = false;
|
fActive = false;
|
||||||
|
|
||||||
close(fFD);
|
close(fFD);
|
||||||
@@ -495,70 +521,48 @@ KeyboardDevice::Stop()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
KeyboardDevice::InitFromSettings(uint32 opcode)
|
KeyboardDevice::UpdateSettings(uint32 opcode)
|
||||||
{
|
{
|
||||||
CALLED();
|
KD_CALLED();
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
if (fThread < 0)
|
||||||
if (get_key_repeat_rate(&fSettings.key_repeat_rate) != B_OK)
|
return B_ERROR;
|
||||||
LOG_ERR("error when get_key_repeat_rate\n");
|
|
||||||
else if (ioctl(fFD, KB_SET_KEY_REPEAT_RATE,
|
|
||||||
&fSettings.key_repeat_rate) != B_OK)
|
|
||||||
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", fFD);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
// schedule updating the settings from within the control thread
|
||||||
if (get_key_repeat_delay(&fSettings.key_repeat_delay) != B_OK)
|
fSettingsCommand = opcode;
|
||||||
LOG_ERR("error when get_key_repeat_delay\n");
|
fUpdateSettings = true;
|
||||||
else if (ioctl(fFD, KB_SET_KEY_REPEAT_DELAY,
|
|
||||||
&fSettings.key_repeat_delay) != B_OK)
|
|
||||||
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", fFD);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
|
||||||
|| opcode == B_KEY_LOCKS_CHANGED) {
|
|
||||||
BAutolock lock(fKeymapLock);
|
|
||||||
fKeymap.LoadCurrent();
|
|
||||||
fModifiers = fKeymap.Locks();
|
|
||||||
UpdateLEDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
// #pragma mark - control thread
|
||||||
KeyboardDevice::UpdateLEDs()
|
|
||||||
{
|
|
||||||
if (fFD < 0)
|
|
||||||
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;
|
|
||||||
|
|
||||||
ioctl(fFD, KB_SET_LEDS, &lockIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int32
|
/*static*/ int32
|
||||||
KeyboardDevice::_ThreadEntry(void* arg)
|
KeyboardDevice::_ControlThreadEntry(void* arg)
|
||||||
{
|
{
|
||||||
KeyboardDevice* device = (KeyboardDevice*)arg;
|
KeyboardDevice* device = (KeyboardDevice*)arg;
|
||||||
return device->_Thread();
|
return device->_ControlThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
KeyboardDevice::_Thread()
|
KeyboardDevice::_ControlThread()
|
||||||
{
|
{
|
||||||
CALLED();
|
KD_CALLED();
|
||||||
|
TRACE("fPath: %s\n", fPath);
|
||||||
|
|
||||||
|
if (fFD < B_OK) {
|
||||||
|
LOG_ERR("KeyboardDevice: error when opening %s: %s\n",
|
||||||
|
fPath, strerror(errno));
|
||||||
|
_ControlThreadCleanup();
|
||||||
|
// TOAST!
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
_UpdateSettings(0);
|
||||||
|
|
||||||
uint8 buffer[16];
|
uint8 buffer[16];
|
||||||
uint8 activeDeadKey = 0;
|
uint8 activeDeadKey = 0;
|
||||||
uint32 lastKeyCode = 0;
|
uint32 lastKeyCode = 0;
|
||||||
@@ -568,29 +572,24 @@ KeyboardDevice::_Thread()
|
|||||||
|
|
||||||
memset(states, 0, sizeof(states));
|
memset(states, 0, sizeof(states));
|
||||||
|
|
||||||
LOG("%s\n", __PRETTY_FUNCTION__);
|
|
||||||
|
|
||||||
while (fActive) {
|
while (fActive) {
|
||||||
if (ioctl(fFD, KB_READ, &buffer) != B_OK) {
|
if (ioctl(fFD, KB_READ, &buffer) != B_OK) {
|
||||||
if (fActive) {
|
_ControlThreadCleanup();
|
||||||
fThread = -1;
|
|
||||||
fOwner->_RemoveDevice(fPath);
|
|
||||||
} else {
|
|
||||||
// In case fActive is already false, another thread
|
|
||||||
// waits for this thread to quit, and may already hold
|
|
||||||
// locks that _RemoveDevice() wants to acquire. In another
|
|
||||||
// words, the device is already being removed, so we simply
|
|
||||||
// quit here.
|
|
||||||
}
|
|
||||||
// TOAST!
|
// TOAST!
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the settings from this thread if necessary
|
||||||
|
if (fUpdateSettings) {
|
||||||
|
_UpdateSettings(fSettingsCommand);
|
||||||
|
fUpdateSettings = false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 keycode = 0;
|
uint32 keycode = 0;
|
||||||
bool isKeyDown = false;
|
bool isKeyDown = false;
|
||||||
bigtime_t timestamp = 0;
|
bigtime_t timestamp = 0;
|
||||||
|
|
||||||
LOG("KB_READ :");
|
LOG_EVENT("KB_READ :");
|
||||||
|
|
||||||
if (fIsAT) {
|
if (fIsAT) {
|
||||||
at_kbd_io* atKeyboard = (at_kbd_io*)buffer;
|
at_kbd_io* atKeyboard = (at_kbd_io*)buffer;
|
||||||
@@ -598,7 +597,7 @@ KeyboardDevice::_Thread()
|
|||||||
keycode = kATKeycodeMap[atKeyboard->scancode - 1];
|
keycode = kATKeycodeMap[atKeyboard->scancode - 1];
|
||||||
isKeyDown = atKeyboard->is_keydown;
|
isKeyDown = atKeyboard->is_keydown;
|
||||||
timestamp = atKeyboard->timestamp;
|
timestamp = atKeyboard->timestamp;
|
||||||
LOG(" %02x", atKeyboard->scancode);
|
LOG_EVENT(" %02x", atKeyboard->scancode);
|
||||||
} else {
|
} else {
|
||||||
raw_key_info* rawKeyInfo= (raw_key_info*)buffer;
|
raw_key_info* rawKeyInfo= (raw_key_info*)buffer;
|
||||||
isKeyDown = rawKeyInfo->is_keydown;
|
isKeyDown = rawKeyInfo->is_keydown;
|
||||||
@@ -609,7 +608,7 @@ KeyboardDevice::_Thread()
|
|||||||
if (keycode == 0)
|
if (keycode == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode);
|
LOG_EVENT(" %Ld, %02x, %02lx\n", timestamp, isKeyDown, keycode);
|
||||||
|
|
||||||
if (isKeyDown && keycode == 0x68) {
|
if (isKeyDown && keycode == 0x68) {
|
||||||
// MENU KEY for Tracker
|
// MENU KEY for Tracker
|
||||||
@@ -638,7 +637,7 @@ KeyboardDevice::_Thread()
|
|||||||
if (isKeyDown && keycode == 0x34 // DELETE KEY
|
if (isKeyDown && keycode == 0x34 // DELETE KEY
|
||||||
&& (states[0x5c >> 3] & (1 << (7 - (0x5c & 0x7))))
|
&& (states[0x5c >> 3] & (1 << (7 - (0x5c & 0x7))))
|
||||||
&& (states[0x5d >> 3] & (1 << (7 - (0x5d & 0x7))))) {
|
&& (states[0x5d >> 3] & (1 << (7 - (0x5d & 0x7))))) {
|
||||||
LOG("TeamMonitor called\n");
|
LOG_EVENT("TeamMonitor called\n");
|
||||||
|
|
||||||
// show the team monitor
|
// show the team monitor
|
||||||
if (fOwner->fTeamMonitorWindow == NULL)
|
if (fOwner->fTeamMonitorWindow == NULL)
|
||||||
@@ -686,7 +685,7 @@ KeyboardDevice::_Thread()
|
|||||||
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))
|
||||||
UpdateLEDs();
|
_UpdateLEDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 newDeadKey = 0;
|
uint8 newDeadKey = 0;
|
||||||
@@ -745,25 +744,25 @@ KeyboardDevice::_Thread()
|
|||||||
if (isKeyDown && !modifiers && activeDeadKey != 0
|
if (isKeyDown && !modifiers && activeDeadKey != 0
|
||||||
&& fInputMethodStarted) {
|
&& fInputMethodStarted) {
|
||||||
// a dead key was completed
|
// a dead key was completed
|
||||||
EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED,
|
||||||
string, true, msg);
|
string, true, msg);
|
||||||
} else if (fOwner->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 (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;
|
||||||
fKeymap.GetChars(keycode, fModifiers, 0, &string, &numBytes);
|
fKeymap.GetChars(keycode, fModifiers, 0, &string, &numBytes);
|
||||||
|
|
||||||
if (EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
if (_EnqueueInlineInputMethod(B_INPUT_METHOD_CHANGED, string) == B_OK)
|
||||||
fInputMethodStarted = true;
|
fInputMethodStarted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isKeyDown && !modifiers) {
|
if (!isKeyDown && !modifiers) {
|
||||||
if (activeDeadKey != 0) {
|
if (activeDeadKey != 0) {
|
||||||
EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
_EnqueueInlineInputMethod(B_INPUT_METHOD_STOPPED);
|
||||||
fInputMethodStarted = false;
|
fInputMethodStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,15 +776,116 @@ KeyboardDevice::_Thread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyboardDevice::_ControlThreadCleanup()
|
||||||
|
{
|
||||||
|
// NOTE: Only executed when the control thread detected an error
|
||||||
|
// and from within the control thread!
|
||||||
|
|
||||||
|
if (fActive) {
|
||||||
|
fThread = -1;
|
||||||
|
fOwner->_RemoveDevice(fPath);
|
||||||
|
} else {
|
||||||
|
// In case active is already false, another thread
|
||||||
|
// waits for this thread to quit, and may already hold
|
||||||
|
// locks that _RemoveDevice() wants to acquire. In another
|
||||||
|
// words, the device is already being removed, so we simply
|
||||||
|
// quit here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyboardDevice::_UpdateSettings(uint32 opcode)
|
||||||
|
{
|
||||||
|
KD_CALLED();
|
||||||
|
|
||||||
|
if (opcode == 0 || opcode == B_KEY_REPEAT_RATE_CHANGED) {
|
||||||
|
if (get_key_repeat_rate(&fSettings.key_repeat_rate) != B_OK) {
|
||||||
|
LOG_ERR("error when get_key_repeat_rate\n");
|
||||||
|
} else if (ioctl(fFD, KB_SET_KEY_REPEAT_RATE,
|
||||||
|
&fSettings.key_repeat_rate) != B_OK) {
|
||||||
|
LOG_ERR("error when KB_SET_KEY_REPEAT_RATE, fd:%d\n", fFD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode == 0 || opcode == B_KEY_REPEAT_DELAY_CHANGED) {
|
||||||
|
if (get_key_repeat_delay(&fSettings.key_repeat_delay) != B_OK) {
|
||||||
|
LOG_ERR("error when get_key_repeat_delay\n");
|
||||||
|
} else if (ioctl(fFD, KB_SET_KEY_REPEAT_DELAY,
|
||||||
|
&fSettings.key_repeat_delay) != B_OK) {
|
||||||
|
LOG_ERR("error when KB_SET_KEY_REPEAT_DELAY, fd:%d\n", fFD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode == 0 || opcode == B_KEY_MAP_CHANGED
|
||||||
|
|| opcode == B_KEY_LOCKS_CHANGED) {
|
||||||
|
BAutolock lock(fKeymapLock);
|
||||||
|
fKeymap.LoadCurrent();
|
||||||
|
fModifiers = fKeymap.Locks();
|
||||||
|
_UpdateLEDs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyboardDevice::_UpdateLEDs()
|
||||||
|
{
|
||||||
|
if (fFD < 0)
|
||||||
|
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;
|
||||||
|
|
||||||
|
ioctl(fFD, KB_SET_LEDS, &lockIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
KeyboardDevice::_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 = fOwner->EnqueueMessage(message);
|
||||||
|
if (status != B_OK)
|
||||||
|
delete message;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
KeyboardInputDevice::KeyboardInputDevice()
|
KeyboardInputDevice::KeyboardInputDevice()
|
||||||
:
|
:
|
||||||
fDevices(2, true),
|
fDevices(2, true),
|
||||||
|
fDeviceListLock("KeyboardInputDevice list"),
|
||||||
fTeamMonitorWindow(NULL)
|
fTeamMonitorWindow(NULL)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
|
||||||
StartMonitoringDevice(kKeyboardDevicesDirectory);
|
StartMonitoringDevice(kKeyboardDevicesDirectory);
|
||||||
_RecursiveScan(kKeyboardDevicesDirectory);
|
_RecursiveScan(kKeyboardDevicesDirectory);
|
||||||
@@ -794,7 +894,7 @@ KeyboardInputDevice::KeyboardInputDevice()
|
|||||||
|
|
||||||
KeyboardInputDevice::~KeyboardInputDevice()
|
KeyboardInputDevice::~KeyboardInputDevice()
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
|
||||||
if (fTeamMonitorWindow) {
|
if (fTeamMonitorWindow) {
|
||||||
fTeamMonitorWindow->PostMessage(B_QUIT_REQUESTED);
|
fTeamMonitorWindow->PostMessage(B_QUIT_REQUESTED);
|
||||||
@@ -809,7 +909,7 @@ KeyboardInputDevice::~KeyboardInputDevice()
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::SystemShuttingDown()
|
KeyboardInputDevice::SystemShuttingDown()
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
if (fTeamMonitorWindow)
|
if (fTeamMonitorWindow)
|
||||||
fTeamMonitorWindow->PostMessage(SYSTEM_SHUTTING_DOWN);
|
fTeamMonitorWindow->PostMessage(SYSTEM_SHUTTING_DOWN);
|
||||||
|
|
||||||
@@ -820,7 +920,7 @@ KeyboardInputDevice::SystemShuttingDown()
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::InitCheck()
|
KeyboardInputDevice::InitCheck()
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
return BInputServerDevice::InitCheck();
|
return BInputServerDevice::InitCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,7 +928,9 @@ KeyboardInputDevice::InitCheck()
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::Start(const char* name, void* cookie)
|
KeyboardInputDevice::Start(const char* name, void* cookie)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
TRACE("name %s\n", name);
|
||||||
|
|
||||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
|
|
||||||
return device->Start();
|
return device->Start();
|
||||||
@@ -838,10 +940,10 @@ KeyboardInputDevice::Start(const char* name, void* cookie)
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::Stop(const char* name, void* cookie)
|
KeyboardInputDevice::Stop(const char* name, void* cookie)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
TRACE("name %s\n", name);
|
||||||
|
|
||||||
LOG("Stop(%s)\n", name);
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
|
|
||||||
device->Stop();
|
device->Stop();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -852,15 +954,15 @@ status_t
|
|||||||
KeyboardInputDevice::Control(const char* name, void* cookie,
|
KeyboardInputDevice::Control(const char* name, void* cookie,
|
||||||
uint32 command, BMessage* message)
|
uint32 command, BMessage* message)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
LOG("Control(%s, code: %lu)\n", name, command);
|
TRACE("KeyboardInputDevice::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) {
|
||||||
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
KeyboardDevice* device = (KeyboardDevice*)cookie;
|
||||||
device->InitFromSettings(command);
|
device->UpdateSettings(command);
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -869,7 +971,7 @@ KeyboardInputDevice::Control(const char* name, void* cookie,
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::_HandleMonitor(BMessage* message)
|
KeyboardInputDevice::_HandleMonitor(BMessage* message)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
|
||||||
const char* path;
|
const char* path;
|
||||||
int32 opcode;
|
int32 opcode;
|
||||||
@@ -906,7 +1008,10 @@ KeyboardInputDevice::_FindDevice(const char* path) const
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::_AddDevice(const char* path)
|
KeyboardInputDevice::_AddDevice(const char* path)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
TRACE("path: %s\n", path);
|
||||||
|
|
||||||
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
_RemoveDevice(path);
|
_RemoveDevice(path);
|
||||||
|
|
||||||
@@ -927,12 +1032,15 @@ KeyboardInputDevice::_AddDevice(const char* path)
|
|||||||
status_t
|
status_t
|
||||||
KeyboardInputDevice::_RemoveDevice(const char* path)
|
KeyboardInputDevice::_RemoveDevice(const char* path)
|
||||||
{
|
{
|
||||||
CALLED();
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
KeyboardDevice* device = _FindDevice(path);
|
KeyboardDevice* device = _FindDevice(path);
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
KID_CALLED();
|
||||||
|
TRACE("path: %s\n", path);
|
||||||
|
|
||||||
input_device_ref* devices[2];
|
input_device_ref* devices[2];
|
||||||
devices[0] = device->DeviceRef();
|
devices[0] = device->DeviceRef();
|
||||||
devices[1] = NULL;
|
devices[1] = NULL;
|
||||||
@@ -948,7 +1056,9 @@ KeyboardInputDevice::_RemoveDevice(const char* path)
|
|||||||
void
|
void
|
||||||
KeyboardInputDevice::_RecursiveScan(const char* directory)
|
KeyboardInputDevice::_RecursiveScan(const char* directory)
|
||||||
{
|
{
|
||||||
CALLED();
|
KID_CALLED();
|
||||||
|
TRACE("directory: %s\n", directory);
|
||||||
|
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
BDirectory dir(directory);
|
BDirectory dir(directory);
|
||||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <Handler.h>
|
#include <Handler.h>
|
||||||
#include <InputServerDevice.h>
|
#include <InputServerDevice.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
#include <List.h>
|
|
||||||
|
|
||||||
#include <InputServerTypes.h>
|
#include <InputServerTypes.h>
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
@@ -29,23 +28,24 @@ public:
|
|||||||
virtual ~KeyboardDevice();
|
virtual ~KeyboardDevice();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
status_t EnqueueInlineInputMethod(int32 opcode,
|
|
||||||
const char* string = NULL,
|
|
||||||
bool confirmed = false,
|
|
||||||
BMessage* keyDown = NULL);
|
|
||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
status_t InitFromSettings(uint32 opcode = 0);
|
status_t UpdateSettings(uint32 opcode = 0);
|
||||||
void UpdateLEDs();
|
|
||||||
|
|
||||||
const char* Path() const { return fPath; }
|
const char* Path() const { return fPath; }
|
||||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int32 _ThreadEntry(void* arg);
|
static int32 _ControlThreadEntry(void* arg);
|
||||||
int32 _Thread();
|
int32 _ControlThread();
|
||||||
|
void _ControlThreadCleanup();
|
||||||
|
void _UpdateSettings(uint32 opcode);
|
||||||
|
void _UpdateLEDs();
|
||||||
|
status_t _EnqueueInlineInputMethod(int32 opcode,
|
||||||
|
const char* string = NULL,
|
||||||
|
bool confirmed = false,
|
||||||
|
BMessage* keyDown = NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KeyboardInputDevice* fOwner;
|
KeyboardInputDevice* fOwner;
|
||||||
@@ -59,6 +59,9 @@ private:
|
|||||||
volatile bool fInputMethodStarted;
|
volatile bool fInputMethodStarted;
|
||||||
uint32 fModifiers;
|
uint32 fModifiers;
|
||||||
|
|
||||||
|
volatile bool fUpdateSettings;
|
||||||
|
volatile uint32 fSettingsCommand;
|
||||||
|
|
||||||
Keymap fKeymap;
|
Keymap fKeymap;
|
||||||
BLocker fKeymapLock;
|
BLocker fKeymapLock;
|
||||||
};
|
};
|
||||||
@@ -92,6 +95,7 @@ private:
|
|||||||
status_t _RemoveDevice(const char* path);
|
status_t _RemoveDevice(const char* path);
|
||||||
|
|
||||||
BObjectList<KeyboardDevice> fDevices;
|
BObjectList<KeyboardDevice> fDevices;
|
||||||
|
BLocker fDeviceListLock;
|
||||||
TeamMonitorWindow* fTeamMonitorWindow;
|
TeamMonitorWindow* fTeamMonitorWindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -31,7 +32,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#undef TRACE
|
#undef TRACE
|
||||||
#undef CALLED
|
|
||||||
//#define TRACE_MOUSE_DEVICE
|
//#define TRACE_MOUSE_DEVICE
|
||||||
#ifdef TRACE_MOUSE_DEVICE
|
#ifdef TRACE_MOUSE_DEVICE
|
||||||
|
|
||||||
@@ -76,64 +76,63 @@
|
|||||||
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
_to.Append(' ', (sFunctionDepth + 1) * 2); \
|
||||||
debug_printf("%p -> %s", this, _to.String()); \
|
debug_printf("%p -> %s", this, _to.String()); \
|
||||||
debug_printf(x); }
|
debug_printf(x); }
|
||||||
# define LOG(text...) debug_printf(text)
|
|
||||||
# define LOG_EVENT(text...) do {} while (0)
|
# define LOG_EVENT(text...) do {} while (0)
|
||||||
# define LOG_ERR(text...) LOG(text)
|
# define LOG_ERR(text...) TRACE(text)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...) do {} while (0)
|
# define TRACE(x...) do {} while (0)
|
||||||
# define MD_CALLED(x...) TRACE(x)
|
# define MD_CALLED(x...) TRACE(x)
|
||||||
# define MID_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)
|
# define LOG_EVENT(text...) TRACE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//#define LOG_DEVICES(text...) debug_printf(text)
|
|
||||||
#define LOG_DEVICES(text...) LOG(text)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||||
const static char* kMouseDevicesDirectory = "/dev/input/mouse";
|
const static char* kMouseDevicesDirectory = "/dev/input/mouse";
|
||||||
|
|
||||||
|
|
||||||
class MouseDevice {
|
class MouseDevice {
|
||||||
public:
|
public:
|
||||||
MouseDevice(MouseInputDevice& target, const char* path);
|
MouseDevice(MouseInputDevice& target,
|
||||||
~MouseDevice();
|
const char* path);
|
||||||
|
~MouseDevice();
|
||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
status_t UpdateSettings();
|
status_t UpdateSettings();
|
||||||
|
|
||||||
const char* Path() const { return fPath.String(); }
|
const char* Path() const { return fPath.String(); }
|
||||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Run();
|
char* _BuildShortName() const;
|
||||||
static status_t _ThreadFunction(void* arg);
|
|
||||||
|
|
||||||
BMessage* _BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
static status_t _ControlThreadEntry(void* arg);
|
||||||
int32 deltaX, int32 deltaY) const;
|
void _ControlThread();
|
||||||
void _ComputeAcceleration(const mouse_movement& movements,
|
void _ControlThreadCleanup();
|
||||||
int32& deltaX, int32& deltaY) const;
|
void _UpdateSettings();
|
||||||
uint32 _RemapButtons(uint32 buttons) const;
|
|
||||||
|
|
||||||
char* _BuildShortName() const;
|
BMessage* _BuildMouseMessage(uint32 what,
|
||||||
|
uint64 when, uint32 buttons,
|
||||||
|
int32 deltaX, int32 deltaY) const;
|
||||||
|
void _ComputeAcceleration(
|
||||||
|
const mouse_movement& movements,
|
||||||
|
int32& deltaX, int32& deltaY) const;
|
||||||
|
uint32 _RemapButtons(uint32 buttons) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MouseInputDevice& fTarget;
|
MouseInputDevice& fTarget;
|
||||||
BString fPath;
|
BString fPath;
|
||||||
int fDevice;
|
int fDevice;
|
||||||
|
|
||||||
input_device_ref fDeviceRef;
|
input_device_ref fDeviceRef;
|
||||||
mouse_settings fSettings;
|
mouse_settings fSettings;
|
||||||
bool fDeviceRemapsButtons;
|
bool fDeviceRemapsButtons;
|
||||||
|
|
||||||
thread_id fThread;
|
thread_id fThread;
|
||||||
volatile bool fActive;
|
volatile bool fActive;
|
||||||
|
volatile bool fUpdateSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -154,7 +153,8 @@ MouseDevice::MouseDevice(MouseInputDevice& target, const char* driverPath)
|
|||||||
fDevice(-1),
|
fDevice(-1),
|
||||||
fDeviceRemapsButtons(false),
|
fDeviceRemapsButtons(false),
|
||||||
fThread(-1),
|
fThread(-1),
|
||||||
fActive(false)
|
fActive(false),
|
||||||
|
fUpdateSettings(false)
|
||||||
{
|
{
|
||||||
MD_CALLED();
|
MD_CALLED();
|
||||||
|
|
||||||
@@ -175,9 +175,6 @@ MouseDevice::~MouseDevice()
|
|||||||
MD_CALLED();
|
MD_CALLED();
|
||||||
TRACE("delete\n");
|
TRACE("delete\n");
|
||||||
|
|
||||||
if (fTarget._HasDevice(this))
|
|
||||||
TRACE("still in the list!\n");
|
|
||||||
|
|
||||||
if (fActive)
|
if (fActive)
|
||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
@@ -191,15 +188,12 @@ MouseDevice::Start()
|
|||||||
MD_CALLED();
|
MD_CALLED();
|
||||||
|
|
||||||
fDevice = open(fPath.String(), O_RDWR);
|
fDevice = open(fPath.String(), O_RDWR);
|
||||||
if (fDevice < 0)
|
// let the control thread handle any error on opening the device
|
||||||
return errno;
|
|
||||||
|
|
||||||
UpdateSettings();
|
|
||||||
|
|
||||||
char threadName[B_OS_NAME_LENGTH];
|
char threadName[B_OS_NAME_LENGTH];
|
||||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||||
|
|
||||||
fThread = spawn_thread(_ThreadFunction, threadName,
|
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||||
kMouseThreadPriority, (void*)this);
|
kMouseThreadPriority, (void*)this);
|
||||||
|
|
||||||
status_t status;
|
status_t status;
|
||||||
@@ -213,7 +207,6 @@ MouseDevice::Start()
|
|||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
LOG_ERR("%s: can't spawn/resume watching thread: %s\n",
|
LOG_ERR("%s: can't spawn/resume watching thread: %s\n",
|
||||||
fDeviceRef.name, strerror(status));
|
fDeviceRef.name, strerror(status));
|
||||||
close(fDevice);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,45 +241,63 @@ MouseDevice::UpdateSettings()
|
|||||||
{
|
{
|
||||||
MD_CALLED();
|
MD_CALLED();
|
||||||
|
|
||||||
// retrieve current values
|
if (fThread < 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
fUpdateSettings = true;
|
||||||
LOG_ERR("error when get_mouse_map\n");
|
// This will provoke the control thread to update the settings.
|
||||||
else
|
|
||||||
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
|
||||||
|
|
||||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
|
||||||
LOG_ERR("error when get_click_speed\n");
|
|
||||||
else
|
|
||||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
|
||||||
|
|
||||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_speed\n");
|
|
||||||
else {
|
|
||||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_acceleration\n");
|
|
||||||
else {
|
|
||||||
mouse_accel accel;
|
|
||||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
|
||||||
accel.speed = fSettings.accel.speed;
|
|
||||||
accel.accel_factor = fSettings.accel.accel_factor;
|
|
||||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_type\n");
|
|
||||||
else
|
|
||||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char*
|
||||||
|
MouseDevice::_BuildShortName() const
|
||||||
|
{
|
||||||
|
BString string(fPath);
|
||||||
|
BString name;
|
||||||
|
|
||||||
|
int32 slash = string.FindLast("/");
|
||||||
|
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||||
|
int32 index = atoi(name.String()) + 1;
|
||||||
|
|
||||||
|
int32 previousSlash = string.FindLast("/", slash);
|
||||||
|
string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1);
|
||||||
|
|
||||||
|
if (name == "ps2")
|
||||||
|
name = "PS/2";
|
||||||
|
else
|
||||||
|
name.Capitalize();
|
||||||
|
|
||||||
|
name << " Mouse " << index;
|
||||||
|
|
||||||
|
return strdup(name.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - control thread
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseDevice::_ControlThreadEntry(void* arg)
|
||||||
|
{
|
||||||
|
MouseDevice* device = (MouseDevice*)arg;
|
||||||
|
device->_ControlThread();
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MouseDevice::_Run()
|
MouseDevice::_ControlThread()
|
||||||
{
|
{
|
||||||
|
if (fDevice < 0) {
|
||||||
|
_ControlThreadCleanup();
|
||||||
|
// TOAST!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_UpdateSettings();
|
||||||
|
|
||||||
uint32 lastButtons = 0;
|
uint32 lastButtons = 0;
|
||||||
|
|
||||||
while (fActive) {
|
while (fActive) {
|
||||||
@@ -294,20 +305,17 @@ MouseDevice::_Run()
|
|||||||
memset(&movements, 0, sizeof(movements));
|
memset(&movements, 0, sizeof(movements));
|
||||||
|
|
||||||
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
||||||
if (fActive) {
|
_ControlThreadCleanup();
|
||||||
fThread = -1;
|
|
||||||
fTarget._RemoveDevice(fPath.String());
|
|
||||||
} else {
|
|
||||||
// In case active is already false, another thread
|
|
||||||
// waits for this thread to quit, and may already hold
|
|
||||||
// locks that _RemoveDevice() wants to acquire. In another
|
|
||||||
// words, the device is already being removed, so we simply
|
|
||||||
// quit here.
|
|
||||||
}
|
|
||||||
// TOAST!
|
// TOAST!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// take care of updating the settings first, if necessary
|
||||||
|
if (fUpdateSettings) {
|
||||||
|
_UpdateSettings();
|
||||||
|
fUpdateSettings = false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 buttons = lastButtons ^ movements.buttons;
|
uint32 buttons = lastButtons ^ movements.buttons;
|
||||||
|
|
||||||
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
||||||
@@ -361,12 +369,62 @@ MouseDevice::_Run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
MouseDevice::_ThreadFunction(void* arg)
|
MouseDevice::_ControlThreadCleanup()
|
||||||
{
|
{
|
||||||
MouseDevice* device = (MouseDevice*)arg;
|
// NOTE: Only executed when the control thread detected an error
|
||||||
device->_Run();
|
// and from within the control thread!
|
||||||
return B_OK;
|
|
||||||
|
if (fActive) {
|
||||||
|
fThread = -1;
|
||||||
|
fTarget._RemoveDevice(fPath.String());
|
||||||
|
} else {
|
||||||
|
// In case active is already false, another thread
|
||||||
|
// waits for this thread to quit, and may already hold
|
||||||
|
// locks that _RemoveDevice() wants to acquire. In another
|
||||||
|
// words, the device is already being removed, so we simply
|
||||||
|
// quit here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MouseDevice::_UpdateSettings()
|
||||||
|
{
|
||||||
|
MD_CALLED();
|
||||||
|
|
||||||
|
// retrieve current values
|
||||||
|
|
||||||
|
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_map\n");
|
||||||
|
else {
|
||||||
|
fDeviceRemapsButtons
|
||||||
|
= ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_click_speed\n");
|
||||||
|
else
|
||||||
|
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||||
|
|
||||||
|
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_speed\n");
|
||||||
|
else {
|
||||||
|
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_acceleration\n");
|
||||||
|
else {
|
||||||
|
mouse_accel accel;
|
||||||
|
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||||
|
accel.speed = fSettings.accel.speed;
|
||||||
|
accel.accel_factor = fSettings.accel.accel_factor;
|
||||||
|
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_type\n");
|
||||||
|
else
|
||||||
|
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -445,36 +503,13 @@ MouseDevice::_RemapButtons(uint32 buttons) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char*
|
|
||||||
MouseDevice::_BuildShortName() const
|
|
||||||
{
|
|
||||||
BString string(fPath);
|
|
||||||
BString name;
|
|
||||||
|
|
||||||
int32 slash = string.FindLast("/");
|
|
||||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
|
||||||
int32 index = atoi(name.String()) + 1;
|
|
||||||
|
|
||||||
int32 previousSlash = string.FindLast("/", slash);
|
|
||||||
string.CopyInto(name, previousSlash + 1, slash - previousSlash - 1);
|
|
||||||
|
|
||||||
if (name == "ps2")
|
|
||||||
name = "PS/2";
|
|
||||||
else
|
|
||||||
name.Capitalize();
|
|
||||||
|
|
||||||
name << " Mouse " << index;
|
|
||||||
|
|
||||||
return strdup(name.String());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
MouseInputDevice::MouseInputDevice()
|
MouseInputDevice::MouseInputDevice()
|
||||||
:
|
:
|
||||||
fDevices(2, true)
|
fDevices(2, true),
|
||||||
|
fDeviceListLock("MouseInputDevice list")
|
||||||
{
|
{
|
||||||
MID_CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
@@ -592,7 +627,7 @@ MouseInputDevice::_RecursiveScan(const char* directory)
|
|||||||
|
|
||||||
|
|
||||||
MouseDevice*
|
MouseDevice*
|
||||||
MouseInputDevice::_FindDevice(const char* path)
|
MouseInputDevice::_FindDevice(const char* path) const
|
||||||
{
|
{
|
||||||
MID_CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
@@ -611,6 +646,8 @@ MouseInputDevice::_AddDevice(const char* path)
|
|||||||
{
|
{
|
||||||
MID_CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
_RemoveDevice(path);
|
_RemoveDevice(path);
|
||||||
|
|
||||||
MouseDevice* device = new(std::nothrow) MouseDevice(*this, path);
|
MouseDevice* device = new(std::nothrow) MouseDevice(*this, path);
|
||||||
@@ -640,6 +677,8 @@ MouseInputDevice::_RemoveDevice(const char* path)
|
|||||||
{
|
{
|
||||||
MID_CALLED();
|
MID_CALLED();
|
||||||
|
|
||||||
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
MouseDevice* device = _FindDevice(path);
|
MouseDevice* device = _FindDevice(path);
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
TRACE("%s not found\n", path);
|
TRACE("%s not found\n", path);
|
||||||
@@ -660,14 +699,4 @@ MouseInputDevice::_RemoveDevice(const char* path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <InputServerDevice.h>
|
#include <InputServerDevice.h>
|
||||||
#include <InterfaceDefs.h>
|
#include <InterfaceDefs.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
|
|
||||||
@@ -38,14 +39,13 @@ private:
|
|||||||
status_t _HandleMonitor(BMessage* message);
|
status_t _HandleMonitor(BMessage* message);
|
||||||
void _RecursiveScan(const char* directory);
|
void _RecursiveScan(const char* directory);
|
||||||
|
|
||||||
MouseDevice* _FindDevice(const char* path);
|
MouseDevice* _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);
|
||||||
|
|
||||||
bool _HasDevice(const MouseDevice* device) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BObjectList<MouseDevice> fDevices;
|
BObjectList<MouseDevice> fDevices;
|
||||||
|
BLocker fDeviceListLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" BInputServerDevice* instantiate_input_device();
|
extern "C" BInputServerDevice* instantiate_input_device();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "kb_mouse_settings.h"
|
#include "kb_mouse_settings.h"
|
||||||
#include "touchpad_settings.h"
|
#include "touchpad_settings.h"
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
@@ -49,50 +50,57 @@ const static char* kTouchpadDevicesDirectoryPS2 = "/dev/input/touchpad/ps2";
|
|||||||
|
|
||||||
|
|
||||||
class TouchpadDevice {
|
class TouchpadDevice {
|
||||||
public:
|
public:
|
||||||
TouchpadDevice(TouchpadInputDevice& target, const char* path);
|
TouchpadDevice(TouchpadInputDevice& target,
|
||||||
~TouchpadDevice();
|
const char* path);
|
||||||
|
~TouchpadDevice();
|
||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
status_t UpdateSettings();
|
status_t UpdateSettings();
|
||||||
|
status_t UpdateTouchpadSettings(const BMessage* message);
|
||||||
|
|
||||||
const char* Path() const { return fPath.String(); }
|
const char* Path() const { return fPath.String(); }
|
||||||
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
input_device_ref* DeviceRef() { return &fDeviceRef; }
|
||||||
|
|
||||||
bool IsTouchpad() { return fIsTouchpad; }
|
private:
|
||||||
status_t ReadTouchpadSettingsMsg(BMessage* msg);
|
char* _BuildShortName() const;
|
||||||
status_t UpdateTouchpadSettings();
|
|
||||||
|
|
||||||
private:
|
static status_t _ControlThreadEntry(void *arg);
|
||||||
void _Run();
|
void _ControlThread();
|
||||||
static status_t _ThreadFunction(void *arg);
|
void _ControlThreadCleanup();
|
||||||
|
void _UpdateSettings();
|
||||||
|
|
||||||
BMessage* _BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
status_t _GetSettingsPath(BPath &path);
|
||||||
int32 deltaX, int32 deltaY) const;
|
status_t _ReadTouchpadSettingsMsg(BMessage* message);
|
||||||
void _ComputeAcceleration(const mouse_movement& movements,
|
status_t _UpdateTouchpadSettings();
|
||||||
int32& deltaX, int32& deltaY) const;
|
|
||||||
uint32 _RemapButtons(uint32 buttons) const;
|
|
||||||
|
|
||||||
char* _BuildShortName() const;
|
BMessage* _BuildMouseMessage(uint32 what,
|
||||||
|
uint64 when, uint32 buttons,
|
||||||
|
int32 deltaX, int32 deltaY) const;
|
||||||
|
void _ComputeAcceleration(
|
||||||
|
const mouse_movement& movements,
|
||||||
|
int32& deltaX, int32& deltaY) const;
|
||||||
|
uint32 _RemapButtons(uint32 buttons) const;
|
||||||
|
|
||||||
status_t _GetSettingsPath(BPath &path);
|
private:
|
||||||
|
TouchpadInputDevice& fTarget;
|
||||||
|
BString fPath;
|
||||||
|
int fDevice;
|
||||||
|
|
||||||
private:
|
input_device_ref fDeviceRef;
|
||||||
TouchpadInputDevice& fTarget;
|
mouse_settings fSettings;
|
||||||
BString fPath;
|
bool fDeviceRemapsButtons;
|
||||||
int fDevice;
|
|
||||||
|
|
||||||
input_device_ref fDeviceRef;
|
thread_id fThread;
|
||||||
mouse_settings fSettings;
|
volatile bool fActive;
|
||||||
bool fDeviceRemapsButtons;
|
volatile bool fUpdateSettings;
|
||||||
|
|
||||||
thread_id fThread;
|
bool fIsTouchpad;
|
||||||
volatile bool fActive;
|
touchpad_settings fTouchpadSettings;
|
||||||
|
BMessage* fTouchpadSettingsMessage;
|
||||||
bool fIsTouchpad;
|
BLocker fTouchpadSettingsLock;
|
||||||
touchpad_settings fTouchpadSettings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +122,10 @@ TouchpadDevice::TouchpadDevice(TouchpadInputDevice& target,
|
|||||||
fDeviceRemapsButtons(false),
|
fDeviceRemapsButtons(false),
|
||||||
fThread(-1),
|
fThread(-1),
|
||||||
fActive(false),
|
fActive(false),
|
||||||
fIsTouchpad(false)
|
fUpdateSettings(false),
|
||||||
|
fIsTouchpad(false),
|
||||||
|
fTouchpadSettingsMessage(NULL),
|
||||||
|
fTouchpadSettingsLock("Touchpad settings lock")
|
||||||
{
|
{
|
||||||
fPath = driverPath;
|
fPath = driverPath;
|
||||||
|
|
||||||
@@ -137,16 +148,8 @@ TouchpadDevice::~TouchpadDevice()
|
|||||||
Stop();
|
Stop();
|
||||||
|
|
||||||
free(fDeviceRef.name);
|
free(fDeviceRef.name);
|
||||||
}
|
|
||||||
|
|
||||||
|
delete fTouchpadSettingsMessage;
|
||||||
status_t
|
|
||||||
TouchpadDevice::_GetSettingsPath(BPath &path)
|
|
||||||
{
|
|
||||||
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
return path.Append(TOUCHPAD_SETTINGS_FILE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -154,36 +157,15 @@ status_t
|
|||||||
TouchpadDevice::Start()
|
TouchpadDevice::Start()
|
||||||
{
|
{
|
||||||
fDevice = open(fPath.String(), O_RDWR);
|
fDevice = open(fPath.String(), O_RDWR);
|
||||||
if (fDevice < 0)
|
// let the control thread handle any error on opening the device
|
||||||
return errno;
|
|
||||||
|
|
||||||
// touchpad settings
|
|
||||||
if (ioctl(fDevice, MS_IS_TOUCHPAD, NULL) == B_OK) {
|
|
||||||
LOG("is touchpad %s\n", fPath.String());
|
|
||||||
fIsTouchpad = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fTouchpadSettings = kDefaultTouchpadSettings;
|
|
||||||
|
|
||||||
BPath path;
|
|
||||||
status_t status = _GetSettingsPath(path);
|
|
||||||
BFile settingsFile(path.Path(), B_READ_ONLY);
|
|
||||||
if (status == B_OK && settingsFile.InitCheck() == B_OK) {
|
|
||||||
if (settingsFile.Read(&fTouchpadSettings, sizeof(touchpad_settings))
|
|
||||||
!= sizeof(touchpad_settings)) {
|
|
||||||
LOG("failed to load settings\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateTouchpadSettings();
|
|
||||||
UpdateSettings();
|
|
||||||
|
|
||||||
char threadName[B_OS_NAME_LENGTH];
|
char threadName[B_OS_NAME_LENGTH];
|
||||||
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
snprintf(threadName, B_OS_NAME_LENGTH, "%s watcher", fDeviceRef.name);
|
||||||
|
|
||||||
fThread = spawn_thread(_ThreadFunction, threadName,
|
fThread = spawn_thread(_ControlThreadEntry, threadName,
|
||||||
kMouseThreadPriority, (void*)this);
|
kMouseThreadPriority, (void*)this);
|
||||||
|
|
||||||
|
status_t status;
|
||||||
if (fThread < B_OK)
|
if (fThread < B_OK)
|
||||||
status = fThread;
|
status = fThread;
|
||||||
else {
|
else {
|
||||||
@@ -225,83 +207,97 @@ TouchpadDevice::Stop()
|
|||||||
status_t
|
status_t
|
||||||
TouchpadDevice::UpdateSettings()
|
TouchpadDevice::UpdateSettings()
|
||||||
{
|
{
|
||||||
// TODO: This is duplicated in MouseInputDevice.cpp -> Refactor
|
if (fThread < 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
CALLED();
|
// trigger updating the settings in the control thread
|
||||||
|
fUpdateSettings = true;
|
||||||
// retrieve current values
|
|
||||||
|
|
||||||
if (get_mouse_map(&fSettings.map) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_map\n");
|
|
||||||
else
|
|
||||||
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
|
||||||
|
|
||||||
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
|
||||||
LOG_ERR("error when get_click_speed\n");
|
|
||||||
else
|
|
||||||
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
|
||||||
|
|
||||||
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_speed\n");
|
|
||||||
else {
|
|
||||||
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_acceleration\n");
|
|
||||||
else {
|
|
||||||
mouse_accel accel;
|
|
||||||
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
|
||||||
accel.speed = fSettings.accel.speed;
|
|
||||||
accel.accel_factor = fSettings.accel.accel_factor;
|
|
||||||
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_mouse_type(&fSettings.type) != B_OK)
|
|
||||||
LOG_ERR("error when get_mouse_type\n");
|
|
||||||
else
|
|
||||||
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
TouchpadDevice::ReadTouchpadSettingsMsg(BMessage* msg)
|
TouchpadDevice::UpdateTouchpadSettings(const BMessage* message)
|
||||||
{
|
{
|
||||||
msg->FindBool("scroll_twofinger",
|
if (fThread < 0)
|
||||||
&(fTouchpadSettings.scroll_twofinger));
|
return B_ERROR;
|
||||||
msg->FindBool("scroll_multifinger",
|
|
||||||
&(fTouchpadSettings.scroll_multifinger));
|
BAutolock _(fTouchpadSettingsLock);
|
||||||
msg->FindFloat("scroll_rightrange",
|
|
||||||
&(fTouchpadSettings.scroll_rightrange));
|
// trigger updating the settings in the control thread
|
||||||
msg->FindFloat("scroll_bottomrange",
|
fUpdateSettings = true;
|
||||||
&(fTouchpadSettings.scroll_bottomrange));
|
|
||||||
msg->FindInt16("scroll_xstepsize",
|
delete fTouchpadSettingsMessage;
|
||||||
(int16*)&(fTouchpadSettings.scroll_xstepsize));
|
fTouchpadSettingsMessage = new BMessage(*message);
|
||||||
msg->FindInt16("scroll_ystepsize",
|
|
||||||
(int16*)&(fTouchpadSettings.scroll_ystepsize));
|
|
||||||
msg->FindInt8("scroll_acceleration",
|
|
||||||
(int8*)&(fTouchpadSettings.scroll_acceleration));
|
|
||||||
msg->FindInt8("tapgesture_sensibility",
|
|
||||||
(int8*)&(fTouchpadSettings.tapgesture_sensibility));
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
char *
|
||||||
TouchpadDevice::UpdateTouchpadSettings()
|
TouchpadDevice::_BuildShortName() const
|
||||||
{
|
{
|
||||||
if (fIsTouchpad) {
|
BString string(fPath);
|
||||||
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
|
BString name;
|
||||||
return B_OK;
|
|
||||||
}
|
int32 slash = string.FindLast("/");
|
||||||
return B_ERROR;
|
string.CopyInto(name, slash + 1, string.Length() - slash);
|
||||||
|
//int32 index = atoi(name.String()) + 1;
|
||||||
|
|
||||||
|
BString final = "Touchpad ";
|
||||||
|
final += name;
|
||||||
|
|
||||||
|
LOG("NAME %s, %s\n", final.String(), fPath.String());
|
||||||
|
|
||||||
|
return strdup(final.String());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - control thread
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TouchpadDevice::_ControlThreadEntry(void* arg)
|
||||||
|
{
|
||||||
|
TouchpadDevice* device = (TouchpadDevice*)arg;
|
||||||
|
device->_ControlThread();
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TouchpadDevice::_Run()
|
TouchpadDevice::_ControlThread()
|
||||||
{
|
{
|
||||||
|
if (fDevice < 0) {
|
||||||
|
_ControlThreadCleanup();
|
||||||
|
// TOAST!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// touchpad settings
|
||||||
|
if (ioctl(fDevice, MS_IS_TOUCHPAD, NULL) == B_OK) {
|
||||||
|
LOG("is touchpad %s\n", fPath.String());
|
||||||
|
fIsTouchpad = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fTouchpadSettings = kDefaultTouchpadSettings;
|
||||||
|
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
status_t status = _GetSettingsPath(path);
|
||||||
|
BFile settingsFile(path.Path(), B_READ_ONLY);
|
||||||
|
if (status == B_OK && settingsFile.InitCheck() == B_OK) {
|
||||||
|
if (settingsFile.Read(&fTouchpadSettings, sizeof(touchpad_settings))
|
||||||
|
!= sizeof(touchpad_settings)) {
|
||||||
|
LOG("failed to load settings\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_UpdateTouchpadSettings();
|
||||||
|
_UpdateSettings();
|
||||||
|
|
||||||
// TODO: Exact duplicate of MouseDevice::_Run() -> Refactor
|
// TODO: Exact duplicate of MouseDevice::_Run() -> Refactor
|
||||||
uint32 lastButtons = 0;
|
uint32 lastButtons = 0;
|
||||||
|
|
||||||
@@ -310,20 +306,24 @@ TouchpadDevice::_Run()
|
|||||||
memset(&movements, 0, sizeof(movements));
|
memset(&movements, 0, sizeof(movements));
|
||||||
|
|
||||||
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
if (ioctl(fDevice, MS_READ, &movements) != B_OK) {
|
||||||
if (fActive) {
|
_ControlThreadCleanup();
|
||||||
fThread = -1;
|
|
||||||
fTarget._RemoveDevice(fPath.String());
|
|
||||||
} else {
|
|
||||||
// In case active is already false, another thread
|
|
||||||
// waits for this thread to quit, and may already hold
|
|
||||||
// locks that _RemoveDevice() wants to acquire. In another
|
|
||||||
// words, the device is already being removed, so we simply
|
|
||||||
// quit here.
|
|
||||||
}
|
|
||||||
// TOAST!
|
// TOAST!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update the settings if necessary
|
||||||
|
if (fUpdateSettings) {
|
||||||
|
fUpdateSettings = false;
|
||||||
|
BAutolock _(fTouchpadSettingsLock);
|
||||||
|
if (fTouchpadSettingsMessage) {
|
||||||
|
_ReadTouchpadSettingsMsg(fTouchpadSettingsMessage);
|
||||||
|
_UpdateTouchpadSettings();
|
||||||
|
delete fTouchpadSettingsMessage;
|
||||||
|
fTouchpadSettingsMessage = NULL;
|
||||||
|
} else
|
||||||
|
_UpdateSettings();
|
||||||
|
}
|
||||||
|
|
||||||
uint32 buttons = lastButtons ^ movements.buttons;
|
uint32 buttons = lastButtons ^ movements.buttons;
|
||||||
|
|
||||||
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
uint32 remappedButtons = _RemapButtons(movements.buttons);
|
||||||
@@ -377,15 +377,110 @@ TouchpadDevice::_Run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
void
|
||||||
TouchpadDevice::_ThreadFunction(void* arg)
|
TouchpadDevice::_ControlThreadCleanup()
|
||||||
{
|
{
|
||||||
TouchpadDevice* device = (TouchpadDevice*)arg;
|
// NOTE: Only executed when the control thread detected an error
|
||||||
device->_Run();
|
// and from within the control thread!
|
||||||
|
|
||||||
|
if (fActive) {
|
||||||
|
fThread = -1;
|
||||||
|
fTarget._RemoveDevice(fPath.String());
|
||||||
|
} else {
|
||||||
|
// In case active is already false, another thread
|
||||||
|
// waits for this thread to quit, and may already hold
|
||||||
|
// locks that _RemoveDevice() wants to acquire. In another
|
||||||
|
// words, the device is already being removed, so we simply
|
||||||
|
// quit here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TouchpadDevice::_UpdateSettings()
|
||||||
|
{
|
||||||
|
// TODO: This is duplicated in MouseInputDevice.cpp -> Refactor
|
||||||
|
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
// retrieve current values
|
||||||
|
|
||||||
|
if (get_mouse_map(&fSettings.map) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_map\n");
|
||||||
|
else
|
||||||
|
fDeviceRemapsButtons = ioctl(fDevice, MS_SET_MAP, &fSettings.map) == B_OK;
|
||||||
|
|
||||||
|
if (get_click_speed(&fSettings.click_speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_click_speed\n");
|
||||||
|
else
|
||||||
|
ioctl(fDevice, MS_SET_CLICKSPEED, &fSettings.click_speed);
|
||||||
|
|
||||||
|
if (get_mouse_speed(&fSettings.accel.speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_speed\n");
|
||||||
|
else {
|
||||||
|
if (get_mouse_acceleration(&fSettings.accel.accel_factor) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_acceleration\n");
|
||||||
|
else {
|
||||||
|
mouse_accel accel;
|
||||||
|
ioctl(fDevice, MS_GET_ACCEL, &accel);
|
||||||
|
accel.speed = fSettings.accel.speed;
|
||||||
|
accel.accel_factor = fSettings.accel.accel_factor;
|
||||||
|
ioctl(fDevice, MS_SET_ACCEL, &fSettings.accel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_mouse_type(&fSettings.type) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_type\n");
|
||||||
|
else
|
||||||
|
ioctl(fDevice, MS_SET_TYPE, &fSettings.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TouchpadDevice::_GetSettingsPath(BPath &path)
|
||||||
|
{
|
||||||
|
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
return path.Append(TOUCHPAD_SETTINGS_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TouchpadDevice::_ReadTouchpadSettingsMsg(BMessage* message)
|
||||||
|
{
|
||||||
|
message->FindBool("scroll_twofinger",
|
||||||
|
&(fTouchpadSettings.scroll_twofinger));
|
||||||
|
message->FindBool("scroll_multifinger",
|
||||||
|
&(fTouchpadSettings.scroll_multifinger));
|
||||||
|
message->FindFloat("scroll_rightrange",
|
||||||
|
&(fTouchpadSettings.scroll_rightrange));
|
||||||
|
message->FindFloat("scroll_bottomrange",
|
||||||
|
&(fTouchpadSettings.scroll_bottomrange));
|
||||||
|
message->FindInt16("scroll_xstepsize",
|
||||||
|
(int16*)&(fTouchpadSettings.scroll_xstepsize));
|
||||||
|
message->FindInt16("scroll_ystepsize",
|
||||||
|
(int16*)&(fTouchpadSettings.scroll_ystepsize));
|
||||||
|
message->FindInt8("scroll_acceleration",
|
||||||
|
(int8*)&(fTouchpadSettings.scroll_acceleration));
|
||||||
|
message->FindInt8("tapgesture_sensibility",
|
||||||
|
(int8*)&(fTouchpadSettings.tapgesture_sensibility));
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
TouchpadDevice::_UpdateTouchpadSettings()
|
||||||
|
{
|
||||||
|
if (fIsTouchpad) {
|
||||||
|
ioctl(fDevice, MS_SET_TOUCHPAD_SETTINGS, &fTouchpadSettings);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BMessage*
|
BMessage*
|
||||||
TouchpadDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
TouchpadDevice::_BuildMouseMessage(uint32 what, uint64 when, uint32 buttons,
|
||||||
int32 deltaX, int32 deltaY) const
|
int32 deltaX, int32 deltaY) const
|
||||||
@@ -467,29 +562,13 @@ TouchpadDevice::_RemapButtons(uint32 buttons) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
TouchpadDevice::_BuildShortName() const
|
|
||||||
{
|
|
||||||
BString string(fPath);
|
|
||||||
BString name;
|
|
||||||
|
|
||||||
int32 slash = string.FindLast("/");
|
|
||||||
string.CopyInto(name, slash + 1, string.Length() - slash);
|
|
||||||
//int32 index = atoi(name.String()) + 1;
|
|
||||||
|
|
||||||
BString final = "Touchpad ";
|
|
||||||
final += name;
|
|
||||||
|
|
||||||
LOG("NAME %s, %s\n", final.String(), fPath.String());
|
|
||||||
|
|
||||||
return strdup(final.String());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
TouchpadInputDevice::TouchpadInputDevice()
|
TouchpadInputDevice::TouchpadInputDevice()
|
||||||
|
:
|
||||||
|
fDevices(2, true),
|
||||||
|
fDeviceListLock("TouchpadInputDevice list")
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
@@ -545,10 +624,8 @@ TouchpadInputDevice::Control(const char* name, void* cookie,
|
|||||||
if (command == B_NODE_MONITOR)
|
if (command == B_NODE_MONITOR)
|
||||||
return _HandleMonitor(message);
|
return _HandleMonitor(message);
|
||||||
|
|
||||||
if (command == MS_SET_TOUCHPAD_SETTINGS) {
|
if (command == MS_SET_TOUCHPAD_SETTINGS)
|
||||||
device->ReadTouchpadSettingsMsg(message);
|
return device->UpdateTouchpadSettings(message);
|
||||||
return device->UpdateTouchpadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command >= B_MOUSE_TYPE_CHANGED
|
if (command >= B_MOUSE_TYPE_CHANGED
|
||||||
&& command <= B_MOUSE_ACCELERATION_CHANGED)
|
&& command <= B_MOUSE_ACCELERATION_CHANGED)
|
||||||
@@ -602,7 +679,7 @@ TouchpadInputDevice::_RecursiveScan(const char* directory)
|
|||||||
|
|
||||||
|
|
||||||
TouchpadDevice*
|
TouchpadDevice*
|
||||||
TouchpadInputDevice::_FindDevice(const char *path)
|
TouchpadInputDevice::_FindDevice(const char *path) const
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
@@ -621,6 +698,10 @@ TouchpadInputDevice::_AddDevice(const char *path)
|
|||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
|
_RemoveDevice(path);
|
||||||
|
|
||||||
TouchpadDevice* device = new (std::nothrow) TouchpadDevice(*this, path);
|
TouchpadDevice* device = new (std::nothrow) TouchpadDevice(*this, path);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
LOG("No memory\n");
|
LOG("No memory\n");
|
||||||
@@ -647,6 +728,8 @@ TouchpadInputDevice::_RemoveDevice(const char *path)
|
|||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
|
BAutolock _(fDeviceListLock);
|
||||||
|
|
||||||
TouchpadDevice* device = _FindDevice(path);
|
TouchpadDevice* device = _FindDevice(path);
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <InputServerDevice.h>
|
#include <InputServerDevice.h>
|
||||||
#include <InterfaceDefs.h>
|
#include <InterfaceDefs.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
|
|
||||||
@@ -41,11 +42,12 @@ public:
|
|||||||
status_t _HandleMonitor(BMessage* message);
|
status_t _HandleMonitor(BMessage* message);
|
||||||
void _RecursiveScan(const char* directory);
|
void _RecursiveScan(const char* directory);
|
||||||
|
|
||||||
TouchpadDevice* _FindDevice(const char* path);
|
TouchpadDevice* _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);
|
||||||
|
|
||||||
BObjectList<TouchpadDevice> fDevices;
|
BObjectList<TouchpadDevice> fDevices;
|
||||||
|
BLocker fDeviceListLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" BInputServerDevice* instantiate_input_device();
|
extern "C" BInputServerDevice* instantiate_input_device();
|
||||||
|
|||||||
Reference in New Issue
Block a user