How do I determine keyboard layout?

This forum is for general developer support questions.
Post Reply
colinward
Beta Tester
Beta Tester
Posts: 8
Joined: Sun Jan 06, 2013 9:29 am

How do I determine keyboard layout?

Post by colinward »

Hello everyone.

I have a use case where I would like to treat the right ALT key differently depending on the keyboard layout.

On US keyboard layouts it is a "normal" ALT but on most European keyboards it is an alt-gr.

But you get the same key code when it is pressed regardless of the keyboard layout that is set. How can I determine the keyboard layout (ie. US or German) so that I change change the behaviour of my program?

I was hunting around the Autodocs but was surprised that I couldn't find anything.
User avatar
javierdlr
Beta Tester
Beta Tester
Posts: 389
Joined: Sun Jun 19, 2011 10:13 pm
Location: Donostia (GUIPUZCOA) - Spain
Contact:

Re: How do I determine keyboard layout?

Post by javierdlr »

Will inputevents.h help you to get/know what ALT key was pressed?

/* --- InputEvent.ie_Qualifier --- */
#define IEQUALIFIER_LSHIFT 0x0001
#define IEQUALIFIER_RSHIFT 0x0002
#define IEQUALIFIER_CAPSLOCK 0x0004
#define IEQUALIFIER_CONTROL 0x0008
#define IEQUALIFIER_LALT 0x0010
#define IEQUALIFIER_RALT 0x0020
User avatar
broadblues
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 600
Joined: Sat Jun 18, 2011 2:40 am
Location: Portsmouth, UK
Contact:

Re: How do I determine keyboard layout?

Post by broadblues »

colinward wrote:Hello everyone.

I have a use case where I would like to treat the right ALT key differently depending on the keyboard layout.

On US keyboard layouts it is a "normal" ALT but on most European keyboards it is an alt-gr.

But you get the same key code when it is pressed regardless of the keyboard layout that is set. How can I determine the keyboard layout (ie. US or German) so that I change change the behaviour of my program?

I was hunting around the Autodocs but was surprised that I couldn't find anything.
I'm not sure why you need this? Left and Right alt have distinct codes on any keyboard? (according to the includes at least)

#define RAWKEY_LALT 0x64
#define RAWKEY_RALT 0x65

Andyway a combination of AskKeyMapDeFault() and ObtainKeyMapInfo() should work out what keymap you are using.
colinward
Beta Tester
Beta Tester
Posts: 8
Joined: Sun Jan 06, 2013 9:29 am

Re: How do I determine keyboard layout?

Post by colinward »

broadblues wrote: I'm not sure why you need this? Left and Right alt have distinct codes on any keyboard? (according to the includes at least)

#define RAWKEY_LALT 0x64
#define RAWKEY_RALT 0x65

Andyway a combination of AskKeyMapDeFault() and ObtainKeyMapInfo() should work out what keymap you are using.
Left and right ALT having distinct values is the problem here.

I am writing a cross platform text editor/IDE and I need to do my own keyboard handling, which means I need to handle raw keys and "cook" them myself. Using only VANILLAKEY events doesn't give enough control for something like a text editor.

This works for most keys but for some, such as the LALT and RALT key, you need special treatment. The LALT you always treat as a generic ALT but the RALT needs to be treated only as a generic ALT if a US keyboard is used (or a keyboard without an AltGr key). For most European keyboards the AltGr key is present so you have to treat the RALT as though it is NOT an ALT key in order to get all of the characters that are generated with the AltGr key.

I also have this problem on the Windows and Linux versions but there you can use something like this:

KeyboardLayout = GetKeyboardLayout(0);

if (KeyboardLayout == SUBLANG_ENGLISH_US)
{
// RALT is ALT
}
else
{
/ RALT is AltGr
}

The problem is that there is nothing like GetKeyboardLayout() on Amiga OS. I can't find anything interesting in the structure returned by AskKeyMapDefault() that gives the same information as above.

How can I find out if the current keyboard layout is a US keyboard layout? How does the Sys:Prefs/Input program do it?

Even better, is there a way of knowing whether to treat RALT as a normal ALT or as an AltGr key? That would be better than hard coding a check for US keyboards as there are probably other keyboards out there that don't have an AltGr key.
User avatar
thomasrapp
Posts: 310
Joined: Sat Jun 18, 2011 11:22 pm

Re: How do I determine keyboard layout?

Post by thomasrapp »

There are functions in console.device and keymap.library to "cook" a raw key into a vanilla key. You don't need to do this yourself.

Also I don't see how the different Alt keys are relevant to AmigaOS. At least on the German keyboard layout in Windows only the right Alt key is used for special characters. The left Alt key has no function except to select menu items. On AmigaOS the Amiga keys are used for menu items, therefore you can treat the left Alt key exactly like the right Alt key.

But as I already said, the Alt keys should not be handled by your program. Use OS functions for that. All you need to handle as raw keys are the F and Cursor keys. Maybe Help.

You may even set both IDCMP_RAWKEY and IDCMP_VANILLAKEY, then you get a vanilla key event for every single-character ASCII code and a raw key event for all other keys.
User avatar
javierdlr
Beta Tester
Beta Tester
Posts: 389
Joined: Sun Jun 19, 2011 10:13 pm
Location: Donostia (GUIPUZCOA) - Spain
Contact:

Re: How do I determine keyboard layout?

Post by javierdlr »

colinward wrote: ...
The problem is that there is nothing like GetKeyboardLayout() on Amiga OS. I can't find anything interesting in the structure returned by AskKeyMapDefault() that gives the same information as above.

How can I find out if the current keyboard layout is a US keyboard layout? How does the Sys:Prefs/Input program do it?

Even better, is there a way of knowing whether to treat RALT as a normal ALT or as an AltGr key? That would be better than hard coding a check for US keyboards as there are probably other keyboards out there that don't have an AltGr key.
Hi. What I do in KeymapSwitcher.docky is to read input.prefs and store it [in (STRPTR)keymap]:

Code: Select all

void ReadInputPrefsKeymap(STRPTR keymap)
{
 struct IFFHandle *iffhandle;
 struct StoredProperty *sp;
 int32 ifferror;

 IUtility->Strlcpy(keymap, "usa", 64); // default keymap (usa=usa1)

 if( (iffhandle=IIFFParse->AllocIFF()) )
 {
  // Open the file for reading
  if((iffhandle->iff_Stream=(int32)IDOS->Open("ENV:Sys/input.prefs", MODE_OLDFILE)) )
  {
   IIFFParse->InitIFFasDOS(iffhandle); // initialize the iff handle
   if( (ifferror=IIFFParse->OpenIFF(iffhandle, IFFF_READ)) == 0 )
   {
    IIFFParse->PropChunk(iffhandle, ID_PREF, ID_INPT);
    for(;;)
    {
     ifferror = IIFFParse->ParseIFF(iffhandle, IFFPARSE_STEP);

     if( (sp=IIFFParse->FindProp(iffhandle, ID_PREF, ID_INPT)) )
     {
      if(IUtility->Stricmp( ((struct InputPrefs *)sp->sp_Data)->ip_KeymapName, "usa1") == 0)
       IUtility->Strlcpy(keymap, "usa", 64); // show USA instead of USA1
      else
       IUtility->Strlcpy(keymap, ((struct InputPrefs *)sp->sp_Data)->ip_KeymapName, 64);

      break;
     }
    }

    IIFFParse->CloseIFF(iffhandle);
   }

   IDOS->Close(iffhandle->iff_Stream);
   }
   else
    IDOS->Printf( GetString(&li, MSG_ERROR_NO_INPUTPREFS) );

   IIFFParse->FreeIFF(iffhandle);
   }
#ifdef _DEBUG_
IDOS->Printf("ReadInputPrefsKeymap(): '%s'\n",keymap);
#endif
}
Post Reply