PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/machinepublishers/glass/ui/monocle/MonocleApplication.java

https://gitlab.com/hemp85/jBrowserDriver
Java | 433 lines | 332 code | 50 blank | 51 comment | 23 complexity | 8efb2eae1d36eeaad468cb87dcab4fff MD5 | raw file
  1. /*
  2. * Copyright (c) 2010, 2016, 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.machinepublishers.glass.ui.monocle;
  26. import java.io.File;
  27. import java.lang.reflect.Constructor;
  28. import java.nio.ByteBuffer;
  29. import java.nio.IntBuffer;
  30. import java.security.AccessController;
  31. import java.security.PrivilegedAction;
  32. import java.util.Arrays;
  33. import java.util.concurrent.atomic.AtomicBoolean;
  34. import com.sun.glass.ui.Application;
  35. import com.sun.glass.ui.CommonDialogs.ExtensionFilter;
  36. import com.sun.glass.ui.CommonDialogs.FileChooserResult;
  37. import com.sun.glass.ui.Cursor;
  38. import com.sun.glass.ui.Pixels;
  39. import com.sun.glass.ui.Robot;
  40. import com.sun.glass.ui.Screen;
  41. import com.sun.glass.ui.Size;
  42. import com.sun.glass.ui.Timer;
  43. import com.sun.glass.ui.View;
  44. import com.sun.glass.ui.Window;
  45. import javafx.scene.control.TextInputDialog;
  46. public final class MonocleApplication extends Application {
  47. private final NativePlatform platform = NativePlatformFactory.getNativePlatform();
  48. private final RunnableProcessor runnableProcessor = platform.getRunnableProcessor();
  49. /** Bit to indicate that a device has touch support */
  50. private static final int DEVICE_TOUCH = 0;
  51. /** Bit to indicate that a device has multitouch support */
  52. private static final int DEVICE_MULTITOUCH = 1;
  53. /** Bit to indicate that a device has relative motion pointer support */
  54. private static final int DEVICE_POINTER = 2;
  55. /** Bit to indicate that a device has arrow keys and a select key */
  56. private static final int DEVICE_5WAY = 3;
  57. /** Bit to indicate that a device has a full PC keyboard */
  58. private static final int DEVICE_PC_KEYBOARD = 4;
  59. /** Largest bit used in device capability bitmasks */
  60. private static final int DEVICE_MAX = 4;
  61. /** A running count of the numbers of devices with each device capability */
  62. private int[] deviceFlags = new int[DEVICE_MAX + 1];
  63. private Thread shutdownHookThread;
  64. private Runnable renderEndNotifier = () -> platform.getScreen().swapBuffers();
  65. MonocleApplication() {
  66. // for (InputDevice device : platform.getInputDeviceRegistry().getInputDevices()) {
  67. // updateDeviceFlags(device, true);
  68. // }
  69. // platform.getInputDeviceRegistry().getInputDevices().addListener(
  70. // (SetChangeListener<InputDevice>) change -> {
  71. // if (change.wasAdded()) {
  72. // InputDevice device = change.getElementAdded();
  73. // updateDeviceFlags(device, true);
  74. // } else if (change.wasRemoved()) {
  75. // InputDevice device = change.getElementRemoved();
  76. // updateDeviceFlags(device, false);
  77. // }
  78. // });
  79. }
  80. private void updateDeviceFlags(InputDevice device, boolean added) {
  81. int modifier = added ? 1 : -1;
  82. if (device.isTouch()) {
  83. deviceFlags[DEVICE_TOUCH] += modifier;
  84. }
  85. if (device.isMultiTouch()) {
  86. deviceFlags[DEVICE_MULTITOUCH] += modifier;
  87. }
  88. if (device.isRelative()) {
  89. deviceFlags[DEVICE_POINTER] += modifier;
  90. if (deviceFlags[DEVICE_POINTER] >= 1 && added) {
  91. staticCursor_setVisible(true);
  92. } else if (deviceFlags[DEVICE_POINTER] < 1 && !added) {
  93. staticCursor_setVisible(false);
  94. }
  95. }
  96. if (device.isFullKeyboard()) {
  97. deviceFlags[DEVICE_PC_KEYBOARD] += modifier;
  98. }
  99. if (device.is5Way()) {
  100. deviceFlags[DEVICE_5WAY] += modifier;
  101. }
  102. }
  103. @Override
  104. protected void runLoop(Runnable launchable) {
  105. runnableProcessor.invokeLater(launchable);
  106. long stackSize = AccessController.doPrivileged(
  107. (PrivilegedAction<Long>) () -> Long.getLong("monocle.stackSize", 0));
  108. Thread t = new Thread(
  109. new ThreadGroup("Event"),
  110. runnableProcessor,
  111. "Event Thread",
  112. stackSize);
  113. setEventThread(t);
  114. t.start();
  115. shutdownHookThread = new Thread("Monocle shutdown hook") {
  116. @Override
  117. public void run() {
  118. platform.shutdown();
  119. }
  120. };
  121. Runtime.getRuntime().addShutdownHook(shutdownHookThread);
  122. }
  123. @Override
  124. protected void _invokeAndWait(Runnable runnable) {
  125. runnableProcessor.invokeAndWait(runnable);
  126. }
  127. @Override
  128. protected void _invokeLater(Runnable runnable) {
  129. runnableProcessor.invokeLater(runnable);
  130. }
  131. @Override
  132. protected Object _enterNestedEventLoop() {
  133. return runnableProcessor.enterNestedEventLoop();
  134. }
  135. @Override
  136. protected void _leaveNestedEventLoop(Object retValue) {
  137. runnableProcessor.leaveNestedEventLoop(retValue);
  138. }
  139. @Override
  140. public Window createWindow(Window owner, Screen screen, int styleMask) {
  141. return new MonocleWindow(owner, screen, styleMask);
  142. }
  143. @Override
  144. public Window createWindow(long parent) {
  145. return new MonocleWindow(parent);
  146. }
  147. @Override
  148. public View createView() {
  149. return new MonocleView();
  150. }
  151. @Override
  152. public Cursor createCursor(int type) {
  153. return new MonocleCursor(type);
  154. }
  155. @Override
  156. public Cursor createCursor(int x, int y, Pixels pixels) {
  157. return new MonocleCursor(x, y, pixels);
  158. }
  159. @Override
  160. protected void staticCursor_setVisible(boolean visible) {
  161. NativeCursor cursor = NativePlatformFactory.getNativePlatform().getCursor();
  162. cursor.setVisibility(deviceFlags[DEVICE_POINTER] >= 1 ? visible : false);
  163. }
  164. @Override
  165. protected Size staticCursor_getBestSize(int width, int height) {
  166. NativeCursor cursor = NativePlatformFactory.getNativePlatform().getCursor();
  167. return cursor.getBestSize();
  168. }
  169. @Override
  170. public Pixels createPixels(int width, int height, ByteBuffer data) {
  171. return new MonoclePixels(width, height, data);
  172. }
  173. @Override
  174. public Pixels createPixels(int width, int height, IntBuffer data) {
  175. return new MonoclePixels(width, height, data);
  176. }
  177. // @Override
  178. public Pixels createPixels(int width, int height, IntBuffer data,
  179. float scalex, float scaley) {
  180. return new MonoclePixels(width, height, data);//Java 8 and Java 9 constructors conflict--work around: use a constructor they both have
  181. }
  182. // @Override
  183. public Pixels createPixels(int width, int height, IntBuffer data, float scale) {
  184. return new MonoclePixels(width, height, data);//Java 8 and Java 9 constructors conflict--work around: use a constructor they both have
  185. }
  186. @Override
  187. protected int staticPixels_getNativeFormat() {
  188. return platform.getScreen().getNativeFormat();
  189. }
  190. @Override
  191. public Robot createRobot() {
  192. return new MonocleRobot();
  193. }
  194. @Override
  195. protected double staticScreen_getVideoRefreshPeriod() {
  196. return 0.0;
  197. }
  198. @Override
  199. protected Screen[] staticScreen_getScreens() {
  200. Screen screen = null;
  201. try {
  202. NativeScreen ns = platform.getScreen();
  203. final AtomicBoolean java9 = new AtomicBoolean();
  204. Constructor c = AccessController.doPrivileged(
  205. new PrivilegedAction<Constructor>() {
  206. @Override
  207. public Constructor run() {
  208. try {
  209. Constructor c = Screen.class.getDeclaredConstructor(
  210. Long.TYPE,
  211. Integer.TYPE,
  212. Integer.TYPE, Integer.TYPE,
  213. Integer.TYPE, Integer.TYPE,
  214. Integer.TYPE, Integer.TYPE,
  215. Integer.TYPE, Integer.TYPE,
  216. Integer.TYPE, Integer.TYPE, Float.TYPE);
  217. c.setAccessible(true);
  218. return c;
  219. } catch (Exception e) {
  220. try {
  221. Constructor c = Screen.class.getDeclaredConstructor(
  222. Long.TYPE,
  223. Integer.TYPE,
  224. Integer.TYPE, Integer.TYPE,
  225. Integer.TYPE, Integer.TYPE,
  226. Integer.TYPE, Integer.TYPE,
  227. Integer.TYPE, Integer.TYPE,
  228. Integer.TYPE, Integer.TYPE,
  229. Integer.TYPE, Integer.TYPE,
  230. Integer.TYPE, Integer.TYPE,
  231. Float.TYPE, Float.TYPE,
  232. Float.TYPE, Float.TYPE);
  233. c.setAccessible(true);
  234. java9.set(true);
  235. return c;
  236. } catch (Exception e2) {
  237. e2.printStackTrace();
  238. return null;
  239. }
  240. }
  241. }
  242. });
  243. if (c != null) {
  244. if (java9.get()) {
  245. screen = (Screen) c.newInstance(1l, // dummy native pointer;
  246. ns.getDepth(),
  247. 0, 0, ns.getWidth(), ns.getHeight(),
  248. 0, 0, ns.getWidth(), ns.getHeight(),
  249. 0, 0, ns.getWidth(), ns.getHeight(),
  250. ns.getDPI(), ns.getDPI(),
  251. ns.getScale(), ns.getScale(),
  252. ns.getScale(), ns.getScale());
  253. // Move the cursor to the middle of the screen
  254. MouseState mouseState = new MouseState();
  255. mouseState.setX(ns.getWidth() / 2);
  256. mouseState.setY(ns.getHeight() / 2);
  257. MouseInput.getInstance().setState(mouseState, false);
  258. } else {
  259. screen = (Screen) c.newInstance(
  260. 1l, // dummy native pointer;
  261. ns.getDepth(),
  262. 0, 0, ns.getWidth(), ns.getHeight(),
  263. 0, 0, ns.getWidth(), ns.getHeight(),
  264. ns.getDPI(), ns.getDPI(),
  265. ns.getScale());
  266. // Move the cursor to the middle of the screen
  267. MouseState mouseState = new MouseState();
  268. mouseState.setX(ns.getWidth() / 2);
  269. mouseState.setY(ns.getHeight() / 2);
  270. MouseInput.getInstance().setState(mouseState, false);
  271. }
  272. }
  273. } catch (Throwable t) {
  274. t.printStackTrace();
  275. }
  276. return new Screen[] { screen };
  277. }
  278. @Override
  279. public Timer createTimer(Runnable runnable) {
  280. return new MonocleTimer(runnable);
  281. }
  282. @Override
  283. protected int staticTimer_getMinPeriod() {
  284. return MonocleTimer.getMinPeriod_impl();
  285. }
  286. @Override
  287. protected int staticTimer_getMaxPeriod() {
  288. return MonocleTimer.getMaxPeriod_impl();
  289. }
  290. public boolean hasWindowManager() {
  291. return false;
  292. }
  293. @Override
  294. protected FileChooserResult staticCommonDialogs_showFileChooser(
  295. Window owner, String folder, String filename, String title,
  296. int type, boolean multipleMode,
  297. ExtensionFilter[] extensionFilters,
  298. int defaultFilterIndex) {
  299. TextInputDialog dialog = new TextInputDialog();
  300. dialog.showAndWait();
  301. File[] files;
  302. String filePaths = dialog.getEditor().getText();
  303. if (filePaths != null && !filePaths.isEmpty()) {
  304. String[] filePathParts = filePaths.split(":");
  305. files = new File[filePathParts.length];
  306. for (int i = 0; i < filePathParts.length; i++) {
  307. files[i] = new File(filePathParts[i]);
  308. }
  309. } else {
  310. files = new File[0];
  311. }
  312. return new FileChooserResult(Arrays.asList(files), null);
  313. }
  314. @Override
  315. protected File staticCommonDialogs_showFolderChooser(Window owner,
  316. String folder,
  317. String title) {
  318. Thread.dumpStack();
  319. throw new UnsupportedOperationException();
  320. }
  321. @Override
  322. protected long staticView_getMultiClickTime() {
  323. return MonocleView._getMultiClickTime();
  324. }
  325. @Override
  326. protected int staticView_getMultiClickMaxX() {
  327. return MonocleView._getMultiClickMaxX();
  328. }
  329. @Override
  330. protected int staticView_getMultiClickMaxY() {
  331. return MonocleView._getMultiClickMaxY();
  332. }
  333. @Override
  334. protected boolean _supportsTransparentWindows() {
  335. return true;
  336. }
  337. @Override
  338. protected boolean _supportsUnifiedWindows() {
  339. return false;
  340. }
  341. @Override
  342. public boolean hasTwoLevelFocus() {
  343. return deviceFlags[DEVICE_PC_KEYBOARD] == 0 && deviceFlags[DEVICE_5WAY] > 0;
  344. }
  345. @Override
  346. public boolean hasVirtualKeyboard() {
  347. return deviceFlags[DEVICE_PC_KEYBOARD] == 0 && deviceFlags[DEVICE_TOUCH] > 0;
  348. }
  349. @Override
  350. public boolean hasTouch() {
  351. return deviceFlags[DEVICE_TOUCH] > 0;
  352. }
  353. @Override
  354. public boolean hasMultiTouch() {
  355. return deviceFlags[DEVICE_MULTITOUCH] > 0;
  356. }
  357. @Override
  358. public boolean hasPointer() {
  359. return deviceFlags[DEVICE_POINTER] > 0;
  360. }
  361. //@Override
  362. public void notifyRenderingFinished() {
  363. invokeLater(renderEndNotifier);
  364. }
  365. @Override
  366. protected void finishTerminating() {
  367. //if this method is getting called, we don't need the shutdown hook
  368. Runtime.getRuntime().removeShutdownHook(shutdownHookThread);
  369. setEventThread(null);
  370. platform.shutdown();
  371. super.finishTerminating();
  372. }
  373. void enterDnDEventLoop() {
  374. _enterNestedEventLoop();
  375. }
  376. void leaveDndEventLoop() {
  377. _leaveNestedEventLoop(null);
  378. }
  379. //@Override
  380. protected int _getKeyCodeForChar(char c) {
  381. return KeyInput.getInstance().getKeyCodeForChar(c);
  382. }
  383. }