-
-
Notifications
You must be signed in to change notification settings - Fork 628
/
EventLoop.java
97 lines (80 loc) · 3.77 KB
/
EventLoop.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
* Copyright LWJGL. All rights reserved.
* License terms: https://www.lwjgl.org/license
*/
package org.lwjgl.glfw;
import org.lwjgl.system.*;
import org.lwjgl.system.macosx.*;
import static org.lwjgl.system.APIUtil.*;
import static org.lwjgl.system.JNI.*;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.system.macosx.LibC.*;
import static org.lwjgl.system.macosx.ObjCRuntime.*;
/**
* Contains checks for the event loop issues on OS X.
*
* <p>On-screen GLFW windows can only be used in the main thread and only if that thread is the first thread in the process. This requires running the JVM with
* {@code -XstartOnFirstThread}, which means that other window toolkits (AWT/Swing, JavaFX, etc.) cannot be used at the same time.</p>
*
* <p>Another window toolkit <em>can</em> be used if GLFW windows are never shown (created with {@link GLFW#GLFW_VISIBLE GLFW_VISIBLE} equal to
* {@link GLFW#GLFW_FALSE GLFW_FALSE}) and only used as contexts for offscreen rendering. This is possible if the window toolkit has initialized and created
* the shared application (NSApp) before a GLFW window is created.</p>
*/
final class EventLoop {
static final class OffScreen {
static {
if (Platform.get() == Platform.MACOSX && !isMainThread()) {
// The only way to avoid a crash is if the shared application (NSApp) has been created by something else
SharedLibrary AppKit = MacOSXLibrary.getWithIdentifier("com.apple.AppKit");
try {
long NSApp = AppKit.getFunctionAddress("NSApp"); // The NSApp global variable is an exported symbol
if (memGetAddress(NSApp) == NULL) {
throw new IllegalStateException(
isJavaStartedOnFirstThread()
? "GLFW windows may only be created on the main thread."
: "GLFW windows may only be created on the main thread and that thread must be the first thread in the process. Please run " +
"the JVM with -XstartOnFirstThread. For offscreen rendering, make sure another window toolkit (e.g. AWT or JavaFX) is " +
"initialized before GLFW."
);
}
apiLog("GLFW can only be used for offscreen rendering.");
} finally {
AppKit.free();
}
}
}
private OffScreen() {
}
static void check() {
// intentionally empty to trigger the static initializer
}
}
static final class OnScreen {
static {
if (Platform.get() == Platform.MACOSX && !isMainThread()) {
throw new IllegalStateException(
"Please run the JVM with -XstartOnFirstThread and make sure a window toolkit other than GLFW (e.g. AWT or JavaFX) is not initialized."
);
}
}
private OnScreen() {
}
static void check() {
// intentionally empty to trigger the static initializer
}
}
private EventLoop() {
}
private static boolean isMainThread() {
if (!Configuration.GLFW_CHECK_THREAD0.get(true)) {
return true;
}
long objc_msgSend = ObjCRuntime.getLibrary().getFunctionAddress("objc_msgSend");
long NSThread = objc_getClass("NSThread");
long currentThread = invokePPP(NSThread, sel_getUid("currentThread"), objc_msgSend);
return invokePPZ(currentThread, sel_getUid("isMainThread"), objc_msgSend);
}
private static boolean isJavaStartedOnFirstThread() {
return "1".equals(System.getenv().get("JAVA_STARTED_ON_FIRST_THREAD_" + getpid()));
}
}