Skip to content

Commit 3c126c1

Browse files
committed
Cleanup code around checking the IME status on Windows
We shouldn't allow for partial initialization of the User32 function pointers, since they should never be accessed on anything other than Windows 2000 or later. Mod code also should not call directly into platform code where possible, so introduce a helper method that dispatches to the correct platform code.
1 parent 44554e2 commit 3c126c1

4 files changed

Lines changed: 36 additions & 28 deletions

File tree

common/src/boot/java/net/caffeinemc/mods/sodium/client/platform/PlatformHelper.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.caffeinemc.mods.sodium.client.platform;
22

3+
import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils;
4+
import net.caffeinemc.mods.sodium.client.platform.windows.api.Imm32;
35
import org.jspecify.annotations.NonNull;
46
import org.jspecify.annotations.Nullable;
57
import org.slf4j.Logger;
@@ -26,4 +28,13 @@ public static void showCriticalErrorAndClose(
2628
MessageBox.showMessageBox(window, MessageBox.IconType.ERROR, messageTitle, messageBody, helpUrl);
2729
System.exit(1 /* failure code */);
2830
}
31+
32+
public static boolean isUsingIME() {
33+
if (OsUtils.getOs() == OsUtils.OperatingSystem.WIN) {
34+
return Imm32.checkIMEStatus();
35+
}
36+
37+
// Not handled on other platforms, so just assume we are not using an IME.
38+
return false;
39+
}
2940
}
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
package net.caffeinemc.mods.sodium.client.platform.windows.api;
22

33
public class Imm32 {
4-
//private static final MethodHandle IsIME;
4+
public static boolean checkIMEStatus() {
5+
long hkl = User32.callGetKeyboardLayout(0);
56

6-
static {
7-
//Linker linker = Linker.nativeLinker();
8-
//SymbolLookup imm32 = SymbolLookup.libraryLookup("imm32", Arena.global());
9-
//IsIME = linker.downcallHandle(imm32.find("ImmIsIME").orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS));
10-
}
7+
if (hkl == 0) {
8+
// Assume English keyboard layout.
9+
return false;
10+
}
1111

12-
public static boolean CheckIMEStatus() {
13-
long handle = User32.callGetKeyboardLayout(0);
14-
int langId = (int)(handle & 0xFFFF);
12+
int langId = (int)(hkl & 0xFFFF);
1513

1614
// ImmIsIME does not return a sensible result for this, sadly. Maybe it will some day. But it returns true almost all the time right now.
1715
return isImeLanguage(langId);
1816
}
1917

20-
public static boolean isImeLanguage(int langId) {
21-
return langId == 2052 /* zh-CN */ || langId == 1028 /* zh-TW */ || langId == 3076 /* zh-HK */ || langId == 4100 /* zh-SG */ || langId == 1041 /* ja-JP */ || langId == 1042 /* ko-KR */;
18+
private static boolean isImeLanguage(int langId) {
19+
return langId == 2052 /* zh-CN */ ||
20+
langId == 1028 /* zh-TW */ ||
21+
langId == 3076 /* zh-HK */ ||
22+
langId == 4100 /* zh-SG */ ||
23+
langId == 1041 /* ja-JP */ ||
24+
langId == 1042 /* ko-KR */;
2225
}
2326
}

common/src/boot/java/net/caffeinemc/mods/sodium/client/platform/windows/api/User32.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,32 @@
88

99
import static org.lwjgl.system.APIUtil.apiGetFunctionAddress;
1010
import static org.lwjgl.system.APIUtil.apiGetFunctionAddressOptional;
11+
import static org.lwjgl.system.MemoryUtil.NULL;
1112

1213
public class User32 {
1314
private static final SharedLibrary LIBRARY;
1415

1516
static {
16-
if (OsUtils.getOs() == OsUtils.OperatingSystem.WIN) {
17-
LIBRARY = APIUtil.apiCreateLibrary("user32");
18-
19-
PFN_MessageBoxIndirectW = apiGetFunctionAddress(LIBRARY, "MessageBoxIndirectW");
20-
PFN_GetKeyboardLayout = apiGetFunctionAddressOptional(LIBRARY, "GetKeyboardLayout");
21-
} else {
22-
LIBRARY = null;
23-
PFN_GetKeyboardLayout = -1;
24-
PFN_MessageBoxIndirectW = -1;
25-
}
17+
LIBRARY = APIUtil.apiCreateLibrary("user32");
18+
19+
PFN_MessageBoxIndirectW = apiGetFunctionAddress(LIBRARY, "MessageBoxIndirectW");
20+
PFN_GetKeyboardLayout = apiGetFunctionAddress(LIBRARY, "GetKeyboardLayout");
2621
}
2722

2823
private static final long PFN_MessageBoxIndirectW;
2924
private static final long PFN_GetKeyboardLayout;
3025

3126
/**
32-
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw>Winuser.h Documentation</a>
27+
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw">Winuser.h Documentation</a>
3328
*/
3429
public static void callMessageBoxIndirectW(MsgBoxParamSw params) {
35-
if (PFN_MessageBoxIndirectW == -1) return;
36-
3730
JNI.callPI(params.address(), PFN_MessageBoxIndirectW);
3831
}
3932

33+
/**
34+
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardlayout">Winuser.h Documentation</a>
35+
*/
4036
public static long callGetKeyboardLayout(int thread) {
41-
if (PFN_GetKeyboardLayout == -1) return 0;
42-
4337
return JNI.callPI(thread, PFN_GetKeyboardLayout);
4438
}
4539
}

common/src/main/java/net/caffeinemc/mods/sodium/mixin/core/MinecraftMixin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import net.caffeinemc.mods.sodium.client.config.ConfigManager;
99
import net.caffeinemc.mods.sodium.client.gui.SodiumConfigBuilder;
1010
import net.caffeinemc.mods.sodium.client.gui.SodiumOptions;
11-
import net.caffeinemc.mods.sodium.client.platform.windows.api.Imm32;
11+
import net.caffeinemc.mods.sodium.client.platform.PlatformHelper;
1212
import net.minecraft.client.GameLoadCookie;
1313
import net.minecraft.client.Minecraft;
1414
import net.minecraft.client.main.GameConfig;
@@ -67,7 +67,7 @@ private void setFullscreen(GameConfig gameConfig, CallbackInfo ci) {
6767
return; // Do not get stuck in a loop of setting exclusive fullscreen! That'd be very annoying.
6868
}
6969

70-
var hasIME = OsUtils.getOs() == OsUtils.OperatingSystem.WIN && Imm32.CheckIMEStatus();
70+
var hasIME = PlatformHelper.isUsingIME();
7171
Minecraft.getInstance().options.exclusiveFullscreen().set(!hasIME);
7272

7373
if (hasIME) {

0 commit comments

Comments
 (0)