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