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