Skip to content

Commit effa043

Browse files
Copied cocoa ime blocker
1 parent cdf5ca6 commit effa043

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,6 @@ project(':cleanroom') {
485485
installer "io.netty:netty-codec-dns:$props.netty_version"
486486
installer "io.netty:netty-resolver-dns:$props.netty_version"
487487

488-
// installer 'io.netty:netty-all:4.1.93.Final'
489-
490-
// TODO: Unpin in 1.18.1 or when Mojang bumps the Log4J version
491488
installer 'org.apache.logging.log4j:log4j-api:2.24.1'
492489
installer 'org.apache.logging.log4j:log4j-core:2.24.1'
493490
installer 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.1'
@@ -504,6 +501,8 @@ project(':cleanroom') {
504501
installer 'jakarta.activation:jakarta.activation-api:2.1.3'
505502
installer 'org.glassfish.corba:glassfish-corba-omgapi:4.2.5'
506503
installer 'org.openjdk.nashorn:nashorn-core:15.4'
504+
installer 'ca.weblite:java-objc-bridge:1.2'
505+
507506

508507
// Mixin
509508
installer 'com.cleanroommc:sponge-mixin:0.20.7+mixin.0.8.7'

src/main/java/com/cleanroommc/client/IMEHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.cleanroommc.client;
22

3+
import com.cleanroommc.client.ime.CocoaIMEHandler;
34
import com.cleanroommc.client.ime.WindowsIMEHandler;
45
import net.minecraftforge.fml.common.FMLLog;
56
import org.lwjgl.glfw.GLFW;
@@ -11,7 +12,8 @@ public class IMEHandler {
1112
static {
1213
switch (GLFW.glfwGetPlatform()) {
1314
case GLFW.GLFW_PLATFORM_WIN32 -> instance = new WindowsIMEHandler();
14-
default -> FMLLog.log.warn("Unsupported platform: " + GLFW.glfwGetPlatform());
15+
case GLFW.GLFW_PLATFORM_COCOA -> instance = new CocoaIMEHandler();
16+
default -> FMLLog.log.warn("Unsupported platform: {}", GLFW.glfwGetPlatform());
1517
}
1618
}
1719
public static void setIME(boolean active) {
Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,72 @@
11
package com.cleanroommc.client.ime;
22

3+
import ca.weblite.objc.Runtime;
4+
import ca.weblite.objc.RuntimeUtils;
5+
import com.sun.jna.Callback;
6+
import com.sun.jna.Library;
7+
import com.sun.jna.Native;
38
import com.sun.jna.Pointer;
49

510
import java.util.function.Consumer;
611

12+
/**
13+
* Copied from <a href="https://github.com/reserveword/IMBlocker/pull/38">IMBlocker</a>
14+
*/
715
public class CocoaIMEHandler implements Consumer<Boolean> {
16+
private static boolean active = false;
17+
static private final Pointer viewClass = Runtime.INSTANCE.objc_getClass("GLFWContentView");
18+
static private Pointer view = null;
19+
static private final InterpretKeyEventsCallback Imp;
20+
static private final InterpretKeyEventsCallback NewImp;
821

22+
23+
static {
24+
// see https://github.com/glfw/glfw/blob/b4c3ef9d0fdf46845f3e81e5d989dab06e71e6c1/src/cocoa_window.m#L571
25+
// Replacing the method dynamically to determine whether to send text based on state
26+
// see reference for objc_runtime's dynamic manipulation at https://developer.apple.com/documentation/objectivec/objective-c_runtime
27+
var selector = RuntimeUtils.sel("interpretKeyEvents:");
28+
var method = Runtime.INSTANCE.class_getInstanceMethod(viewClass, selector);
29+
Imp = ObjC.INSTANCE.method_getImplementation(method);
30+
NewImp = (self, sel, eventArray) -> {
31+
if (view == null) view = self;
32+
if (!active) {
33+
var textInputContext = RuntimeUtils.cls("NSTextInputContext");
34+
var current = RuntimeUtils.msgPointer(textInputContext, "currentInputContext");
35+
RuntimeUtils.msg(current, "discardMarkedText");
36+
return;
37+
}
38+
Imp.invoke(self, sel, eventArray);
39+
};
40+
ObjC.INSTANCE.class_replaceMethod(viewClass, selector, NewImp, "v@:@");
41+
}
42+
/**
43+
* The underlying native type is IMP, which should be a function pointer to the implementation of interpretKeyEvents:
44+
* @see <a href="https://developer.apple.com/documentation/objectivec/objective-c_runtime/imp">Documentation for IMP</a>
45+
* @see <a href="https://developer.apple.com/documentation/appkit/nsresponder/1531599-interpretkeyevents?language=objc">Documentation for interpretKeyEvents:</a>
46+
*/
47+
private interface InterpretKeyEventsCallback extends Callback {
48+
/**
49+
* @param self "this" pointer for NSObject
50+
* @param selector selector for interpretKeyEvents:
51+
* @param eventArray an array of NSEvent objects
52+
*/
53+
void invoke(Pointer self, Pointer selector, Pointer eventArray);
54+
}
55+
56+
/**
57+
* @see <a href="https://developer.apple.com/documentation/objectivec/objective-c_runtime">Apple Developer Documentation for objc_runtime:</a>
58+
*/
59+
private interface ObjC extends Library {
60+
ObjC INSTANCE = Native.load("objc.A", ObjC.class);
61+
62+
void class_replaceMethod(Pointer cls, Pointer selector, InterpretKeyEventsCallback imp, String types);
63+
64+
InterpretKeyEventsCallback method_getImplementation(Pointer selector);
65+
}
966
@Override
1067
public void accept(Boolean aBoolean) {
11-
68+
if (active != aBoolean) {
69+
active = aBoolean;
70+
}
1271
}
1372
}

src/main/java/com/cleanroommc/client/ime/WindowsIMEHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import com.sun.jna.platform.win32.WinNT;
77

88
import java.util.function.Consumer;
9-
import java.util.function.Supplier;
109

10+
/**
11+
* Copied from <a href="https://github.com/reserveword/IMBlocker/blob/master/common/src/main/java/io/github/reserveword/imblocker/common/IMManagerWindows.java">IMBlocker</a>
12+
*/
1113
public class WindowsIMEHandler implements Consumer<Boolean> {
1214

1315
private static native WinNT.HANDLE ImmGetContext(WinDef.HWND hwnd);

0 commit comments

Comments
 (0)