Author: axeld Date: 2010-04-16 09:47:41 +0200 (Fri, 16 Apr 2010) New Revision: 36328 Changeset: http://dev.haiku-os.org/changeset/36328/haiku Added: haiku/trunk/headers/private/shared/Keymap.h haiku/trunk/src/kits/shared/Keymap.cpp Modified: haiku/trunk/src/add-ons/input_server/devices/keyboard/Jamfile haiku/trunk/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.cpp haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.h haiku/trunk/src/bin/consoled/Jamfile haiku/trunk/src/bin/consoled/consoled.cpp haiku/trunk/src/kits/shared/Jamfile haiku/trunk/src/preferences/keymap/Jamfile haiku/trunk/src/preferences/keymap/Keymap.cpp haiku/trunk/src/preferences/keymap/Keymap.h haiku/trunk/src/preferences/keymap/KeymapWindow.cpp Log: * Factored out a single base class out of the three Keymap implementations we had in our tree. * Adapted Keymap, <input>keyboard, and consoled to use it - the additional functionality is implemented via a subclass in the first two cases. * "keymap" will come next. Copied: haiku/trunk/headers/private/shared/Keymap.h (from rev 36300, haiku/trunk/src/bin/keymap/Keymap.h) =================================================================== --- haiku/trunk/headers/private/shared/Keymap.h (rev 0) +++ haiku/trunk/headers/private/shared/Keymap.h 2010-04-16 07:47:41 UTC (rev 36328) @@ -0,0 +1,60 @@ +/* + * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + */ +#ifndef _KEYMAP_H +#define _KEYMAP_H + + +#include <DataIO.h> +#include <InterfaceDefs.h> + + +class BKeymap { +public: + BKeymap(); + virtual ~BKeymap(); + + status_t SetTo(const char* path); + status_t SetTo(BDataIO& stream); + status_t SetToCurrent(); + status_t SetToDefault(); + void Unset(); + + bool IsModifierKey(uint32 keyCode) const; + uint32 Modifier(uint32 keyCode) const; + uint32 KeyForModifier(uint32 modifier) const; + uint8 IsDeadKey(uint32 keyCode, + uint32 modifiers, + bool* isEnabled = NULL) const; + bool IsDeadSecondKey(uint32 keyCode, + uint32 modifiers, + uint8 activeDeadKey) const; + void GetChars(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey, char** chars, + int32* numBytes) const; + + const key_map& Map() const { return fKeys; } + + bool operator==(const BKeymap& other) const; + bool operator!=(const BKeymap& other) const; + + BKeymap& operator=(const BKeymap& other); + +protected: + int32 Offset(uint32 keyCode, uint32 modifiers, + uint32* _table = NULL) const; + uint8 DeadKeyIndex(int32 offset) const; + +protected: + char* fChars; + key_map fKeys; + uint32 fCharsSize; +}; + + +#endif // KEYMAP_H Modified: haiku/trunk/src/add-ons/input_server/devices/keyboard/Jamfile =================================================================== --- haiku/trunk/src/add-ons/input_server/devices/keyboard/Jamfile 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/add-ons/input_server/devices/keyboard/Jamfile 2010-04-16 07:47:41 UTC (rev 36328) @@ -12,7 +12,7 @@ TeamMonitorWindow.cpp TeamListItem.cpp - : input_server be $(TARGET_LIBSUPC++) ; + : input_server be libshared.a $(TARGET_LIBSUPC++) ; Package haiku-inputkit-cvs : <input>keyboard : Modified: haiku/trunk/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp =================================================================== --- haiku/trunk/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp 2010-04-16 07:47:41 UTC (rev 36328) @@ -531,8 +531,8 @@ if (opcode == 0 || opcode == B_KEY_MAP_CHANGED || opcode == B_KEY_LOCKS_CHANGED) { BAutolock lock(fKeymapLock); - fKeymap.LoadCurrent(); - fModifiers = fKeymap.Locks(); + fKeymap.RetrieveCurrent(); + fModifiers = fKeymap.Map().lock_settings; _UpdateLEDs(); fControlKey = fKeymap.KeyForModifier(B_LEFT_CONTROL_KEY); fCommandKey = fKeymap.KeyForModifier(B_LEFT_COMMAND_KEY); Modified: haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.cpp =================================================================== --- haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.cpp 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.cpp 2010-04-16 07:47:41 UTC (rev 36328) @@ -13,11 +13,7 @@ #include <File.h> #include <InputServerTypes.h> #include <Message.h> -#ifdef CONSOLED -# include <FindDirectory.h> -#else -# include <input_globals.h> -#endif +#include <input_globals.h> #include <errno.h> #include <new> @@ -64,6 +60,17 @@ // #pragma mark - +Keymap::Keymap() +{ + RetrieveCurrent(); +} + + +Keymap::~Keymap() +{ +} + + void Keymap::DumpKeymap() { @@ -87,413 +94,20 @@ } -Keymap::Keymap() - : - fChars(NULL) -{ -#ifndef CONSOLED - key_map *keys; - _get_key_map(&keys, &fChars, &fCharsSize); - - if (keys) { - memcpy(&fKeys, keys, sizeof(key_map)); - free(keys); - } -#endif -} - - -Keymap::~Keymap() -{ - free(fChars); -} - - -/* we need to know if a key is a modifier key to choose - a valid key when several are pressed together -*/ -bool -Keymap::IsModifierKey(uint32 keyCode) -{ - return keyCode == fKeys.caps_key - || keyCode == fKeys.num_key - || keyCode == fKeys.scroll_key - || keyCode == fKeys.left_shift_key - || keyCode == fKeys.right_shift_key - || keyCode == fKeys.left_command_key - || keyCode == fKeys.right_command_key - || keyCode == fKeys.left_control_key - || keyCode == fKeys.right_control_key - || keyCode == fKeys.left_option_key - || keyCode == fKeys.right_option_key - || keyCode == fKeys.menu_key; -} - - -//! We need to know a modifier for a key -uint32 -Keymap::Modifier(uint32 keyCode) -{ - if (keyCode == fKeys.caps_key) - return B_CAPS_LOCK; - if (keyCode == fKeys.num_key) - return B_NUM_LOCK; - if (keyCode == fKeys.scroll_key) - return B_SCROLL_LOCK; - if (keyCode == fKeys.left_shift_key) - return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.right_shift_key) - return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; - if (keyCode == fKeys.left_command_key) - return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.right_command_key) - return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; - if (keyCode == fKeys.left_control_key) - return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.right_control_key) - return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; - if (keyCode == fKeys.left_option_key) - return B_LEFT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.right_option_key) - return B_RIGHT_OPTION_KEY | B_OPTION_KEY; - if (keyCode == fKeys.menu_key) - return B_MENU_KEY; - - return 0; -} - - -uint32 -Keymap::KeyForModifier(uint32 modifier) -{ - if (modifier == B_CAPS_LOCK) - return fKeys.caps_key; - if (modifier == B_NUM_LOCK) - return fKeys.num_key; - if (modifier == B_SCROLL_LOCK) - return fKeys.scroll_key; - if (modifier == B_LEFT_SHIFT_KEY || modifier == B_SHIFT_KEY) - return fKeys.left_shift_key; - if (modifier == B_RIGHT_SHIFT_KEY) - return fKeys.right_shift_key; - if (modifier == B_LEFT_COMMAND_KEY || modifier == B_COMMAND_KEY) - return fKeys.left_command_key; - if (modifier == B_RIGHT_COMMAND_KEY) - return fKeys.right_command_key; - if (modifier == B_LEFT_CONTROL_KEY || modifier == B_CONTROL_KEY) - return fKeys.left_control_key; - if (modifier == B_RIGHT_CONTROL_KEY) - return fKeys.right_control_key; - if (modifier == B_LEFT_OPTION_KEY || modifier == B_OPTION_KEY) - return fKeys.left_option_key; - if (modifier == B_RIGHT_OPTION_KEY) - return fKeys.right_option_key; - if (modifier == B_MENU_KEY) - return fKeys.menu_key; - - return 0; -} - - -//! Tell if a key is a dead key, needed for draw a dead key -uint8 -Keymap::IsDeadKey(uint32 keyCode, uint32 modifiers) -{ - if (keyCode >= 256) - return 0; - - int32 offset; - uint32 tableMask = 0; - - switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; tableMask = B_SHIFT_TABLE; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; tableMask = B_CAPS_TABLE; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; tableMask = B_CAPS_SHIFT_TABLE; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; tableMask = B_OPTION_TABLE; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; tableMask = B_OPTION_SHIFT_TABLE; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; tableMask = B_OPTION_CAPS_TABLE; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; tableMask = B_OPTION_CAPS_SHIFT_TABLE; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; tableMask = B_CONTROL_TABLE; break; - default: offset = fKeys.normal_map[keyCode]; tableMask = B_NORMAL_TABLE; break; - } - - if (offset <= 0 || offset > fCharsSize) - return 0; - - uint32 numBytes = fChars[offset]; - if (!numBytes) - return 0; - - char chars[4]; - strncpy(chars, &(fChars[offset+1]), numBytes ); - chars[numBytes] = 0; - - int32 deadOffsets[] = { - fKeys.acute_dead_key[1], - fKeys.grave_dead_key[1], - fKeys.circumflex_dead_key[1], - fKeys.dieresis_dead_key[1], - fKeys.tilde_dead_key[1] - }; - - uint32 deadTables[] = { - fKeys.acute_tables, - fKeys.grave_tables, - fKeys.circumflex_tables, - fKeys.dieresis_tables, - fKeys.tilde_tables - }; - - for (int32 i = 0; i < 5; i++) { - if ((deadTables[i] & tableMask) == 0) - continue; - - if (offset == deadOffsets[i]) - return i + 1; - - uint32 deadNumBytes = fChars[deadOffsets[i]]; - if (!deadNumBytes) - continue; - - if (!strncmp(chars, &(fChars[deadOffsets[i] + 1]), deadNumBytes)) - return i + 1; - } - return 0; -} - - -//! Tell if a key is a dead second key, needed for draw a dead second key -bool -Keymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey) -{ - if (!activeDeadKey || keyCode >= 256) - return false; - - int32 offset; - - switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; - default: offset = fKeys.normal_map[keyCode]; break; - } - - if (offset <= 0 || offset > fCharsSize) - return false; - - uint32 numBytes = fChars[offset]; - if (!numBytes) - return false; - - int32* deadOffsets[] = { - fKeys.acute_dead_key, - fKeys.grave_dead_key, - fKeys.circumflex_dead_key, - fKeys.dieresis_dead_key, - fKeys.tilde_dead_key - }; - - int32 *deadOffset = deadOffsets[activeDeadKey-1]; - - for (int32 i=0; i<32; i++) { - if (offset == deadOffset[i]) - return true; - - uint32 deadNumBytes = fChars[deadOffset[i]]; - if (!deadNumBytes) - continue; - - if (!strncmp(&(fChars[offset+1]), &(fChars[deadOffset[i]+1]), deadNumBytes)) - return true; - - i++; - } - - return false; -} - - -//! Get the char for a key given modifiers and active dead key -void -Keymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, - char** chars, int32* numBytes) -{ - *numBytes = 0; - *chars = NULL; - - if (keyCode >= 256) - return; - - // here we take NUMLOCK into account - if (modifiers & B_NUM_LOCK) { - switch (keyCode) { - case 0x37: - case 0x38: - case 0x39: - case 0x48: - case 0x49: - case 0x4a: - case 0x58: - case 0x59: - case 0x5a: - case 0x64: - case 0x65: - modifiers ^= B_SHIFT_KEY; - break; - } - } - - int32 offset; - - // here we choose the right map given the modifiers - switch (modifiers & 0xcf) { - case B_SHIFT_KEY: offset = fKeys.shift_map[keyCode]; break; - case B_CAPS_LOCK: offset = fKeys.caps_map[keyCode]; break; - case B_CAPS_LOCK|B_SHIFT_KEY: offset = fKeys.caps_shift_map[keyCode]; break; - case B_OPTION_KEY: offset = fKeys.option_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY: offset = fKeys.option_shift_map[keyCode]; break; - case B_OPTION_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_map[keyCode]; break; - case B_OPTION_KEY|B_SHIFT_KEY|B_CAPS_LOCK: offset = fKeys.option_caps_shift_map[keyCode]; break; - case B_CONTROL_KEY: offset = fKeys.control_map[keyCode]; break; - - default: - offset = fKeys.normal_map[keyCode]; - break; - } - - if (offset <= 0) - return; - - // here we get the char size - *numBytes = fChars[offset]; - if (!*numBytes) - return; - - // here we take an potential active dead key - int32 *deadKey; - switch (activeDeadKey) { - case 1: deadKey = fKeys.acute_dead_key; break; - case 2: deadKey = fKeys.grave_dead_key; break; - case 3: deadKey = fKeys.circumflex_dead_key; break; - case 4: deadKey = fKeys.dieresis_dead_key; break; - case 5: deadKey = fKeys.tilde_dead_key; break; - default: - { - // if not dead, we copy and return the char - char *str = *chars = new (std::nothrow) char[*numBytes + 1]; - if (str == NULL) { - *numBytes = 0; - return; - } - strncpy(str, &(fChars[offset + 1]), *numBytes); - str[*numBytes] = 0; - return; - } - } - - // if dead key, we search for our current offset char in the dead key offset table - // string comparison is needed - for (int32 i = 0; i < 32; i++) { - if (strncmp(&(fChars[offset + 1]), &(fChars[deadKey[i] + 1]), *numBytes) == 0) { - *numBytes = fChars[deadKey[i + 1]]; - - switch (*numBytes) { - case 0: - // Not mapped - *chars = NULL; - break; - default: - { - // 1-, 2-, 3-, or 4-byte UTF-8 character - char *str = *chars = new (std::nothrow) char[*numBytes + 1]; - if (str == NULL) { - *numBytes = 0; - return; - } - strncpy(str, &fChars[deadKey[i + 1] + 1], *numBytes); - str[*numBytes] = 0; - break; - } - } - return; - } - i++; - } - - // if not found we return the whole sequence (the dead key itself plus - // the following char) - int32 deadKeyNumBytes = fChars[deadKey[1]]; - int32 fullNumBytes = deadKeyNumBytes + *numBytes; - *chars = new (std::nothrow) char[fullNumBytes + 1]; - if (*chars == NULL) { - *numBytes = 0; - return; - } - strncpy(*chars, &fChars[deadKey[1] + 1], deadKeyNumBytes); - strncpy(*chars + deadKeyNumBytes, &fChars[offset + 1], *numBytes); - *numBytes = fullNumBytes; - (*chars)[fullNumBytes] = 0; -} - - status_t -Keymap::LoadCurrent() +Keymap::RetrieveCurrent() { -#ifndef CONSOLED - key_map* keys = NULL; - free(fChars); - fChars = NULL; + Unset(); - _get_key_map(&keys, &fChars, &fCharsSize); + key_map* keys; + _get_key_map(&keys, &fChars, (ssize_t*)&fCharsSize); if (!keys) { fprintf(stderr, "error while getting current keymap!\n"); return B_ERROR; } + memcpy(&fKeys, keys, sizeof(fKeys)); free(keys); return B_OK; -#else // CONSOLED - char path[PATH_MAX]; - status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, - path, sizeof(path)); - if (status != B_OK) - return status; - - strlcat(path, "/Key_map", sizeof(path)); - int file = open(path, O_RDONLY); - if (file < 0) - return errno; - - if (read(file, &fKeys, sizeof(fKeys)) < (ssize_t)sizeof(fKeys)) { - fprintf(stderr, "error reading keymap keys\n"); - return B_BAD_VALUE; - } - - for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) - ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); - - if (read(file, &fCharsSize, sizeof(uint32)) < (ssize_t)sizeof(uint32)) { - fprintf(stderr, "error reading keymap size\n"); - return B_BAD_VALUE; - } - - fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); - if (fCharsSize < 0) - return B_BAD_VALUE; - - fChars = new char[fCharsSize]; - - if (read(file, fChars, fCharsSize) < 0) { - fprintf(stderr, "error reading keymap chars\n"); - return B_ERROR; - } - - return B_OK; -#endif // CONSOLED } Modified: haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.h =================================================================== --- haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.h 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/add-ons/input_server/devices/keyboard/Keymap.h 2010-04-16 07:47:41 UTC (rev 36328) @@ -1,5 +1,5 @@ /* - * Copyright 2004, Haiku. + * Copyright 2004-2010, Haiku. * Distributed under the terms of the MIT License. * * Authors: @@ -9,33 +9,18 @@ #define KEYMAP_H -#include <InterfaceDefs.h> +#include <Keymap.h> #include <Entry.h> -class Keymap { +class Keymap : public BKeymap { public: Keymap(); ~Keymap(); void DumpKeymap(); - bool IsModifierKey(uint32 keyCode); - uint32 Modifier(uint32 keyCode); - uint32 KeyForModifier(uint32 modifier); - uint8 IsDeadKey(uint32 keyCode, uint32 modifiers); - bool IsDeadSecondKey(uint32 keyCode, - uint32 modifiers, uint8 activeDeadKey); - void GetChars(uint32 keyCode, uint32 modifiers, - uint8 activeDeadKey, char** chars, - int32* numBytes); - uint32 Locks() { return fKeys.lock_settings; }; - status_t LoadCurrent(); - -private: - char* fChars; - key_map fKeys; - ssize_t fCharsSize; + status_t RetrieveCurrent(); }; Modified: haiku/trunk/src/bin/consoled/Jamfile =================================================================== --- haiku/trunk/src/bin/consoled/Jamfile 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/bin/consoled/Jamfile 2010-04-16 07:47:41 UTC (rev 36328) @@ -1,25 +1,9 @@ SubDir HAIKU_TOP src bin consoled ; -UsePrivateHeaders input ; -UsePrivateHeaders kernel ; +UsePrivateHeaders input kernel shared ; UseHeaders [ FDirName $(HAIKU_TOP) src apps terminal ] ; -UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) servers input ] ; -SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons input_server devices - keyboard ] ; -SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers input ] ; - -{ - local defines = [ FDefines CONSOLED ] ; - SubDirCcFlags $(defines) -Wall -Wno-multichar ; - SubDirC++Flags $(defines) -Wall -Wno-multichar ; -} - Application consoled : consoled.cpp - - Keymap.cpp - : $(TARGET_LIBSUPC++) + : be libshared.a $(TARGET_LIBSUPC++) ; - -Includes [ FGristFiles consoled.cpp ] : <src!servers!input>SystemKeymap.h ; Modified: haiku/trunk/src/bin/consoled/consoled.cpp =================================================================== --- haiku/trunk/src/bin/consoled/consoled.cpp 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/bin/consoled/consoled.cpp 2010-04-16 07:47:41 UTC (rev 36328) @@ -16,16 +16,15 @@ #include <termios.h> #include <unistd.h> +#include <FindDirectory.h> #include <image.h> #include <InterfaceDefs.h> #include <OS.h> #include <keyboard_mouse_driver.h> +#include <Keymap.h> -#include "SystemKeymap.h" -#include "Keymap.h" - struct console; struct keyboard { @@ -91,8 +90,19 @@ uint8 activeDeadKey = 0; uint32 modifiers = 0; - Keymap keymap; - keymap.LoadCurrent(); + BKeymap keymap; + // Load current keymap from disk (we can't talk to the input server) + // TODO: find a better way (we shouldn't have to care about the on-disk + // location) + char path[PATH_MAX]; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, + path, sizeof(path)); + if (status == B_OK) { + strlcat(path, "/Key_map", sizeof(path)); + status = keymap.SetTo(path); + } + if (status != B_OK) + keymap.SetToDefault(); for (;;) { raw_key_info rawKeyInfo; Modified: haiku/trunk/src/kits/shared/Jamfile =================================================================== --- haiku/trunk/src/kits/shared/Jamfile 2010-04-16 05:53:47 UTC (rev 36327) +++ haiku/trunk/src/kits/shared/Jamfile 2010-04-16 07:47:41 UTC (rev 36328) @@ -5,6 +5,7 @@ UseLibraryHeaders agg ; UsePrivateHeaders shared libbe ; +UseHeaders [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) servers input ] ; # for RWLockManager only UsePrivateSystemHeaders ; @@ -17,12 +18,14 @@ CommandPipe.cpp DragTrackingFilter.cpp HashString.cpp + Keymap.cpp RWLockManager.cpp ShakeTrackingFilter.cpp StringForSize.cpp Variant.cpp ; +Includes [ FGristFiles Keymap.cpp ] : <src!servers!input>SystemKeymap.h ; UseLibraryHeaders mapm ; Copied: haiku/trunk/src/kits/shared/Keymap.cpp (from rev 36300, haiku/trunk/src/bin/keymap/Keymap.cpp) =================================================================== --- haiku/trunk/src/kits/shared/Keymap.cpp (rev 0) +++ haiku/trunk/src/kits/shared/Keymap.cpp 2010-04-16 07:47:41 UTC (rev 36328) @@ -0,0 +1,537 @@ +/* + * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval + * Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + */ + + +#include <Keymap.h> + +#include <new> + +#include <stdlib.h> +#include <string.h> + +#include <ByteOrder.h> +#include <File.h> + +#include "SystemKeymap.h" + // generated by the build system + + +// Private only at this point, as we might want to improve the dead key +// implementation in the future +enum dead_key_index { + kDeadKeyAcute = 1, + kDeadKeyGrave, + kDeadKeyCircumflex, + kDeadKeyDiaeresis, + kDeadKeyTilde +}; + + +static const uint32 kModifierKeys = B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY + | B_CAPS_LOCK | B_OPTION_KEY | B_MENU_KEY; + + +BKeymap::BKeymap() + : + fChars(NULL), + fCharsSize(0) +{ + Unset(); +} + + +BKeymap::~BKeymap() +{ + delete[] fChars; +} + + +/*! Load a map from a file. + File format in big endian: + struct key_map + uint32 size of following charset + charset (offsets go into this with size of character followed by + character) +*/ +status_t +BKeymap::SetTo(const char* path) +{ + BFile file; + status_t status = file.SetTo(path, B_READ_ONLY); + if (status != B_OK) + return status; + + return SetTo(file); +} + + +status_t +BKeymap::SetTo(BDataIO& stream) +{ + if (stream.Read(&fKeys, sizeof(fKeys)) < 1) + return B_IO_ERROR; + + // convert from big-endian + for (uint32 i = 0; i < sizeof(fKeys) / 4; i++) { + ((uint32*)&fKeys)[i] = B_BENDIAN_TO_HOST_INT32(((uint32*)&fKeys)[i]); + } + + if (fKeys.version != 3) + return B_BAD_DATA; + + if (stream.Read(&fCharsSize, sizeof(uint32)) < 1) + return B_IO_ERROR; + + fCharsSize = B_BENDIAN_TO_HOST_INT32(fCharsSize); + if (fCharsSize > 16 * 1024) { + Unset(); + return B_BAD_DATA; + } + + delete[] fChars; + fChars = new char[fCharsSize]; + + if (stream.Read(fChars, fCharsSize) != (ssize_t)fCharsSize) { + Unset(); + return B_IO_ERROR; + } + + return B_OK; +} + + +status_t +BKeymap::SetToCurrent() +{ +#if (defined(__BEOS__) || defined(__HAIKU__)) + key_map* keys = NULL; + get_key_map(&keys, &fChars); + if (!keys) + return B_ERROR; + + memcpy(&fKeys, keys, sizeof(fKeys)); + free(keys); + return B_OK; +#else // ! __BEOS__ + fprintf(stderr, "Unsupported operation on this platform!\n"); + exit(1); +#endif // ! __BEOS__ +} + + +status_t +BKeymap::SetToDefault() +{ + fKeys = kSystemKeymap; + fCharsSize = kSystemKeyCharsSize; + + fChars = new (std::nothrow) char[fCharsSize]; + if (fChars == NULL) { + Unset(); + return B_NO_MEMORY; + } + + memcpy(fChars, kSystemKeyChars, fCharsSize); + return B_OK; +} + + +void +BKeymap::Unset() +{ + delete fChars; + fChars = NULL; + fCharsSize = 0; + + memset(&fKeys, 0, sizeof(fKeys)); +} + + +/*! We need to know if a key is a modifier key to choose + a valid key when several are pressed together +*/ +bool +BKeymap::IsModifierKey(uint32 keyCode) const +{ + return keyCode == fKeys.caps_key + || keyCode == fKeys.num_key + || keyCode == fKeys.left_shift_key + || keyCode == fKeys.right_shift_key + || keyCode == fKeys.left_command_key + || keyCode == fKeys.right_command_key + || keyCode == fKeys.left_control_key + || keyCode == fKeys.right_control_key + || keyCode == fKeys.left_option_key + || keyCode == fKeys.right_option_key + || keyCode == fKeys.menu_key; +} + + +//! We need to know a modifier for a key +uint32 +BKeymap::Modifier(uint32 keyCode) const +{ + if (keyCode == fKeys.caps_key) + return B_CAPS_LOCK; + if (keyCode == fKeys.num_key) + return B_NUM_LOCK; + if (keyCode == fKeys.scroll_key) + return B_SCROLL_LOCK; + if (keyCode == fKeys.left_shift_key) + return B_LEFT_SHIFT_KEY | B_SHIFT_KEY; + if (keyCode == fKeys.right_shift_key) + return B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; + if (keyCode == fKeys.left_command_key) + return B_LEFT_COMMAND_KEY | B_COMMAND_KEY; + if (keyCode == fKeys.right_command_key) + return B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; + if (keyCode == fKeys.left_control_key) + return B_LEFT_CONTROL_KEY | B_CONTROL_KEY; + if (keyCode == fKeys.right_control_key) + return B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; + if (keyCode == fKeys.left_option_key) + return B_LEFT_OPTION_KEY | B_OPTION_KEY; + if (keyCode == fKeys.right_option_key) + return B_RIGHT_OPTION_KEY | B_OPTION_KEY; + if (keyCode == fKeys.menu_key) + return B_MENU_KEY; + + return 0; +} + + +uint32 +BKeymap::KeyForModifier(uint32 modifier) const +{ + if (modifier == B_CAPS_LOCK) + return fKeys.caps_key; + if (modifier == B_NUM_LOCK) + return fKeys.num_key; + if (modifier == B_SCROLL_LOCK) + return fKeys.scroll_key; + if (modifier == B_LEFT_SHIFT_KEY || modifier == B_SHIFT_KEY) + return fKeys.left_shift_key; + if (modifier == B_RIGHT_SHIFT_KEY) + return fKeys.right_shift_key; + if (modifier == B_LEFT_COMMAND_KEY || modifier == B_COMMAND_KEY) + return fKeys.left_command_key; + if (modifier == B_RIGHT_COMMAND_KEY) + return fKeys.right_command_key; + if (modifier == B_LEFT_CONTROL_KEY || modifier == B_CONTROL_KEY) + return fKeys.left_control_key; + if (modifier == B_RIGHT_CONTROL_KEY) + return fKeys.right_control_key; + if (modifier == B_LEFT_OPTION_KEY || modifier == B_OPTION_KEY) + return fKeys.left_option_key; + if (modifier == B_RIGHT_OPTION_KEY) + return fKeys.right_option_key; + if (modifier == B_MENU_KEY) + return fKeys.menu_key; + + return 0; +} + + +/*! Checks whether a key is a dead key. + If it is, the enabled/disabled state of that dead key will be passed + out via isEnabled (isEnabled is not touched for non-dead keys). +*/ +uint8 +BKeymap::IsDeadKey(uint32 keyCode, uint32 modifiers, bool* _isEnabled) const +{ + uint32 tableMask = 0; + int32 offset = Offset(keyCode, modifiers, &tableMask); + uint8 deadKeyIndex = DeadKeyIndex(offset); + if (deadKeyIndex > 0 && _isEnabled != NULL) { + uint32 deadTables[] = { + fKeys.acute_tables, + fKeys.grave_tables, + fKeys.circumflex_tables, + fKeys.dieresis_tables, + fKeys.tilde_tables + }; + *_isEnabled = (deadTables[deadKeyIndex - 1] & tableMask) != 0; + } + + return deadKeyIndex; +} + + +//! Tell if a key is a dead second key. +bool +BKeymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, + uint8 activeDeadKey) const +{ + if (!activeDeadKey) + return false; + + int32 offset = Offset(keyCode, modifiers); + if (offset < 0) + return false; + + uint32 numBytes = fChars[offset]; + if (!numBytes) + return false; + + const int32* deadOffsets[] = { + fKeys.acute_dead_key, + fKeys.grave_dead_key, + fKeys.circumflex_dead_key, + fKeys.dieresis_dead_key, + fKeys.tilde_dead_key + }; [... truncated: 893 lines follow ...]