1 /* 2 * Copyright (c) 2010, 2013, 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.win; 26 27 import com.sun.glass.ui.*; 28 import com.sun.glass.ui.CommonDialogs.ExtensionFilter; 29 import com.sun.glass.ui.CommonDialogs.FileChooserResult; 30 import com.sun.glass.utils.NativeLibLoader; 31 import com.sun.javafx.application.PlatformImpl; 32 import com.sun.javafx.tk.Toolkit; 33 34 import java.io.File; 35 import java.nio.ByteBuffer; 36 import java.nio.IntBuffer; 37 import java.security.AccessController; 38 import java.security.PrivilegedAction; 39 import java.util.List; 40 41 import javafx.scene.accessibility.Accessible; 42 43 final class WinApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter { 44 45 private static native void initIDs(); 46 static { 47 // This loading of msvcr100.dll (VS2010) is required when run with Java 6 48 // since it was build with VS2003 and doesn't include msvcr100.dll in it's JRE. 49 // Note: See README-builds.html on MSVC requirement: VS2010 is required. 50 AccessController.doPrivileged(new PrivilegedAction<Void>() { 51 public Void run() { 52 verbose = Boolean.getBoolean("javafx.verbose"); 53 try { 54 NativeLibLoader.loadLibrary("msvcr100"); 55 } catch (Throwable t) { 56 if (verbose) { 57 System.err.println("Error: failed to load msvcr100.dll : " + t); 58 } 59 } 60 Application.loadNativeLibrary(); 61 return null; 62 } 63 }); 64 initIDs(); 65 } 66 67 private final InvokeLaterDispatcher invokeLaterDispatcher; 68 WinApplication() { 69 boolean isEventThread = AccessController 70 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread")); 71 if (!isEventThread) { 72 invokeLaterDispatcher = new InvokeLaterDispatcher(this); 73 invokeLaterDispatcher.start(); 74 } else { 75 invokeLaterDispatcher = null; 76 } 77 } 78 79 private static boolean verbose; 80 81 // returng toolkit window HWND 82 private native long _init(); 83 private native void _setClassLoader(ClassLoader classLoader); 84 private native void _runLoop(Runnable launchable); 85 private native void _terminateLoop(); 86 87 @Override 88 protected void runLoop(final Runnable launchable) { 89 boolean isEventThread = AccessController 90 .doPrivileged((PrivilegedAction<Boolean>) () -> Boolean.getBoolean("javafx.embed.isEventThread")); 91 92 ClassLoader classLoader = WinApplication.class.getClassLoader(); 93 _setClassLoader(classLoader); 94 95 if (isEventThread) { 96 _init(); 97 setEventThread(Thread.currentThread()); 98 launchable.run(); 99 return; 100 } 101 final Thread toolkitThread = 102 AccessController.doPrivileged((PrivilegedAction<Thread>) () -> new Thread(() -> { 103 _init(); 104 _runLoop(launchable); 105 }, "WindowsNativeRunloopThread")); 106 setEventThread(toolkitThread); 107 toolkitThread.start(); 108 } 109 110 @Override protected void finishTerminating() { 111 final Thread toolkitThread = getEventThread(); 112 if (toolkitThread != null) { 113 _terminateLoop(); 114 setEventThread(null); 115 } 116 super.finishTerminating(); 117 } 118 119 @Override public boolean shouldUpdateWindow() { 120 return true; 121 } 122 123 native private Object _enterNestedEventLoopImpl(); 124 native private void _leaveNestedEventLoopImpl(Object retValue); 125 126 @Override protected Object _enterNestedEventLoop() { 127 if (invokeLaterDispatcher != null) { 128 invokeLaterDispatcher.notifyEnteringNestedEventLoop(); 129 } 130 try { 131 return _enterNestedEventLoopImpl(); 132 } finally { 133 if (invokeLaterDispatcher != null) { 134 invokeLaterDispatcher.notifyLeftNestedEventLoop(); 135 } 136 } 137 } 138 139 @Override protected void _leaveNestedEventLoop(Object retValue) { 140 if (invokeLaterDispatcher != null) { 141 invokeLaterDispatcher.notifyLeavingNestedEventLoop(); 142 } 143 _leaveNestedEventLoopImpl(retValue); 144 } 145 146 // FACTORY METHODS 147 148 @Override public Window createWindow(Window owner, Screen screen, int styleMask) { 149 return new WinWindow(owner, screen, styleMask); 150 } 151 152 @Override public Window createWindow(long parent) { 153 return new WinChildWindow(parent); 154 } 155 156 @Override public View createView() { 157 return new WinView(); 158 } 159 160 @Override public Cursor createCursor(int type) { 161 return new WinCursor(type); 162 } 163 164 @Override public Cursor createCursor(int x, int y, Pixels pixels) { 165 return new WinCursor(x, y, pixels); 166 } 167 168 @Override protected void staticCursor_setVisible(boolean visible) { 169 WinCursor.setVisible_impl(visible); 170 } 171 172 @Override protected Size staticCursor_getBestSize(int width, int height) { 173 return WinCursor.getBestSize_impl(width, height); 174 } 175 176 @Override public Pixels createPixels(int width, int height, ByteBuffer data) { 177 return new WinPixels(width, height, data); 178 } 179 180 @Override public Pixels createPixels(int width, int height, IntBuffer data) { 181 return new WinPixels(width, height, data); 182 } 183 184 @Override 185 public Pixels createPixels(int width, int height, IntBuffer data, float scale) { 186 return new WinPixels(width, height, data, scale); 187 } 188 189 @Override protected int staticPixels_getNativeFormat() { 190 return WinPixels.getNativeFormat_impl(); 191 } 192 193 @Override public Robot createRobot() { 194 return new WinRobot(); 195 } 196 197 @Override protected double staticScreen_getVideoRefreshPeriod() { 198 return 0.0; // indicate millisecond resolution 199 } 200 201 @Override native protected Screen[] staticScreen_getScreens(); 202 203 @Override public Timer createTimer(Runnable runnable) { 204 return new WinTimer(runnable); 205 } 206 207 @Override protected int staticTimer_getMinPeriod() { 208 return WinTimer.getMinPeriod_impl(); 209 } 210 211 @Override protected int staticTimer_getMaxPeriod() { 212 return WinTimer.getMaxPeriod_impl(); 213 } 214 215 @Override public PlatformAccessible createAccessible(Accessible accessible) { 216 return WinAccessible.createAccessible(accessible); 217 } 218 219 @Override protected FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type, 220 boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex) { 221 if (invokeLaterDispatcher != null) { 222 invokeLaterDispatcher.notifyEnteringNestedEventLoop(); 223 } 224 return WinCommonDialogs.showFileChooser_impl(owner, folder, filename, title, type, multipleMode, extensionFilters, defaultFilterIndex); 225 } 226 227 @Override protected File staticCommonDialogs_showFolderChooser(Window owner, String folder, String title) { 228 if (invokeLaterDispatcher != null) { 229 invokeLaterDispatcher.notifyEnteringNestedEventLoop(); 230 } 231 return WinCommonDialogs.showFolderChooser_impl(owner, folder, title); 232 } 233 234 @Override protected long staticView_getMultiClickTime() { 235 return WinView.getMultiClickTime_impl(); 236 } 237 238 @Override protected int staticView_getMultiClickMaxX() { 239 return WinView.getMultiClickMaxX_impl(); 240 } 241 242 @Override protected int staticView_getMultiClickMaxY() { 243 return WinView.getMultiClickMaxY_impl(); 244 } 245 246 @Override native protected void _invokeAndWait(Runnable runnable); 247 248 native private void _submitForLaterInvocation(Runnable r); 249 // InvokeLaterDispatcher.InvokeLaterSubmitter 250 @Override public void submitForLaterInvocation(Runnable r) { 251 _submitForLaterInvocation(r); 252 } 253 254 @Override protected void _invokeLater(Runnable runnable) { 255 if (invokeLaterDispatcher != null) { 256 invokeLaterDispatcher.invokeLater(runnable); 257 } else { 258 submitForLaterInvocation(runnable); 259 } 260 } 261 262 protected boolean notifyThemeChanged(String themeName) { 263 return PlatformImpl.setAccessibilityTheme(themeName); 264 } 265 266 private native String _getHighContrastTheme(); 267 @Override public String getHighContrastTheme() { 268 return _getHighContrastTheme(); 269 } 270 271 @Override 272 protected boolean _supportsInputMethods() { 273 return true; 274 } 275 276 @Override 277 protected boolean _supportsTransparentWindows() { 278 return true; 279 } 280 281 @Override native protected boolean _supportsUnifiedWindows(); 282 283 public String getDataDirectory() { 284 checkEventThread(); 285 String baseDirectory = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getenv("APPDATA")); 286 if (baseDirectory == null || baseDirectory.length() == 0) { 287 return super.getDataDirectory(); 288 } 289 return baseDirectory + File.separator + name + File.separator; 290 } 291 }