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