Win32GraphicsDevice.java revision 13220:a8e9ad77ac81
1177633Sdfr/* 2177633Sdfr * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3177633Sdfr * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4177633Sdfr * 5177633Sdfr * This code is free software; you can redistribute it and/or modify it 6177633Sdfr * under the terms of the GNU General Public License version 2 only, as 7177633Sdfr * published by the Free Software Foundation. Oracle designates this 8177633Sdfr * particular file as subject to the "Classpath" exception as provided 9177633Sdfr * by Oracle in the LICENSE file that accompanied this code. 10177633Sdfr * 11177633Sdfr * This code is distributed in the hope that it will be useful, but WITHOUT 12177633Sdfr * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13177633Sdfr * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14177633Sdfr * version 2 for more details (a copy is included in the LICENSE file that 15177633Sdfr * accompanied this code). 16177633Sdfr * 17177633Sdfr * You should have received a copy of the GNU General Public License version 18177633Sdfr * 2 along with this work; if not, write to the Free Software Foundation, 19177633Sdfr * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20177633Sdfr * 21177633Sdfr * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22177633Sdfr * or visit www.oracle.com if you need additional information or have any 23177633Sdfr * questions. 24177633Sdfr */ 25177633Sdfr 26177633Sdfrpackage sun.awt; 27177633Sdfr 28177633Sdfrimport java.awt.AWTPermission; 29177633Sdfrimport java.awt.GraphicsDevice; 30177633Sdfrimport java.awt.GraphicsConfiguration; 31177633Sdfrimport java.awt.GraphicsEnvironment; 32177633Sdfrimport java.awt.DisplayMode; 33177633Sdfrimport java.awt.EventQueue; 34177633Sdfrimport java.awt.Frame; 35177633Sdfrimport java.awt.Rectangle; 36177633Sdfrimport java.awt.Window; 37177633Sdfrimport java.awt.event.WindowAdapter; 38177633Sdfrimport java.awt.event.WindowEvent; 39177633Sdfrimport java.awt.event.WindowListener; 40177633Sdfrimport java.awt.geom.Point2D; 41177633Sdfrimport java.awt.image.ColorModel; 42177633Sdfrimport java.util.ArrayList; 43177633Sdfrimport java.util.Vector; 44177633Sdfrimport java.awt.peer.WindowPeer; 45177633Sdfrimport java.security.AccessController; 46177633Sdfrimport sun.awt.windows.WWindowPeer; 47177633Sdfrimport sun.java2d.SunGraphicsEnvironment; 48177633Sdfrimport sun.java2d.opengl.WGLGraphicsConfig; 49177633Sdfrimport sun.java2d.windows.WindowsFlags; 50177633Sdfrimport sun.security.action.GetPropertyAction; 51177633Sdfrimport static sun.awt.Win32GraphicsEnvironment.debugScaleX; 52177633Sdfrimport static sun.awt.Win32GraphicsEnvironment.debugScaleY; 53177633Sdfr 54177633Sdfr/** 55177633Sdfr * This is an implementation of a GraphicsDevice object for a single 56177633Sdfr * Win32 screen. 57177633Sdfr * 58177633Sdfr * @see GraphicsEnvironment 59177633Sdfr * @see GraphicsConfiguration 60177633Sdfr */ 61177633Sdfrpublic class Win32GraphicsDevice extends GraphicsDevice implements 62177633Sdfr DisplayChangedListener { 63177633Sdfr int screen; 64177633Sdfr ColorModel dynamicColorModel; // updated with dev changes 65177633Sdfr ColorModel colorModel; // static for device 66177633Sdfr protected GraphicsConfiguration[] configs; 67177633Sdfr protected GraphicsConfiguration defaultConfig; 68177633Sdfr 69192971Skmacy private final String idString; 70192971Skmacy protected String descString; 71177633Sdfr // Note that we do not synchronize access to this variable - it doesn't 72177633Sdfr // really matter if a thread does an operation on graphics device which is 73177633Sdfr // about to become invalid (or already become) - we are prepared to deal 74177633Sdfr // with this on the native level. 75177633Sdfr private boolean valid; 76177633Sdfr 77177633Sdfr // keep track of top-level windows on this display 78177633Sdfr private SunDisplayChanger topLevels = new SunDisplayChanger(); 79192971Skmacy // REMIND: we may disable the use of pixel formats for some accelerated 80192971Skmacy // pipelines which are mutually exclusive with opengl, for which 81177633Sdfr // pixel formats were added in the first place 82177633Sdfr protected static boolean pfDisabled; 83177633Sdfr private static AWTPermission fullScreenExclusivePermission; 84177633Sdfr // the original display mode we had before entering the fullscreen 85177633Sdfr // mode 86177633Sdfr private DisplayMode defaultDisplayMode; 87177633Sdfr // activation/deactivation listener for the full-screen window 88177633Sdfr private WindowListener fsWindowListener; 89177633Sdfr 90177633Sdfr private float scaleX; 91192971Skmacy private float scaleY; 92192971Skmacy 93177633Sdfr static { 94177633Sdfr 95177633Sdfr // 4455041 - Even when ddraw is disabled, ddraw.dll is loaded when 96177633Sdfr // pixel format calls are made. This causes problems when a Java app 97177633Sdfr // is run as an NT service. To prevent the loading of ddraw.dll 98177633Sdfr // completely, sun.awt.nopixfmt should be set as well. Apps which use 99177633Sdfr // OpenGL w/ Java probably don't want to set this. 100177633Sdfr String nopixfmt = java.security.AccessController.doPrivileged( 101177633Sdfr new sun.security.action.GetPropertyAction("sun.awt.nopixfmt")); 102177633Sdfr pfDisabled = (nopixfmt != null); 103177633Sdfr initIDs(); 104177633Sdfr } 105177633Sdfr 106177633Sdfr private static native void initIDs(); 107177633Sdfr 108177633Sdfr native void initDevice(int screen); 109177633Sdfr native void initNativeScale(int screen); 110177633Sdfr native void setNativeScale(int screen, float scaleX, float scaleY); 111177633Sdfr native float getNativeScaleX(int screen); 112177633Sdfr native float getNativeScaleY(int screen); 113177633Sdfr 114177633Sdfr public Win32GraphicsDevice(int screennum) { 115177633Sdfr this.screen = screennum; 116177633Sdfr // we cache the strings because we want toString() and getIDstring 117177633Sdfr // to reflect the original screen number (which may change if the 118177633Sdfr // device is removed) 119177633Sdfr idString = "\\Display"+screen; 120177633Sdfr // REMIND: may be should use class name? 121177633Sdfr descString = "Win32GraphicsDevice[screen=" + screen; 122177633Sdfr valid = true; 123177633Sdfr 124177633Sdfr initDevice(screennum); 125177633Sdfr initScaleFactors(); 126177633Sdfr } 127177633Sdfr 128177633Sdfr /** 129177633Sdfr * Returns the type of the graphics device. 130177633Sdfr * @see #TYPE_RASTER_SCREEN 131177633Sdfr * @see #TYPE_PRINTER 132177633Sdfr * @see #TYPE_IMAGE_BUFFER 133177633Sdfr */ 134177633Sdfr public int getType() { 135177633Sdfr return TYPE_RASTER_SCREEN; 136177633Sdfr } 137177633Sdfr 138177633Sdfr /** 139177633Sdfr * Returns the Win32 screen of the device. 140177633Sdfr */ 141177633Sdfr public int getScreen() { 142177633Sdfr return screen; 143177633Sdfr } 144177633Sdfr 145177633Sdfr public float getDefaultScaleX() { 146177633Sdfr return scaleX; 147177633Sdfr } 148177633Sdfr 149177633Sdfr public float getDefaultScaleY() { 150177633Sdfr return scaleY; 151177633Sdfr } 152177633Sdfr 153177633Sdfr private void initScaleFactors() { 154177633Sdfr if (SunGraphicsEnvironment.isUIScaleEnabled()) { 155177633Sdfr if (debugScaleX > 0 && debugScaleY > 0) { 156177633Sdfr scaleX = debugScaleX; 157177633Sdfr scaleY = debugScaleY; 158177633Sdfr setNativeScale(screen, scaleX, scaleY); 159177633Sdfr } else { 160177633Sdfr initNativeScale(screen); 161177633Sdfr scaleX = getNativeScaleX(screen); 162177633Sdfr scaleY = getNativeScaleY(screen); 163177633Sdfr } 164177633Sdfr } else { 165177633Sdfr scaleX = 1; 166177633Sdfr scaleY = 1; 167177633Sdfr } 168177633Sdfr } 169177633Sdfr 170177633Sdfr /** 171177633Sdfr * Returns whether this is a valid devicie. Device can become 172177633Sdfr * invalid as a result of device removal event. 173177633Sdfr */ 174177633Sdfr public boolean isValid() { 175177633Sdfr return valid; 176177633Sdfr } 177177633Sdfr 178177633Sdfr /** 179177633Sdfr * Called from native code when the device was removed. 180177633Sdfr * 181177633Sdfr * @param defaultScreen the current default screen 182177633Sdfr */ 183177633Sdfr protected void invalidate(int defaultScreen) { 184177633Sdfr valid = false; 185177633Sdfr screen = defaultScreen; 186177633Sdfr } 187177633Sdfr 188177633Sdfr /** 189177633Sdfr * Returns the identification string associated with this graphics 190177633Sdfr * device. 191177633Sdfr */ 192177633Sdfr public String getIDstring() { 193177633Sdfr return idString; 194177633Sdfr } 195177633Sdfr 196177633Sdfr 197177633Sdfr /** 198177633Sdfr * Returns all of the graphics 199177633Sdfr * configurations associated with this graphics device. 200177633Sdfr */ 201177633Sdfr public GraphicsConfiguration[] getConfigurations() { 202177633Sdfr if (configs==null) { 203177633Sdfr if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) { 204177633Sdfr defaultConfig = getDefaultConfiguration(); 205177633Sdfr if (defaultConfig != null) { 206177633Sdfr configs = new GraphicsConfiguration[1]; 207177633Sdfr configs[0] = defaultConfig; 208177633Sdfr return configs.clone(); 209177633Sdfr } 210177633Sdfr } 211177633Sdfr 212177633Sdfr int max = getMaxConfigs(screen); 213177633Sdfr int defaultPixID = getDefaultPixID(screen); 214177633Sdfr Vector<GraphicsConfiguration> v = new Vector<>( max ); 215177633Sdfr if (defaultPixID == 0) { 216177633Sdfr // Workaround for failing GDI calls 217309503Sngie defaultConfig = Win32GraphicsConfig.getConfig(this, 218177633Sdfr defaultPixID); 219177633Sdfr v.addElement(defaultConfig); 220177633Sdfr } 221177633Sdfr else { 222177633Sdfr for (int i = 1; i <= max; i++) { 223177633Sdfr if (isPixFmtSupported(i, screen)) { 224177633Sdfr if (i == defaultPixID) { 225177633Sdfr defaultConfig = Win32GraphicsConfig.getConfig( 226177633Sdfr this, i); 227177633Sdfr v.addElement(defaultConfig); 228177633Sdfr } 229177633Sdfr else { 230177633Sdfr v.addElement(Win32GraphicsConfig.getConfig( 231177633Sdfr this, i)); 232177633Sdfr } 233177633Sdfr } 234192971Skmacy } 235192971Skmacy } 236192971Skmacy configs = new GraphicsConfiguration[v.size()]; 237192971Skmacy v.copyInto(configs); 238192971Skmacy } 239192971Skmacy return configs.clone(); 240192971Skmacy } 241192971Skmacy 242192971Skmacy /** 243192971Skmacy * Returns the maximum number of graphics configurations available, or 1 244192971Skmacy * if PixelFormat calls fail or are disabled. 245192971Skmacy * This number is less than or equal to the number of graphics 246192971Skmacy * configurations supported. 247192971Skmacy */ 248192971Skmacy protected int getMaxConfigs(int screen) { 249192971Skmacy if (pfDisabled) { 250192971Skmacy return 1; 251192971Skmacy } else { 252192971Skmacy return getMaxConfigsImpl(screen); 253192971Skmacy } 254192971Skmacy } 255192971Skmacy 256192971Skmacy private native int getMaxConfigsImpl(int screen); 257192971Skmacy 258192971Skmacy /** 259192971Skmacy * Returns whether or not the PixelFormat indicated by index is 260192971Skmacy * supported. Supported PixelFormats support drawing to a Window 261192971Skmacy * (PFD_DRAW_TO_WINDOW), support GDI (PFD_SUPPORT_GDI), and in the 262192971Skmacy * case of an 8-bit format (cColorBits <= 8) uses indexed colors 263192971Skmacy * (iPixelType == PFD_TYPE_COLORINDEX). 264192971Skmacy * We use the index 0 to indicate that PixelFormat calls don't work, or 265192971Skmacy * are disabled. Do not call this function with an index of 0. 266192971Skmacy * @param index a PixelFormat index 267192971Skmacy */ 268192971Skmacy private native boolean isPixFmtSupported(int index, int screen); 269192971Skmacy 270192971Skmacy /** 271192971Skmacy * Returns the PixelFormatID of the default graphics configuration 272192971Skmacy * associated with this graphics device, or 0 if PixelFormats calls fail or 273192971Skmacy * are disabled. 274192971Skmacy */ 275192971Skmacy protected int getDefaultPixID(int screen) { 276 if (pfDisabled) { 277 return 0; 278 } else { 279 return getDefaultPixIDImpl(screen); 280 } 281 } 282 283 /** 284 * Returns the default PixelFormat ID from GDI. Do not call if PixelFormats 285 * are disabled. 286 */ 287 private native int getDefaultPixIDImpl(int screen); 288 289 /** 290 * Returns the default graphics configuration 291 * associated with this graphics device. 292 */ 293 public GraphicsConfiguration getDefaultConfiguration() { 294 if (defaultConfig == null) { 295 // first try to create a WGLGraphicsConfig if OGL is enabled 296 // REMIND: the WGL code does not yet work properly in multimon 297 // situations, so we will fallback on GDI if we are not on the 298 // default device... 299 if (WindowsFlags.isOGLEnabled() && isDefaultDevice()) { 300 int defPixID = WGLGraphicsConfig.getDefaultPixFmt(screen); 301 defaultConfig = WGLGraphicsConfig.getConfig(this, defPixID); 302 if (WindowsFlags.isOGLVerbose()) { 303 if (defaultConfig != null) { 304 System.out.print("OpenGL pipeline enabled"); 305 } else { 306 System.out.print("Could not enable OpenGL pipeline"); 307 } 308 System.out.println(" for default config on screen " + 309 screen); 310 } 311 } 312 313 // Fix for 4669614. Most apps are not concerned with PixelFormats, 314 // yet we ALWAYS used them for determining ColorModels and such. 315 // By passing in 0 as the PixelFormatID here, we signal that 316 // PixelFormats should not be used, thus avoid loading the opengl 317 // library. Apps concerned with PixelFormats can still use 318 // GraphicsConfiguration.getConfigurations(). 319 // Note that calling native pixel format functions tends to cause 320 // problems between those functions (which are OpenGL-related) 321 // and our use of DirectX. For example, some Matrox boards will 322 // crash or hang calling these functions when any app is running 323 // in DirectX fullscreen mode. So avoiding these calls unless 324 // absolutely necessary is preferable. 325 if (defaultConfig == null) { 326 defaultConfig = Win32GraphicsConfig.getConfig(this, 0); 327 } 328 } 329 return defaultConfig; 330 } 331 332 public String toString() { 333 return valid ? descString + "]" : descString + ", removed]"; 334 } 335 336 /** 337 * Returns true if this is the default GraphicsDevice for the 338 * GraphicsEnvironment. 339 */ 340 private boolean isDefaultDevice() { 341 return (this == 342 GraphicsEnvironment. 343 getLocalGraphicsEnvironment().getDefaultScreenDevice()); 344 } 345 346 private static boolean isFSExclusiveModeAllowed() { 347 SecurityManager security = System.getSecurityManager(); 348 if (security != null) { 349 if (fullScreenExclusivePermission == null) { 350 fullScreenExclusivePermission = 351 new AWTPermission("fullScreenExclusive"); 352 } 353 try { 354 security.checkPermission(fullScreenExclusivePermission); 355 } catch (SecurityException e) { 356 return false; 357 } 358 } 359 return true; 360 } 361 362 /** 363 * returns true unless we're not allowed to use fullscreen mode. 364 */ 365 @Override 366 public boolean isFullScreenSupported() { 367 return isFSExclusiveModeAllowed(); 368 } 369 370 @Override 371 public synchronized void setFullScreenWindow(Window w) { 372 Window old = getFullScreenWindow(); 373 if (w == old) { 374 return; 375 } 376 if (!isFullScreenSupported()) { 377 super.setFullScreenWindow(w); 378 return; 379 } 380 381 // Enter windowed mode. 382 if (old != null) { 383 // restore the original display mode 384 if (defaultDisplayMode != null) { 385 setDisplayMode(defaultDisplayMode); 386 // we set the default display mode to null here 387 // because the default mode could change during 388 // the life of the application (user can change it through 389 // the desktop properties dialog, for example), so 390 // we need to record it every time prior to 391 // entering the fullscreen mode. 392 defaultDisplayMode = null; 393 } 394 WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(old); 395 if (peer != null) { 396 peer.setFullScreenExclusiveModeState(false); 397 // we used to destroy the buffers on exiting fs mode, this 398 // is no longer needed since fs change will cause a surface 399 // data replacement 400 synchronized(peer) { 401 exitFullScreenExclusive(screen, peer); 402 } 403 } 404 removeFSWindowListener(old); 405 } 406 super.setFullScreenWindow(w); 407 if (w != null) { 408 // always record the default display mode prior to going 409 // fullscreen 410 defaultDisplayMode = getDisplayMode(); 411 addFSWindowListener(w); 412 // Enter full screen exclusive mode. 413 WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(w); 414 if (peer != null) { 415 synchronized(peer) { 416 enterFullScreenExclusive(screen, peer); 417 // Note: removed replaceSurfaceData() call because 418 // changing the window size or making it visible 419 // will cause this anyway, and both of these events happen 420 // as part of switching into fullscreen mode. 421 } 422 peer.setFullScreenExclusiveModeState(true); 423 } 424 425 // fix for 4868278 426 peer.updateGC(); 427 } 428 } 429 430 // Entering and exiting full-screen mode are done within a 431 // tree-lock and should never lock on any resources which are 432 // required by other threads which may have them and may require 433 // the tree-lock. 434 // REMIND: in the future these methods may need to become protected so that 435 // subclasses could override them and use appropriate api other than GDI 436 // for implementing these functions. 437 protected native void enterFullScreenExclusive(int screen, WindowPeer w); 438 protected native void exitFullScreenExclusive(int screen, WindowPeer w); 439 440 @Override 441 public boolean isDisplayChangeSupported() { 442 return (isFullScreenSupported() && getFullScreenWindow() != null); 443 } 444 445 @Override 446 public synchronized void setDisplayMode(DisplayMode dm) { 447 if (!isDisplayChangeSupported()) { 448 super.setDisplayMode(dm); 449 return; 450 } 451 if (dm == null || (dm = getMatchingDisplayMode(dm)) == null) { 452 throw new IllegalArgumentException("Invalid display mode"); 453 } 454 if (getDisplayMode().equals(dm)) { 455 return; 456 } 457 Window w = getFullScreenWindow(); 458 if (w != null) { 459 WWindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(w); 460 configDisplayMode(screen, peer, dm.getWidth(), dm.getHeight(), 461 dm.getBitDepth(), dm.getRefreshRate()); 462 // resize the fullscreen window to the dimensions of the new 463 // display mode 464 Rectangle screenBounds = getDefaultConfiguration().getBounds(); 465 w.setBounds(screenBounds.x, screenBounds.y, 466 dm.getWidth(), dm.getHeight()); 467 // Note: no call to replaceSurfaceData is required here since 468 // replacement will be caused by an upcoming display change event 469 } else { 470 throw new IllegalStateException("Must be in fullscreen mode " + 471 "in order to set display mode"); 472 } 473 } 474 475 protected native DisplayMode getCurrentDisplayMode(int screen); 476 protected native void configDisplayMode(int screen, WindowPeer w, int width, 477 int height, int bitDepth, 478 int refreshRate); 479 protected native void enumDisplayModes(int screen, ArrayList<DisplayMode> modes); 480 481 @Override 482 public synchronized DisplayMode getDisplayMode() { 483 DisplayMode res = getCurrentDisplayMode(screen); 484 return res; 485 } 486 487 @Override 488 public synchronized DisplayMode[] getDisplayModes() { 489 ArrayList<DisplayMode> modes = new ArrayList<>(); 490 enumDisplayModes(screen, modes); 491 int listSize = modes.size(); 492 DisplayMode[] retArray = new DisplayMode[listSize]; 493 for (int i = 0; i < listSize; i++) { 494 retArray[i] = modes.get(i); 495 } 496 return retArray; 497 } 498 499 protected synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) { 500 if (!isDisplayChangeSupported()) { 501 return null; 502 } 503 DisplayMode[] modes = getDisplayModes(); 504 for (DisplayMode mode : modes) { 505 if (dm.equals(mode) || 506 (dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN && 507 dm.getWidth() == mode.getWidth() && 508 dm.getHeight() == mode.getHeight() && 509 dm.getBitDepth() == mode.getBitDepth())) 510 { 511 return mode; 512 } 513 } 514 return null; 515 } 516 517 /* 518 * From the DisplayChangeListener interface. 519 * Called from Win32GraphicsEnvironment when the display settings have 520 * changed. 521 */ 522 public void displayChanged() { 523 dynamicColorModel = null; 524 defaultConfig = null; 525 configs = null; 526 // pass on to all top-level windows on this display 527 topLevels.notifyListeners(); 528 initScaleFactors(); 529 } 530 531 /** 532 * Part of the DisplayChangedListener interface: devices 533 * do not need to react to this event 534 */ 535 public void paletteChanged() { 536 } 537 538 /* 539 * Add a DisplayChangeListener to be notified when the display settings 540 * are changed. Typically, only top-level containers need to be added 541 * to Win32GraphicsDevice. 542 */ 543 public void addDisplayChangedListener(DisplayChangedListener client) { 544 topLevels.add(client); 545 } 546 547 /* 548 * Remove a DisplayChangeListener from this Win32GraphicsDevice 549 */ 550 public void removeDisplayChangedListener(DisplayChangedListener client) { 551 topLevels.remove(client); 552 } 553 554 /** 555 * Creates and returns the color model associated with this device 556 */ 557 private native ColorModel makeColorModel (int screen, 558 boolean dynamic); 559 560 /** 561 * Returns a dynamic ColorModel which is updated when there 562 * are any changes (e.g., palette changes) in the device 563 */ 564 public ColorModel getDynamicColorModel() { 565 if (dynamicColorModel == null) { 566 dynamicColorModel = makeColorModel(screen, true); 567 } 568 return dynamicColorModel; 569 } 570 571 /** 572 * Returns the non-dynamic ColorModel associated with this device 573 */ 574 public ColorModel getColorModel() { 575 if (colorModel == null) { 576 colorModel = makeColorModel(screen, false); 577 } 578 return colorModel; 579 } 580 581 /** 582 * WindowAdapter class responsible for de/iconifying full-screen window 583 * of this device. 584 * 585 * The listener restores the default display mode when window is iconified 586 * and sets it back to the one set by the user on de-iconification. 587 */ 588 private static class Win32FSWindowAdapter extends WindowAdapter { 589 private Win32GraphicsDevice device; 590 private DisplayMode dm; 591 592 Win32FSWindowAdapter(Win32GraphicsDevice device) { 593 this.device = device; 594 } 595 596 private void setFSWindowsState(Window other, int state) { 597 GraphicsDevice gds[] = 598 GraphicsEnvironment.getLocalGraphicsEnvironment(). 599 getScreenDevices(); 600 // check if the de/activation was caused by other 601 // fs window and ignore the event if that's the case 602 if (other != null) { 603 for (GraphicsDevice gd : gds) { 604 if (other == gd.getFullScreenWindow()) { 605 return; 606 } 607 } 608 } 609 // otherwise apply state to all fullscreen windows 610 for (GraphicsDevice gd : gds) { 611 Window fsw = gd.getFullScreenWindow(); 612 if (fsw instanceof Frame) { 613 ((Frame)fsw).setExtendedState(state); 614 } 615 } 616 } 617 618 @Override 619 public void windowDeactivated(WindowEvent e) { 620 setFSWindowsState(e.getOppositeWindow(), Frame.ICONIFIED); 621 } 622 623 @Override 624 public void windowActivated(WindowEvent e) { 625 setFSWindowsState(e.getOppositeWindow(), Frame.NORMAL); 626 } 627 628 @Override 629 public void windowIconified(WindowEvent e) { 630 // restore the default display mode for this device 631 DisplayMode ddm = device.defaultDisplayMode; 632 if (ddm != null) { 633 dm = device.getDisplayMode(); 634 device.setDisplayMode(ddm); 635 } 636 } 637 638 @Override 639 public void windowDeiconified(WindowEvent e) { 640 // restore the user-set display mode for this device 641 if (dm != null) { 642 device.setDisplayMode(dm); 643 dm = null; 644 } 645 } 646 } 647 648 /** 649 * Adds a WindowListener to be used as 650 * activation/deactivation listener for the current full-screen window. 651 * 652 * @param w full-screen window 653 */ 654 protected void addFSWindowListener(final Window w) { 655 // Note: even though we create a listener for Window instances of 656 // fs windows they will not receive window events. 657 fsWindowListener = new Win32FSWindowAdapter(this); 658 659 // Fix for 6709453. Using invokeLater to avoid listening 660 // for the events already posted to the queue. 661 EventQueue.invokeLater(new Runnable() { 662 public void run() { 663 w.addWindowListener(fsWindowListener); 664 } 665 }); 666 } 667 668 /** 669 * Removes the fs window listener. 670 * 671 * @param w full-screen window 672 */ 673 protected void removeFSWindowListener(Window w) { 674 w.removeWindowListener(fsWindowListener); 675 fsWindowListener = null; 676 } 677} 678