glazewm icon indicating copy to clipboard operation
glazewm copied to clipboard

feat: keyboard language component

Open jawee opened this issue 1 year ago • 10 comments

Component for showing current input language (keyboard layout).

jawee avatar Jan 20 '24 11:01 jawee

Works for en-US and ja-JP but not for Ukrainian for some reason. It just returns an empty string. Locale ID shows 61608 and LCIDToLocaleName returns an empty string for Ukrainian.

Video-Nomad avatar Jan 20 '24 11:01 Video-Nomad

And ukrainian is supposed to be 1058 (0x422) according to https://www.ryadel.com/en/microsoft-windows-lcid-list-decimal-and-hex-all-locale-codes-ids/

For some reason the value from GetKeyboardLayout doesn't follow the same "format" as swedish and us that I tested with. Will try to figure it out.

uk-UA (0x422): 0xfffffffff0a80422; sv-SE (0x41d): 0x00000000041d0809; en-US (0x409): 0x0000000004092000;

jawee avatar Jan 20 '24 13:01 jawee

Not sure if this will work for every possible language. But added a few at random, and those I tried seem to work fine with this solution. Feels a bit hacky, but seems to be working pretty good.

jawee avatar Jan 23 '24 17:01 jawee

@jawee I actually just wanted to post another solution right before your commit. Worked for me so far. Haven't tested it extensively though.

  private const uint LOCALE_SNAME = 0x0000005c;

  private static string GetInputLanguage()
  {
    var layout = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));

    var sb = new StringBuilder();
    GetLocaleInfoW((uint)layout & 0xFFFF, LOCALE_SNAME, sb, sb.Capacity);

    return sb.ToString();
  }
    [DllImport("kernel32.dll")]
    public static extern IntPtr GetLocaleInfoW(uint locale, uint LCType, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpLCData, int cchData);

Video-Nomad avatar Jan 23 '24 18:01 Video-Nomad

It also might be a good idea to expose the updateInterval for the Observable as a config option, similar to how CpuComponent handles it. 1 second is way too slow for me, and 250 milliseconds feels more responsive, but people might want to configure that themselves.

Video-Nomad avatar Jan 23 '24 19:01 Video-Nomad

Your solution looks cleaner in my opinion, I'm open to using that. I'll try to do some more testing sometime within the next few days.

Had a few minutes before having to start work, so I made the refresh interval configureable, I defaulted it to 1 second though, but open to change that to 250ms as well if that's preferable. Once a second works fine for my use case :)

jawee avatar Jan 24 '24 05:01 jawee

I feel like 1 second is a reasonable default value. Feel free to update the code with the solution I provided if you find it acceptable. Thanks for the component 👍

Video-Nomad avatar Jan 24 '24 07:01 Video-Nomad

Did some more testing, with more languages, and my solution seems fine for the all languages I've tried. I also tried your solution, but it didn't work for swedish, so I think my solution is a decent starting point for now. :)

jawee avatar Jan 26 '24 16:01 jawee

@jawee Very strange. I tested it on Swedish and it worked on my end.

4WRXh6ps1h

In any case, if it works it works 👍

Video-Nomad avatar Jan 26 '24 16:01 Video-Nomad

Probably because I use english language, but swedish keyboard layout. :) (probably really weird..)

image

jawee avatar Feb 01 '24 10:02 jawee

Due to the C# -> Rust rewrite, some of these older PRs aren't compatible anymore. Can't merge as is, and I'm sorry about not finding the time to get this in while the C# version was active. Nevertheless, thank you for contributing to GlazeWM 🙏

Ps if you're interested in updating this to be a zebar provider in rust, just lmk!

lars-berger avatar Aug 11 '24 17:08 lars-berger