1 /* 2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.glass.ui.gtk; 26 27 import com.sun.glass.ui.Application; 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 40 import java.io.File; 41 import java.nio.ByteBuffer; 42 import java.nio.IntBuffer; 43 import java.security.AccessController; 44 import java.security.PrivilegedAction; 45 import java.util.Map; 46 import java.util.concurrent.CountDownLatch; 47 48 final class GtkApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter { 49 50 static { 51 AccessController.doPrivileged((PrivilegedAction<Void>) () -> { 52 Application.loadNativeLibrary(); 53 return null; 54 }); 55 } 56 57 public static int screen = -1; 58 public static long display = 0; 59 public static long visualID = 0; 60 61 private final InvokeLaterDispatcher invokeLaterDispatcher; 62 63 GtkApplication() { 64 // Check whether the Display is valid and throw an exception if not. 65 // We use UnsupportedOperationException rather than HeadlessException 66 // so as not to introduce a dependency on AWT. 67 if (!isDisplayValid()) { 68 throw new UnsupportedOperationException("Unable to open DISPLAY"); 69 } 70 71 // Embedded in SWT, with shared event thread 72 boolean isEventThread = AccessController 73 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread")); 74 if (!isEventThread) { 75 invokeLaterDispatcher = new InvokeLaterDispatcher(this); 76 invokeLaterDispatcher.start(); 77 } else { 78 invokeLaterDispatcher = null; 79 } 80 } 81 82 private static boolean isDisplayValid() { 83 return _isDisplayValid(); 84 } 85 86 private void initDisplay() { 87 Map ds = getDeviceDetails(); 88 if (ds != null) { 89 Object value; 90 value = ds.get("XDisplay"); 91 if (value != null) { 92 display = (Long)value; 93 } 94 value = ds.get("XVisualID"); 95 if (value != null) { 96 visualID = (Long)value; 97 } 98 value = ds.get("XScreenID"); 99 if (value != null) { 100 screen = (Integer)value; 101 } 102 } 103 } 104 138 init(); 139 _runLoop(launchable, noErrorTrap); 140 }, "GtkNativeMainLoopThread")); 141 setEventThread(toolkitThread); 142 toolkitThread.start(); 143 } 144 145 @Override 146 protected void finishTerminating() { 147 final Thread toolkitThread = getEventThread(); 148 if (toolkitThread != null) { 149 _terminateLoop(); 150 setEventThread(null); 151 } 152 super.finishTerminating(); 153 } 154 155 @Override public boolean shouldUpdateWindow() { 156 return true; 157 } 158 159 private static native boolean _isDisplayValid(); 160 161 private native void _terminateLoop(); 162 163 private native void _init(long eventProc, boolean disableGrab); 164 165 private native void _runLoop(Runnable launchable, boolean noErrorTrap); 166 167 @Override 168 protected void _invokeAndWait(final Runnable runnable) { 169 if (invokeLaterDispatcher != null) { 170 invokeLaterDispatcher.invokeAndWait(runnable); 171 } else { 172 final CountDownLatch latch = new CountDownLatch(1); 173 submitForLaterInvocation(() -> { 174 if (runnable != null) runnable.run(); 175 latch.countDown(); 176 }); 177 try { 178 latch.await(); 179 } catch (InterruptedException e) { | 1 /* 2 * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.glass.ui.gtk; 26 27 import com.sun.glass.ui.Application; 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.javafx.util.Logging; 40 import com.sun.glass.utils.NativeLibLoader; 41 import sun.util.logging.PlatformLogger; 42 43 import java.io.File; 44 import java.lang.reflect.Method; 45 import java.nio.ByteBuffer; 46 import java.nio.IntBuffer; 47 import java.security.AccessController; 48 import java.security.PrivilegedAction; 49 import java.util.Map; 50 import java.util.concurrent.CountDownLatch; 51 import java.lang.annotation.Native; 52 53 final class GtkApplication extends Application implements 54 InvokeLaterDispatcher.InvokeLaterSubmitter { 55 private static final String SWT_INTERNAL_CLASS = 56 "org.eclipse.swt.internal.gtk.OS"; 57 private static final int forcedGtkVersion; 58 59 static { 60 //check for SWT-GTK lib presence 61 Class<?> OS = AccessController. 62 doPrivileged((PrivilegedAction<Class<?>>) () -> { 63 try { 64 return Class.forName(SWT_INTERNAL_CLASS, true, 65 ClassLoader.getSystemClassLoader()); 66 } catch (Exception e) {} 67 try { 68 return Class.forName(SWT_INTERNAL_CLASS, true, 69 Thread.currentThread().getContextClassLoader()); 70 } catch (Exception e) {} 71 return null; 72 }); 73 if (OS != null) { 74 PlatformLogger logger = Logging.getJavaFXLogger(); 75 logger.fine("SWT-GTK library found. Try to obtain GTK version."); 76 Method method = AccessController. 77 doPrivileged((PrivilegedAction<Method>) () -> { 78 try { 79 return OS.getMethod("gtk_major_version"); 80 } catch (Exception e) { 81 return null; 82 } 83 }); 84 int ver = 0; 85 if (method != null) { 86 try { 87 ver = ((Number)method.invoke(OS)).intValue(); 88 } catch (Exception e) { 89 logger.warning("Method gtk_major_version() of " + 90 "the org.eclipse.swt.internal.gtk.OS class " + 91 "returns error. SWT GTK version cannot be detected. " + 92 "GTK3 will be used as default."); 93 ver = 3; 94 } 95 } 96 if (ver < 2 || ver > 3) { 97 logger.warning("SWT-GTK uses unsupported major GTK version " 98 + ver + ". GTK3 will be used as default."); 99 ver = 3; 100 } 101 forcedGtkVersion = ver; 102 } else { 103 forcedGtkVersion = 0; 104 } 105 106 AccessController.doPrivileged((PrivilegedAction<Void>) () -> { 107 Application.loadNativeLibrary(); 108 return null; 109 }); 110 } 111 112 public static int screen = -1; 113 public static long display = 0; 114 public static long visualID = 0; 115 116 private final InvokeLaterDispatcher invokeLaterDispatcher; 117 118 GtkApplication() { 119 120 final int gtkVersion = forcedGtkVersion == 0 ? 121 AccessController.doPrivileged((PrivilegedAction<Integer>) () -> { 122 String v = System.getProperty("jdk.gtk.version","2"); 123 int ret = 0; 124 if ("3".equals(v) || v.startsWith("3.")) { 125 ret = 3; 126 } else if ("2".equals(v) || v.startsWith("2.")) { 127 ret = 2; 128 } 129 return ret; 130 }) : forcedGtkVersion; 131 132 boolean gtkVersionVerbose = 133 AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> { 134 return Boolean.getBoolean("jdk.gtk.verbose"); 135 136 }); 137 138 int libraryToLoad = _queryLibrary(gtkVersion, gtkVersionVerbose); 139 140 AccessController.doPrivileged((PrivilegedAction<Void>) () -> { 141 if (libraryToLoad == QUERY_NO_DISPLAY) { 142 throw new UnsupportedOperationException("Unable to open DISPLAY"); 143 } else if (libraryToLoad == QUERY_USE_CURRENT) { 144 if (gtkVersionVerbose) { 145 System.out.println("Glass GTK library to load is already loaded"); 146 } 147 } else if (libraryToLoad == QUERY_LOAD_GTK2) { 148 if (gtkVersionVerbose) { 149 System.out.println("Glass GTK library to load is glassgtk2"); 150 } 151 NativeLibLoader.loadLibrary("glassgtk2"); 152 } else if (libraryToLoad == QUERY_LOAD_GTK3) { 153 if (gtkVersionVerbose) { 154 System.out.println("Glass GTK library to load is glassgtk3"); 155 } 156 NativeLibLoader.loadLibrary("glassgtk3"); 157 } else { 158 throw new UnsupportedOperationException("Internal Error"); 159 } 160 return null; 161 }); 162 163 int version = _initGTK(gtkVersion, gtkVersionVerbose); 164 if (version == -1) { 165 throw new RuntimeException("Error loading GTK libraries"); 166 } 167 168 // Embedded in SWT, with shared event thread 169 boolean isEventThread = AccessController 170 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread")); 171 if (!isEventThread) { 172 invokeLaterDispatcher = new InvokeLaterDispatcher(this); 173 invokeLaterDispatcher.start(); 174 } else { 175 invokeLaterDispatcher = null; 176 } 177 } 178 179 @Native private static final int QUERY_ERROR = -2; 180 @Native private static final int QUERY_NO_DISPLAY = -1; 181 @Native private static final int QUERY_USE_CURRENT = 1; 182 @Native private static final int QUERY_LOAD_GTK2 = 2; 183 @Native private static final int QUERY_LOAD_GTK3 = 3; 184 /* 185 * check the system and return an indication of which library to load 186 * return values are the QUERY_ constants 187 */ 188 private static native int _queryLibrary(int version, boolean verbose); 189 190 private static native int _initGTK(int version, boolean verbose); 191 192 private void initDisplay() { 193 Map ds = getDeviceDetails(); 194 if (ds != null) { 195 Object value; 196 value = ds.get("XDisplay"); 197 if (value != null) { 198 display = (Long)value; 199 } 200 value = ds.get("XVisualID"); 201 if (value != null) { 202 visualID = (Long)value; 203 } 204 value = ds.get("XScreenID"); 205 if (value != null) { 206 screen = (Integer)value; 207 } 208 } 209 } 210 244 init(); 245 _runLoop(launchable, noErrorTrap); 246 }, "GtkNativeMainLoopThread")); 247 setEventThread(toolkitThread); 248 toolkitThread.start(); 249 } 250 251 @Override 252 protected void finishTerminating() { 253 final Thread toolkitThread = getEventThread(); 254 if (toolkitThread != null) { 255 _terminateLoop(); 256 setEventThread(null); 257 } 258 super.finishTerminating(); 259 } 260 261 @Override public boolean shouldUpdateWindow() { 262 return true; 263 } 264 265 private native void _terminateLoop(); 266 267 private native void _init(long eventProc, boolean disableGrab); 268 269 private native void _runLoop(Runnable launchable, boolean noErrorTrap); 270 271 @Override 272 protected void _invokeAndWait(final Runnable runnable) { 273 if (invokeLaterDispatcher != null) { 274 invokeLaterDispatcher.invokeAndWait(runnable); 275 } else { 276 final CountDownLatch latch = new CountDownLatch(1); 277 submitForLaterInvocation(() -> { 278 if (runnable != null) runnable.run(); 279 latch.countDown(); 280 }); 281 try { 282 latch.await(); 283 } catch (InterruptedException e) { |