1 /* 2 * Copyright (c) 2011, 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.lwawt.macosx; 27 28 import java.awt.*; 29 import java.awt.datatransfer.Clipboard; 30 import java.awt.dnd.*; 31 import java.awt.dnd.peer.DragSourceContextPeer; 32 import java.awt.event.InputEvent; 33 import java.awt.event.InvocationEvent; 34 import java.awt.event.KeyEvent; 35 import java.awt.im.InputMethodHighlight; 36 import java.awt.peer.*; 37 import java.lang.reflect.*; 38 import java.security.*; 39 import java.util.*; 40 import java.util.concurrent.Callable; 41 42 import sun.awt.*; 43 import sun.lwawt.*; 44 import sun.lwawt.LWWindowPeer.PeerType; 45 46 47 class NamedCursor extends Cursor { 48 NamedCursor(String name) { 49 super(name); 50 } 51 } 52 53 /** 54 * Mac OS X Cocoa-based AWT Toolkit. 55 */ 56 public class LWCToolkit extends LWToolkit { 57 // While it is possible to enumerate all mouse devices 58 // and query them for the number of buttons, the code 59 // that does it is rather complex. Instead, we opt for 60 // the easy way and just support up to 5 mouse buttons, 61 // like Windows. 62 private static final int BUTTONS = 5; 63 64 private static native void initIDs(); 65 66 // On Mac OS we don't need to actually start the new event loop since there is 67 // a mechanic that allows us to just reschedule the next event in a native event loop 68 // for immediate execution and because this method is being called repeatedly we just 69 // executing one such event every time we call this method 70 static native void startNativeNestedEventLoop(); 71 72 // Since we don't start an additional event loop this method is a no-op 73 // and shouldn't be caled, left only for the better understanding of the concept on 74 // other OS'es 75 static native void stopNativeNestedEventLoop(); 76 77 private static CInputMethodDescriptor sInputMethodDescriptor; 78 79 static { 80 System.err.flush(); 81 java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Object>() { 82 public Object run() { 83 System.loadLibrary("awt"); 84 System.loadLibrary("fontmanager"); 85 return null; 86 } 87 }); 88 if (!GraphicsEnvironment.isHeadless()) { 89 initIDs(); 90 } 91 } 92 93 static String getSystemProperty(final String name, final String deflt) { 94 return AccessController.doPrivileged (new PrivilegedAction<String>() { 95 public String run() { 96 return System.getProperty(name, deflt); 97 } 98 }); 99 } 100 101 public LWCToolkit() { 102 SunToolkit.setDataTransfererClassName("sun.lwawt.macosx.CDataTransferer"); 103 104 areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); 105 //set system property if not yet assigned 106 System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); 107 } 108 109 /* 110 * System colors with default initial values, overwritten by toolkit if system values differ and are available. 111 */ 112 private final static int NUM_APPLE_COLORS = 3; 113 public final static int KEYBOARD_FOCUS_COLOR = 0; 114 public final static int INACTIVE_SELECTION_BACKGROUND_COLOR = 1; 115 public final static int INACTIVE_SELECTION_FOREGROUND_COLOR = 2; 116 private static int[] appleColors = { 117 0xFF808080, // keyboardFocusColor = Color.gray; 118 0xFFC0C0C0, // secondarySelectedControlColor 119 0xFF303030, // controlDarkShadowColor 120 }; 121 122 private native void loadNativeColors(final int[] systemColors, final int[] appleColors); 123 124 protected void loadSystemColors(final int[] systemColors) { 125 if (systemColors == null) return; 126 loadNativeColors(systemColors, appleColors); 127 } 128 129 private static class AppleSpecificColor extends Color { 130 int index; 131 public AppleSpecificColor(int index) { 132 super(appleColors[index]); 133 this.index = index; 134 } 135 136 public int getRGB() { 137 return appleColors[index]; 138 } 139 } 140 141 /** 142 * Returns Apple specific colors that we may expose going forward. 143 * 144 */ 145 public static Color getAppleColor(int color) { 146 return new AppleSpecificColor(color); 147 } 148 149 static void systemColorsChanged() { 150 // This is only called from native code. 151 EventQueue.invokeLater(new Runnable() { 152 public void run() { 153 AccessController.doPrivileged (new PrivilegedAction<Object>() { 154 public Object run() { 155 try { 156 final Method updateColorsMethod = SystemColor.class.getDeclaredMethod("updateSystemColors", new Class[0]); 157 updateColorsMethod.setAccessible(true); 158 updateColorsMethod.invoke(null, new Object[0]); 159 } catch (final Throwable e) { 160 e.printStackTrace(); 161 // swallow this if something goes horribly wrong 162 } 163 return null; 164 } 165 }); 166 } 167 }); 168 } 169 170 @Override 171 protected PlatformWindow createPlatformWindow(PeerType peerType) { 172 if (peerType == PeerType.EMBEDDEDFRAME) { 173 return new CPlatformEmbeddedFrame(); 174 } else { 175 return new CPlatformWindow(peerType); 176 } 177 } 178 179 @Override 180 protected PlatformComponent createPlatformComponent() { 181 return new CPlatformComponent(); 182 } 183 184 @Override 185 protected FileDialogPeer createFileDialogPeer(FileDialog target) { 186 return new CFileDialog(target); 187 } 188 189 @Override 190 public MenuPeer createMenu(Menu target) { 191 MenuPeer peer = new CMenu(target); 192 targetCreatedPeer(target, peer); 193 return peer; 194 } 195 196 @Override 197 public MenuBarPeer createMenuBar(MenuBar target) { 198 MenuBarPeer peer = new CMenuBar(target); 199 targetCreatedPeer(target, peer); 200 return peer; 201 } 202 203 @Override 204 public MenuItemPeer createMenuItem(MenuItem target) { 205 MenuItemPeer peer = new CMenuItem(target); 206 targetCreatedPeer(target, peer); 207 return peer; 208 } 209 210 @Override 211 public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) { 212 CheckboxMenuItemPeer peer = new CCheckboxMenuItem(target); 213 targetCreatedPeer(target, peer); 214 return peer; 215 } 216 217 @Override 218 public PopupMenuPeer createPopupMenu(PopupMenu target) { 219 PopupMenuPeer peer = new CPopupMenu(target); 220 targetCreatedPeer(target, peer); 221 return peer; 222 223 } 224 225 @Override 226 public SystemTrayPeer createSystemTray(SystemTray target) { 227 SystemTrayPeer peer = new CSystemTray(); 228 targetCreatedPeer(target, peer); 229 return peer; 230 } 231 232 @Override 233 public TrayIconPeer createTrayIcon(TrayIcon target) { 234 TrayIconPeer peer = new CTrayIcon(target); 235 targetCreatedPeer(target, peer); 236 return peer; 237 } 238 239 @Override 240 public LWCursorManager getCursorManager() { 241 return CCursorManager.getInstance(); 242 } 243 244 @Override 245 public Cursor createCustomCursor(final Image cursor, final Point hotSpot, final String name) throws IndexOutOfBoundsException, HeadlessException { 246 return new CCustomCursor(cursor, hotSpot, name); 247 } 248 249 @Override 250 public Dimension getBestCursorSize(final int preferredWidth, final int preferredHeight) throws HeadlessException { 251 return CCustomCursor.getBestCursorSize(preferredWidth, preferredHeight); 252 } 253 254 @Override 255 protected void platformCleanup() { 256 // TODO Auto-generated method stub 257 258 } 259 260 @Override 261 protected void platformInit() { 262 // TODO Auto-generated method stub 263 264 } 265 266 @Override 267 protected void platformRunMessage() { 268 // TODO Auto-generated method stub 269 270 } 271 272 @Override 273 protected void platformShutdown() { 274 // TODO Auto-generated method stub 275 276 } 277 278 class OSXPlatformFont extends sun.awt.PlatformFont 279 { 280 public OSXPlatformFont(String name, int style) 281 { 282 super(name, style); 283 } 284 protected char getMissingGlyphCharacter() 285 { 286 // Follow up for real implementation 287 return (char)0xfff8; // see http://developer.apple.com/fonts/LastResortFont/ 288 } 289 } 290 public FontPeer getFontPeer(String name, int style) { 291 return new OSXPlatformFont(name, style); 292 } 293 294 @Override 295 protected MouseInfoPeer createMouseInfoPeerImpl() { 296 return new CMouseInfoPeer(); 297 } 298 299 300 @Override 301 protected int getScreenHeight() { 302 return GraphicsEnvironment.getLocalGraphicsEnvironment() 303 .getDefaultScreenDevice().getDefaultConfiguration().getBounds().height; 304 } 305 306 @Override 307 protected int getScreenWidth() { 308 return GraphicsEnvironment.getLocalGraphicsEnvironment() 309 .getDefaultScreenDevice().getDefaultConfiguration().getBounds().width; 310 } 311 312 @Override 313 protected void initializeDesktopProperties() { 314 super.initializeDesktopProperties(); 315 Map <Object, Object> fontHints = new HashMap<Object, Object>(); 316 fontHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 317 fontHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 318 desktopProperties.put(SunToolkit.DESKTOPFONTHINTS, fontHints); 319 desktopProperties.put("awt.mouse.numButtons", BUTTONS); 320 321 // These DnD properties must be set, otherwise Swing ends up spewing NPEs 322 // all over the place. The values came straight off of MToolkit. 323 desktopProperties.put("DnD.Autoscroll.initialDelay", new Integer(50)); 324 desktopProperties.put("DnD.Autoscroll.interval", new Integer(50)); 325 desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5)); 326 327 desktopProperties.put("DnD.isDragImageSupported", new Boolean(true)); 328 329 // Register DnD cursors 330 desktopProperties.put("DnD.Cursor.CopyDrop", new NamedCursor("DnD.Cursor.CopyDrop")); 331 desktopProperties.put("DnD.Cursor.MoveDrop", new NamedCursor("DnD.Cursor.MoveDrop")); 332 desktopProperties.put("DnD.Cursor.LinkDrop", new NamedCursor("DnD.Cursor.LinkDrop")); 333 desktopProperties.put("DnD.Cursor.CopyNoDrop", new NamedCursor("DnD.Cursor.CopyNoDrop")); 334 desktopProperties.put("DnD.Cursor.MoveNoDrop", new NamedCursor("DnD.Cursor.MoveNoDrop")); 335 desktopProperties.put("DnD.Cursor.LinkNoDrop", new NamedCursor("DnD.Cursor.LinkNoDrop")); 336 337 } 338 339 340 /* 341 * The method returns true if some events were processed during that timeout. 342 * @see sun.awt.SunToolkit#syncNativeQueue(long) 343 */ 344 @Override 345 protected boolean syncNativeQueue(long timeout) { 346 return nativeSyncQueue(timeout); 347 } 348 349 @Override 350 public native void beep(); 351 352 @Override 353 public int getScreenResolution() throws HeadlessException { 354 return ((CGraphicsDevice) GraphicsEnvironment 355 .getLocalGraphicsEnvironment().getDefaultScreenDevice()).getScreenResolution(); 356 } 357 358 @Override 359 public Insets getScreenInsets(final GraphicsConfiguration gc) { 360 final CGraphicsConfig cgc = (CGraphicsConfig) gc; 361 final int displayId = cgc.getDevice().getCoreGraphicsScreen(); 362 Rectangle fullScreen, workArea; 363 final long screen = CWrapper.NSScreen.screenByDisplayId(displayId); 364 try { 365 fullScreen = CWrapper.NSScreen.frame(screen).getBounds(); 366 workArea = CWrapper.NSScreen.visibleFrame(screen).getBounds(); 367 } finally { 368 CWrapper.NSObject.release(screen); 369 } 370 // Convert between Cocoa's coordinate system and Java. 371 return new Insets(fullScreen.height - workArea.height - workArea.y, 372 workArea.x, workArea.y, 373 fullScreen.width - workArea.width - workArea.x); 374 } 375 376 @Override 377 public void sync() { 378 // TODO Auto-generated method stub 379 380 } 381 382 @Override 383 public RobotPeer createRobot(Robot target, GraphicsDevice screen) { 384 return new CRobot(target, (CGraphicsDevice)screen); 385 } 386 387 private native boolean isCapsLockOn(); 388 389 /* 390 * NOTE: Among the keys this method is supposed to check, 391 * only Caps Lock works as a true locking key with OS X. 392 * There is no Scroll Lock key on modern Apple keyboards, 393 * and with a PC keyboard plugged in Scroll Lock is simply 394 * ignored: no LED lights up if you press it. 395 * The key located at the same position on Apple keyboards 396 * as Num Lock on PC keyboards is called Clear, doesn't lock 397 * anything and is used for entirely different purpose. 398 */ 399 public boolean getLockingKeyState(int keyCode) throws UnsupportedOperationException { 400 switch (keyCode) { 401 case KeyEvent.VK_NUM_LOCK: 402 case KeyEvent.VK_SCROLL_LOCK: 403 case KeyEvent.VK_KANA_LOCK: 404 throw new UnsupportedOperationException("Toolkit.getLockingKeyState"); 405 406 case KeyEvent.VK_CAPS_LOCK: 407 return isCapsLockOn(); 408 409 default: 410 throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); 411 } 412 } 413 414 //Is it allowed to generate events assigned to extra mouse buttons. 415 //Set to true by default. 416 private static boolean areExtraMouseButtonsEnabled = true; 417 418 public boolean areExtraMouseButtonsEnabled() throws HeadlessException { 419 return areExtraMouseButtonsEnabled; 420 } 421 422 public int getNumberOfButtons(){ 423 return BUTTONS; 424 } 425 426 427 @Override 428 public boolean isTraySupported() { 429 return true; 430 } 431 432 @Override 433 public boolean isAlwaysOnTopSupported() { 434 return true; 435 } 436 437 // Intended to be called from the LWCToolkit.m only. 438 private static void installToolkitThreadNameInJava() { 439 Thread.currentThread().setName(CThreading.APPKIT_THREAD_NAME); 440 } 441 442 @Override 443 public boolean isWindowOpacitySupported() { 444 return true; 445 } 446 447 @Override 448 public boolean isFrameStateSupported(int state) throws HeadlessException { 449 switch (state) { 450 case Frame.NORMAL: 451 case Frame.ICONIFIED: 452 case Frame.MAXIMIZED_BOTH: 453 return true; 454 default: 455 return false; 456 } 457 } 458 459 /** 460 * Determines which modifier key is the appropriate accelerator 461 * key for menu shortcuts. 462 * <p> 463 * Menu shortcuts, which are embodied in the 464 * <code>MenuShortcut</code> class, are handled by the 465 * <code>MenuBar</code> class. 466 * <p> 467 * By default, this method returns <code>Event.CTRL_MASK</code>. 468 * Toolkit implementations should override this method if the 469 * <b>Control</b> key isn't the correct key for accelerators. 470 * @return the modifier mask on the <code>Event</code> class 471 * that is used for menu shortcuts on this toolkit. 472 * @see java.awt.MenuBar 473 * @see java.awt.MenuShortcut 474 * @since JDK1.1 475 */ 476 public int getMenuShortcutKeyMask() { 477 return Event.META_MASK; 478 } 479 480 @Override 481 public Image getImage(final String filename) { 482 final Image nsImage = checkForNSImage(filename); 483 if (nsImage != null) return nsImage; 484 485 return super.getImage(filename); 486 } 487 488 static final String nsImagePrefix = "NSImage://"; 489 protected Image checkForNSImage(final String imageName) { 490 if (imageName == null) return null; 491 if (!imageName.startsWith(nsImagePrefix)) return null; 492 return CImage.getCreator().createImageFromName(imageName.substring(nsImagePrefix.length())); 493 } 494 495 // Thread-safe Object.equals() called from native 496 public static boolean doEquals(final Object a, final Object b, Component c) { 497 if (a == b) return true; 498 499 final boolean[] ret = new boolean[1]; 500 501 try { invokeAndWait(new Runnable() { public void run() { synchronized(ret) { 502 ret[0] = a.equals(b); 503 }}}, c); } catch (Exception e) { e.printStackTrace(); } 504 505 synchronized(ret) { return ret[0]; } 506 } 507 508 // Kicks an event over to the appropriate eventqueue and waits for it to finish 509 // To avoid deadlocking, we manually run the NSRunLoop while waiting 510 // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop 511 // The CInvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop 512 public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { 513 invokeAndWait(event, component, true); 514 } 515 516 public static <T> T invokeAndWait(final Callable<T> callable, Component component) throws Exception { 517 final CallableWrapper<T> wrapper = new CallableWrapper<T>(callable); 518 invokeAndWait(wrapper, component); 519 return wrapper.getResult(); 520 } 521 522 static final class CallableWrapper<T> implements Runnable { 523 final Callable<T> callable; 524 T object; 525 Exception e; 526 527 public CallableWrapper(final Callable<T> callable) { 528 this.callable = callable; 529 } 530 531 public void run() { 532 try { 533 object = callable.call(); 534 } catch (final Exception e) { 535 this.e = e; 536 } 537 } 538 539 public T getResult() throws Exception { 540 if (e != null) throw e; 541 return object; 542 } 543 } 544 545 public static void invokeAndWait(Runnable event, Component component, boolean detectDeadlocks) throws InterruptedException, InvocationTargetException { 546 long mediator = createAWTRunLoopMediator(); 547 548 InvocationEvent invocationEvent = new CPeerEvent(event, mediator); 549 550 if (component != null) { 551 AppContext appContext = SunToolkit.targetToAppContext(component); 552 SunToolkit.postEvent(appContext, invocationEvent); 553 554 // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock 555 sun.awt.SunToolkitSubclass.flushPendingEvents(appContext); 556 } else { 557 // This should be the equivalent to EventQueue.invokeAndWait 558 ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); 559 } 560 561 doAWTRunLoop(mediator, true, detectDeadlocks); 562 563 Throwable eventException = invocationEvent.getException(); 564 if (eventException != null) { 565 if (eventException instanceof UndeclaredThrowableException) { 566 eventException = ((UndeclaredThrowableException)eventException).getUndeclaredThrowable(); 567 } 568 throw new InvocationTargetException(eventException); 569 } 570 } 571 572 public static void invokeLater(Runnable event, Component component) throws InvocationTargetException { 573 final InvocationEvent invocationEvent = new CPeerEvent(event, 0); 574 575 if (component != null) { 576 final AppContext appContext = SunToolkit.targetToAppContext(component); 577 SunToolkit.postEvent(appContext, invocationEvent); 578 579 // 3746956 - flush events from PostEventQueue to prevent them from getting stuck and causing a deadlock 580 sun.awt.SunToolkitSubclass.flushPendingEvents(appContext); 581 } else { 582 // This should be the equivalent to EventQueue.invokeAndWait 583 ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent); 584 } 585 586 final Throwable eventException = invocationEvent.getException(); 587 if (eventException == null) return; 588 589 if (eventException instanceof UndeclaredThrowableException) { 590 throw new InvocationTargetException(((UndeclaredThrowableException)eventException).getUndeclaredThrowable()); 591 } 592 throw new InvocationTargetException(eventException); 593 } 594 595 // This exists purely to get around permissions issues with getSystemEventQueueImpl 596 EventQueue getSystemEventQueueForInvokeAndWait() { 597 return getSystemEventQueueImpl(); 598 } 599 600 601 // DnD support 602 603 public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 604 DragSourceContextPeer dscp = CDragSourceContextPeer.createDragSourceContextPeer(dge); 605 606 return dscp; 607 } 608 609 public <T extends DragGestureRecognizer> T createDragGestureRecognizer(Class<T> abstractRecognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl) { 610 DragGestureRecognizer dgr = null; 611 612 // Create a new mouse drag gesture recognizer if we have a class match: 613 if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) 614 dgr = new CMouseDragGestureRecognizer(ds, c, srcActions, dgl); 615 616 return (T)dgr; 617 } 618 619 // InputMethodSupport Method 620 /** 621 * Returns the default keyboard locale of the underlying operating system 622 */ 623 public Locale getDefaultKeyboardLocale() { 624 Locale locale = CInputMethod.getNativeLocale(); 625 626 if (locale == null) { 627 return super.getDefaultKeyboardLocale(); 628 } 629 630 return locale; 631 } 632 633 public java.awt.im.spi.InputMethodDescriptor getInputMethodAdapterDescriptor() { 634 if (sInputMethodDescriptor == null) 635 sInputMethodDescriptor = new CInputMethodDescriptor(); 636 637 return sInputMethodDescriptor; 638 } 639 640 /** 641 * Returns a map of visual attributes for thelevel description 642 * of the given input method highlight, or null if no mapping is found. 643 * The style field of the input method highlight is ignored. The map 644 * returned is unmodifiable. 645 * @param highlight input method highlight 646 * @return style attribute map, or null 647 * @since 1.3 648 */ 649 public Map mapInputMethodHighlight(InputMethodHighlight highlight) { 650 return CInputMethod.mapInputMethodHighlight(highlight); 651 } 652 653 /** 654 * Returns key modifiers used by Swing to set up a focus accelerator key stroke. 655 */ 656 @Override 657 public int getFocusAcceleratorKeyMask() { 658 return InputEvent.CTRL_MASK | InputEvent.ALT_MASK; 659 } 660 661 /** 662 * Tests whether specified key modifiers mask can be used to enter a printable 663 * character. 664 */ 665 @Override 666 public boolean isPrintableCharacterModifiersMask(int mods) { 667 return ((mods & (InputEvent.META_MASK | InputEvent.CTRL_MASK)) == 0); 668 } 669 670 /** 671 * Returns whether popup is allowed to be shown above the task bar. 672 */ 673 @Override 674 public boolean canPopupOverlapTaskBar() { 675 return false; 676 } 677 678 // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early 679 // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop 680 public static class CPeerEvent extends PeerEvent { 681 private long _mediator = 0; 682 683 public CPeerEvent(Runnable runnable, long mediator) { 684 super(Toolkit.getDefaultToolkit(), runnable, null, true, 0); 685 _mediator = mediator; 686 } 687 688 public void dispatch() { 689 try { 690 super.dispatch(); 691 } finally { 692 if (_mediator != 0) { 693 LWCToolkit.stopAWTRunLoop(_mediator); 694 } 695 } 696 } 697 } 698 699 // Call through to native methods 700 public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); } 701 public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); } 702 703 private static Boolean sunAwtDisableCALayers = null; 704 705 /** 706 * Returns the value of "sun.awt.disableCALayers" property. Default 707 * value is {@code false}. 708 */ 709 public synchronized static boolean getSunAwtDisableCALayers() { 710 if (sunAwtDisableCALayers == null) { 711 sunAwtDisableCALayers = 712 getBooleanSystemProperty("sun.awt.disableCALayers"); 713 } 714 return sunAwtDisableCALayers.booleanValue(); 715 } 716 717 718 /* 719 * Returns true if the application (one of its windows) owns keyboard focus. 720 */ 721 public native boolean isApplicationActive(); 722 723 /************************ 724 * Native methods section 725 ************************/ 726 727 // These are public because they are accessed from WebKitPluginObject in JavaDeploy 728 // Basic usage: 729 // createAWTRunLoopMediator. Start client code on another thread. doAWTRunLoop. When client code is finished, stopAWTRunLoop. 730 public static native long createAWTRunLoopMediator(); 731 public static native void doAWTRunLoop(long mediator, boolean awtMode, boolean detectDeadlocks); 732 public static native void stopAWTRunLoop(long mediator); 733 734 private native boolean nativeSyncQueue(long timeout); 735 736 @Override 737 public Clipboard createPlatformClipboard() { 738 return new CClipboard("System"); 739 } 740 741 @Override 742 public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) { 743 return (exclusionType == null) || 744 (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) || 745 (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) || 746 (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); 747 } 748 749 @Override 750 public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) { 751 //TODO: FileDialog blocks excluded windows... 752 //TODO: Test: 2 file dialogs, separate AppContexts: a) Dialog 1 blocked, shouldn't be. Frame 4 blocked (shouldn't be). 753 return (modalityType == null) || 754 (modalityType == Dialog.ModalityType.MODELESS) || 755 (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) || 756 (modalityType == Dialog.ModalityType.APPLICATION_MODAL) || 757 (modalityType == Dialog.ModalityType.TOOLKIT_MODAL); 758 } 759 760 @Override 761 public boolean isWindowTranslucencySupported() { 762 return true; 763 } 764 765 @Override 766 public boolean isTranslucencyCapable(GraphicsConfiguration gc) { 767 return true; 768 } 769 770 @Override 771 public boolean enableInputMethodsForTextComponent() { 772 return true; 773 } 774 }