1 /* 2 * Copyright (c) 2008, 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 26 package com.sun.javafx.tk.quantum; 27 28 import java.nio.ByteBuffer; 29 import java.security.AccessControlException; 30 import java.security.AccessController; 31 import java.security.AllPermission; 32 import java.security.Permission; 33 import java.security.PrivilegedAction; 34 import java.security.AccessControlContext; 35 import java.util.HashMap; 36 import java.util.LinkedList; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.concurrent.atomic.AtomicReference; 40 41 import javafx.scene.input.KeyCombination; 42 import javafx.stage.Modality; 43 import javafx.stage.Stage; 44 import javafx.stage.StageStyle; 45 46 import com.sun.glass.events.WindowEvent; 47 import com.sun.glass.ui.*; 48 import com.sun.glass.ui.accessible.AccessibleBaseProvider; 49 import com.sun.glass.ui.accessible.AccessibleRoot; 50 import com.sun.javafx.PlatformUtil; 51 import com.sun.javafx.iio.common.PushbroomScaler; 52 import com.sun.javafx.iio.common.ScalerFactory; 53 import com.sun.javafx.tk.FocusCause; 54 import com.sun.javafx.tk.TKScene; 55 import com.sun.javafx.tk.TKStage; 56 import com.sun.prism.Image; 57 import com.sun.prism.PixelFormat; 58 import com.sun.javafx.accessible.providers.AccessibleProvider; 59 import com.sun.javafx.accessible.providers.AccessibleStageProvider; 60 61 class WindowStage extends GlassStage { 62 63 protected Window platformWindow; 64 65 protected javafx.stage.Stage fxStage; 66 67 private StageStyle style; 68 private GlassStage owner = null; 69 private Modality modality = Modality.NONE; 70 71 private OverlayWarning warning = null; 72 private boolean rtl = false; 73 private boolean transparent = false; 74 private boolean isPrimaryStage = false; 75 private boolean isAppletStage = false; // true if this is an embedded applet window 76 private boolean isPopupStage = false; 77 private boolean isInFullScreen = false; 78 79 // A flag to indicate whether a call was generated from 80 // an input event handler. 81 private boolean inEventHandler = false; 82 83 private static final AtomicReference<WindowStage> activeFSWindow = new AtomicReference<>(); 84 85 // An active window is visible && enabled && focusable. 86 // The list is maintained in the z-order, so that the last element 87 // represents the topmost window (or more accurately, the last 88 // focused window, which we assume is very close to the last topmost one). 89 private static List<WindowStage> activeWindows = new LinkedList<>(); 90 91 private static Map<Window, WindowStage> platformWindows = new HashMap<>(); 92 93 private static GlassAppletWindow appletWindow = null; 94 static void setAppletWindow(GlassAppletWindow aw) { 95 appletWindow = aw; 96 } 97 static GlassAppletWindow getAppletWindow() { 98 return appletWindow; 99 } 100 101 public WindowStage(javafx.stage.Window peerWindow, final StageStyle stageStyle, Modality modality, TKStage owner) { 102 this.style = stageStyle; 103 this.owner = (GlassStage)owner; 104 this.modality = modality; 105 106 if (peerWindow instanceof javafx.stage.Stage) { 107 fxStage = (Stage)peerWindow; 108 } else { 109 fxStage = null; 110 } 111 112 transparent = stageStyle == StageStyle.TRANSPARENT; 113 if (owner == null) { 114 if (this.modality == Modality.WINDOW_MODAL) { 115 this.modality = Modality.NONE; 116 } 117 } 118 } 119 120 final void setIsPrimary() { 121 isPrimaryStage = true; 122 if (appletWindow != null) { 123 // this is an embedded applet stage 124 isAppletStage = true; 125 } 126 } 127 128 final void setIsPopup() { 129 isPopupStage = true; 130 } 131 132 // Called by QuantumToolkit, so we can override initPlatformWindow in subclasses 133 public final WindowStage init(GlassSystemMenu sysmenu) { 134 initPlatformWindow(); 135 platformWindow.setEventHandler(new GlassWindowEventHandler(this)); 136 if (sysmenu.isSupported()) { 137 sysmenu.createMenuBar(); 138 platformWindow.setMenuBar(sysmenu.getMenuBar()); 139 } 140 return this; 141 } 142 143 private void initPlatformWindow() { 144 if (platformWindow == null) { 145 Application app = Application.GetApplication(); 146 if (isPrimaryStage && (null != appletWindow)) { 147 platformWindow = app.createWindow(appletWindow.getGlassWindow().getNativeWindow()); 148 } else { 149 Window ownerWindow = null; 150 if (owner instanceof WindowStage) { 151 ownerWindow = ((WindowStage)owner).platformWindow; 152 } 153 boolean resizable = false; 154 boolean focusable = true; 155 int windowMask = rtl ? Window.RIGHT_TO_LEFT : 0; 156 if (isPopupStage) { // TODO: make it a stage style? 157 windowMask |= Window.TRANSPARENT | Window.POPUP; 158 focusable = false; 159 } else { 160 switch (style) { 161 case UNIFIED: 162 if (app.supportsUnifiedWindows()) { 163 windowMask |= Window.UNIFIED; 164 } 165 // fall through 166 case DECORATED: 167 windowMask |= 168 Window.TITLED | Window.CLOSABLE | Window.MINIMIZABLE | Window.MAXIMIZABLE; 169 resizable = true; 170 break; 171 case UTILITY: 172 windowMask |= Window.TITLED | Window.UTILITY | Window.CLOSABLE; 173 break; 174 default: 175 windowMask |= 176 (transparent ? Window.TRANSPARENT : Window.UNTITLED) | Window.CLOSABLE; 177 break; 178 } 179 } 180 platformWindow = 181 app.createWindow(ownerWindow, Screen.getMainScreen(), windowMask); 182 platformWindow.setResizable(resizable); 183 platformWindow.setFocusable(focusable); 184 } 185 } 186 platformWindows.put(platformWindow, this); 187 } 188 189 final Window getPlatformWindow() { 190 return platformWindow; 191 } 192 193 static WindowStage findWindowStage(Window platformWindow) { 194 return platformWindows.get(platformWindow); 195 } 196 197 protected GlassStage getOwner() { 198 return owner; 199 } 200 201 protected ViewScene getViewScene() { 202 return (ViewScene)getScene(); 203 } 204 205 StageStyle getStyle() { 206 return style; 207 } 208 209 @Override public TKScene createTKScene(boolean depthBuffer, boolean antiAliasing, AccessControlContext acc) { 210 ViewScene scene = new ViewScene(depthBuffer, antiAliasing); 211 scene.setSecurityContext(acc); 212 return scene; 213 } 214 215 /** 216 * Set the scene to be displayed in this stage 217 * 218 * @param scene The peer of the scene to be displayed 219 */ 220 @Override public void setScene(TKScene scene) { 221 GlassScene oldScene = getScene(); 222 super.setScene(scene); 223 if (scene != null) { 224 GlassScene newScene = getViewScene(); 225 View view = newScene.getPlatformView(); 226 ViewPainter.renderLock.lock(); 227 try { 228 platformWindow.setView(view); 229 if (oldScene != null) oldScene.updateSceneState(); 230 newScene.updateSceneState(); 231 } finally { 232 ViewPainter.renderLock.unlock(); 233 } 234 requestFocus(); 235 applyFullScreen(); 236 } else { 237 ViewPainter.renderLock.lock(); 238 try { 239 // platformWindow can be null here, if this window is owned, 240 // and its owner is being closed. 241 if (platformWindow != null) { 242 platformWindow.setView(null); 243 } 244 if (oldScene != null) { 245 oldScene.updateSceneState(); 246 } 247 } finally { 248 ViewPainter.renderLock.unlock(); 249 } 250 } 251 if (oldScene != null) { 252 ViewPainter painter = ((ViewScene)oldScene).getPainter(); 253 QuantumRenderer.getInstance().disposePresentable(painter.presentable); // latched on RT 254 } 255 } 256 257 @Override public void setBounds(float x, float y, boolean xSet, boolean ySet, 258 float w, float h, float cw, float ch, 259 float xGravity, float yGravity) 260 { 261 if (isAppletStage) { 262 xSet = ySet = false; 263 } 264 platformWindow.setBounds((int)x, (int)y, xSet, ySet, 265 (int)w, (int)h, (int)cw, (int)ch, 266 xGravity, yGravity); 267 } 268 269 @Override public void setMinimumSize(int minWidth, int minHeight) { 270 platformWindow.setMinimumSize(minWidth, minHeight); 271 } 272 273 @Override public void setMaximumSize(int maxWidth, int maxHeight) { 274 platformWindow.setMaximumSize(maxWidth, maxHeight); 275 } 276 277 @Override public void setIcons(java.util.List icons) { 278 279 int SMALL_ICON_HEIGHT = 32; 280 int SMALL_ICON_WIDTH = 32; 281 if (PlatformUtil.isMac()) { //Mac Sized Icons 282 SMALL_ICON_HEIGHT = 128; 283 SMALL_ICON_WIDTH = 128; 284 } else if (PlatformUtil.isWindows()) { //Windows Sized Icons 285 SMALL_ICON_HEIGHT = 32; 286 SMALL_ICON_WIDTH = 32; 287 } else if (PlatformUtil.isLinux()) { //Linux icons 288 SMALL_ICON_HEIGHT = 128; 289 SMALL_ICON_WIDTH = 128; 290 } 291 292 if (icons == null || icons.size() < 1) { //no icons passed in 293 return; 294 } 295 296 int width = platformWindow.getWidth(); 297 int height = platformWindow.getHeight(); 298 299 Image image = null; 300 double bestSimilarity = 3; //Impossibly high value 301 for (int i = 0; i < icons.size(); i++) { 302 //Iterate imageList looking for best matching image. 303 //'Similarity' measure is defined as good scale factor and small insets. 304 //best possible similarity is 0 (no scale, no insets). 305 //It's found by experimentation that good-looking results are achieved 306 //with scale factors x1, x3/4, x2/3, xN, x1/N. 307 //Check to make sure the image/image format is correct. 308 Image im = (Image)icons.get(i); 309 if (im == null || !(im.getPixelFormat() == PixelFormat.BYTE_RGB || 310 im.getPixelFormat() == PixelFormat.BYTE_BGRA_PRE || 311 im.getPixelFormat() == PixelFormat.BYTE_GRAY)) 312 { 313 continue; 314 } 315 316 int iw = im.getWidth(); 317 int ih = im.getHeight(); 318 319 if (iw > 0 && ih > 0) { 320 //Calc scale factor 321 double scaleFactor = Math.min((double)SMALL_ICON_WIDTH / (double)iw, 322 (double)SMALL_ICON_HEIGHT / (double)ih); 323 //Calculate scaled image dimensions 324 //adjusting scale factor to nearest "good" value 325 int adjw; 326 int adjh; 327 double scaleMeasure = 1; //0 - best (no) scale, 1 - impossibly bad 328 if (scaleFactor >= 2) { 329 //Need to enlarge image more than twice 330 //Round down scale factor to multiply by integer value 331 scaleFactor = Math.floor(scaleFactor); 332 adjw = iw * (int)scaleFactor; 333 adjh = ih * (int)scaleFactor; 334 scaleMeasure = 1.0 - 0.5 / scaleFactor; 335 } else if (scaleFactor >= 1) { 336 //Don't scale 337 scaleFactor = 1.0; 338 adjw = iw; 339 adjh = ih; 340 scaleMeasure = 0; 341 } else if (scaleFactor >= 0.75) { 342 //Multiply by 3/4 343 scaleFactor = 0.75; 344 adjw = iw * 3 / 4; 345 adjh = ih * 3 / 4; 346 scaleMeasure = 0.3; 347 } else if (scaleFactor >= 0.6666) { 348 //Multiply by 2/3 349 scaleFactor = 0.6666; 350 adjw = iw * 2 / 3; 351 adjh = ih * 2 / 3; 352 scaleMeasure = 0.33; 353 } else { 354 //Multiply size by 1/scaleDivider 355 //where scaleDivider is minimum possible integer 356 //larger than 1/scaleFactor 357 double scaleDivider = Math.ceil(1.0 / scaleFactor); 358 scaleFactor = 1.0 / scaleDivider; 359 adjw = (int)Math.round((double)iw / scaleDivider); 360 adjh = (int)Math.round((double)ih / scaleDivider); 361 scaleMeasure = 1.0 - 1.0 / scaleDivider; 362 } 363 double similarity = ((double)width - (double)adjw) / (double)width + 364 ((double)height - (double)adjh) / (double)height + //Large padding is bad 365 scaleMeasure; //Large rescale is bad 366 if (similarity < bestSimilarity) { 367 image = im; 368 } 369 if (similarity == 0) break; 370 } 371 } 372 373 if (image == null) { 374 //No images were found, possibly all are broken 375 return; 376 } 377 378 PushbroomScaler scaler = ScalerFactory.createScaler(image.getWidth(), image.getHeight(), 379 image.getBytesPerPixelUnit(), 380 SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT, true); 381 382 //shrink the image and convert the format to INT_ARGB_PRE 383 ByteBuffer buf = (ByteBuffer) image.getPixelBuffer(); 384 byte bytes[] = new byte[buf.limit()]; 385 386 int iheight = image.getHeight(); 387 388 //Iterate through each scanline of the image 389 //and pass it one at a time to the scaling object 390 for (int z = 0; z < iheight; z++) { 391 buf.position(z*image.getScanlineStride()); 392 buf.get(bytes, 0, image.getScanlineStride()); 393 scaler.putSourceScanline(bytes, 0); 394 } 395 396 buf.rewind(); 397 398 final Image img = image.iconify(scaler.getDestination(), SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT); 399 platformWindow.setIcon(PixelUtils.imageToPixels(img)); 400 } 401 402 @Override public void setTitle(String title) { 403 platformWindow.setTitle(title); 404 } 405 406 @Override public void setVisible(final boolean visible) { 407 // Before setting visible to false on the native window, we unblock 408 // other windows. 409 if (!visible) { 410 removeActiveWindow(this); 411 if (modality == Modality.WINDOW_MODAL) { 412 if (owner != null && owner instanceof WindowStage) { 413 ((WindowStage) owner).setEnabled(true); 414 } 415 } else if (modality == Modality.APPLICATION_MODAL) { 416 windowsSetEnabled(true); 417 } else { 418 // Note: This method is required to workaround a glass issue 419 // mentioned in RT-12607 420 if (owner != null && owner instanceof WindowStage) { 421 WindowStage ownerStage = (WindowStage)owner; 422 ownerStage.requestToFront(); 423 } 424 } 425 } 426 try { 427 ViewPainter.renderLock.lock(); 428 // platformWindow can be null here, if this window is owned, 429 // and its owner is being closed. 430 if (platformWindow != null) { 431 platformWindow.setVisible(visible); 432 } 433 super.setVisible(visible); 434 } finally { 435 ViewPainter.renderLock.unlock(); 436 } 437 // After setting visible to true on the native window, we block 438 // other windows. 439 if (visible) { 440 if (modality == Modality.WINDOW_MODAL) { 441 if (owner != null && owner instanceof WindowStage) { 442 ((WindowStage) owner).setEnabled(false); 443 } 444 } else if (modality == Modality.APPLICATION_MODAL) { 445 windowsSetEnabled(false); 446 } 447 if (isAppletStage && null != appletWindow) { 448 appletWindow.assertStageOrder(); 449 } 450 } 451 452 applyFullScreen(); 453 } 454 455 @Override boolean isVisible() { 456 return platformWindow.isVisible(); 457 } 458 459 @Override public void setOpacity(float opacity) { 460 platformWindow.setAlpha(opacity); 461 } 462 463 public boolean needsUpdateWindow() { 464 return transparent && (Application.GetApplication().shouldUpdateWindow()); 465 } 466 467 @Override public void setIconified(boolean iconified) { 468 if (platformWindow.isMinimized() == iconified) { 469 return; 470 } 471 platformWindow.minimize(iconified); 472 } 473 474 @Override public void setMaximized(boolean maximized) { 475 if (platformWindow.isMaximized() == maximized) { 476 return; 477 } 478 platformWindow.maximize(maximized); 479 } 480 481 @Override public void setResizable(boolean resizable) { 482 platformWindow.setResizable(resizable); 483 // note: for child windows this is ignored and we fail silently 484 } 485 486 // Return true if this stage is trusted for full screen - doesn't have a 487 // security manager, or a permission check doesn't result in a security 488 // exeception. 489 boolean isTrustedFullScreen() { 490 return hasPermission(fullScreenPermission); 491 } 492 493 // Safely exit full screen 494 void exitFullScreen() { 495 setFullScreen(false); 496 } 497 498 boolean isApplet() { 499 return isPrimaryStage && null != appletWindow; 500 } 501 502 private boolean hasPermission(Permission perm) { 503 try { 504 if (System.getSecurityManager() != null) { 505 getAccessControlContext().checkPermission(perm); 506 } 507 return true; 508 } catch (AccessControlException ae) { 509 return false; 510 } 511 } 512 513 // We may need finer-grained permissions in the future, but for 514 // now AllPermission is good enough to do the job we need, such 515 // as fullscreen support for signed/unsigned application. 516 private static final Permission fullScreenPermission = new AllPermission(); 517 518 private boolean fullScreenFromUserEvent = false; 519 520 private KeyCombination savedFullScreenExitKey = null; 521 522 public final KeyCombination getSavedFullScreenExitKey() { 523 return savedFullScreenExitKey; 524 } 525 526 private void applyFullScreen() { 527 if (platformWindow == null) { 528 // applyFullScreen() can be called from setVisible(false), while the 529 // platformWindow has already been destroyed. 530 return; 531 } 532 View v = platformWindow.getView(); 533 if (isVisible() && v != null && v.isInFullscreen() != isInFullScreen) { 534 if (isInFullScreen) { 535 // Check whether app is full screen trusted or flag is set 536 // indicating that the fullscreen request came from an input 537 // event handler. 538 // If not notify the stageListener to reset fullscreen to false. 539 final boolean isTrusted = isTrustedFullScreen(); 540 if (!isTrusted && !fullScreenFromUserEvent) { 541 exitFullScreen(); 542 } else { 543 v.enterFullscreen(false, false, false); 544 if (warning != null && warning.inWarningTransition()) { 545 warning.setView(getViewScene()); 546 } else { 547 boolean showWarning = true; 548 549 KeyCombination key = null; 550 String exitMessage = null; 551 552 if (isTrusted && (fxStage != null)) { 553 // copy the user set definitions for later use. 554 key = fxStage.getFullScreenExitKeyCombination(); 555 556 exitMessage = fxStage.getFullScreenExitHint(); 557 } 558 559 savedFullScreenExitKey = 560 key == null 561 ? defaultFullScreenExitKeycombo 562 : key; 563 564 // if the hint is "" dont show 565 if (exitMessage != null && 566 (exitMessage.equals(""))) { 567 showWarning = false; 568 } 569 570 // if the key is NO_MATCH dont show 571 if (savedFullScreenExitKey.equals(KeyCombination.NO_MATCH)) { 572 showWarning = false; 573 } 574 575 if (showWarning && warning == null) { 576 warning = new OverlayWarning(getViewScene()); 577 } 578 579 if (showWarning && warning != null) { 580 warning.warn(exitMessage); 581 } 582 } 583 } 584 } else { 585 if (warning != null) { 586 warning.cancel(); 587 warning = null; 588 } 589 v.exitFullscreen(false); 590 } 591 // Reset flag once we are done process fullscreen 592 fullScreenFromUserEvent = false; 593 } else if (!isVisible() && warning != null) { 594 // if the window is closed - re-open with fresh warning 595 warning.cancel(); 596 warning = null; 597 } 598 } 599 600 @Override public void setFullScreen(boolean fullScreen) { 601 if (isInFullScreen == fullScreen) { 602 return; 603 } 604 605 // Set a flag indicating whether this method was called from 606 // an input event handler. 607 if (isInEventHandler()) { 608 fullScreenFromUserEvent = true; 609 } 610 611 WindowStage fsWindow = activeFSWindow.get(); 612 if (fullScreen && (fsWindow != null)) { 613 fsWindow.setFullScreen(false); 614 } 615 isInFullScreen = fullScreen; 616 applyFullScreen(); 617 if (fullScreen) { 618 activeFSWindow.set(this); 619 } 620 } 621 622 void fullscreenChanged(final boolean fs) { 623 if (!fs) { 624 activeFSWindow.compareAndSet(this, null); 625 } 626 AccessController.doPrivileged(new PrivilegedAction<Void>() { 627 @Override 628 public Void run() { 629 if (stageListener != null) { 630 stageListener.changedFullscreen(fs); 631 } 632 return null; 633 } 634 }, getAccessControlContext()); 635 } 636 637 @Override public void toBack() { 638 platformWindow.toBack(); 639 if (isAppletStage && null != appletWindow) { 640 appletWindow.assertStageOrder(); 641 } 642 } 643 644 @Override public void toFront() { 645 platformWindow.requestFocus(); // RT-17836 646 platformWindow.toFront(); 647 if (isAppletStage && null != appletWindow) { 648 appletWindow.assertStageOrder(); 649 } 650 } 651 652 @Override public void close() { 653 super.close(); 654 ViewPainter.renderLock.lock(); 655 try { 656 // prevents closing a closed platform window 657 if (platformWindow != null) { 658 platformWindows.remove(platformWindow); 659 platformWindow.close(); 660 platformWindow = null; 661 } 662 GlassScene oldScene = getViewScene(); 663 if (oldScene != null) { 664 oldScene.updateSceneState(); 665 } 666 } finally { 667 ViewPainter.renderLock.unlock(); 668 } 669 } 670 671 // setPlatformWindowClosed is only set upon receiving platform window has 672 // closed notification. This state is necessary to prevent the platform 673 // window from being closed more than once. 674 void setPlatformWindowClosed() { 675 platformWindow = null; 676 } 677 678 static void addActiveWindow(WindowStage window) { 679 activeWindows.remove(window); 680 activeWindows.add(window); 681 } 682 683 static void removeActiveWindow(WindowStage window) { 684 activeWindows.remove(window); 685 } 686 687 final void handleFocusDisabled() { 688 if (activeWindows.isEmpty()) { 689 return; 690 } 691 WindowStage window = activeWindows.get(activeWindows.size() - 1); 692 window.setIconified(false); 693 window.requestToFront(); 694 window.requestFocus(); 695 } 696 697 @Override public boolean grabFocus() { 698 return platformWindow.grabFocus(); 699 } 700 701 @Override public void ungrabFocus() { 702 platformWindow.ungrabFocus(); 703 } 704 705 @Override public void requestFocus() { 706 platformWindow.requestFocus(); 707 } 708 709 @Override public void requestFocus(FocusCause cause) { 710 switch (cause) { 711 case TRAVERSED_FORWARD: 712 platformWindow.requestFocus(WindowEvent.FOCUS_GAINED_FORWARD); 713 break; 714 case TRAVERSED_BACKWARD: 715 platformWindow.requestFocus(WindowEvent.FOCUS_GAINED_BACKWARD); 716 break; 717 case ACTIVATED: 718 platformWindow.requestFocus(WindowEvent.FOCUS_GAINED); 719 break; 720 case DEACTIVATED: 721 platformWindow.requestFocus(WindowEvent.FOCUS_LOST); 722 break; 723 } 724 } 725 726 @Override 727 protected void setPlatformEnabled(boolean enabled) { 728 super.setPlatformEnabled(enabled); 729 platformWindow.setEnabled(enabled); 730 if (enabled) { 731 requestToFront(); 732 } else { 733 removeActiveWindow(this); 734 } 735 } 736 737 void setEnabled(boolean enabled) { 738 if ((owner != null) && (owner instanceof WindowStage)) { 739 ((WindowStage) owner).setEnabled(enabled); 740 } 741 /* 742 * RT-17588 - exit if stage is closed from under us as 743 * any further access to the Glass layer 744 * will throw an exception 745 */ 746 if (enabled && platformWindow.isClosed()) { 747 return; 748 } 749 setPlatformEnabled(enabled); 750 if (enabled) { 751 if (isAppletStage && null != appletWindow) { 752 appletWindow.assertStageOrder(); 753 } 754 } 755 } 756 757 // Note: This method is required to workaround a glass issue mentioned in RT-12607 758 protected void requestToFront() { 759 platformWindow.toFront(); 760 platformWindow.requestFocus(); 761 } 762 763 public void setInEventHandler(boolean inEventHandler) { 764 this.inEventHandler = inEventHandler; 765 } 766 767 public boolean isInEventHandler() { 768 return inEventHandler; 769 } 770 771 @Override 772 public void requestInput(String text, int type, double width, double height, 773 double Mxx, double Mxy, double Mxz, double Mxt, 774 double Myx, double Myy, double Myz, double Myt, 775 double Mzx, double Mzy, double Mzz, double Mzt) { 776 platformWindow.requestInput(text, type, width, height, 777 Mxx, Mxy, Mxz, Mxt, 778 Myx, Myy, Myz, Myt, 779 Mzx, Mzy, Mzz, Mzt); 780 } 781 782 @Override 783 public void releaseInput() { 784 platformWindow.releaseInput(); 785 } 786 787 @Override public void setRTL(boolean b) { 788 rtl = b; 789 } 790 791 /** 792 * 793 * Accessibility glue for native 794 * 795 */ 796 797 /** 798 * Initialize Accessibility 799 * 800 * @param ac the Glass accessible root object. 801 */ 802 @Override public void setAccessibilityInitIsComplete(Object ac) { 803 if (ac instanceof AccessibleRoot) { 804 platformWindow.setAccessibilityInitIsComplete((AccessibleRoot)ac); 805 } else { 806 platformWindow.setAccessibilityInitIsComplete(null); 807 } 808 } 809 810 /** 811 * Create accessible Glass object corresponding to stage 812 * 813 * @param ac the FX accessible root/stage node. 814 * 815 * @return the Glass AccessibleRoot object. 816 */ 817 @Override 818 public Object accessibleCreateStageProvider(AccessibleStageProvider ac) { 819 return AccessibleRoot.createAccessible(ac, platformWindow); 820 } 821 822 /** 823 * Create Glass accessible object corresponding to controls 824 * 825 * @param ac the FX accessible node 826 * 827 * @return the Glass accessible Object 828 */ 829 @Override public Object accessibleCreateBasicProvider(AccessibleProvider ac) { 830 return AccessibleBaseProvider.createProvider(ac); 831 } 832 833 /** 834 * Delete Glass accessible object corresponding to controls 835 * 836 * @param glassAcc the Glass accessible 837 */ 838 @Override public void accessibleDestroyBasicProvider(Object glassAcc) { 839 if (glassAcc instanceof AccessibleBaseProvider) { 840 ((AccessibleBaseProvider)glassAcc).destroyAccessible(); 841 } 842 } 843 844 /** 845 * Fire accessible event 846 * 847 * @param glassAcc the Glass accessible 848 * @param eventID identifies the event. 849 */ 850 @Override public void accessibleFireEvent(Object glassAcc, int eventID) { 851 if (glassAcc instanceof AccessibleBaseProvider) { 852 ((AccessibleBaseProvider)glassAcc).fireEvent(eventID); 853 } 854 } 855 856 /** 857 * Fire accessible property change event 858 * 859 * @param glassAcc the Glass accessible 860 * @param propertyId identifies the property 861 * @param oldProperty the old value of the property 862 * @param newProperty the new value of the property 863 */ 864 @Override public void accessibleFirePropertyChange( Object glassAcc, int propertyId, 865 int oldProperty, int newProperty ) { 866 if (glassAcc instanceof AccessibleBaseProvider) { 867 ((AccessibleBaseProvider)glassAcc). 868 firePropertyChange(propertyId, oldProperty, newProperty); 869 } 870 } 871 872 /** 873 * Fire accessible property change event 874 * 875 * @param glassAcc the Glass accessible 876 * @param propertyId identifies the property 877 * @param oldProperty the old value of the property 878 * @param newProperty the new value of the property 879 */ 880 @Override public void accessibleFirePropertyChange( Object glassAcc, int propertyId, 881 boolean oldProperty, 882 boolean newProperty ) { 883 if (glassAcc instanceof AccessibleBaseProvider) { 884 ((AccessibleBaseProvider)glassAcc). 885 firePropertyChange(propertyId, oldProperty, newProperty); 886 } 887 } 888 }