Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java
41153 views
1
/*
2
* Copyright (c) 1997, 2021, 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
26
package sun.awt;
27
28
import java.awt.AWTPermission;
29
import java.awt.DisplayMode;
30
import java.awt.EventQueue;
31
import java.awt.Frame;
32
import java.awt.GraphicsConfiguration;
33
import java.awt.GraphicsDevice;
34
import java.awt.GraphicsEnvironment;
35
import java.awt.Rectangle;
36
import java.awt.Window;
37
import java.awt.event.WindowAdapter;
38
import java.awt.event.WindowEvent;
39
import java.awt.event.WindowListener;
40
import java.awt.image.ColorModel;
41
import java.awt.peer.WindowPeer;
42
import java.util.ArrayList;
43
import java.util.Vector;
44
45
import sun.awt.windows.WWindowPeer;
46
import sun.java2d.SunGraphicsEnvironment;
47
import sun.java2d.opengl.WGLGraphicsConfig;
48
import sun.java2d.windows.WindowsFlags;
49
50
import static sun.awt.Win32GraphicsEnvironment.debugScaleX;
51
import static sun.awt.Win32GraphicsEnvironment.debugScaleY;
52
53
/**
54
* This is an implementation of a GraphicsDevice object for a single
55
* Win32 screen.
56
*
57
* @see GraphicsEnvironment
58
* @see GraphicsConfiguration
59
*/
60
public class Win32GraphicsDevice extends GraphicsDevice implements
61
DisplayChangedListener {
62
int screen;
63
ColorModel dynamicColorModel; // updated with dev changes
64
ColorModel colorModel; // static for device
65
protected GraphicsConfiguration[] configs;
66
protected GraphicsConfiguration defaultConfig;
67
68
private final String idString;
69
protected String descString;
70
// Note that we do not synchronize access to this variable - it doesn't
71
// really matter if a thread does an operation on graphics device which is
72
// about to become invalid (or already become) - we are prepared to deal
73
// with this on the native level.
74
private boolean valid;
75
76
// keep track of top-level windows on this display
77
private SunDisplayChanger topLevels = new SunDisplayChanger();
78
// REMIND: we may disable the use of pixel formats for some accelerated
79
// pipelines which are mutually exclusive with opengl, for which
80
// pixel formats were added in the first place
81
protected static boolean pfDisabled;
82
private static AWTPermission fullScreenExclusivePermission;
83
// the original display mode we had before entering the fullscreen
84
// mode
85
private DisplayMode defaultDisplayMode;
86
// activation/deactivation listener for the full-screen window
87
private WindowListener fsWindowListener;
88
89
private float scaleX;
90
private float scaleY;
91
92
static {
93
94
// 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when
95
// pixel format calls are made. This causes problems when a Java app
96
// is run as an NT service. To prevent the loading of ddraw.dll
97
// completely, sun.awt.nopixfmt should be set as well. Apps which use
98
// OpenGL w/ Java probably don't want to set this.
99
@SuppressWarnings("removal")
100
String nopixfmt = java.security.AccessController.doPrivileged(
101
new sun.security.action.GetPropertyAction("sun.awt.nopixfmt"));
102
pfDisabled = (nopixfmt != null);
103
initIDs();
104
}
105
106
private static native void initIDs();
107
108
native void initDevice(int screen);
109
native void initNativeScale(int screen);
110
native void setNativeScale(int screen, float scaleX, float scaleY);
111
native float getNativeScaleX(int screen);
112
native float getNativeScaleY(int screen);
113
114
public Win32GraphicsDevice(int screennum) {
115
this.screen = screennum;
116
// we cache the strings because we want toString() and getIDstring
117
// to reflect the original screen number (which may change if the
118
// device is removed)
119
idString = "\\Display"+screen;
120
// REMIND: may be should use class name?
121
descString = "Win32GraphicsDevice[screen=" + screen;
122
valid = true;
123
124
initDevice(screennum);
125
initScaleFactors();
126
}
127
128
/**
129
* Returns the type of the graphics device.
130
* @see #TYPE_RASTER_SCREEN
131
* @see #TYPE_PRINTER
132
* @see #TYPE_IMAGE_BUFFER
133
*/
134
@Override
135
public int getType() {
136
return TYPE_RASTER_SCREEN;
137
}
138
139
/**
140
* Returns the Win32 screen of the device.
141
*/
142
public int getScreen() {
143
return screen;
144
}
145
146
public float getDefaultScaleX() {
147
return scaleX;
148
}
149
150
public float getDefaultScaleY() {
151
return scaleY;
152
}
153
154
private void initScaleFactors() {
155
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
156
if (debugScaleX > 0 && debugScaleY > 0) {
157
scaleX = debugScaleX;
158
scaleY = debugScaleY;
159
setNativeScale(screen, scaleX, scaleY);
160
} else {
161
initNativeScale(screen);
162
scaleX = getNativeScaleX(screen);
163
scaleY = getNativeScaleY(screen);
164
}
165
} else {
166
scaleX = 1;
167
scaleY = 1;
168
}
169
}
170
171
/**
172
* Returns whether this is a valid devicie. Device can become
173
* invalid as a result of device removal event.
174
*/
175
public boolean isValid() {
176
return valid;
177
}
178
179
/**
180
* Called from native code when the device was removed.
181
*
182
* @param defaultScreen the current default screen
183
*/
184
protected void invalidate(int defaultScreen) {
185
valid = false;
186
screen = defaultScreen;
187
}
188
189
/**
190
* Returns the identification string associated with this graphics
191
* device.
192
*/
193
@Override
194
public String getIDstring() {
195
return idString;
196
}
197
198
199
/**
200
* Returns all of the graphics
201
* configurations associated with this graphics device.
202
*/
203
@Override
204
public GraphicsConfiguration[] getConfigurations() {
205
if (configs==null) {
206
if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
207
defaultConfig = getDefaultConfiguration();
208
if (defaultConfig != null) {
209
configs = new GraphicsConfiguration[1];
210
configs[0] = defaultConfig;
211
return configs.clone();
212
}
213
}
214
215
int max = getMaxConfigs(screen);
216
int defaultPixID = getDefaultPixID(screen);
217
Vector<GraphicsConfiguration> v = new Vector<>( max );
218
if (defaultPixID == 0) {
219
// Workaround for failing GDI calls
220
defaultConfig = Win32GraphicsConfig.getConfig(this,
221
defaultPixID);
222
v.addElement(defaultConfig);
223
}
224
else {
225
for (int i = 1; i <= max; i++) {
226
if (isPixFmtSupported(i, screen)) {
227
if (i == defaultPixID) {
228
defaultConfig = Win32GraphicsConfig.getConfig(
229
this, i);
230
v.addElement(defaultConfig);
231
}
232
else {
233
v.addElement(Win32GraphicsConfig.getConfig(
234
this, i));
235
}
236
}
237
}
238
}
239
configs = new GraphicsConfiguration[v.size()];
240
v.copyInto(configs);
241
}
242
return configs.clone();
243
}
244
245
/**
246
* Returns the maximum number of graphics configurations available, or 1
247
* if PixelFormat calls fail or are disabled.
248
* This number is less than or equal to the number of graphics
249
* configurations supported.
250
*/
251
protected int getMaxConfigs(int screen) {
252
if (pfDisabled) {
253
return 1;
254
} else {
255
return getMaxConfigsImpl(screen);
256
}
257
}
258
259
private native int getMaxConfigsImpl(int screen);
260
261
/**
262
* Returns whether or not the PixelFormat indicated by index is
263
* supported. Supported PixelFormats support drawing to a Window
264
* (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the
265
* case of an 8-bit format (cColorBits <= 8) uses indexed colors
266
* (iPixelType == PFD_TYPE_COLORINDEX).
267
* We use the index 0 to indicate that PixelFormat calls don't work, or
268
* are disabled. Do not call this function with an index of 0.
269
* @param index a PixelFormat index
270
*/
271
private native boolean isPixFmtSupported(int index, int screen);
272
273
/**
274
* Returns the PixelFormatID of the default graphics configuration
275
* associated with this graphics device, or 0 if PixelFormats calls fail or
276
* are disabled.
277
*/
278
protected int getDefaultPixID(int screen) {
279
if (pfDisabled) {
280
return 0;
281
} else {
282
return getDefaultPixIDImpl(screen);
283
}
284
}
285
286
/**
287
* Returns the default PixelFormat ID from GDI. Do not call if PixelFormats
288
* are disabled.
289
*/
290
private native int getDefaultPixIDImpl(int screen);
291
292
/**
293
* Returns the default graphics configuration
294
* associated with this graphics device.
295
*/
296
@Override
297
public GraphicsConfiguration getDefaultConfiguration() {
298
if (defaultConfig == null) {
299
// first try to create a WGLGraphicsConfig if OGL is enabled
300
// REMIND: the WGL code does not yet work properly in multimon
301
// situations, so we will fallback on GDI if we are not on the
302
// default device...
303
if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) {
304
int defPixID = WGLGraphicsConfig.getDefaultPixFmt(screen);
305
defaultConfig = WGLGraphicsConfig.getConfig(this, defPixID);
306
if (WindowsFlags.isOGLVerbose()) {
307
if (defaultConfig != null) {
308
System.out.print("OpenGL pipeline enabled");
309
} else {
310
System.out.print("Could not enable OpenGL pipeline");
311
}
312
System.out.println(" for default config on screen " +
313
screen);
314
}
315
}
316
317
// Fix for 4669614. Most apps are not concerned with PixelFormats,
318
// yet we ALWAYS used them for determining ColorModels and such.
319
// By passing in 0 as the PixelFormatID here, we signal that
320
// PixelFormats should not be used, thus avoid loading the opengl
321
// library. Apps concerned with PixelFormats can still use
322
// GraphicsConfiguration.getConfigurations().
323
// Note that calling native pixel format functions tends to cause
324
// problems between those functions (which are OpenGL-related)
325
// and our use of DirectX. For example, some Matrox boards will
326
// crash or hang calling these functions when any app is running
327
// in DirectX fullscreen mode. So avoiding these calls unless
328
// absolutely necessary is preferable.
329
if (defaultConfig == null) {
330
defaultConfig = Win32GraphicsConfig.getConfig(this, 0);
331
}
332
}
333
return defaultConfig;
334
}
335
336
@Override
337
public String toString() {
338
return valid ? descString + "]" : descString + ", removed]";
339
}
340
341
/**
342
* Returns true if this is the default GraphicsDevice for the
343
* GraphicsEnvironment.
344
*/
345
private boolean isDefaultDevice() {
346
return (this ==
347
GraphicsEnvironment.
348
getLocalGraphicsEnvironment().getDefaultScreenDevice());
349
}
350
351
private static boolean isFSExclusiveModeAllowed() {
352
@SuppressWarnings("removal")
353
SecurityManager security = System.getSecurityManager();
354
if (security != null) {
355
if (fullScreenExclusivePermission == null) {
356
fullScreenExclusivePermission =
357
new AWTPermission("fullScreenExclusive");
358
}
359
try {
360
security.checkPermission(fullScreenExclusivePermission);
361
} catch (SecurityException e) {
362
return false;
363
}
364
}
365
return true;
366
}
367
368
/**
369
* returns true unless we're not allowed to use fullscreen mode.
370
*/
371
@Override
372
public boolean isFullScreenSupported() {
373
return isFSExclusiveModeAllowed();
374
}
375
376
@Override
377
public synchronized void setFullScreenWindow(Window w) {
378
Window old = getFullScreenWindow();
379
if (w == old) {
380
return;
381
}
382
if (!isFullScreenSupported()) {
383
super.setFullScreenWindow(w);
384
return;
385
}
386
387
// Enter windowed mode.
388
if (old != null) {
389
// restore the original display mode
390
if (defaultDisplayMode != null) {
391
setDisplayMode(defaultDisplayMode);
392
// we set the default display mode to null here
393
// because the default mode could change during
394
// the life of the application (user can change it through
395
// the desktop properties dialog, for example), so
396
// we need to record it every time prior to
397
// entering the fullscreen mode.
398
defaultDisplayMode = null;
399
}
400
WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(old);
401
if (peer != null) {
402
peer.setFullScreenExclusiveModeState(false);
403
// we used to destroy the buffers on exiting fs mode, this
404
// is no longer needed since fs change will cause a surface
405
// data replacement
406
synchronized(peer) {
407
exitFullScreenExclusive(screen, peer);
408
}
409
}
410
removeFSWindowListener(old);
411
}
412
super.setFullScreenWindow(w);
413
if (w != null) {
414
// always record the default display mode prior to going
415
// fullscreen
416
defaultDisplayMode = getDisplayMode();
417
addFSWindowListener(w);
418
// Enter full screen exclusive mode.
419
WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
420
if (peer != null) {
421
synchronized(peer) {
422
enterFullScreenExclusive(screen, peer);
423
// Note: removed replaceSurfaceData() call because
424
// changing the window size or making it visible
425
// will cause this anyway, and both of these events happen
426
// as part of switching into fullscreen mode.
427
}
428
peer.setFullScreenExclusiveModeState(true);
429
}
430
431
// fix for 4868278
432
peer.updateGC();
433
}
434
}
435
436
// Entering and exiting full-screen mode are done within a
437
// tree-lock and should never lock on any resources which are
438
// required by other threads which may have them and may require
439
// the tree-lock.
440
// REMIND: in the future these methods may need to become protected so that
441
// subclasses could override them and use appropriate api other than GDI
442
// for implementing these functions.
443
protected native void enterFullScreenExclusive(int screen, WindowPeer w);
444
protected native void exitFullScreenExclusive(int screen, WindowPeer w);
445
446
@Override
447
public boolean isDisplayChangeSupported() {
448
return (isFullScreenSupported() && getFullScreenWindow() != null);
449
}
450
451
@Override
452
public synchronized void setDisplayMode(DisplayMode dm) {
453
if (!isDisplayChangeSupported()) {
454
super.setDisplayMode(dm);
455
return;
456
}
457
if (dm == null || (dm = getMatchingDisplayMode(dm)) == null) {
458
throw new IllegalArgumentException("Invalid display mode");
459
}
460
if (getDisplayMode().equals(dm)) {
461
return;
462
}
463
Window w = getFullScreenWindow();
464
if (w != null) {
465
WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
466
configDisplayMode(screen, peer, dm.getWidth(), dm.getHeight(),
467
dm.getBitDepth(), dm.getRefreshRate());
468
// resize the fullscreen window to the dimensions of the new
469
// display mode
470
Rectangle screenBounds = getDefaultConfiguration().getBounds();
471
w.setBounds(screenBounds.x, screenBounds.y,
472
screenBounds.width, screenBounds.height);
473
// Note: no call to replaceSurfaceData is required here since
474
// replacement will be caused by an upcoming display change event
475
} else {
476
throw new IllegalStateException("Must be in fullscreen mode " +
477
"in order to set display mode");
478
}
479
}
480
481
protected native DisplayMode getCurrentDisplayMode(int screen);
482
protected native void configDisplayMode(int screen, WindowPeer w, int width,
483
int height, int bitDepth,
484
int refreshRate);
485
protected native void enumDisplayModes(int screen, ArrayList<DisplayMode> modes);
486
487
@Override
488
public synchronized DisplayMode getDisplayMode() {
489
DisplayMode res = getCurrentDisplayMode(screen);
490
return res;
491
}
492
493
@Override
494
public synchronized DisplayMode[] getDisplayModes() {
495
ArrayList<DisplayMode> modes = new ArrayList<>();
496
enumDisplayModes(screen, modes);
497
int listSize = modes.size();
498
DisplayMode[] retArray = new DisplayMode[listSize];
499
for (int i = 0; i < listSize; i++) {
500
retArray[i] = modes.get(i);
501
}
502
return retArray;
503
}
504
505
protected synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) {
506
if (!isDisplayChangeSupported()) {
507
return null;
508
}
509
DisplayMode[] modes = getDisplayModes();
510
for (DisplayMode mode : modes) {
511
if (dm.equals(mode) ||
512
(dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN &&
513
dm.getWidth() == mode.getWidth() &&
514
dm.getHeight() == mode.getHeight() &&
515
dm.getBitDepth() == mode.getBitDepth()))
516
{
517
return mode;
518
}
519
}
520
return null;
521
}
522
523
/*
524
* From the DisplayChangeListener interface.
525
* Called from Win32GraphicsEnvironment when the display settings have
526
* changed.
527
*/
528
@Override
529
public void displayChanged() {
530
dynamicColorModel = null;
531
defaultConfig = null;
532
configs = null;
533
initScaleFactors();
534
// pass on to all top-level windows on this display
535
topLevels.notifyListeners();
536
}
537
538
/**
539
* Part of the DisplayChangedListener interface: devices
540
* do not need to react to this event
541
*/
542
@Override
543
public void paletteChanged() {
544
}
545
546
/*
547
* Add a DisplayChangeListener to be notified when the display settings
548
* are changed. Typically, only top-level containers need to be added
549
* to Win32GraphicsDevice.
550
*/
551
public void addDisplayChangedListener(DisplayChangedListener client) {
552
topLevels.add(client);
553
}
554
555
/*
556
* Remove a DisplayChangeListener from this Win32GraphicsDevice
557
*/
558
public void removeDisplayChangedListener(DisplayChangedListener client) {
559
topLevels.remove(client);
560
}
561
562
/**
563
* Creates and returns the color model associated with this device
564
*/
565
private native ColorModel makeColorModel (int screen,
566
boolean dynamic);
567
568
/**
569
* Returns a dynamic ColorModel which is updated when there
570
* are any changes (e.g., palette changes) in the device
571
*/
572
public ColorModel getDynamicColorModel() {
573
if (dynamicColorModel == null) {
574
dynamicColorModel = makeColorModel(screen, true);
575
}
576
return dynamicColorModel;
577
}
578
579
/**
580
* Returns the non-dynamic ColorModel associated with this device
581
*/
582
public ColorModel getColorModel() {
583
if (colorModel == null) {
584
colorModel = makeColorModel(screen, false);
585
}
586
return colorModel;
587
}
588
589
/**
590
* WindowAdapter class responsible for de/iconifying full-screen window
591
* of this device.
592
*
593
* The listener restores the default display mode when window is iconified
594
* and sets it back to the one set by the user on de-iconification.
595
*/
596
private static class Win32FSWindowAdapter extends WindowAdapter {
597
private Win32GraphicsDevice device;
598
private DisplayMode dm;
599
600
Win32FSWindowAdapter(Win32GraphicsDevice device) {
601
this.device = device;
602
}
603
604
private void setFSWindowsState(Window other, int state) {
605
GraphicsDevice[] gds =
606
GraphicsEnvironment.getLocalGraphicsEnvironment().
607
getScreenDevices();
608
// check if the de/activation was caused by other
609
// fs window and ignore the event if that's the case
610
if (other != null) {
611
for (GraphicsDevice gd : gds) {
612
if (other == gd.getFullScreenWindow()) {
613
return;
614
}
615
}
616
}
617
// otherwise apply state to all fullscreen windows
618
for (GraphicsDevice gd : gds) {
619
Window fsw = gd.getFullScreenWindow();
620
if (fsw instanceof Frame) {
621
((Frame)fsw).setExtendedState(state);
622
}
623
}
624
}
625
626
@Override
627
public void windowDeactivated(WindowEvent e) {
628
setFSWindowsState(e.getOppositeWindow(), Frame.ICONIFIED);
629
}
630
631
@Override
632
public void windowActivated(WindowEvent e) {
633
setFSWindowsState(e.getOppositeWindow(), Frame.NORMAL);
634
}
635
636
@Override
637
public void windowIconified(WindowEvent e) {
638
// restore the default display mode for this device
639
DisplayMode ddm = device.defaultDisplayMode;
640
if (ddm != null) {
641
dm = device.getDisplayMode();
642
device.setDisplayMode(ddm);
643
}
644
}
645
646
@Override
647
public void windowDeiconified(WindowEvent e) {
648
// restore the user-set display mode for this device
649
if (dm != null) {
650
device.setDisplayMode(dm);
651
dm = null;
652
}
653
}
654
}
655
656
/**
657
* Adds a WindowListener to be used as
658
* activation/deactivation listener for the current full-screen window.
659
*
660
* @param w full-screen window
661
*/
662
protected void addFSWindowListener(final Window w) {
663
// Note: even though we create a listener for Window instances of
664
// fs windows they will not receive window events.
665
fsWindowListener = new Win32FSWindowAdapter(this);
666
667
// Fix for 6709453. Using invokeLater to avoid listening
668
// for the events already posted to the queue.
669
EventQueue.invokeLater(new Runnable() {
670
@Override
671
public void run() {
672
w.addWindowListener(fsWindowListener);
673
}
674
});
675
}
676
677
/**
678
* Removes the fs window listener.
679
*
680
* @param w full-screen window
681
*/
682
protected void removeFSWindowListener(Window w) {
683
w.removeWindowListener(fsWindowListener);
684
fsWindowListener = null;
685
}
686
}
687
688