28 import com.sun.glass.ui.CommonDialogs.ExtensionFilter;
29 import com.sun.glass.ui.CommonDialogs.FileChooserResult;
30 import com.sun.glass.ui.Cursor;
31 import com.sun.glass.ui.InvokeLaterDispatcher;
32 import com.sun.glass.ui.Pixels;
33 import com.sun.glass.ui.Robot;
34 import com.sun.glass.ui.Screen;
35 import com.sun.glass.ui.Size;
36 import com.sun.glass.ui.Timer;
37 import com.sun.glass.ui.View;
38 import com.sun.glass.ui.Window;
39 import com.sun.prism.impl.PrismSettings;
40
41 import java.io.File;
42 import java.nio.ByteBuffer;
43 import java.nio.IntBuffer;
44 import java.security.AccessController;
45 import java.security.PrivilegedAction;
46 import java.util.Map;
47 import java.util.concurrent.CountDownLatch;
48
49 final class GtkApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter {
50
51 static {
52 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
53 Application.loadNativeLibrary();
54 return null;
55 });
56 }
57
58 public static int screen = -1;
59 public static long display = 0;
60 public static long visualID = 0;
61
62 static float overrideUIScale;
63
64 private final InvokeLaterDispatcher invokeLaterDispatcher;
65
66 private static float getFloat(String propname, float defval, String description) {
67 String str = System.getProperty(propname);
71 if (str == null) {
72 return defval;
73 }
74 str = str.trim();
75 float val;
76 if (str.endsWith("%")) {
77 val = Integer.parseInt(str.substring(0, str.length()-1)) / 100.0f;
78 } else if (str.endsWith("DPI") || str.endsWith("dpi")) {
79 val = Integer.parseInt(str.substring(0, str.length()-3)) / 96.0f;
80 } else {
81 val = Float.parseFloat(str);
82 }
83 if (PrismSettings.verbose) {
84 System.out.println(description+val);
85 }
86 return val;
87 }
88
89 GtkApplication() {
90
91 // Check whether the Display is valid and throw an exception if not.
92 // We use UnsupportedOperationException rather than HeadlessException
93 // so as not to introduce a dependency on AWT.
94 if (!isDisplayValid()) {
95 throw new UnsupportedOperationException("Unable to open DISPLAY");
96 }
97
98 int gtkVersion =
99 AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
100 String v = System.getProperty("jdk.gtk.version","2");
101 int ret = 0;
102 if ("3".equals(v) || v.startsWith("3.")) {
103 ret = 3;
104 } else if ("2".equals(v) || v.startsWith("2.")) {
105 ret = 2;
106 }
107 return ret;
108 });
109 boolean gtkVersionVerbose =
110 AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
111 return Boolean.getBoolean("jdk.gtk.verbose");
112 });
113 if (PrismSettings.allowHiDPIScaling) {
114 overrideUIScale = AccessController.doPrivileged((PrivilegedAction<Float>) () ->
115 getFloat("glass.gtk.uiScale", -1.0f, "Forcing UI scaling factor: "));
116 } else {
117 overrideUIScale = -1.0f;
118 }
119 int version = _initGTK(gtkVersion, gtkVersionVerbose, overrideUIScale);
120
121 if (version == -1) {
122 throw new RuntimeException("Error loading GTK libraries");
123 }
124
125 // Embedded in SWT, with shared event thread
126 boolean isEventThread = AccessController
127 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread"));
128 if (!isEventThread) {
129 invokeLaterDispatcher = new InvokeLaterDispatcher(this);
130 invokeLaterDispatcher.start();
131 } else {
132 invokeLaterDispatcher = null;
133 }
134 }
135
136 private static native int _initGTK(int version, boolean verbose, float overrideUIScale);
137
138 private static boolean isDisplayValid() {
139 return _isDisplayValid();
140 }
141
142 private void initDisplay() {
143 Map ds = getDeviceDetails();
144 if (ds != null) {
145 Object value;
146 value = ds.get("XDisplay");
147 if (value != null) {
148 display = (Long)value;
149 }
150 value = ds.get("XVisualID");
151 if (value != null) {
152 visualID = (Long)value;
153 }
154 value = ds.get("XScreenID");
155 if (value != null) {
156 screen = (Integer)value;
157 }
158 }
159 }
160
194 init();
195 _runLoop(launchable, noErrorTrap);
196 }, "GtkNativeMainLoopThread"));
197 setEventThread(toolkitThread);
198 toolkitThread.start();
199 }
200
201 @Override
202 protected void finishTerminating() {
203 final Thread toolkitThread = getEventThread();
204 if (toolkitThread != null) {
205 _terminateLoop();
206 setEventThread(null);
207 }
208 super.finishTerminating();
209 }
210
211 @Override public boolean shouldUpdateWindow() {
212 return true;
213 }
214
215 private static native boolean _isDisplayValid();
216
217 private native void _terminateLoop();
218
219 private native void _init(long eventProc, boolean disableGrab);
220
221 private native void _runLoop(Runnable launchable, boolean noErrorTrap);
222
223 @Override
224 protected void _invokeAndWait(final Runnable runnable) {
225 if (invokeLaterDispatcher != null) {
226 invokeLaterDispatcher.invokeAndWait(runnable);
227 } else {
228 final CountDownLatch latch = new CountDownLatch(1);
229 submitForLaterInvocation(() -> {
230 if (runnable != null) runnable.run();
231 latch.countDown();
232 });
233 try {
234 latch.await();
235 } catch (InterruptedException e) {
|
28 import com.sun.glass.ui.CommonDialogs.ExtensionFilter;
29 import com.sun.glass.ui.CommonDialogs.FileChooserResult;
30 import com.sun.glass.ui.Cursor;
31 import com.sun.glass.ui.InvokeLaterDispatcher;
32 import com.sun.glass.ui.Pixels;
33 import com.sun.glass.ui.Robot;
34 import com.sun.glass.ui.Screen;
35 import com.sun.glass.ui.Size;
36 import com.sun.glass.ui.Timer;
37 import com.sun.glass.ui.View;
38 import com.sun.glass.ui.Window;
39 import com.sun.prism.impl.PrismSettings;
40
41 import java.io.File;
42 import java.nio.ByteBuffer;
43 import java.nio.IntBuffer;
44 import java.security.AccessController;
45 import java.security.PrivilegedAction;
46 import java.util.Map;
47 import java.util.concurrent.CountDownLatch;
48 import java.lang.annotation.Native;
49
50 final class GtkApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter {
51
52 static {
53 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
54 Application.loadNativeLibrary();
55 return null;
56 });
57 }
58
59 public static int screen = -1;
60 public static long display = 0;
61 public static long visualID = 0;
62
63 static float overrideUIScale;
64
65 private final InvokeLaterDispatcher invokeLaterDispatcher;
66
67 private static float getFloat(String propname, float defval, String description) {
68 String str = System.getProperty(propname);
72 if (str == null) {
73 return defval;
74 }
75 str = str.trim();
76 float val;
77 if (str.endsWith("%")) {
78 val = Integer.parseInt(str.substring(0, str.length()-1)) / 100.0f;
79 } else if (str.endsWith("DPI") || str.endsWith("dpi")) {
80 val = Integer.parseInt(str.substring(0, str.length()-3)) / 96.0f;
81 } else {
82 val = Float.parseFloat(str);
83 }
84 if (PrismSettings.verbose) {
85 System.out.println(description+val);
86 }
87 return val;
88 }
89
90 GtkApplication() {
91
92 int gtkVersion =
93 AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
94 String v = System.getProperty("jdk.gtk.version","2");
95 int ret = 0; // start with "no preference
96 if ("3".equals(v) || v.startsWith("3.")) {
97 ret = 3;
98 } else if ("2".equals(v) || v.startsWith("2.")) {
99 ret = 2;
100 }
101 return ret;
102 });
103 boolean gtkVersionVerbose =
104 AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
105 return Boolean.getBoolean("jdk.gtk.verbose");
106 });
107 if (PrismSettings.allowHiDPIScaling) {
108 overrideUIScale = AccessController.doPrivileged((PrivilegedAction<Float>) () ->
109 getFloat("glass.gtk.uiScale", -1.0f, "Forcing UI scaling factor: "));
110 } else {
111 overrideUIScale = -1.0f;
112 }
113
114 int libraryToLoad = _queryLibrary(gtkVersion, gtkVersionVerbose);
115
116 if (libraryToLoad == QUERY_NO_DISPLAY) {
117 throw new UnsupportedOperationException("Unable to open DISPLAY");
118 } else if (libraryToLoad == QUERY_USE_CURRENT) {
119 if (gtkVersionVerbose)
120 System.out.println("Glass GTK library to load is already loaded");
121 } else if (libraryToLoad == QUERY_LOAD_GTK2) {
122 if (gtkVersionVerbose)
123 System.out.println("Glass GTK library to load is glassgtk2");
124 com.sun.glass.utils.NativeLibLoader.loadLibrary("glassgtk2");
125 } else if (libraryToLoad == QUERY_LOAD_GTK3) {
126 if (gtkVersionVerbose)
127 System.out.println("Glass GTK library to load is glassgtk3");
128 com.sun.glass.utils.NativeLibLoader.loadLibrary("glassgtk3");
129 } else {
130 throw new UnsupportedOperationException("Internal Error");
131 }
132
133 int version = _initGTK(gtkVersion, gtkVersionVerbose, overrideUIScale);
134
135 if (version == -1) {
136 throw new RuntimeException("Error loading GTK libraries");
137 }
138
139 // Embedded in SWT, with shared event thread
140 boolean isEventThread = AccessController
141 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread"));
142 if (!isEventThread) {
143 invokeLaterDispatcher = new InvokeLaterDispatcher(this);
144 invokeLaterDispatcher.start();
145 } else {
146 invokeLaterDispatcher = null;
147 }
148 }
149
150 @Native private static final int QUERY_ERROR = -2;
151 @Native private static final int QUERY_NO_DISPLAY = -1;
152 @Native private static final int QUERY_USE_CURRENT = 1;
153 @Native private static final int QUERY_LOAD_GTK2 = 2;
154 @Native private static final int QUERY_LOAD_GTK3 = 3;
155 /*
156 * check the system and return an indication of which library to load
157 * return values are the QUERY_ constants
158 */
159 private static native int _queryLibrary(int version, boolean verbose);
160
161 private static native int _initGTK(int version, boolean verbose, float overrideUIScale);
162
163 private void initDisplay() {
164 Map ds = getDeviceDetails();
165 if (ds != null) {
166 Object value;
167 value = ds.get("XDisplay");
168 if (value != null) {
169 display = (Long)value;
170 }
171 value = ds.get("XVisualID");
172 if (value != null) {
173 visualID = (Long)value;
174 }
175 value = ds.get("XScreenID");
176 if (value != null) {
177 screen = (Integer)value;
178 }
179 }
180 }
181
215 init();
216 _runLoop(launchable, noErrorTrap);
217 }, "GtkNativeMainLoopThread"));
218 setEventThread(toolkitThread);
219 toolkitThread.start();
220 }
221
222 @Override
223 protected void finishTerminating() {
224 final Thread toolkitThread = getEventThread();
225 if (toolkitThread != null) {
226 _terminateLoop();
227 setEventThread(null);
228 }
229 super.finishTerminating();
230 }
231
232 @Override public boolean shouldUpdateWindow() {
233 return true;
234 }
235
236 private native void _terminateLoop();
237
238 private native void _init(long eventProc, boolean disableGrab);
239
240 private native void _runLoop(Runnable launchable, boolean noErrorTrap);
241
242 @Override
243 protected void _invokeAndWait(final Runnable runnable) {
244 if (invokeLaterDispatcher != null) {
245 invokeLaterDispatcher.invokeAndWait(runnable);
246 } else {
247 final CountDownLatch latch = new CountDownLatch(1);
248 submitForLaterInvocation(() -> {
249 if (runnable != null) runnable.run();
250 latch.countDown();
251 });
252 try {
253 latch.await();
254 } catch (InterruptedException e) {
|