gwdevhub / GWToolboxpp

Tools for Guild Wars players
http://www.gwtoolbox.com/
MIT License
147 stars 76 forks source link

[QoL] disable gw adding English (US) keyboard layout #782

Closed DubbleClick closed 1 year ago

3vcloud commented 2 years ago

Can you flesh this one out for me a bit?

DubbleClick commented 2 years ago

When launched, GW adds the EN-US Keyboard layout. If you remove the keyboard layout from Windows after gw added it, gw will no longer register any keyboard inputs.

Desired behaviour would be that GW behaves like a normal program and doesn't add a stupid keyboard layout in the first place.

3vcloud commented 2 years ago

Not easy to do; if we don't use EN-US to determine keypresses in-game, we have to rely on the host machine's keyboard setup, which would mean testing lots of different languages to match up with the EN-US keys

truekenny commented 1 year ago

I've been struggling with this myself for a long time, here's what I came up with to remove the second ENG layout that the game added:

My game adds the ENG-INTL layout for me (which can't be removed via the Windows interface, so it's added in the script first (so I can then remove it in the script later)). I only need RU and ENG-US.

The essence of the script:

  1. I replace the layouts with RU (the first one so that the Windows interface is exactly like this), then ENG-US, ENG-INTL;
  2. I change layouts to RU, ENG-US;
  3. I simulate pressing Alt-Shift so that after the script is executed, the ENG-US layout is selected.
#step 1
$1 = Get-WinUserLanguageList
$1.Clear();
$1.Add("ru")
$1.Add("en-US")
$1[1].InputMethodTips.Clear()
$1[1].InputMethodTips.Add('0409:00000409') #en us
$1[1].InputMethodTips.Add('0409:00020409') #en intl
Set-WinUserLanguageList -LanguageList $1 -Force 

#step 2
$1 = Get-WinUserLanguageList
$1.Clear();
# First - Windows GUI Language
$1.Add("ru")
$1.Add("en-US")
$1[1].InputMethodTips.Clear()
$1[1].InputMethodTips.Add('0409:00000409')
Set-WinUserLanguageList -LanguageList $1 -Force 

# maybe not need
Set-WinDefaultInputMethodOverride -InputTip '0409:00000409'

#step 3
#Send Alt+Shift
$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys('%+')

You need to save this script in a text file like: script.ps1. Create a desktop shortcut: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Users\PATH-TO-SCRIPT\Desktop\lang.ps1"

After the game, I run this script and the layouts come back to normal.

3vcloud commented 1 year ago

https://learn.microsoft.com/en-gb/windows/win32/api/winuser/nf-winuser-loadkeyboardlayouta for reference - after Windows 8 it looks like when a program wants a specific keyboard layout, Windows changes it for the whole system, not just that program. If anyone can flesh out why they thought this was a brilliant idea, I'd be very interested to know.

truekenny commented 1 year ago

@3vcloud

After checking the code 60dafc531be467be1a1ffd5b190372e68af1fc8d I have the impression that it will not solve the problem I described:

Before starting the game, I have the following layouts: 419 and 409. After the game, the following are: 419, 409 and 20409 (ENG-INTL).

If Windows after executing the line LoadKeyboardLayoutA("00000409", 0); adds layout 20409, then it will turn out that as a result of executing this code, instead of the original 419 and 409, the following 419 and 20409 will remain.

Additional information I discovered today:

  1. if layout 419 is active when starting the game, then the game adds 20409;
  2. if layout 409 is active when starting the game, then the game does NOT add 20409.

Sorry if I misunderstood the code.

3vcloud commented 1 year ago

I've tested this with en-uk and en-au, using en-uk when starting GW.

Force remove en-us before continuing.

Start guild wars without toolbox; I've now got 3 languages (en-uk, en-au, en-us) when I close gw.

Force remove en-us before continuing.

Start guild wars via gwlauncher with toolbox injected at runtime: toolbox will load the 409 layout, assign it to GW memory and then remove the 409 layout if the result of this call has increased the number of available keyboard languages.

Did you test the code or just read it through? If you tested it, then I'll need to dig a little deeper but I'm surprised that this didn't fix it for you

truekenny commented 1 year ago

I just read the code.

Now I tried to remove en-US and your words were confirmed, after the game en-US was added.

But I always use the layouts ru (419:419) and en-US (409:409). And when I start the game with the ru layout active, the game adds en-INTL (409:20409) and not en-US like in your example.

I'm worried something might go wrong because my game adds InputMethodTips : {0409:00020409}

For completeness of information, before the start of the game:

Windows PowerShell > Get-WinUserLanguageList

LanguageTag : en
Autonym : Russian
EnglishName : Russian
LocalizedName : Russian
ScriptName : Cyrillic
InputMethodTips : {0419:00000419}
Spellchecking : True
Handwriting : False

LanguageTag : en-US
Autonym : English (United States)
EnglishName : English
LocalizedName : English (United States)
ScriptName : Latin
InputMethodTips : {0409:00000409}
Spellchecking : True
Handwriting : False

After starting the game with the ru layout, a "temporary" en-INTL appears, which is not displayed in the output of this command (and will disappear if you restart the computer).

3vcloud commented 1 year ago

It doesn't matter what keyboard language it spits out; if its one that wasn't there before, it'll make sure to remove it again if you're using toolbox at runtime. The only reason the code is explicitly asking for 409 is because that it what GW is asking for. In reality we don't care what the result is because the game will handle it from there.

TL;DR don't worry its magic

truekenny commented 1 year ago

In version 6.7, in one day (about 10 launches of the game), an extra layout was added three times again. I did not find the sequence of steps for stable reproduction of the problem. The last time I noticed only that the problem was reproduced at the start of the game.

In version 6.5, which I used for 10 days, the problem was never noticed.

I haven't played with version 6.6.

3vcloud commented 1 year ago

The keyboard fix only works if toolbox is run when the game is launched. If toolbox is run after the game loads the login screen, it won’t do anything

truekenny commented 1 year ago

I always use GwLauncher to launch the game (https://github.com/GregLando113/gwlauncher). In infrequent moments, which have been seen so far only on version 6.7, an additional layout is added again. Does this mean, for example, that GwLauncher doesn't inject GWToolboxpp right away?

I rolled back to version 6.5 to test this version longer.

3vcloud commented 1 year ago

You could check the log file in the toolbox folder if it happens again, the module prints a message if it failed to intercept gw

truekenny commented 1 year ago

The problem reproduced three times out of three under the following conditions:

  1. Version 6.7, Windows 10 (up to date);

  2. The computer is in StandBy mode (Sleep, not Hibernate);

  3. The computer was put to sleep with the GwLauncher program running in the tray; the system had two layouts RU and En-US (active En-US);

  4. We wake up the computer;

  5. Open GwLauncher from tray, run the game for the first time after waking up;

  6. Before the appearance of the game Splash Window, I have time to notice that a new layout appears;

  7. After manually deleting an extra layout, subsequent launches (if you do not send the computer to StandBy mode) do not cause this layout to be added again.

Maybe some steps are redundant.

I managed to save two log files (log.txt), the first log is when the layout was added, the second log is when the layout was not added, but they are absolutely identical (except for timestamps) (compared the logs with diff).

truekenny commented 1 year ago

Version 6.6 also adds an extra layout, as in the comment above.

Also, the layout is added the first time you start the game using GwLauncher after restarting the computer.

In version 6.5 everything is fine.

truekenny commented 1 year ago

After a couple of months, I decided to try version 6.7 again and now the error that I described above does not reproduce for several days that I play with version 6.7.