-
Notifications
You must be signed in to change notification settings - Fork 579
Expand file tree
/
Copy pathApplication.java
More file actions
878 lines (764 loc) · 30.6 KB
/
Application.java
File metadata and controls
878 lines (764 loc) · 30.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
/*
* Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.glass.ui;
import com.sun.glass.events.KeyEvent;
import com.sun.glass.ui.CommonDialogs.ExtensionFilter;
import com.sun.glass.ui.CommonDialogs.FileChooserResult;
import com.sun.javafx.application.preferences.PreferenceMapping;
import com.sun.javafx.stage.PlatformStageBackdrop;
import javafx.stage.StageBackdrop;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.LinkedList;
import java.util.Optional;
import java.util.function.Supplier;
public abstract class Application {
private final static String DEFAULT_NAME = "java";
protected String name = DEFAULT_NAME;
public static class EventHandler {
// currently used only on Mac OS X
public void handleWillFinishLaunchingAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleDidFinishLaunchingAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleWillBecomeActiveAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleDidBecomeActiveAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleWillResignActiveAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleDidResignActiveAction(Application app, long time) {
}
// currently used only on iOS
public void handleDidReceiveMemoryWarning(Application app, long time) {
}
// currently used only on Mac OS X
public void handleWillHideAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleDidHideAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleWillUnhideAction(Application app, long time) {
}
// currently used only on Mac OS X
public void handleDidUnhideAction(Application app, long time) {
}
// currently used only on Mac OS X
// the open files which started up the app will arrive before app becomes active
public void handleOpenFilesAction(Application app, long time, String files[]) {
}
// currently used only on Mac OS X
public void handleQuitAction(Application app, long time) {
}
public void handlePreferencesChanged(Map<String, Object> preferences) {
}
}
private EventHandler eventHandler;
private boolean initialActiveEventReceived = false;
private String initialOpenedFiles[] = null;
private static boolean loaded = false;
private static Application application;
private static Thread eventThread;
private static final boolean disableThreadChecks = ((Supplier<Boolean>) () -> {
final String str =
System.getProperty("glass.disableThreadChecks", "false");
return "true".equalsIgnoreCase(str);
}).get();
// May be called on any thread.
protected static synchronized void loadNativeLibrary(final String libname) {
// load the native library of the specified libname.
// the platform default by convention is "glass", all others should have a suffix, ie glass-x11
if (!loaded) {
com.sun.glass.utils.NativeLibLoader.loadLibrary(libname);
loaded = true;
}
}
// May be called on any thread.
protected static synchronized void loadNativeLibrary() {
// use the "platform default" name of "glass"
loadNativeLibrary("glass");
}
private static volatile Map deviceDetails = null;
// provides a means for the user to pass platorm specific details
// to the native glass impl. Can be null.
// May need be called before Run.
// May be called on any thread.
public static void setDeviceDetails(Map details) {
deviceDetails = details;
}
// May be called on any thread.
public static Map getDeviceDetails() {
return deviceDetails;
}
protected Application() {
}
// May be called on any thread.
public static void run(final Runnable launchable) {
if (application != null) {
throw new IllegalStateException("Application is already running");
}
application = PlatformFactory.getPlatformFactory().createApplication();
// each concrete Application should set the app name using its own platform mechanism:
// on Mac OS X - use NSBundle info, which can be overriden by -Xdock:name
// on Windows - TODO
// on Linux - TODO
//application.name = DEFAULT_NAME; // default
try {
application.runLoop(() -> {
Screen.initScreens();
launchable.run();
});
} catch (Throwable t) {
t.printStackTrace();
}
}
// runLoop never exits until app terminates
protected abstract void runLoop(Runnable launchable);
// should return after loop termination completion
protected void finishTerminating() {
// To make sure application object is not used outside of the run loop
application = null;
// The eventThread is null at this point, no need to check it
}
/**
* Gets the name for the application. The application name may
* be used to identify the application in the user interface or
* as part of the platform specific path used to store application
* data.
*
* This is a hint and may not be used on some platforms.
*
* @return the application name
*/
public String getName() {
checkEventThread();
return name;
}
/**
* Sets the name for the application. The application name may
* be used to identify the application in the user interface or
* as part of the platform specific path used to store application
* data.
*
* The name could be set only once. All subsequent calls are ignored.
*
* This is a hint and may not be used on some platforms.
*
* @param name the new application name
*/
public void setName(String name) {
checkEventThread();
if (name != null && DEFAULT_NAME.equals(this.name)) {
this.name = name;
}
}
/**
* Gets a platform specific path that can be used to store
* application data. The application name typically appears
* as part of the path.
*
* On some platforms, the path may not yet exist and the caller
* will need to create it.
*
* @return the platform specific path for the application data
*/
public String getDataDirectory() {
checkEventThread();
String userHome = System.getProperty("user.home");
return userHome + File.separator + "." + name + File.separator;
}
// Subclasses can override the following notify methods.
// Overridden methods need to call super.
protected void notifyWillFinishLaunching() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleWillFinishLaunchingAction(this, System.nanoTime());
}
}
protected void notifyDidFinishLaunching() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidFinishLaunchingAction(this, System.nanoTime());
}
}
protected void notifyWillBecomeActive() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleWillBecomeActiveAction(this, System.nanoTime());
}
}
protected void notifyDidBecomeActive() {
this.initialActiveEventReceived = true;
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidBecomeActiveAction(this, System.nanoTime());
}
}
protected void notifyWillResignActive() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleWillResignActiveAction(this, System.nanoTime());
}
}
protected void notifyPreferencesChanged(Map<String, Object> preferences) {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handlePreferencesChanged(preferences);
}
}
protected void notifyDidResignActive() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidResignActiveAction(this, System.nanoTime());
}
}
protected void notifyDidReceiveMemoryWarning() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidReceiveMemoryWarning(this, System.nanoTime());
}
}
protected void notifyWillHide() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleWillHideAction(this, System.nanoTime());
}
}
protected void notifyDidHide() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidHideAction(this, System.nanoTime());
}
}
protected void notifyWillUnhide() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleWillUnhideAction(this, System.nanoTime());
}
}
protected void notifyDidUnhide() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleDidUnhideAction(this, System.nanoTime());
}
}
// notificiation when user drag and drops files onto app icon
protected void notifyOpenFiles(String files[]) {
if ((this.initialActiveEventReceived == false) && (this.initialOpenedFiles == null)) {
// rememeber the initial opened files
this.initialOpenedFiles = files;
}
EventHandler handler = getEventHandler();
if ((handler != null) && (files != null)) {
handler.handleOpenFilesAction(this, System.nanoTime(), files);
}
}
protected void notifyWillQuit() {
EventHandler handler = getEventHandler();
if (handler != null) {
handler.handleQuitAction(this, System.nanoTime());
}
}
/**
* Install app's default native menus:
* on Mac OS X - Apple menu (showing the app name) with a single Quit menu item
* on Windows - NOP
* on Linux - NOP
*/
public void installDefaultMenus(MenuBar menubar) {
checkEventThread();
// To override in subclasses
}
public EventHandler getEventHandler() {
//checkEventThread(); // Glass (Mac)
// When an app is closing, Mac calls notify- Will/DidHide, Will/DidResignActive
// on a thread other than the Main thread
return eventHandler;
}
public void setEventHandler(EventHandler eventHandler) {
checkEventThread();
boolean resendOpenFiles = ((this.eventHandler != null) && (this.initialOpenedFiles != null));
this.eventHandler = eventHandler;
if (resendOpenFiles == true) {
// notify the new event handler with initial opened files
notifyOpenFiles(this.initialOpenedFiles);
}
}
private boolean terminateWhenLastWindowClosed = true;
public final boolean shouldTerminateWhenLastWindowClosed() {
checkEventThread();
return terminateWhenLastWindowClosed;
}
public final void setTerminateWhenLastWindowClosed(boolean b) {
checkEventThread();
terminateWhenLastWindowClosed = b;
}
public boolean shouldUpdateWindow() {
checkEventThread();
return false; // overridden in platform application class
}
public boolean hasWindowManager() {
//checkEventThread(); // Prism (Mac)
return true; // overridden in platform application class
}
/**
* Notifies the Application that rendering has completed for current pulse.
*
* This is called on the render thread.
*/
public void notifyRenderingFinished() {
}
public void terminate() {
checkEventThread();
try {
final List<Window> windows = new LinkedList<>(Window.getWindows());
for (Window window : windows) {
// first make windows invisible
window.setVisible(false);
}
for (Window window : windows) {
// now we can close windows
window.close();
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
finishTerminating();
}
}
// May be called on any thread
static public Application GetApplication() {
return Application.application;
}
// May be called on any thread
protected static void setEventThread(Thread thread) {
Application.eventThread = thread;
}
// May be called on any thread
protected static Thread getEventThread() {
return Application.eventThread;
}
/**
* Returns {@code true} if the current thread is the event thread.
*/
public static boolean isEventThread() {
return Thread.currentThread() == Application.eventThread;
}
/**
* Verifies that the current thread is the event thread, and throws
* an exception if this is not so.
*
* The check can be disabled by setting the "glass.disableThreadChecks"
* system property. It is preferred, however, to fix the application code
* instead.
*
* @throws IllegalStateException if the current thread is not the event thread
*/
public static void checkEventThread() {
//TODO: we do NOT advertise the "glass.disableThreadChecks".
// If we never get a complaint about this check, we can consider
// dropping the system property and perform the check unconditionally
if (!disableThreadChecks &&
Thread.currentThread() != Application.eventThread)
{
throw new IllegalStateException(
"This operation is permitted on the event thread only; currentThread = "
+ Thread.currentThread().getName());
}
}
// Called from native, when a JNI exception has occurred
public static void reportException(Throwable t) {
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler handler =
currentThread.getUncaughtExceptionHandler();
handler.uncaughtException(currentThread, t);
}
abstract protected void _invokeAndWait(java.lang.Runnable runnable);
/**
* Block the current thread and wait until the given runnable finishes
* running on the native event loop thread.
*/
public static void invokeAndWait(java.lang.Runnable runnable) {
if (runnable == null) {
return;
}
if (isEventThread()) {
runnable.run();
} else {
GetApplication()._invokeAndWait(runnable);
}
}
abstract protected void _invokeLater(java.lang.Runnable runnable);
/**
* Schedule the given runnable to run on the native event loop thread
* some time in the future, and return immediately.
*/
public static void invokeLater(java.lang.Runnable runnable) {
if (runnable == null) {
return;
}
GetApplication()._invokeLater(runnable);
}
protected abstract Object _enterNestedEventLoop();
protected abstract void _leaveNestedEventLoop(Object retValue);
private static int nestedEventLoopCounter = 0;
/**
* Starts a nested event loop.
*
* Calling this method temporarily blocks processing of the current event,
* and starts a nested event loop to handle other native events. To
* proceed with the blocked execution path, the application should call the
* {@link #leaveNestedEventLoop(Object)} method.
*
* Note that this method may only be invoked on the main (event handling)
* thread.
*
* An application may enter several nested loops recursively. There's no
* limit of recursion other than that imposed by the native stack size.
*
* @return an object passed to the leaveNestedEventLoop() method
* @throws RuntimeException if the current thread is not the main thread
*/
static Object enterNestedEventLoop() {
checkEventThread();
nestedEventLoopCounter++;
try {
return GetApplication()._enterNestedEventLoop();
} finally {
nestedEventLoopCounter--;
}
}
/**
* Terminates the current nested event loop.
*
* After calling this method and returning from the current event handler,
* the execusion returns to the point where the {@link #enterNestedEventLoop}
* was called previously. You may specify a return value for the
* enterNestedEventLoop() method by passing the argument {@code retValue} to
* the leaveNestedEventLoop().
*
* Note that this method may only be invoked on the main (event handling)
* thread.
*
* @throws RuntimeException if the current thread is not the main thread
* @throws IllegalStateException if the application hasn't started a nested
* event loop
*/
static void leaveNestedEventLoop(Object retValue) {
checkEventThread();
if (nestedEventLoopCounter == 0) {
throw new IllegalStateException("Not in a nested event loop");
}
GetApplication()._leaveNestedEventLoop(retValue);
}
public static boolean isNestedLoopRunning() {
checkEventThread();
return nestedEventLoopCounter > 0;
}
//TODO: move to the EventHandler
public void menuAboutAction() {
System.err.println("about");
}
// FACTORY METHODS
/**
* Create a window.
*
* The styleMask argument is a bitmask of window styles as defined in the
* Window class. Note, however, that visual kinds (UNTITLED, TITLED,
* or TRANSPARENT) can't be combined together. Also, functional types
* (NORMAL, POPUP, or UTILITY) can't be combined together. A window is
* allowed to be of exactly one visual kind, and exactly one functional
* type.
*/
public abstract Window createWindow(Window owner, Screen screen, int styleMask, int backdropID);
/**
* Create a window with no backdrop.
*/
public final Window createWindow(Window owner, Screen screen, int styleMask) {
return createWindow(owner, screen, styleMask, Window.NO_BACKDROP_ID);
}
/**
* Create a window.
*
* The styleMask argument is a bitmask of window styles as defined in the
* Window class. Note, however, that visual kinds (UNTITLED, TITLED,
* or TRANSPARENT) can't be combined together. Also, functional types
* (NORMAL, POPUP, or UTILITY) can't be combined together. A window is
* allowed to be of exactly one visual kind, and exactly one functional
* type.
*/
public final Window createWindow(Screen screen, int styleMask) {
return createWindow(null, screen, styleMask, Window.NO_BACKDROP_ID);
}
public abstract View createView();
public abstract Cursor createCursor(int type);
public abstract Cursor createCursor(int x, int y, Pixels pixels);
protected abstract void staticCursor_setVisible(boolean visible);
protected abstract Size staticCursor_getBestSize(int width, int height);
public final Menu createMenu(String title) {
return new Menu(title);
}
public final Menu createMenu(String title, boolean enabled) {
return new Menu(title, enabled);
}
public final MenuBar createMenuBar() {
return new MenuBar();
}
public final MenuItem createMenuItem(String title) {
return createMenuItem(title, null);
}
public final MenuItem createMenuItem(String title, MenuItem.Callback callback) {
return createMenuItem(title, callback, KeyEvent.VK_UNDEFINED, KeyEvent.MODIFIER_NONE);
}
public final MenuItem createMenuItem(String title, MenuItem.Callback callback,
int shortcutKey, int shortcutModifiers) {
return createMenuItem(title, callback, shortcutKey, shortcutModifiers, null);
}
public final MenuItem createMenuItem(String title, MenuItem.Callback callback,
int shortcutKey, int shortcutModifiers, Pixels pixels) {
return new MenuItem(title, callback, shortcutKey, shortcutModifiers, pixels);
}
public abstract Pixels createPixels(int width, int height, ByteBuffer data);
public abstract Pixels createPixels(int width, int height, ByteBuffer data, float scalex, float scaley);
public abstract Pixels createPixels(int width, int height, IntBuffer data);
public abstract Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley);
protected abstract int staticPixels_getNativeFormat();
/* utility method called from native code */
static Pixels createPixels(int width, int height, int[] data, float scalex, float scaley) {
return Application.GetApplication().createPixels(width, height, IntBuffer.wrap(data), scalex, scaley);
}
/* utility method called from native code */
static float getScaleFactor(final int x, final int y, final int w, final int h) {
float scale = 0.0f;
// Find the maximum scale for screens this area overlaps
for (Screen s : Screen.getScreens()) {
final int sx = s.getX(), sy = s.getY(), sw = s.getWidth(), sh = s.getHeight();
if (x < (sx + sw) && (x + w) > sx && y < (sy + sh) && (y + h) > sy) {
if (scale < s.getRecommendedOutputScaleX()) {
scale = s.getRecommendedOutputScaleX();
}
if (scale < s.getRecommendedOutputScaleY()) {
scale = s.getRecommendedOutputScaleY();
}
}
}
return scale == 0.0f ? 1.0f : scale;
}
public abstract GlassRobot createRobot();
protected abstract double staticScreen_getVideoRefreshPeriod();
protected abstract Screen[] staticScreen_getScreens();
public abstract Timer createTimer(Runnable runnable);
protected abstract int staticTimer_getMinPeriod();
protected abstract int staticTimer_getMaxPeriod();
public final EventLoop createEventLoop() {
return new EventLoop();
}
public Accessible createAccessible() { return null; }
protected abstract FileChooserResult staticCommonDialogs_showFileChooser(Window owner, String folder, String filename, String title, int type,
boolean multipleMode, ExtensionFilter[] extensionFilters, int defaultFilterIndex);
protected abstract File staticCommonDialogs_showFolderChooser(Window owner, String folder, String title);
protected abstract long staticView_getMultiClickTime();
protected abstract int staticView_getMultiClickMaxX();
protected abstract int staticView_getMultiClickMaxY();
protected abstract void _showDocument(final String uri);
protected boolean _supportsInputMethods() {
// Overridden in subclasses
return false;
}
public final boolean supportsInputMethods() {
checkEventThread();
return _supportsInputMethods();
}
protected abstract boolean _supportsTransparentWindows();
public final boolean supportsTransparentWindows() {
checkEventThread();
return _supportsTransparentWindows();
}
public boolean hasTwoLevelFocus() {
return false;
}
public boolean hasVirtualKeyboard() {
return false;
}
public boolean hasTouch() {
return false;
}
public boolean hasMultiTouch() {
return false;
}
public boolean hasPointer() {
return true;
}
protected abstract boolean _supportsUnifiedWindows();
public final boolean supportsUnifiedWindows() {
checkEventThread();
return _supportsUnifiedWindows();
}
protected abstract boolean _supportsExtendedWindows();
public final boolean supportsExtendedWindows() {
checkEventThread();
return _supportsExtendedWindows();
}
protected boolean _supportsWindowBackdrops() {
return false;
}
public final boolean supportsWindowBackdrops() {
checkEventThread();
return _supportsWindowBackdrops();
}
protected boolean _supportsSystemMenu() {
// Overridden in subclasses
return false;
}
public final boolean supportsSystemMenu() {
checkEventThread();
return _supportsSystemMenu();
}
protected abstract int _getKeyCodeForChar(char c, int hint);
/**
* Returns a VK_ code of a key capable of producing the given unicode
* character with respect to the currently active keyboard layout or
* VK_UNDEFINED if the character isn't present in the current layout. The
* hint is the VK_ code of the key the system is attempting to match
* (which may be VK_UNDEFINED for a key on the main keyboard). It can be
* used to optimize the search or to distinguish between the main
* keyboard and the numeric keypad.
*
* @param c the character
* @param hint the code of the key the system is attempting to match
* @return integer code for the given char
*/
public static int getKeyCodeForChar(char c, int hint) {
return application._getKeyCodeForChar(c, hint);
}
protected int _isKeyLocked(int keyCode) {
// Overridden in subclasses
return KeyEvent.KEY_LOCK_UNKNOWN;
}
public final Optional<Boolean> isKeyLocked(int keyCode) {
checkEventThread();
int lockState = _isKeyLocked(keyCode);
switch (lockState) {
case KeyEvent.KEY_LOCK_OFF:
return Optional.of(false);
case KeyEvent.KEY_LOCK_ON:
return Optional.of(true);
default:
return Optional.empty();
}
}
/**
* Returns the current set of platform properties as a map of platform-specific keys to
* arbitrary values. This is a snapshot, and won't be updated. There are no guarantees on
* the implementation type, modifiability or serializability of the returned {@code Map}.
*
* @return the current set of platform preferences
*/
public Map<String, Object> getPlatformPreferences() {
return Map.of();
}
/**
* Returns a map of platform-specific keys to platform-independent keys defined by JavaFX, including a
* function that maps the platform-specific value to the platform-independent value.
* <p>
* For example, the platform-specific key "Windows.UIColor.Foreground" is mapped to the key "foregroundColor",
* which makes it easier to write shared code without depending on platform-specific details.
* <p>
* The following platform-independent keys are currently supported, which correspond to the names of
* properties on the {@link com.sun.javafx.application.preferences.PreferenceProperties} class:
* <ul>
* <li>foregroundColor
* <li>backgroundColor
* <li>accentColor
* <li>reducedMotion
* <li>reducedTransparency
* <li>persistentScrollBars
* </ul>
*
* @return a map of platform-specific keys to well-known keys
*/
public Map<String, PreferenceMapping<?, ?>> getPlatformKeyMappings() {
return Map.of();
}
/**
* Returns a mapping of platform-specific keys to the types of their values.
* Polymorphic types are supported by specifying the common base type; for example, a key can
* be mapped to {@code Paint.class} to support any type of paint.
* <p>
* Implementors must keep this map in sync with the mappings reported by the native Glass toolkit.
* If a native toolkit reports mappings for keys that are not contained in this map, the typed getters
* in {@link javafx.application.Platform.Preferences} might not throw {@code IllegalArgumentException}
* as specified.
*
* @return a map of platform-specific keys to types
*/
public Map<String, Class<?>> getPlatformKeys() {
return Map.of();
}
/**
* Checks whether there are any problems with platform preferences detection,
* and if so, emits a warning.
*/
public void checkPlatformPreferencesSupport() {}
private static native void _overrideNativeWindowHandle(Class lwFrameWrapperClass,
Object frame,
long handle, Runnable closeWindow);
public static void overrideNativeWindowHandle(Class lwFrameWrapperClass, Object frame,
long handle, Runnable closeWindow) {
_overrideNativeWindowHandle(lwFrameWrapperClass, frame, handle, closeWindow);
}
public void showDocument(String uri) {
_showDocument(uri);
}
/**
* Return the list of backdrops supported on this platform.
* The default is an empty list.
*/
public List<String> getPlatformBackdropNames() {
return List.of();
}
/**
* Create a Platform backdrop for the specified name
*/
public PlatformStageBackdrop createPlatformBackdrop(String name) {
return null;
}
/**
* Return the platform identifier for the backdrop
*/
public int getBackdropIdentifier(StageBackdrop backdrop) {
return Window.NO_BACKDROP_ID;
}
}