[haiku-development] Re: Keymap management backend.

  • From: Alexandre Deckner <alex@xxxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Fri, 05 Sep 2008 18:55:43 +0200

Stephan Assmus wrote:
Alexandre Deckner wrote:
Hi devs,
I started adding a few extensions to the keymap management in the input server as it was suggested by Axel in the commit list discussion for r24924 . This greatly simplifies the code and allow fixing bugs and to further enhance the Keymap preflet , and has all kinds of nice implications like easy keymap switching and keymap change on readonly systems. Well everything is said in the aforementioned thread.

It's 50% done, but now comes my first implementation question: Since i'm creating a new api, wouldn't it be better to add these new calls in a new (small) c++ api, instead of extending InterfaceDefs.h ?

I tried to extend the C interface but it felt really ugly and time consuming (i pass on the details but i lost hours on c strings and tables). Besides it also add some uglyness in the client apps. Awkward, when you know that the client apps and the i.s are written in lovely Be-style c++ .

Now i've put the few static methods i need in a separate c++ api that talks directly with the i.s. It works well, allowed me to progress faster, and it really feels better :)

Should i pursue with this approach? If yes, how to integrate it nicely? For now i've just put a InputServerAPI.cpp/h in the same places as InterfaceDefs.h/cpp and it works so far.

If you feel that it's nicer I think you should definitely pursue it. Alternative to an "InputServerAPI", you could also make a class specifically for controlling keymaps. "BKeymapController" or "BKeymapManager" comes to mind, perhaps even "BKeymapRoster" depending on it's capabilities. This way the C++ API could be more fine grained and targeted at the specific need. You just need to put it into the BPrivate namespace.
Ok, here is a proof of concept, WIP, RFC, whatever you want to call it. There's one important TODO left (see comment about keymap config file), but the rest is pretty much done and working except the ability to create new keymaps from a preflet.

So with this, you can:
- Change the keymap on a readonly system (think installer).
- Dramatically simplify the preflet code and make it safer, and reliably show wich keymap is currently active.
- Easily write a keymap switcher.
- And maybe more...

For those interested, have a look at those two attached diffs, one for the backend and one for the preflet.

Thanks,
Alex

PS: I won't have time to work on it in the next few days, so no hurry if you'd like to comment.



Index: src/kits/interface/KeymapManager.cpp
===================================================================
--- src/kits/interface/KeymapManager.cpp        (revision 0)
+++ src/kits/interface/KeymapManager.cpp        (revision 0)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2008, Haiku, Inc.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Alexandre Deckner <alex@xxxxxxxxxxxx>
+ */
+
+/*!    BKeymapManager, new API for keymap management */
+
+#include <input_globals.h>
+#include <InputServerTypes.h>
+#include <InterfacePrivate.h>
+#include <Keymap.h>
+#include <KeymapManager.h>
+#include <Message.h>
+#include <String.h>
+
+
+namespace BPrivate {
+
+status_t
+BKeymapManager::ActivateKeymap(const BString &name)
+{      
+       BMessage command(IS_BKM_ACTIVATE_KEYMAP);
+       command.AddString("name", name);
+       
+       BMessage reply;
+       status_t err;
+
+       _control_input_server_(&command, &reply);
+       
+       if (reply.FindInt32("status", &err) != B_OK)
+               return B_ERROR;
+
+       return err;     
+}
+       
+
+status_t
+BKeymapManager::GetActiveKeymapName(BString &name)
+{      
+       BMessage command(IS_BKM_GET_ACTIVE_KEYMAP_NAME);
+       BMessage reply;
+       status_t err;
+
+       _control_input_server_(&command, &reply);
+       
+       if (reply.FindInt32("status", &err) != B_OK)
+               return B_ERROR;
+       
+       return reply.FindString("name", &name); 
+}
+
+       
+status_t
+BKeymapManager::GetKeymapNames(NameList &list)
+{
+       BMessage command(IS_BKM_GET_KEYMAP_NAMES);
+       BMessage reply;
+       int32 err;
+
+       _control_input_server_(&command, &reply);
+       
+       if (reply.FindInt32("status", &err) != B_OK)
+               return B_ERROR;
+               
+       int32 count = 0;
+       if (reply.FindInt32("count", &count) != B_OK)   //plus necessaire en 
principe
+               return B_ERROR; 
+       
+       for (int i = 0; i < count; i++) {
+               BString name;
+               if (reply.FindString("name", i, &name) == B_OK) {
+                       list.push_back(name);   
+               } else {
+                       //break;
+                       //
+               }               
+       }
+
+       return B_OK; //TODO
+       
+}
+
+       
+//same as InterfaceDefs get_key_map
+BKeymap *
+BKeymapManager::GetKeymap(const BString &name)
+{
+       BMessage command(IS_BKM_GET_KEYMAP);    
+       command.AddString("name", name);        
+       BMessage reply; 
+       
+       _control_input_server_(&command, &reply);
+       
+       //TODO pass directly a BKeymap
+       ssize_t map_count, key_count;
+       const void *map_array = 0, *key_array = 0;
+               
+       if (reply.FindData("keymap", B_ANY_TYPE, &map_array, &map_count) != 
B_OK) {
+               //*map = 0; *key_buffer = 0;
+               return NULL;
+       }
+
+       if (reply.FindData("key_buffer", B_ANY_TYPE, &key_array, &key_count) != 
B_OK) {
+               //*map = 0; *key_buffer = 0;
+               return NULL;
+       }
+       printf("BKeymapManager::GetKeymap name=%s map_count=%u key_count=%u\n", 
name.String(), map_count, key_count);
+       
+       BKeymap *keymap = new BKeymap(); //TODO
+       keymap->fChars = new char[key_count];   //ugly
+       //*map = (key_map *)malloc(map_count);
+       memcpy(&keymap->fKeys, map_array, map_count);
+       //*key_buffer = (char *)malloc(*key_buffer_size);
+       memcpy(keymap->fChars, key_array, key_count);
+       keymap->fCharsSize = key_count;
+       
+       return keymap;
+}      
+       
+       
+} // namespace BPrivate
Index: src/kits/interface/Keymap.cpp
===================================================================
--- src/kits/interface/Keymap.cpp       (revision 0)
+++ src/kits/interface/Keymap.cpp       (revision 0)
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2004-2008 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Sandor Vroemisse
+ *             Jérôme Duval
+ *             Alexandre Deckner <alex@xxxxxxxxxxxx>
+ */
+
+#include <Keymap.h>
+#include <stdio.h>
+#include <string.h>
+
+namespace BPrivate {
+
+static void 
+print_key(char *chars, int32 offset) 
+{
+       int size = chars[offset++];
+       
+       switch(size) {
+       case 0:
+               // Not mapped 
+               printf("N/A"); 
+               break; 
+       
+       case 1:
+               // 1-byte UTF-8/ASCII character 
+               printf("%c", chars[offset]); 
+               break; 
+       
+       default:
+               // 2-, 3-, or 4-byte UTF-8 character 
+               { 
+                       char *str = new char[size + 1]; 
+                       strncpy(str, &(chars[offset]), size);
+                       str[size] = 0; 
+                       printf("%s", str); 
+                       delete [] str; 
+               } 
+               break; 
+       } 
+       
+       printf("\t"); 
+}
+       
+       
+BKeymap::BKeymap()
+       : fIsValid(false)
+{
+       //TODO
+}
+
+
+BKeymap::~BKeymap()
+{
+               
+}
+
+
+void
+BKeymap::Dump()
+{
+       // Print a chart of the normal, shift, option, and option+shift 
+       // keys. 
+       printf("Key 
#\tNormal\tShift\tCaps\tC+S\tOption\tO+S\tO+C\tO+C+S\tControl\n"); 
+       for (int idx = 0; idx < 128; idx++) { 
+               printf(" 0x%x\t", idx ); 
+               print_key(fChars, fKeys.normal_map[idx]); 
+               print_key(fChars, fKeys.shift_map[idx]); 
+               print_key(fChars, fKeys.caps_map[idx]); 
+               print_key(fChars, fKeys.caps_shift_map[idx]); 
+               print_key(fChars, fKeys.option_map[idx]); 
+               print_key(fChars, fKeys.option_shift_map[idx]); 
+               print_key(fChars, fKeys.option_caps_map[idx]); 
+               print_key(fChars, fKeys.option_caps_shift_map[idx]); 
+               print_key(fChars, fKeys.control_map[idx]); 
+               printf("\n"); 
+       } 
+
+}
+
+
+/* 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)
+{
+       if ((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))
+                       return true;
+       return false;
+}
+
+
+// tell if a key is a dead key, needed for draw a dead key
+uint8
+BKeymap::IsDeadKey(uint32 keyCode, uint32 modifiers)
+{
+       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)
+               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 ) 
== 0) {
+                       return i+1;
+               }
+       }
+       return 0;
+}
+
+
+// tell if a key is a dead second key, needed for draw a dead second key
+bool
+BKeymap::IsDeadSecondKey(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey)
+{
+       if (!activeDeadKey)
+               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;
+       }
+       
+       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 ) == 0)
+                       return true;
+               i++;
+       }
+       return false;
+}
+
+
+// get the char for a key given modifiers and active dead key
+void
+BKeymap::GetChars(uint32 keyCode, uint32 modifiers, uint8 activeDeadKey, 
char** chars, int32* numBytes)
+{
+       int32 offset;
+       
+       *numBytes = 0;
+       *chars = NULL;
+       
+       // 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;
+               }       
+
+       // 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;
+       }
+       
+       // here we get the char size
+       *numBytes = fChars[offset];
+       
+       if (!*numBytes)
+               return;
+       
+       // here we take an potential active dead key
+       int32 *dead_key;
+       switch(activeDeadKey) {
+               case 1: dead_key = fKeys.acute_dead_key; break;
+               case 2: dead_key = fKeys.grave_dead_key; break;
+               case 3: dead_key = fKeys.circumflex_dead_key; break;
+               case 4: dead_key = fKeys.dieresis_dead_key; break;
+               case 5: dead_key = fKeys.tilde_dead_key; break;
+               default: 
+               {
+                       // if not dead, we copy and return the char
+                       char *str = *chars = new char[*numBytes + 1]; 
+                       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[dead_key[i]+1]), 
*numBytes ) == 0) {
+                       *numBytes = fChars[dead_key[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 char[*numBytes 
+ 1]; 
+                                       strncpy(str, &fChars[dead_key[i+1]+1], 
*numBytes );
+                                       str[*numBytes] = 0; 
+                               } 
+                                       break; 
+                       }
+                       return;
+               }               
+               i++;
+       }
+
+       // if not found we return the current char mapped       
+       *chars = new char[*numBytes + 1];
+       strncpy(*chars, &(fChars[offset+1]), *numBytes );
+       (*chars)[*numBytes] = 0;        
+       
+}
+
+
+} //namespace BPrivate
Index: src/kits/interface/Jamfile
===================================================================
--- src/kits/interface/Jamfile  (revision 27334)
+++ src/kits/interface/Jamfile  (working copy)
@@ -60,6 +60,8 @@
        GroupView.cpp
        Input.cpp
        InterfaceDefs.cpp
+       Keymap.cpp
+       KeymapManager.cpp
        Layout.cpp
        LayoutContext.cpp
        LayoutItem.cpp
Index: src/servers/input/InputServer.cpp
===================================================================
--- src/servers/input/InputServer.cpp   (revision 27334)
+++ src/servers/input/InputServer.cpp   (working copy)
@@ -150,7 +150,18 @@
 {
        CALLED();
        gInputServer = this;
-
+       
+       //TODO: There's no way to know what keymap was actually loaded from
+       //the "Key_map" file, except with an attribute trick. So this will not
+       //work if you changed the default Key_map in your UserBuildConfig.
+       //In fact, now we should just put this name in a config file and
+       // "BKMActivate" that one on IS startup. 
+       //In the same vain, we should now save the active keymap in this same
+       //config file on IS exit. Since with the new system we don't do any
+       //file write when activating a keymap.
+       
+       fActiveKeymapName = "American";
+       
        _StartEventLoop();
 
        char parameter[32];
@@ -379,6 +390,108 @@
 }
 
 
+status_t
+InputServer::_BKMPreloadKeymaps()
+{
+       BPath path;
+       if (find_directory(B_BEOS_ETC_DIRECTORY, &path) != B_OK)
+               return B_ERROR;
+       
+       path.Append("Keymap");
+       
+       BDirectory directory;
+       entry_ref ref;
+       
+       if (directory.SetTo(path.Path()) == B_OK)
+               while( directory.GetNextRef(&ref) == B_OK ) {
+                       _BKMPreloadKeymap(ref);
+               }
+       
+       return B_OK;
+}
+
+
+status_t
+InputServer::_BKMPreloadKeymap(const entry_ref &ref)
+{
+       KeymapStruct *keymapStruct = new KeymapStruct();        //TODO use 
BPrivate::BKeymap
+       BString name(ref.name); 
+       printf("InputServer::_PreloadKeymap %s\n", ref.name);   
+       
+       BPath path(&ref);
+
+       status_t err;
+
+       BFile file(path.Path(), B_READ_ONLY);
+       if ((err = file.InitCheck()) != B_OK)
+               return err;
+       
+       if (file.Read(&keymapStruct->fKeys, sizeof(keymapStruct->fKeys)) < 
(ssize_t)sizeof(keymapStruct->fKeys))
+               return B_BAD_VALUE;
+
+       for (uint32 i = 0; i < sizeof(keymapStruct->fKeys) / 4; i++)
+               ((uint32*)&keymapStruct->fKeys)[i] = 
B_BENDIAN_TO_HOST_INT32(((uint32*)&keymapStruct->fKeys)[i]);
+
+       if (file.Read(&keymapStruct->fCharsSize, sizeof(uint32)) < 
(ssize_t)sizeof(uint32))
+               return B_BAD_VALUE;
+
+       keymapStruct->fCharsSize = 
B_BENDIAN_TO_HOST_INT32(keymapStruct->fCharsSize);
+       if (keymapStruct->fCharsSize <= 0)
+               return B_BAD_VALUE;
+       
+       keymapStruct->fChars = new (nothrow) char[fCharsSize];
+       if (keymapStruct->fChars == NULL)
+               return B_NO_MEMORY;
+
+       if (file.Read(keymapStruct->fChars, keymapStruct->fCharsSize) != 
(signed)keymapStruct->fCharsSize)
+               return B_BAD_VALUE;
+               
+       fKeymaps.insert(KeymapList::value_type(name, keymapStruct));
+       
+       printf("InputServer::_PreloadKeymap %s OK!\n", ref.name);               
+       return B_OK;
+}
+
+
+KeymapStruct *
+InputServer::_BKMGetKeymap(const BString &name)
+{      
+       KeymapList::iterator it = fKeymaps.find(name);
+       if (it != fKeymaps.end()) {
+               printf("InputServer::_GetKeymap %s OK!\n", name.String());
+               return (*it).second;
+       } else {
+               printf("InputServer::_GetKeymap %s ERROR!\n", name.String());
+               return NULL;
+       }
+}
+
+
+status_t
+InputServer::_BKMActivateKeymap(const BString &name)
+{
+       printf("InputServer::_ActivateKeymap %s\n", name.String());
+       KeymapStruct *keymapStruct = _BKMGetKeymap(name);
+       
+       if (keymapStruct) {             
+               fKeys = keymapStruct->fKeys;
+               fCharsSize = keymapStruct->fCharsSize;
+               
+               delete[] fChars;
+               fChars = new (nothrow) char[fCharsSize];
+               if (fChars == NULL)
+                       return B_NO_MEMORY;
+               memcpy(fChars, keymapStruct->fChars, fCharsSize);
+               
+               printf("InputServer::_ActivateKeymap OK\n");
+               fActiveKeymapName = name;       
+               return B_OK;
+       }
+       printf("InputServer::_ActivateKeymap ERROR\n"); 
+       return B_ERROR;
+}
+
+
 bool
 InputServer::QuitRequested()
 {
@@ -416,6 +529,10 @@
        BPrivate::AppServerLink link;
        link.StartMessage(AS_REGISTER_INPUT_SERVER);
        link.Flush();
+       
+       // not sure it the best place to do that
+       // we should monitor the keymap directory and update automatically
+       _BKMPreloadKeymaps();
 }
 
 
@@ -559,6 +676,27 @@
                case IS_UNFOCUS_IM_AWARE_VIEW:
                        status = HandleFocusUnfocusIMAwareView(message, &reply);
                        break;
+                       
+               // new BKeymapManager
+               case IS_BKM_ACTIVATE_KEYMAP:
+                       status = HandleBKMActivateKeymap(message, &reply);
+                       break;
+               case IS_BKM_GET_KEYMAP_NAMES:
+                       status = HandleBKMGetKeymapNames(message, &reply);
+                       break;
+               case IS_BKM_GET_KEYMAP:
+                       status = HandleBKMGetKeymap(message, &reply);
+                       break;
+               case IS_BKM_GET_ACTIVE_KEYMAP_NAME:
+                       status = HandleBKMGetActiveKeymapName(message, &reply);
+                       break;  
+                       //TODO
+               //case IS_BKM_INSTALL_KEYMAP:
+               //      status = HandleBKMInstallKeymap(message, &reply);
+               //      break;
+               //case IS_BKM_UNINSTALL_KEYMAP:
+               //      status = HandleBKMUninstallKeymap(message, &reply);
+               //      break;  
 
                // app_server communication
                case IS_ACQUIRE_INPUT:
@@ -922,6 +1060,92 @@
 
 
 status_t
+InputServer::HandleBKMActivateKeymap(BMessage* message, BMessage* reply)
+{
+       CALLED();
+
+       BString name;
+       if (message->FindString("name", &name) == B_OK) {
+               if (_BKMActivateKeymap(name) == B_OK) {
+                       
+                       status_t err = reply->AddInt32("status", B_OK);
+                       if (err != B_OK)
+                               return err;                     
+                       
+                       BMessage msg(IS_CONTROL_DEVICES);
+                       msg.AddInt32("type", B_KEYBOARD_DEVICE);        
+                       msg.AddInt32("code", B_KEY_MAP_CHANGED);        
+                       return fAddOnManager->PostMessage(&msg);        
+               } 
+       } 
+       
+       status_t err = reply->AddInt32("status", B_ERROR);
+       return err;
+}
+
+
+status_t
+InputServer::HandleBKMGetActiveKeymapName(BMessage* message, BMessage* reply)
+{
+       CALLED();
+
+       status_t err = reply->AddString("name", fActiveKeymapName);
+       
+       printf("InputServer::HandleBKMGetActiveKeymapName name=%s\n", 
fActiveKeymapName.String());
+       
+       return reply->AddInt32("status", err);          
+}
+
+
+status_t
+InputServer::HandleBKMGetKeymap(BMessage* message, BMessage* reply)
+{
+       CALLED();
+       
+       BString name;
+       if (message->FindString("name", &name) == B_OK) {
+               printf("InputServer::HandleBKMGetKeymap name=%s\n", 
name.String());
+       
+               KeymapStruct *keymap = _BKMGetKeymap(name);
+               if (keymap) {
+                       printf("InputServer::HandleBKMGetKeymap sending, map 
size=%u and keys size=%u\n", sizeof(keymap->fKeys), keymap->fCharsSize);
+                               
+                       status_t status = reply->AddData("keymap", B_ANY_TYPE, 
&keymap->fKeys, sizeof(keymap->fKeys));
+                       if (status == B_OK)
+                               status = reply->AddData("key_buffer", 
B_ANY_TYPE, keymap->fChars, keymap->fCharsSize);
+
+                       return status;          
+               }       
+       } else {
+               printf("InputServer::HandleBKMGetKeymap ERROR missing name or 
bad name\n");             
+       }
+       return B_ERROR;
+}
+
+
+status_t
+InputServer::HandleBKMGetKeymapNames(BMessage* message, BMessage* reply)
+{
+       CALLED();
+
+       int32 count = 0;        
+       KeymapList::iterator it = fKeymaps.begin();
+       for(; it != fKeymaps.end(); it++) {
+               if (reply->AddString("name",(*it).first) != B_OK) {
+                       //reply->AddInt32("status", B_ERROR);   //TODO
+                       //return B_ERROR;       
+               } else {
+                       count++;        
+                       printf("addString %s OK\n", (*it).first.String());
+               }
+       }               
+       status_t err = reply->AddInt32("count", count);
+        err = reply->AddInt32("status", B_OK);
+       return err;             
+}
+
+
+status_t
 InputServer::HandleFocusUnfocusIMAwareView(BMessage* message,
        BMessage* reply)
 {
Index: headers/os/interface/KeymapManager.h
===================================================================
--- headers/os/interface/KeymapManager.h        (revision 0)
+++ headers/os/interface/KeymapManager.h        (revision 0)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008, Haiku, Inc.
+ * Distributed under the terms of the MIT license.
+ *
+ */
+#ifndef        _KEYMAP_MANAGER_H
+#define        _KEYMAP_MANAGER_H
+
+#include <String.h>
+#include <list>
+
+namespace BPrivate {
+
+class BKeymap;
+
+class BKeymapManager {
+       public:
+       typedef std::list<BString> NameList;
+       
+       static status_t ActivateKeymap(const BString &name);    
+       static status_t GetKeymapNames(NameList &list);
+       static status_t GetActiveKeymapName(BString &name);             
+       static BKeymap* GetKeymap(const BString &name); 
+       
+};
+
+} // namespace BPrivate
+
+#endif // _KEYMAP_MANAGER_H
Index: headers/os/interface/Keymap.h
===================================================================
--- headers/os/interface/Keymap.h       (revision 0)
+++ headers/os/interface/Keymap.h       (revision 0)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2004-2008 Haiku Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ * 
+ */
+
+#ifndef _BKEYMAP_H
+#define _BKEYMAP_H
+
+#include <InterfaceDefs.h>
+#include <String.h>
+
+namespace BPrivate {
+
+class BKeymap 
+{
+public:
+                       BKeymap();
+                       ~BKeymap();
+
+       void    Dump();
+       bool    IsModifierKey(uint32 keyCode);
+       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);         
+       
+//testing //private:
+       char*           fChars;
+       key_map         fKeys;
+       uint32          fCharsSize;
+       BString         fName;
+       bool            fIsValid;       //TODO
+};
+
+
+} //namespace BPrivate
+
+#endif //BKEYMAP_H
Index: src/servers/input/InputServer.h
===================================================================
--- src/servers/input/InputServer.h     (revision 27334)
+++ src/servers/input/InputServer.h     (working copy)
@@ -26,12 +26,14 @@
 #include <ObjectList.h>
 #include <OS.h>
 #include <Screen.h>
+#include <String.h>
 #include <SupportDefs.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <map>
 
 #define INPUTSERVER_SIGNATURE "application/x-vnd.Be-input_server"
        // use this when target should replace R5 input_server
@@ -40,6 +42,13 @@
 
 class BottomlineWindow;
 
+//TODO replace with BPrivate::BKeymap
+struct KeymapStruct {
+       key_map                 fKeys;
+       char*                   fChars;
+       uint32                  fCharsSize;
+};
+
 class InputDeviceListItem {
        public:
                InputDeviceListItem(BInputServerDevice& serverDevice,
@@ -127,6 +136,14 @@
                status_t HandleGetSetKeyRepeatRate(BMessage* message, BMessage* 
reply);
                status_t HandleGetSetKeyMap(BMessage* message, BMessage* reply);
                status_t HandleFocusUnfocusIMAwareView(BMessage* message, 
BMessage* reply);
+               
+                       // BPrivate::BKeymapManager extensions
+               status_t HandleBKMActivateKeymap(BMessage* message, BMessage* 
reply);
+               status_t HandleBKMGetKeymapNames(BMessage* message, BMessage* 
reply);
+               status_t HandleBKMGetKeymap(BMessage* message, BMessage* reply);
+               status_t HandleBKMGetActiveKeymapName(BMessage* message, 
BMessage* reply);              
+               //status_t HandleBKMInstallKeymap(BMessage* message, BMessage* 
reply);
+               //status_t HandleBKMUninstallKeymap(BMessage* message, 
BMessage* reply);
 
                status_t EnqueueDeviceMessage(BMessage* message);
                status_t EnqueueMethodMessage(BMessage* message);
@@ -174,6 +191,13 @@
                status_t _LoadKeymap();
                status_t _LoadSystemKeymap();
                status_t _SaveKeymap(bool isDefault = false);
+               
+                       // BPrivate::BKeymapManager extensions
+               status_t                        _BKMPreloadKeymaps();
+               status_t                        _BKMPreloadKeymap(const 
entry_ref &ref);
+               KeymapStruct*           _BKMGetKeymap(const BString &name); 
//const
+               status_t                        _BKMActivateKeymap(const 
BString &name);
+                                       
                void _InitKeyboardMouseStates();
 
                status_t _StartEventLoop();
@@ -208,10 +232,16 @@
                MouseSettings   fMouseSettings;
 
                BPoint                  fMousePos;              // current 
mouse position
+               
                key_info                fKeyInfo;               // current key 
info
                key_map                 fKeys;                  // current 
key_map
                char*                   fChars;                 // current 
keymap chars
                uint32                  fCharsSize;             // current 
keymap char count
+               
+                       // BPrivate::BKeymapManager extensions
+               typedef std::map<BString, KeymapStruct*> KeymapList;
+               KeymapList              fKeymaps;
+               BString                 fActiveKeymapName;
 
                port_id         fEventLooperPort;
 
Index: headers/private/input/InputServerTypes.h
===================================================================
--- headers/private/input/InputServerTypes.h    (revision 27334)
+++ headers/private/input/InputServerTypes.h    (working copy)
@@ -31,6 +31,13 @@
 #define IS_FOCUS_IM_AWARE_VIEW                         'Ifim'
 #define IS_UNFOCUS_IM_AWARE_VIEW               'Iuim'
 
+#define IS_BKM_ACTIVATE_KEYMAP                 'Ibka'
+#define IS_BKM_GET_KEYMAP_NAMES                        'Ibkn'
+#define IS_BKM_GET_KEYMAP                              'Ibkg'
+#define IS_BKM_GET_ACTIVE_KEYMAP_NAME  'Ibkx'
+//#define IS_BKM_INSTALL_KEYMAP                        'Ibki'
+//#define IS_BKM_UNINSTALL_KEYMAP              'Ibku'
+
 #define IS_FIND_DEVICES                                        'Ifdv'
 #define IS_WATCH_DEVICES                               'Iwdv'
 #define IS_IS_DEVICE_RUNNING                   'Idvr'
Index: src/preferences/keymap/KeymapWindow.cpp
===================================================================
--- src/preferences/keymap/KeymapWindow.cpp     (revision 27334)
+++ src/preferences/keymap/KeymapWindow.cpp     (working copy)
@@ -18,6 +18,7 @@
 #include <Directory.h>
 #include <FindDirectory.h>
 #include <GraphicsDefs.h>
+#include <KeymapManager.h>
 #include <ListView.h>
 #include <MenuItem.h>
 #include <Path.h>
@@ -47,11 +48,9 @@
 static const uint32 kMsgRevertKeymap = 'Rvrt';
 
 KeymapWindow::KeymapWindow()
-       :       BWindow(BRect(80, 25, 692, 281), "Keymap", B_TITLED_WINDOW,
+       :       BWindow(BRect(80, 25, 692+30, 281), "Keymap", B_TITLED_WINDOW,
                        B_NOT_ZOOMABLE | B_NOT_RESIZABLE | 
B_ASYNCHRONOUS_CONTROLS )
 {
-       fFirstTime = true;
-       
        // Add the menu bar
        BMenuBar *menubar = AddMenuBar();
 
@@ -63,24 +62,30 @@
        placeholderView->SetBorder(B_NO_BORDER);
        AddChild(placeholderView);
        
+       //BKM
+       BString activeKeymapName;
+       BPrivate::BKeymapManager::GetActiveKeymapName(activeKeymapName);        
+       fPreviousKeymapName = activeKeymapName;
+       fSelectedKeymapName = activeKeymapName; 
+               
        // Create the Maps box and contents
        AddMaps(placeholderView);
+               
+       fMapView = new MapView(BRect(150+30, 9, 600+30, 189), "mapView", 
activeKeymapName);
+       placeholderView->AddChild(fMapView);    
        
-       fMapView = new MapView(BRect(150, 9, 600, 189), "mapView", 
&fCurrentMap);
-       placeholderView->AddChild(fMapView);
-       
        BMenuItem *item = fFontMenu->FindMarked();
        if (item) {
                fMapView->SetFontFamily(item->Label());
        }
        
        // The 'Use' button
-       fUseButton = new BButton(BRect(527, 200, 600, 220), "useButton", "Use",
+       fUseButton = new BButton(BRect(527+30, 200, 600+30, 220), "useButton", 
"Use",
                new BMessage(kMsgUseKeymap));
        placeholderView->AddChild(fUseButton);
        
        // The 'Revert' button
-       fRevertButton = new BButton(BRect(442, 200, 515, 220), "revertButton",
+       fRevertButton = new BButton(BRect(442+30, 200, 515+30, 220), 
"revertButton",
                 "Revert", new BMessage(kMsgRevertKeymap));
        placeholderView->AddChild(fRevertButton);
        UpdateButtons();
@@ -125,7 +130,7 @@
        
        // Create the File menu
        menu = new BMenu("File");
-       menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS,
+       /*menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS,
                new BMessage(kMsgMenuFileOpen), 'O'));
        menu->AddSeparatorItem();
        currentItem = new BMenuItem("Save",
@@ -134,7 +139,7 @@
        menu->AddItem(currentItem);
        menu->AddItem(new BMenuItem("Save As" B_UTF8_ELLIPSIS,
                new BMessage(kMsgMenuFileSaveAs)));
-       menu->AddSeparatorItem();
+       menu->AddSeparatorItem();*/
        menu->AddItem(new BMenuItem("Quit",
                new BMessage(B_QUIT_REQUESTED), 'Q'));
        menubar->AddItem(menu);
@@ -187,44 +192,25 @@
 KeymapWindow::AddMaps(BView *placeholderView)
 {
        // The Maps box
-       BRect bounds = BRect(9, 11, 140, 226);
+       BRect bounds = BRect(9, 5/*11*/, 140+30, 226);
        BBox *mapsBox = new BBox(bounds);
        mapsBox->SetLabel("Maps");
        placeholderView->AddChild(mapsBox);
 
        // The System list
-       BStringView *systemLabel = new BStringView(BRect(13, 13, 113, 33), 
"system", "System");
-       mapsBox->AddChild(systemLabel);
+       //BStringView *systemLabel = new BStringView(BRect(13, 13, 113+30, 33), 
"system", "System");
+       //mapsBox->AddChild(systemLabel);
        
-       bounds = BRect(13, 35, 103, 105);
+       bounds = BRect(13, 35-13, 103+30, 105+100);
        fSystemListView = new BListView(bounds, "systemList");
        
        mapsBox->AddChild(new BScrollView("systemScrollList", fSystemListView,
                B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
        fSystemListView->SetSelectionMessage(new 
BMessage(kMsgSystemMapSelected));
-
-       // The User list
-       BStringView *userLabel = new BStringView(BRect(13, 110, 113, 128), 
"user", "User");
-       mapsBox->AddChild(userLabel);
-
-       bounds = BRect(13, 130, 103, 200);
-       fUserListView = new BListView(bounds, "userList");
-       // '(Current)'
-       KeymapListItem *currentKeymapItem = 
static_cast<KeymapListItem*>(fUserListView->FirstItem());
-       if (currentKeymapItem != NULL)
-               fUserListView->AddItem(currentKeymapItem);
-       // Saved keymaps
-       mapsBox->AddChild(new BScrollView("userScrollList", fUserListView,
-               B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
-       fUserListView->SetSelectionMessage(new BMessage(kMsgUserMapSelected));
        
        FillSystemMaps();
-       FillUserMaps();
-
-       // try and find the current map name in the two list views (if the name 
was read at all)
-       if (!SelectCurrentMap(fSystemListView))
-               if (!SelectCurrentMap(fUserListView))
-                       fUserListView->Select(0L);
+       
+       _SelectKeymap(fSystemListView, fPreviousKeymapName);
 }
 
 
@@ -243,30 +229,12 @@
                case B_SIMPLE_DATA:
                case B_REFS_RECEIVED: 
                {
-                       entry_ref ref;
-                       int32 i = 0;
-                       while (message->FindRef("refs", i++, &ref) == B_OK) {
-                               fCurrentMap.Load(ref);
-                       }
-                       fMapView->Invalidate();
-                       fSystemListView->DeselectAll();
-                       fUserListView->DeselectAll();
+                       //TODO
                }
                        break;
                case B_SAVE_REQUESTED:
                {
-                       entry_ref ref;
-                       const char *name;
-                       if ((message->FindRef("directory", &ref) == B_OK)
-                               && (message->FindString("name", &name) == 
B_OK)) {
-                               
-                               BDirectory directory(&ref);
-                               BEntry entry(&directory, name);
-                               entry.GetRef(&ref);
-                               fCurrentMap.Save(ref);
-                               
-                               FillUserMaps();
-                       }
+                       //TODO
                }
                        break;
                case kMsgMenuFileOpen:
@@ -296,47 +264,36 @@
                        break;
                case kMsgSystemMapSelected:
                {
-                       KeymapListItem *keymapListItem = 
-                               
static_cast<KeymapListItem*>(fSystemListView->ItemAt(fSystemListView->CurrentSelection()));
-                       if (keymapListItem) {
-                               fCurrentMap.Load(keymapListItem->KeymapEntry());
-                               fMapView->Invalidate();
+                       BStringItem *item = 
+                               
static_cast<BStringItem*>(fSystemListView->ItemAt(fSystemListView->CurrentSelection()));
                                
-                               // Deselect item in other BListView
-                               fUserListView->DeselectAll();
+                               //do nothing if the selection didn't change
+                       if (item && fSelectedKeymapName != item->Text()) {      
                                                                        
+                               fSelectedKeymapName = item->Text();             
                                
+                               fMapView->SetKeymap(fSelectedKeymapName);       
                                                        
+                               fMapView->Invalidate();                         
                                UpdateButtons();
                        }
                }
                        break;
+                       
                case kMsgUserMapSelected:
-               {
-                       KeymapListItem *keymapListItem = 
-                               
static_cast<KeymapListItem*>(fUserListView->ItemAt(fUserListView->CurrentSelection()));
-                       if (keymapListItem) {
-                               fCurrentMap.Load(keymapListItem->KeymapEntry());
-                               
-                               if (fFirstTime) {
-                                       
fPreviousMap.Load(keymapListItem->KeymapEntry());
-                                       
fAppliedMap.Load(keymapListItem->KeymapEntry());
-                                       fFirstTime = false;
-                               }
-                               
-                               fMapView->Invalidate();
-                               
-                               // Deselect item in other BListView
-                               fSystemListView->DeselectAll();
-                               UpdateButtons();
-                       }
-               }
+                       //TODO
                        break;
+                       
                case kMsgUseKeymap:
-                       UseKeymap();
-                       UpdateButtons();
+                       if 
(BPrivate::BKeymapManager::ActivateKeymap(fSelectedKeymapName) != B_OK)
+                               break;
+                       UpdateButtons();                
                        break;
+                       
                case kMsgRevertKeymap:
-                       RevertKeymap();
+                       if 
(BPrivate::BKeymapManager::ActivateKeymap(fPreviousKeymapName) != B_OK)
+                               break;                          
+                       _SelectKeymap(fSystemListView, fPreviousKeymapName);    
                
                        UpdateButtons();
                        break;
+                       
                default:
                        BWindow::MessageReceived(message);
                        break;
@@ -344,158 +301,64 @@
 }
 
 
- void 
+void 
 KeymapWindow::UpdateButtons()
 {
-       fUseButton->SetEnabled(!fCurrentMap.Equals(fAppliedMap));
-       fRevertButton->SetEnabled(!fCurrentMap.Equals(fPreviousMap));
-}
-
-
-void 
-KeymapWindow::RevertKeymap()
-{
-       //saves previous map to the Key_map file
-       
-       printf("REVERT\n");
-       BPath path;
-       if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK)
+       BString activeKeymapName;
+       if (BPrivate::BKeymapManager::GetActiveKeymapName(activeKeymapName) != 
B_OK)
                return;
        
-       path.Append("Key_map");
-
-       entry_ref ref;
-       get_ref_for_path(path.Path(), &ref);
-
-       status_t err;
-       if ((err = fPreviousMap.Save(ref)) != B_OK) {
-               printf("error when saving : %s", strerror(err));
-               return;
-       }
-       fPreviousMap.Use();
-       fAppliedMap.Load(ref);
-       
-       //select and load it (first item in fUserListView is a ref to Key_map)
-       fUserListView->DeselectAll();
-       fUserListView->Select(0);               
+       fUseButton->SetEnabled(fSelectedKeymapName != activeKeymapName);
+       fRevertButton->SetEnabled(fSelectedKeymapName != fPreviousKeymapName);
 }
 
 
-void 
-KeymapWindow::UseKeymap()
-{
-       BPath path;
-       if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
-               return;
-       
-       path.Append("Key_map");
-
-       entry_ref ref;
-       get_ref_for_path(path.Path(), &ref);
-
-       status_t err;
-       if ((err = fCurrentMap.Save(ref)) != B_OK) {
-               printf("error when saving : %s", strerror(err));
-               return;
-       }
-       fCurrentMap.Use();
-       fAppliedMap.Load(ref);
-       
-       fUserListView->Select(0);
-}
-
-
 void
 KeymapWindow::FillSystemMaps()
 {
        BListItem *item;
        while ((item = fSystemListView->RemoveItem(static_cast<int32>(0))))
                delete item;
-
-       BPath path;
-       if (find_directory(B_BEOS_ETC_DIRECTORY, &path) != B_OK)
+               
+       BPrivate::BKeymapManager::NameList list;
+       if (BPrivate::BKeymapManager::GetKeymapNames(list) != B_OK)
                return;
        
-       path.Append("Keymap");
-       
-       BDirectory directory;
-       entry_ref ref;
-       
-       if (directory.SetTo(path.Path()) == B_OK)
-               while( directory.GetNextRef(&ref) == B_OK ) {
-                       fSystemListView->AddItem(new KeymapListItem(ref));
-               }
+       BPrivate::BKeymapManager::NameList::iterator it = list.begin();
+       for(; it != list.end(); it++) {
+               //printf("installed keymap %s\n", (*it).String());
+               fSystemListView->AddItem(new BStringItem((*it).String()));      
+       }
 }
 
 
-void 
-KeymapWindow::FillUserMaps()
+bool
+KeymapWindow::_SelectKeymap(BListView *listView, const BString &keymapName)
 {
-       BListItem *item;
-       while ((item = fUserListView->RemoveItem(static_cast<int32>(0))))
-               delete item;
-
-       BPath path;
-       if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
-               return;
+       printf("KeymapWindow::_SelectKeymap name=%s\n", keymapName.String());
        
-       path.Append("Key_map");
-
-       entry_ref ref;
-       get_ref_for_path(path.Path(), &ref);
-       
-       fUserListView->AddItem(new KeymapListItem(ref, "(Current)"));
-
-       BNode node(&ref);
-       char name[B_FILE_NAME_LENGTH];
-       name[0] = '\0';
-       if (node.InitCheck() == B_OK) {
-               ssize_t readSize = node.ReadAttr("keymap:name", B_STRING_TYPE, 
0, name, sizeof(name) - 1);
-               if (readSize > 0) {
-                       name[readSize] = '\0';
-                       fCurrentMapName = name;
+       bool found = false;     
+       for (int32 i = 0; i < listView->CountItems(); i++) {
+               BStringItem *item = dynamic_cast<BStringItem 
*>(listView->ItemAt(i));
+               if (item && (item->Text() == keymapName)) {
+                       found = true;
+                       listView->Select(i);
+                       listView->ScrollToSelection();
+                       break;
                }
        }       
-
-       if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
-               return;
-       
-       path.Append("Keymap");
-       
-       BDirectory directory;
-       
-       if (directory.SetTo(path.Path()) == B_OK)
-               while( directory.GetNextRef(&ref) == B_OK ) {
-                       fUserListView->AddItem(new KeymapListItem(ref));
-               }
+       return found;   //TODO: should never return false with the new system
 }
 
 
-bool
-KeymapWindow::SelectCurrentMap(BListView *view)
-{
-       bool found = false;
-       if (fCurrentMapName.Length() > 0) {
-               for (int32 i = 0; i < view->CountItems(); i++) {
-                       BStringItem *current = dynamic_cast<BStringItem 
*>(view->ItemAt(i));
-                       if (current && (fCurrentMapName == current->Text())) {
-                               found = true;
-                               view->Select(i);
-                               view->ScrollToSelection();
-                               break;
-                       }
-               }
-       }       
-       return found;
-}
-
-
-MapView::MapView(BRect rect, const char *name, Keymap* keymap)
+MapView::MapView(BRect rect, const char *name, const BString &keymapName)
        : BControl(rect, name, NULL, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP, 
B_WILL_DRAW),
                fCurrentFont(*be_plain_font),
-               fCurrentMap(keymap),
-               fCurrentMouseKey(0)
+               fCurrentMouseKey(0),
+               fKeymap(NULL)
 {
+       SetKeymap(keymapName);                  
+       
        // TODO: Properly handle font sensitivity in drawing the keys.
        // This at least prevents the app from looking horrible until the font 
sensitivity for this app
        // can be done the Right Way.
@@ -991,6 +854,15 @@
 {
        delete fBitmap;
 }
+       
+       
+void 
+MapView::SetKeymap(const BString &name) 
+{
+       BPrivate::BKeymap *keymap = BPrivate::BKeymapManager::GetKeymap(name); 
//attention delete the previous one
+       if (keymap)
+               fKeymap = keymap;
+}
 
 
 void
@@ -1267,8 +1139,8 @@
                fOffscreenView->StrokeRect(r);
                
                bool vertical = fKeysVertical[keyCode];
-               int32 deadKey = fCurrentMap->IsDeadKey(keyCode, 
fOldKeyInfo.modifiers);
-               bool secondDeadKey = fCurrentMap->IsDeadSecondKey(keyCode,
+               int32 deadKey = fKeymap->IsDeadKey(keyCode, 
fOldKeyInfo.modifiers);
+               bool secondDeadKey = fKeymap->IsDeadSecondKey(keyCode,
                         fOldKeyInfo.modifiers, fActiveDeadKey);
                                
                r.InsetBySelf(1, 1);
@@ -1370,8 +1242,8 @@
                return;
                
        bool pressed = (fOldKeyInfo.key_states[keyCode >> 3] & (1 << (7 - 
keyCode % 8))) || (keyCode == fCurrentMouseKey);
-       int32 deadKey = fCurrentMap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
-       bool secondDeadKey = fCurrentMap->IsDeadSecondKey(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey);
+       int32 deadKey = fKeymap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);     
+       bool secondDeadKey = fKeymap->IsDeadSecondKey(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey);
                
        if (!pressed) {
                r.InsetBySelf(1, 1);
@@ -1434,7 +1306,7 @@
        char *str = NULL;
        int32 numBytes;
                        
-       fCurrentMap->GetChars(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey, 
&str, &numBytes);
+       fKeymap->GetChars(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey, &str, 
&numBytes);     //check fOldKeyInfo
        if (str) {
                bool hasGlyphs;
                if (deadKey > 0) {
@@ -1543,7 +1415,7 @@
                                                for (int8 j = 7; stbits; j--, 
stbits >>= 1)
                                                        if (stbits & 1) {
                                                                keyCode = i * 8 
+ j;
-                                                               if 
(!fCurrentMap->IsModifierKey(keyCode)) {
+                                                               if 
(!fKeymap->IsModifierKey(keyCode)) {
                                                                        i = 16;
                                                                        break;
                                                                }
@@ -1556,15 +1428,15 @@
                                        char *str = NULL;
                                        int32 numBytes;
                                        if (fActiveDeadKey) {
-                                               fCurrentMap->GetChars(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
+                                               fKeymap->GetChars(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
                                                if (numBytes > 0) {
                                                        
fTextView->FakeKeyDown(str, numBytes);
                                                }
                                                fActiveDeadKey = 0;
                                                _InvalidateKeys();
                                        } else {
-                                               fCurrentMap->GetChars(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
-                                               fActiveDeadKey = 
fCurrentMap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
+                                               fKeymap->GetChars(keyCode, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
+                                               fActiveDeadKey = 
fKeymap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
                                                if (fActiveDeadKey)
                                                        _InvalidateKeys();
                                                else if (numBytes > 0) {
@@ -1609,7 +1481,7 @@
                                _DrawKey(fCurrentMouseKey);
                                char *str = NULL;
                                int32 numBytes;
-                               fCurrentMap->GetChars(fCurrentMouseKey, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
+                               fKeymap->GetChars(fCurrentMouseKey, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);                        
    
                                if (numBytes > 0) {
                                        fTextView->FakeKeyDown(str, numBytes);
                                        delete str;
@@ -1647,7 +1519,7 @@
                                _InvalidateKey(fCurrentMouseKey);
                                char *str = NULL;
                                int32 numBytes;
-                               fCurrentMap->GetChars(fCurrentMouseKey, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
+                               fKeymap->GetChars(fCurrentMouseKey, 
fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
                                if (numBytes > 0) {
                                        fTextView->FakeKeyDown(str, numBytes);
                                        delete str;
Index: src/preferences/keymap/KeymapWindow.h
===================================================================
--- src/preferences/keymap/KeymapWindow.h       (revision 27334)
+++ src/preferences/keymap/KeymapWindow.h       (working copy)
@@ -13,6 +13,7 @@
 
 #include <Control.h>
 #include <FilePanel.h>
+#include <Keymap.h>
 #include <ListView.h>
 #include <MenuBar.h>
 #include <String.h>
@@ -27,7 +28,7 @@
 class MapView : public BControl
 {
 public:
-       MapView(BRect rect, const char *name, Keymap *keymap);
+       MapView(BRect rect, const char *name, const BString &keymapName);
        ~MapView();
        
        void Draw(BRect rect);
@@ -40,6 +41,9 @@
        void MouseUp(BPoint point);
        void MouseMoved(BPoint point, uint32 transit, const BMessage *msg);
                
+       //BKM
+       void    SetKeymap(const BString &name);
+               
 private:       
        void _InvalidateKey(uint32 keyCode);    
        void _InvalidateKeys();
@@ -61,10 +65,12 @@
        uint8 fKeyState[16];
        BFont fCurrentFont;
        
-       Keymap                          *fCurrentMap;
        KeymapTextView          *fTextView;
        uint32 fCurrentMouseKey;
        uint8 fActiveDeadKey;           // 0 : none, 1 : acute , ...
+       
+       //BKM
+       BPrivate::BKeymap * fKeymap;
 };
 
 
@@ -74,36 +80,32 @@
                        ~KeymapWindow();
        bool    QuitRequested();
        void    MessageReceived( BMessage* message );
-
+       
 protected:
+       
        BMenuBar                        *AddMenuBar();
        void                            AddMaps(BView *placeholderView);
-       void                            UseKeymap();
-       void                            RevertKeymap();
        void                            UpdateButtons();
        
        void                            FillSystemMaps();
        void                            FillUserMaps();
        
-       bool                            SelectCurrentMap(BListView *list);
+       bool                            _SelectKeymap(BListView *view, const 
BString &keymapName);      
 
        BListView                       *fSystemListView;
        BListView                       *fUserListView;
-       // the map that's currently highlighted
+       
        BButton                         *fUseButton;
        BButton                         *fRevertButton;
        BMenu                           *fFontMenu;
        
        MapView                         *fMapView;
-               
-       Keymap                          fCurrentMap;
-       Keymap                          fPreviousMap;
-       Keymap                          fAppliedMap;
-       bool                            fFirstTime;
-       BString                         fCurrentMapName;
+       
+       BString                         fSelectedKeymapName;
+       BString                         fPreviousKeymapName;    
                        
-       BFilePanel                      *fOpenPanel;            // the file 
panel to open
-       BFilePanel                      *fSavePanel;            // the file 
panel to save
+       BFilePanel                      *fOpenPanel;
+       BFilePanel                      *fSavePanel;
 };
 
 #endif // KEYMAP_WINDOW_H

Other related posts: