1 /* 2 * Copyright (c) 2002, 2020, 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.awt.X11; 27 28 import java.awt.AWTError; 29 import java.awt.AWTException; 30 import java.awt.Button; 31 import java.awt.Canvas; 32 import java.awt.Checkbox; 33 import java.awt.CheckboxMenuItem; 34 import java.awt.Choice; 35 import java.awt.Color; 36 import java.awt.Component; 37 import java.awt.Cursor; 38 import java.awt.Desktop; 39 import java.awt.Dialog; 40 import java.awt.Dimension; 41 import java.awt.EventQueue; 42 import java.awt.FileDialog; 43 import java.awt.Frame; 44 import java.awt.GraphicsConfiguration; 45 import java.awt.GraphicsDevice; 46 import java.awt.GraphicsEnvironment; 47 import java.awt.HeadlessException; 48 import java.awt.Image; 49 import java.awt.Insets; 50 import java.awt.JobAttributes; 51 import java.awt.Label; 52 import java.awt.Menu; 53 import java.awt.MenuBar; 54 import java.awt.MenuItem; 55 import java.awt.PageAttributes; 56 import java.awt.Panel; 57 import java.awt.Point; 58 import java.awt.PopupMenu; 59 import java.awt.PrintJob; 60 import java.awt.Rectangle; 61 import java.awt.ScrollPane; 62 import java.awt.Scrollbar; 63 import java.awt.SystemColor; 64 import java.awt.SystemTray; 65 import java.awt.Taskbar; 66 import java.awt.TextArea; 67 import java.awt.TextField; 68 import java.awt.Toolkit; 69 import java.awt.TrayIcon; 70 import java.awt.Window; 71 import java.awt.datatransfer.Clipboard; 72 import java.awt.dnd.DragGestureEvent; 73 import java.awt.dnd.DragGestureListener; 74 import java.awt.dnd.DragGestureRecognizer; 75 import java.awt.dnd.DragSource; 76 import java.awt.dnd.InvalidDnDOperationException; 77 import java.awt.dnd.MouseDragGestureRecognizer; 78 import java.awt.dnd.peer.DragSourceContextPeer; 79 import java.awt.event.InputEvent; 80 import java.awt.event.KeyEvent; 81 import java.awt.event.MouseEvent; 82 import java.awt.font.TextAttribute; 83 import java.awt.im.InputMethodHighlight; 84 import java.awt.im.spi.InputMethodDescriptor; 85 import java.awt.peer.ButtonPeer; 86 import java.awt.peer.CanvasPeer; 87 import java.awt.peer.CheckboxMenuItemPeer; 88 import java.awt.peer.CheckboxPeer; 89 import java.awt.peer.ChoicePeer; 90 import java.awt.peer.DesktopPeer; 91 import java.awt.peer.DialogPeer; 92 import java.awt.peer.FileDialogPeer; 93 import java.awt.peer.FontPeer; 94 import java.awt.peer.FramePeer; 95 import java.awt.peer.KeyboardFocusManagerPeer; 96 import java.awt.peer.LabelPeer; 97 import java.awt.peer.ListPeer; 98 import java.awt.peer.MenuBarPeer; 99 import java.awt.peer.MenuItemPeer; 100 import java.awt.peer.MenuPeer; 101 import java.awt.peer.MouseInfoPeer; 102 import java.awt.peer.PanelPeer; 103 import java.awt.peer.PopupMenuPeer; 104 import java.awt.peer.RobotPeer; 105 import java.awt.peer.ScrollPanePeer; 106 import java.awt.peer.ScrollbarPeer; 107 import java.awt.peer.SystemTrayPeer; 108 import java.awt.peer.TaskbarPeer; 109 import java.awt.peer.TextAreaPeer; 110 import java.awt.peer.TextFieldPeer; 111 import java.awt.peer.TrayIconPeer; 112 import java.awt.peer.WindowPeer; 113 import java.beans.PropertyChangeListener; 114 import java.security.AccessController; 115 import java.security.PrivilegedAction; 116 import java.util.ArrayList; 117 import java.util.Collection; 118 import java.util.HashMap; 119 import java.util.Iterator; 120 import java.util.LinkedList; 121 import java.util.Map; 122 import java.util.NoSuchElementException; 123 import java.util.Properties; 124 import java.util.SortedMap; 125 import java.util.TreeMap; 126 import java.util.Vector; 127 128 import javax.swing.LookAndFeel; 129 import javax.swing.UIDefaults; 130 131 import sun.awt.AWTAccessor; 132 import sun.awt.AWTPermissions; 133 import sun.awt.AppContext; 134 import sun.awt.DisplayChangedListener; 135 import sun.awt.LightweightFrame; 136 import sun.awt.SunToolkit; 137 import sun.awt.UNIXToolkit; 138 import sun.awt.X11GraphicsConfig; 139 import sun.awt.X11GraphicsDevice; 140 import sun.awt.X11GraphicsEnvironment; 141 import sun.awt.XSettings; 142 import sun.awt.datatransfer.DataTransferer; 143 import sun.awt.util.PerformanceLogger; 144 import sun.awt.util.ThreadGroupUtils; 145 import sun.font.FontConfigManager; 146 import sun.java2d.SunGraphicsEnvironment; 147 import sun.print.PrintJob2D; 148 import sun.security.action.GetBooleanAction; 149 import sun.security.action.GetPropertyAction; 150 import sun.util.logging.PlatformLogger; 151 152 import static sun.awt.X11.XlibUtil.scaleDown; 153 154 public final class XToolkit extends UNIXToolkit implements Runnable { 155 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit"); 156 private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XToolkit"); 157 private static final PlatformLogger timeoutTaskLog = PlatformLogger.getLogger("sun.awt.X11.timeoutTask.XToolkit"); 158 private static final PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XToolkit"); 159 private static final PlatformLogger backingStoreLog = PlatformLogger.getLogger("sun.awt.X11.backingStore.XToolkit"); 160 161 //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME. 162 //We use the same hardcoded constant. 163 private static final int AWT_MULTICLICK_DEFAULT_TIME = 500; 164 165 static final boolean PRIMARY_LOOP = false; 166 static final boolean SECONDARY_LOOP = true; 167 168 private static String awtAppClassName = null; 169 170 // the system clipboard - CLIPBOARD selection 171 XClipboard clipboard; 172 // the system selection - PRIMARY selection 173 XClipboard selection; 174 175 // Dynamic Layout Resize client code setting 176 protected static boolean dynamicLayoutSetting = false; 177 178 //Is it allowed to generate events assigned to extra mouse buttons. 179 //Set to true by default. 180 private static boolean areExtraMouseButtonsEnabled = true; 181 182 /** 183 * True when the x settings have been loaded. 184 */ 185 private boolean loadedXSettings; 186 187 /** 188 * XSETTINGS for the default screen. 189 * <p> 190 */ 191 private XSettings xs; 192 193 private FontConfigManager fcManager = new FontConfigManager(); 194 195 static int arrowCursor; 196 static TreeMap<Long, XBaseWindow> winMap = new TreeMap<>(); 197 static HashMap<Object, Object> specialPeerMap = new HashMap<>(); 198 static HashMap<Long, Collection<XEventDispatcher>> winToDispatcher = new HashMap<>(); 199 static UIDefaults uidefaults; 200 static final X11GraphicsEnvironment localEnv; 201 private static final X11GraphicsDevice device; 202 private static final long display; 203 static int awt_multiclick_time; 204 static boolean securityWarningEnabled; 205 206 /** 207 * Dimensions of default virtual screen in pixels. These values are used to 208 * limit the maximum size of the window. 209 */ 210 private static volatile int maxWindowWidthInPixels = -1; 211 private static volatile int maxWindowHeightInPixels = -1; 212 213 private static XMouseInfoPeer xPeer; 214 215 static { initSecurityWarning()216 initSecurityWarning(); 217 if (GraphicsEnvironment.isHeadless()) { 218 localEnv = null; 219 device = null; 220 display = 0; 221 } else { 222 localEnv = (X11GraphicsEnvironment) GraphicsEnvironment 223 .getLocalGraphicsEnvironment(); 224 device = (X11GraphicsDevice) localEnv.getDefaultScreenDevice(); 225 display = device.getDisplay(); setupModifierMap()226 setupModifierMap(); initIDs()227 initIDs(); setBackingStoreType()228 setBackingStoreType(); 229 } 230 } 231 232 /* 233 * Return (potentially) platform specific display timeout for the 234 * tray icon 235 */ getTrayIconDisplayTimeout()236 static native long getTrayIconDisplayTimeout(); 237 initIDs()238 private static native void initIDs(); waitForEvents(long nextTaskTime)239 static native void waitForEvents(long nextTaskTime); 240 static Thread toolkitThread; isToolkitThread()241 static boolean isToolkitThread() { 242 return Thread.currentThread() == toolkitThread; 243 } 244 initSecurityWarning()245 static void initSecurityWarning() { 246 // Enable warning only for internal builds 247 String runtime = AccessController.doPrivileged( 248 new GetPropertyAction("java.runtime.version")); 249 securityWarningEnabled = (runtime != null && runtime.contains("internal")); 250 } 251 isSecurityWarningEnabled()252 static boolean isSecurityWarningEnabled() { 253 return securityWarningEnabled; 254 } 255 awt_output_flush()256 static native void awt_output_flush(); 257 awtFUnlock()258 static void awtFUnlock() { 259 awtUnlock(); 260 awt_output_flush(); 261 } 262 263 nativeLoadSystemColors(int[] systemColors)264 private native void nativeLoadSystemColors(int[] systemColors); 265 getUIDefaults()266 static UIDefaults getUIDefaults() { 267 if (uidefaults == null) { 268 initUIDefaults(); 269 } 270 return uidefaults; 271 } 272 273 @Override loadSystemColors(int[] systemColors)274 public void loadSystemColors(int[] systemColors) { 275 nativeLoadSystemColors(systemColors); 276 MotifColorUtilities.loadSystemColors(systemColors); 277 } 278 279 280 initUIDefaults()281 static void initUIDefaults() { 282 try { 283 // Load Defaults from MotifLookAndFeel 284 285 // This dummy load is necessary to get SystemColor initialized. !!!!!! 286 Color c = SystemColor.text; 287 288 LookAndFeel lnf = new XAWTLookAndFeel(); 289 uidefaults = lnf.getDefaults(); 290 } 291 catch (Exception e) 292 { 293 e.printStackTrace(); 294 } 295 } 296 297 /** 298 * Returns the X11 Display of the default screen device. 299 * 300 * @return X11 Display 301 * @throws AWTError thrown if local GraphicsEnvironment is null, which 302 * means we are in the headless environment 303 */ getDisplay()304 public static long getDisplay() { 305 if (localEnv == null) { 306 throw new AWTError("Local GraphicsEnvironment must not be null"); 307 } 308 return display; 309 } 310 getDefaultRootWindow()311 public static long getDefaultRootWindow() { 312 awtLock(); 313 try { 314 long res = XlibWrapper.RootWindow(XToolkit.getDisplay(), 315 XlibWrapper.DefaultScreen(XToolkit.getDisplay())); 316 317 if (res == 0) { 318 throw new IllegalStateException("Root window must not be null"); 319 } 320 return res; 321 } finally { 322 awtUnlock(); 323 } 324 } 325 init()326 void init() { 327 awtLock(); 328 try { 329 XlibWrapper.XSupportsLocale(); 330 if (XlibWrapper.XSetLocaleModifiers("") == null) { 331 log.finer("X locale modifiers are not supported, using default"); 332 } 333 tryXKB(); 334 335 arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), 336 XCursorFontConstants.XC_arrow); 337 final String extraButtons = "sun.awt.enableExtraMouseButtons"; 338 AccessController.doPrivileged((PrivilegedAction<Void>) () -> { 339 areExtraMouseButtonsEnabled = 340 Boolean.parseBoolean(System.getProperty(extraButtons, "true")); 341 //set system property if not yet assigned 342 System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled); 343 return null; 344 }); 345 // Detect display mode changes 346 XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask); 347 XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() { 348 @Override 349 public void dispatchEvent(XEvent ev) { 350 if (ev.get_type() == XConstants.ConfigureNotify) { 351 awtUnlock(); 352 try { 353 ((X11GraphicsEnvironment)GraphicsEnvironment. 354 getLocalGraphicsEnvironment()). 355 displayChanged(); 356 } finally { 357 awtLock(); 358 } 359 } 360 } 361 }); 362 } finally { 363 awtUnlock(); 364 } 365 PrivilegedAction<Void> a = () -> { 366 Runnable r = () -> { 367 XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); 368 if (peer != null) { 369 peer.dispose(); 370 } 371 if (xs != null) { 372 ((XAWTXSettings)xs).dispose(); 373 } 374 freeXKB(); 375 if (log.isLoggable(PlatformLogger.Level.FINE)) { 376 dumpPeers(); 377 } 378 }; 379 String name = "XToolkt-Shutdown-Thread"; 380 Thread shutdownThread = new Thread( 381 ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false); 382 shutdownThread.setContextClassLoader(null); 383 Runtime.getRuntime().addShutdownHook(shutdownThread); 384 return null; 385 }; 386 AccessController.doPrivileged(a); 387 } 388 getCorrectXIDString(String val)389 static String getCorrectXIDString(String val) { 390 if (val != null) { 391 return val.replace('.', '-'); 392 } else { 393 return val; 394 } 395 } 396 getEnv(String key)397 static native String getEnv(String key); 398 399 getAWTAppClassName()400 static String getAWTAppClassName() { 401 return awtAppClassName; 402 } 403 XToolkit()404 public XToolkit() { 405 super(); 406 if (PerformanceLogger.loggingEnabled()) { 407 PerformanceLogger.setTime("XToolkit construction"); 408 } 409 410 if (!GraphicsEnvironment.isHeadless()) { 411 String mainClassName = null; 412 413 StackTraceElement[] trace = (new Throwable()).getStackTrace(); 414 int bottom = trace.length - 1; 415 if (bottom >= 0) { 416 mainClassName = trace[bottom].getClassName(); 417 } 418 if (mainClassName == null || mainClassName.isEmpty()) { 419 mainClassName = "AWT"; 420 } 421 awtAppClassName = getCorrectXIDString(mainClassName); 422 423 init(); 424 XWM.init(); 425 426 toolkitThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> { 427 String name = "AWT-XAWT"; 428 Thread thread = new Thread( 429 ThreadGroupUtils.getRootThreadGroup(), this, name, 430 0, false); 431 thread.setContextClassLoader(null); 432 thread.setPriority(Thread.NORM_PRIORITY + 1); 433 thread.setDaemon(true); 434 return thread; 435 }); 436 toolkitThread.start(); 437 } 438 } 439 440 @Override createButton(Button target)441 public ButtonPeer createButton(Button target) { 442 ButtonPeer peer = new XButtonPeer(target); 443 targetCreatedPeer(target, peer); 444 return peer; 445 } 446 447 @Override createLightweightFrame(LightweightFrame target)448 public FramePeer createLightweightFrame(LightweightFrame target) { 449 FramePeer peer = new XLightweightFramePeer(target); 450 targetCreatedPeer(target, peer); 451 return peer; 452 } 453 454 @Override createFrame(Frame target)455 public FramePeer createFrame(Frame target) { 456 FramePeer peer = new XFramePeer(target); 457 targetCreatedPeer(target, peer); 458 return peer; 459 } 460 addToWinMap(long window, XBaseWindow xwin)461 static void addToWinMap(long window, XBaseWindow xwin) 462 { 463 synchronized(winMap) { 464 winMap.put(Long.valueOf(window),xwin); 465 } 466 } 467 removeFromWinMap(long window, XBaseWindow xwin)468 static void removeFromWinMap(long window, XBaseWindow xwin) { 469 synchronized(winMap) { 470 winMap.remove(Long.valueOf(window)); 471 } 472 } windowToXWindow(long window)473 static XBaseWindow windowToXWindow(long window) { 474 synchronized(winMap) { 475 return winMap.get(Long.valueOf(window)); 476 } 477 } 478 addEventDispatcher(long window, XEventDispatcher dispatcher)479 static void addEventDispatcher(long window, XEventDispatcher dispatcher) { 480 synchronized(winToDispatcher) { 481 Long key = Long.valueOf(window); 482 Collection<XEventDispatcher> dispatchers = winToDispatcher.get(key); 483 if (dispatchers == null) { 484 dispatchers = new Vector<>(); 485 winToDispatcher.put(key, dispatchers); 486 } 487 dispatchers.add(dispatcher); 488 } 489 } removeEventDispatcher(long window, XEventDispatcher dispatcher)490 static void removeEventDispatcher(long window, XEventDispatcher dispatcher) { 491 synchronized(winToDispatcher) { 492 Long key = Long.valueOf(window); 493 Collection<XEventDispatcher> dispatchers = winToDispatcher.get(key); 494 if (dispatchers != null) { 495 dispatchers.remove(dispatcher); 496 } 497 } 498 } 499 500 private Point lastCursorPos; 501 502 /** 503 * Returns whether there is last remembered cursor position. The 504 * position is remembered from X mouse events on our peers. The 505 * position is stored in {@code p}. 506 * @return true, if there is remembered last cursor position, 507 * false otherwise 508 */ getLastCursorPos(Point p)509 boolean getLastCursorPos(Point p) { 510 awtLock(); 511 try { 512 if (lastCursorPos == null) { 513 return false; 514 } 515 p.setLocation(lastCursorPos); 516 return true; 517 } finally { 518 awtUnlock(); 519 } 520 } 521 processGlobalMotionEvent(XEvent e, XBaseWindow win)522 private void processGlobalMotionEvent(XEvent e, XBaseWindow win) { 523 // Only our windows guaranteely generate MotionNotify, so we 524 // should track enter/leave, to catch the moment when to 525 // switch to XQueryPointer 526 if (e.get_type() == XConstants.MotionNotify) { 527 XMotionEvent ev = e.get_xmotion(); 528 awtLock(); 529 try { 530 if (lastCursorPos == null) { 531 lastCursorPos = new Point(win.scaleDown(ev.get_x_root()), 532 win.scaleDown(ev.get_y_root())); 533 } else { 534 lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()), 535 win.scaleDown(ev.get_y_root())); 536 } 537 } finally { 538 awtUnlock(); 539 } 540 } else if (e.get_type() == XConstants.LeaveNotify) { 541 // Leave from our window 542 awtLock(); 543 try { 544 lastCursorPos = null; 545 } finally { 546 awtUnlock(); 547 } 548 } else if (e.get_type() == XConstants.EnterNotify) { 549 // Entrance into our window 550 XCrossingEvent ev = e.get_xcrossing(); 551 awtLock(); 552 try { 553 if (lastCursorPos == null) { 554 lastCursorPos = new Point(win.scaleDown(ev.get_x_root()), 555 win.scaleDown(ev.get_y_root())); 556 } else { 557 lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()), 558 win.scaleDown(ev.get_y_root())); 559 } 560 } finally { 561 awtUnlock(); 562 } 563 } 564 } 565 566 public interface XEventListener { eventProcessed(XEvent e)567 public void eventProcessed(XEvent e); 568 } 569 570 private Collection<XEventListener> listeners = new LinkedList<XEventListener>(); 571 addXEventListener(XEventListener listener)572 public void addXEventListener(XEventListener listener) { 573 synchronized (listeners) { 574 listeners.add(listener); 575 } 576 } 577 notifyListeners(XEvent xev)578 private void notifyListeners(XEvent xev) { 579 synchronized (listeners) { 580 if (listeners.size() == 0) return; 581 582 XEvent copy = xev.clone(); 583 try { 584 for (XEventListener listener : listeners) { 585 listener.eventProcessed(copy); 586 } 587 } finally { 588 copy.dispose(); 589 } 590 } 591 } 592 dispatchEvent(XEvent ev)593 private void dispatchEvent(XEvent ev) { 594 final XAnyEvent xany = ev.get_xany(); 595 596 XBaseWindow baseWindow = windowToXWindow(xany.get_window()); 597 if (baseWindow != null && (ev.get_type() == XConstants.MotionNotify 598 || ev.get_type() == XConstants.EnterNotify 599 || ev.get_type() == XConstants.LeaveNotify)) { 600 processGlobalMotionEvent(ev, baseWindow); 601 } 602 603 if( ev.get_type() == XConstants.MappingNotify ) { 604 // The 'window' field in this event is unused. 605 // This application itself does nothing to initiate such an event 606 // (no calls of XChangeKeyboardMapping etc.). 607 // SunRay server sends this event to the application once on every 608 // keyboard (not just layout) change which means, quite seldom. 609 XlibWrapper.XRefreshKeyboardMapping(ev.pData); 610 resetKeyboardSniffer(); 611 setupModifierMap(); 612 } 613 XBaseWindow.dispatchToWindow(ev); 614 615 Collection<XEventDispatcher> dispatchers = null; 616 synchronized(winToDispatcher) { 617 Long key = Long.valueOf(xany.get_window()); 618 dispatchers = winToDispatcher.get(key); 619 if (dispatchers != null) { // Clone it to avoid synchronization during dispatching 620 dispatchers = new Vector<>(dispatchers); 621 } 622 } 623 if (dispatchers != null) { 624 Iterator<XEventDispatcher> iter = dispatchers.iterator(); 625 while (iter.hasNext()) { 626 XEventDispatcher disp = iter.next(); 627 disp.dispatchEvent(ev); 628 } 629 } 630 notifyListeners(ev); 631 } 632 processException(Throwable thr)633 static void processException(Throwable thr) { 634 if (log.isLoggable(PlatformLogger.Level.WARNING)) { 635 log.warning("Exception on Toolkit thread", thr); 636 } 637 } 638 awt_toolkit_init()639 static native void awt_toolkit_init(); 640 641 @Override run()642 public void run() { 643 awt_toolkit_init(); 644 run(PRIMARY_LOOP); 645 } 646 run(boolean loop)647 public void run(boolean loop) 648 { 649 XEvent ev = new XEvent(); 650 while(true) { 651 // Fix for 6829923: we should gracefully handle toolkit thread interruption 652 if (Thread.currentThread().isInterrupted()) { 653 // We expect interruption from the AppContext.dispose() method only. 654 // If the thread is interrupted from another place, let's skip it 655 // for compatibility reasons. Probably some time later we'll remove 656 // the check for AppContext.isDisposed() and will unconditionally 657 // break the loop here. 658 if (AppContext.getAppContext().isDisposed()) { 659 break; 660 } 661 } 662 awtLock(); 663 try { 664 if (loop == SECONDARY_LOOP) { 665 // In the secondary loop we may have already acquired awt_lock 666 // several times, so waitForEvents() might be unable to release 667 // the awt_lock and this causes lock up. 668 // For now, we just avoid waitForEvents in the secondary loop. 669 if (!XlibWrapper.XNextSecondaryLoopEvent(getDisplay(),ev.pData)) { 670 break; 671 } 672 } else { 673 callTimeoutTasks(); 674 // If no events are queued, waitForEvents() causes calls to 675 // awtUnlock(), awtJNI_ThreadYield, poll, awtLock(), 676 // so it spends most of its time in poll, without holding the lock. 677 while ((XlibWrapper.XEventsQueued(getDisplay(), XConstants.QueuedAfterReading) == 0) && 678 (XlibWrapper.XEventsQueued(getDisplay(), XConstants.QueuedAfterFlush) == 0)) { 679 callTimeoutTasks(); 680 waitForEvents(getNextTaskTime()); 681 } 682 XlibWrapper.XNextEvent(getDisplay(),ev.pData); 683 } 684 685 if (ev.get_type() != XConstants.NoExpose) { 686 eventNumber++; 687 } 688 if (awt_UseXKB_Calls && ev.get_type() == awt_XKBBaseEventCode) { 689 processXkbChanges(ev); 690 } 691 692 if (XDropTargetEventProcessor.processEvent(ev) || 693 XDragSourceContextPeer.processEvent(ev)) { 694 continue; 695 } 696 697 if (eventLog.isLoggable(PlatformLogger.Level.FINER)) { 698 eventLog.finer("{0}", ev); 699 } 700 701 // Check if input method consumes the event 702 long w = 0; 703 if (windowToXWindow(ev.get_xany().get_window()) != null) { 704 Component owner = 705 XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner(); 706 if (owner != null) { 707 XWindow ownerWindow = AWTAccessor.getComponentAccessor().getPeer(owner); 708 if (ownerWindow != null) { 709 w = ownerWindow.getContentWindow(); 710 } 711 } 712 } 713 if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && ( 714 ev.get_type() == XConstants.KeyPress 715 || ev.get_type() == XConstants.KeyRelease)) { 716 keyEventLog.fine("before XFilterEvent:" + ev); 717 } 718 if (XlibWrapper.XFilterEvent(ev.getPData(), w)) { 719 continue; 720 } 721 if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && ( 722 ev.get_type() == XConstants.KeyPress 723 || ev.get_type() == XConstants.KeyRelease)) { 724 keyEventLog.fine( 725 "after XFilterEvent:" + ev); // IS THIS CORRECT? 726 } 727 728 dispatchEvent(ev); 729 } catch (ThreadDeath td) { 730 XBaseWindow.ungrabInput(); 731 return; 732 } catch (Throwable thr) { 733 XBaseWindow.ungrabInput(); 734 processException(thr); 735 } finally { 736 awtUnlock(); 737 } 738 } 739 } 740 741 /** 742 * Listener installed to detect display changes. 743 */ 744 private static final DisplayChangedListener displayChangedHandler = 745 new DisplayChangedListener() { 746 @Override 747 public void displayChanged() { 748 // 7045370: Reset the cached values 749 XToolkit.maxWindowWidthInPixels = -1; 750 XToolkit.maxWindowHeightInPixels = -1; 751 } 752 753 @Override 754 public void paletteChanged() { 755 } 756 }; 757 758 static { 759 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 760 if (ge instanceof SunGraphicsEnvironment) { addDisplayChangedListener( displayChangedHandler)761 ((SunGraphicsEnvironment) ge).addDisplayChangedListener( 762 displayChangedHandler); 763 } 764 } 765 initScreenSize()766 private static void initScreenSize() { 767 if (maxWindowWidthInPixels == -1 || maxWindowHeightInPixels == -1) { 768 awtLock(); 769 try { 770 XWindowAttributes pattr = new XWindowAttributes(); 771 try { 772 XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 773 XToolkit.getDefaultRootWindow(), 774 pattr.pData); 775 maxWindowWidthInPixels = pattr.get_width(); 776 maxWindowHeightInPixels = pattr.get_height(); 777 } finally { 778 pattr.dispose(); 779 } 780 } finally { 781 awtUnlock(); 782 } 783 } 784 } 785 getMaxWindowWidthInPixels()786 static int getMaxWindowWidthInPixels() { 787 initScreenSize(); 788 return maxWindowWidthInPixels; 789 } 790 getMaxWindowHeightInPixels()791 static int getMaxWindowHeightInPixels() { 792 initScreenSize(); 793 return maxWindowHeightInPixels; 794 } 795 getWorkArea(long root, int scale)796 private static Rectangle getWorkArea(long root, int scale) 797 { 798 XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA"); 799 800 long native_ptr = Native.allocateLongArray(4); 801 try 802 { 803 boolean workareaPresent = XA_NET_WORKAREA.getAtomData(root, 804 XAtom.XA_CARDINAL, native_ptr, 4); 805 if (workareaPresent) 806 { 807 int rootX = (int)Native.getLong(native_ptr, 0); 808 int rootY = (int)Native.getLong(native_ptr, 1); 809 int rootWidth = (int)Native.getLong(native_ptr, 2); 810 int rootHeight = (int)Native.getLong(native_ptr, 3); 811 812 return new Rectangle(scaleDown(rootX, scale), 813 scaleDown(rootY, scale), 814 scaleDown(rootWidth, scale), 815 scaleDown(rootHeight, scale)); 816 } 817 } 818 finally 819 { 820 XlibWrapper.unsafe.freeMemory(native_ptr); 821 } 822 823 return null; 824 } 825 826 /* 827 * If the current window manager supports _NET protocol then the screen 828 * insets are calculated using _NET_WORKAREA property of the root window. 829 * <p> 830 * Note that _NET_WORKAREA is a rectangular area and it does not work 831 * well in the Xinerama mode. 832 * <p> 833 * We will trust the part of this rectangular area only if it starts at the 834 * requested graphics configuration. Below is an example when the 835 * _NET_WORKAREA intersects with the requested graphics configuration but 836 * produces wrong result. 837 * 838 * //<-x1,y1/////// 839 * // // //////////////// 840 * // SCREEN1 // // SCREEN2 // 841 * // ********** // // x2,y2->// 842 * //////////////// // // 843 * //////////////// 844 * 845 * When two screens overlap and the first contains a dock(*****), then 846 * _NET_WORKAREA may start at point x1,y1 and end at point x2,y2. 847 */ 848 @Override getScreenInsets(final GraphicsConfiguration gc)849 public Insets getScreenInsets(final GraphicsConfiguration gc) { 850 GraphicsDevice gd = gc.getDevice(); 851 XNETProtocol np = XWM.getWM().getNETProtocol(); 852 if (np == null || !(gd instanceof X11GraphicsDevice) || !np.active()) { 853 return super.getScreenInsets(gc); 854 } 855 856 XToolkit.awtLock(); 857 try { 858 X11GraphicsDevice x11gd = (X11GraphicsDevice) gd; 859 long root = XlibUtil.getRootWindow(x11gd.getScreen()); 860 Rectangle workArea = getWorkArea(root, x11gd.getScaleFactor()); 861 Rectangle screen = gc.getBounds(); 862 if (workArea != null && screen.contains(workArea.getLocation())) { 863 workArea = workArea.intersection(screen); 864 int top = workArea.y - screen.y; 865 int left = workArea.x - screen.x; 866 int bottom = screen.height - workArea.height - top; 867 int right = screen.width - workArea.width - left; 868 return new Insets(top, left, bottom, right); 869 } 870 // Note that it is better to return zeros than inadequate values 871 return new Insets(0, 0, 0, 0); 872 } finally { 873 XToolkit.awtUnlock(); 874 } 875 } 876 877 /* 878 * The current implementation of disabling background erasing for 879 * canvases is that we don't set any native background color 880 * (with XSetWindowBackground) for the canvas window. However, 881 * this color is set in the peer constructor - see 882 * XWindow.postInit() for details. That's why this method from 883 * SunToolkit is not overridden in XToolkit: it's too late to 884 * disable background erasing :( 885 */ 886 /* 887 @Override 888 public void disableBackgroundErase(Canvas canvas) { 889 XCanvasPeer peer = (XCanvasPeer)canvas.getPeer(); 890 if (peer == null) { 891 throw new IllegalStateException("Canvas must have a valid peer"); 892 } 893 peer.disableBackgroundErase(); 894 } 895 */ 896 897 // Need this for XMenuItemPeer. targetToPeer(Object target)898 protected static Object targetToPeer(Object target) { 899 Object p=null; 900 if (target != null && !GraphicsEnvironment.isHeadless()) { 901 p = specialPeerMap.get(target); 902 } 903 if (p != null) return p; 904 else 905 return SunToolkit.targetToPeer(target); 906 } 907 908 // Need this for XMenuItemPeer. targetDisposedPeer(Object target, Object peer)909 protected static void targetDisposedPeer(Object target, Object peer) { 910 SunToolkit.targetDisposedPeer(target, peer); 911 } 912 913 @Override createRobot(GraphicsDevice screen)914 public RobotPeer createRobot(GraphicsDevice screen) throws AWTException { 915 if (screen instanceof X11GraphicsDevice) { 916 return new XRobotPeer((X11GraphicsDevice) screen); 917 } 918 return super.createRobot(screen); 919 } 920 921 /* 922 * On X, support for dynamic layout on resizing is governed by the 923 * window manager. If the window manager supports it, it happens 924 * automatically. The setter method for this property is 925 * irrelevant on X. 926 */ 927 @Override setDynamicLayout(boolean b)928 public void setDynamicLayout(boolean b) { 929 dynamicLayoutSetting = b; 930 } 931 932 @Override isDynamicLayoutSet()933 protected boolean isDynamicLayoutSet() { 934 return dynamicLayoutSetting; 935 } 936 937 /* Called from isDynamicLayoutActive() and from 938 * lazilyLoadDynamicLayoutSupportedProperty() 939 */ isDynamicLayoutSupported()940 protected boolean isDynamicLayoutSupported() { 941 return XWM.getWM().supportsDynamicLayout(); 942 } 943 944 @Override isDynamicLayoutActive()945 public boolean isDynamicLayoutActive() { 946 return isDynamicLayoutSupported(); 947 } 948 949 @Override getFontPeer(String name, int style)950 public FontPeer getFontPeer(String name, int style){ 951 return new XFontPeer(name, style); 952 } 953 954 @Override createDragSourceContextPeer(DragGestureEvent dge)955 public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 956 final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); 957 if (f != null) { 958 return f.createDragSourceContextPeer(dge); 959 } 960 961 return XDragSourceContextPeer.createDragSourceContextPeer(dge); 962 } 963 964 @Override 965 @SuppressWarnings("unchecked") 966 public <T extends DragGestureRecognizer> T createDragGestureRecognizer(Class<T> recognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl)967 createDragGestureRecognizer(Class<T> recognizerClass, 968 DragSource ds, 969 Component c, 970 int srcActions, 971 DragGestureListener dgl) 972 { 973 final LightweightFrame f = SunToolkit.getLightweightFrame(c); 974 if (f != null) { 975 return f.createDragGestureRecognizer(recognizerClass, ds, c, srcActions, dgl); 976 } 977 978 if (MouseDragGestureRecognizer.class.equals(recognizerClass)) 979 return (T)new XMouseDragGestureRecognizer(ds, c, srcActions, dgl); 980 else 981 return null; 982 } 983 984 @Override createCheckboxMenuItem(CheckboxMenuItem target)985 public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) { 986 XCheckboxMenuItemPeer peer = new XCheckboxMenuItemPeer(target); 987 //vb157120: looks like we don't need to map menu items 988 //in new menus implementation 989 //targetCreatedPeer(target, peer); 990 return peer; 991 } 992 993 @Override createMenuItem(MenuItem target)994 public MenuItemPeer createMenuItem(MenuItem target) { 995 XMenuItemPeer peer = new XMenuItemPeer(target); 996 //vb157120: looks like we don't need to map menu items 997 //in new menus implementation 998 //targetCreatedPeer(target, peer); 999 return peer; 1000 } 1001 1002 @Override createTextField(TextField target)1003 public TextFieldPeer createTextField(TextField target) { 1004 TextFieldPeer peer = new XTextFieldPeer(target); 1005 targetCreatedPeer(target, peer); 1006 return peer; 1007 } 1008 1009 @Override createLabel(Label target)1010 public LabelPeer createLabel(Label target) { 1011 LabelPeer peer = new XLabelPeer(target); 1012 targetCreatedPeer(target, peer); 1013 return peer; 1014 } 1015 1016 @Override createList(java.awt.List target)1017 public ListPeer createList(java.awt.List target) { 1018 ListPeer peer = new XListPeer(target); 1019 targetCreatedPeer(target, peer); 1020 return peer; 1021 } 1022 1023 @Override createCheckbox(Checkbox target)1024 public CheckboxPeer createCheckbox(Checkbox target) { 1025 CheckboxPeer peer = new XCheckboxPeer(target); 1026 targetCreatedPeer(target, peer); 1027 return peer; 1028 } 1029 1030 @Override createScrollbar(Scrollbar target)1031 public ScrollbarPeer createScrollbar(Scrollbar target) { 1032 XScrollbarPeer peer = new XScrollbarPeer(target); 1033 targetCreatedPeer(target, peer); 1034 return peer; 1035 } 1036 1037 @Override createScrollPane(ScrollPane target)1038 public ScrollPanePeer createScrollPane(ScrollPane target) { 1039 XScrollPanePeer peer = new XScrollPanePeer(target); 1040 targetCreatedPeer(target, peer); 1041 return peer; 1042 } 1043 1044 @Override createTextArea(TextArea target)1045 public TextAreaPeer createTextArea(TextArea target) { 1046 TextAreaPeer peer = new XTextAreaPeer(target); 1047 targetCreatedPeer(target, peer); 1048 return peer; 1049 } 1050 1051 @Override createChoice(Choice target)1052 public ChoicePeer createChoice(Choice target) { 1053 XChoicePeer peer = new XChoicePeer(target); 1054 targetCreatedPeer(target, peer); 1055 return peer; 1056 } 1057 1058 @Override createCanvas(Canvas target)1059 public CanvasPeer createCanvas(Canvas target) { 1060 XCanvasPeer peer = (isXEmbedServerRequested() ? new XEmbedCanvasPeer(target) : new XCanvasPeer(target)); 1061 targetCreatedPeer(target, peer); 1062 return peer; 1063 } 1064 1065 @Override createPanel(Panel target)1066 public PanelPeer createPanel(Panel target) { 1067 PanelPeer peer = new XPanelPeer(target); 1068 targetCreatedPeer(target, peer); 1069 return peer; 1070 } 1071 1072 @Override createWindow(Window target)1073 public WindowPeer createWindow(Window target) { 1074 WindowPeer peer = new XWindowPeer(target); 1075 targetCreatedPeer(target, peer); 1076 return peer; 1077 } 1078 1079 @Override createDialog(Dialog target)1080 public DialogPeer createDialog(Dialog target) { 1081 DialogPeer peer = new XDialogPeer(target); 1082 targetCreatedPeer(target, peer); 1083 return peer; 1084 } 1085 1086 private static Boolean sunAwtDisableGtkFileDialogs = null; 1087 1088 /** 1089 * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default 1090 * value is {@code false}. 1091 */ getSunAwtDisableGtkFileDialogs()1092 public static synchronized boolean getSunAwtDisableGtkFileDialogs() { 1093 if (sunAwtDisableGtkFileDialogs == null) { 1094 sunAwtDisableGtkFileDialogs = AccessController.doPrivileged( 1095 new GetBooleanAction("sun.awt.disableGtkFileDialogs")); 1096 } 1097 return sunAwtDisableGtkFileDialogs.booleanValue(); 1098 } 1099 1100 @Override createFileDialog(FileDialog target)1101 public FileDialogPeer createFileDialog(FileDialog target) { 1102 FileDialogPeer peer = null; 1103 // The current GtkFileChooser is available from GTK+ 2.4 1104 if (!getSunAwtDisableGtkFileDialogs() && 1105 (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) { 1106 peer = new GtkFileDialogPeer(target); 1107 } else { 1108 peer = new XFileDialogPeer(target); 1109 } 1110 targetCreatedPeer(target, peer); 1111 return peer; 1112 } 1113 1114 @Override createMenuBar(MenuBar target)1115 public MenuBarPeer createMenuBar(MenuBar target) { 1116 XMenuBarPeer peer = new XMenuBarPeer(target); 1117 targetCreatedPeer(target, peer); 1118 return peer; 1119 } 1120 1121 @Override createMenu(Menu target)1122 public MenuPeer createMenu(Menu target) { 1123 XMenuPeer peer = new XMenuPeer(target); 1124 //vb157120: looks like we don't need to map menu items 1125 //in new menus implementation 1126 //targetCreatedPeer(target, peer); 1127 return peer; 1128 } 1129 1130 @Override createPopupMenu(PopupMenu target)1131 public PopupMenuPeer createPopupMenu(PopupMenu target) { 1132 XPopupMenuPeer peer = new XPopupMenuPeer(target); 1133 targetCreatedPeer(target, peer); 1134 return peer; 1135 } 1136 1137 @Override getMouseInfoPeer()1138 public synchronized MouseInfoPeer getMouseInfoPeer() { 1139 if (xPeer == null) { 1140 xPeer = new XMouseInfoPeer(); 1141 } 1142 return xPeer; 1143 } 1144 createEmbeddedFrame(XEmbeddedFrame target)1145 public XEmbeddedFramePeer createEmbeddedFrame(XEmbeddedFrame target) 1146 { 1147 XEmbeddedFramePeer peer = new XEmbeddedFramePeer(target); 1148 targetCreatedPeer(target, peer); 1149 return peer; 1150 } 1151 createEmbedProxy(XEmbedChildProxy target)1152 XEmbedChildProxyPeer createEmbedProxy(XEmbedChildProxy target) { 1153 XEmbedChildProxyPeer peer = new XEmbedChildProxyPeer(target); 1154 targetCreatedPeer(target, peer); 1155 return peer; 1156 } 1157 1158 @Override getKeyboardFocusManagerPeer()1159 public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException { 1160 return XKeyboardFocusManagerPeer.getInstance(); 1161 } 1162 1163 /** 1164 * Returns a new custom cursor. 1165 */ 1166 @Override createCustomCursor(Image cursor, Point hotSpot, String name)1167 public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) 1168 throws IndexOutOfBoundsException { 1169 return new XCustomCursor(cursor, hotSpot, name); 1170 } 1171 1172 @Override createTrayIcon(TrayIcon target)1173 public TrayIconPeer createTrayIcon(TrayIcon target) 1174 throws HeadlessException, AWTException 1175 { 1176 TrayIconPeer peer = new XTrayIconPeer(target); 1177 targetCreatedPeer(target, peer); 1178 return peer; 1179 } 1180 1181 @Override createSystemTray(SystemTray target)1182 public SystemTrayPeer createSystemTray(SystemTray target) throws HeadlessException { 1183 SystemTrayPeer peer = new XSystemTrayPeer(target); 1184 return peer; 1185 } 1186 1187 @Override isTraySupported()1188 public boolean isTraySupported() { 1189 XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); 1190 if (peer != null) { 1191 return peer.isAvailable(); 1192 } 1193 return false; 1194 } 1195 1196 @Override getDataTransferer()1197 public DataTransferer getDataTransferer() { 1198 return XDataTransferer.getInstanceImpl(); 1199 } 1200 1201 /** 1202 * Returns the supported cursor size 1203 */ 1204 @Override getBestCursorSize(int preferredWidth, int preferredHeight)1205 public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) { 1206 return XCustomCursor.getBestCursorSize( 1207 java.lang.Math.max(1,preferredWidth), java.lang.Math.max(1,preferredHeight)); 1208 } 1209 1210 1211 @Override getMaximumCursorColors()1212 public int getMaximumCursorColors() { 1213 return 2; // Black and white. 1214 } 1215 1216 @Override mapInputMethodHighlight( InputMethodHighlight highlight)1217 public Map<TextAttribute, ?> mapInputMethodHighlight( InputMethodHighlight highlight) { 1218 return XInputMethod.mapInputMethodHighlight(highlight); 1219 } 1220 @Override getLockingKeyState(int key)1221 public boolean getLockingKeyState(int key) { 1222 if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || 1223 key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { 1224 throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); 1225 } 1226 awtLock(); 1227 try { 1228 return getModifierState( key ); 1229 } finally { 1230 awtUnlock(); 1231 } 1232 } 1233 1234 @Override getSystemClipboard()1235 public Clipboard getSystemClipboard() { 1236 SecurityManager security = System.getSecurityManager(); 1237 if (security != null) { 1238 security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); 1239 } 1240 synchronized (this) { 1241 if (clipboard == null) { 1242 clipboard = new XClipboard("System", "CLIPBOARD"); 1243 } 1244 } 1245 return clipboard; 1246 } 1247 1248 @Override getSystemSelection()1249 public Clipboard getSystemSelection() { 1250 SecurityManager security = System.getSecurityManager(); 1251 if (security != null) { 1252 security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); 1253 } 1254 synchronized (this) { 1255 if (selection == null) { 1256 selection = new XClipboard("Selection", "PRIMARY"); 1257 } 1258 } 1259 return selection; 1260 } 1261 1262 @Override beep()1263 public void beep() { 1264 awtLock(); 1265 try { 1266 XlibWrapper.XBell(getDisplay(), 0); 1267 XlibWrapper.XFlush(getDisplay()); 1268 } finally { 1269 awtUnlock(); 1270 } 1271 } 1272 1273 @Override getPrintJob(final Frame frame, final String doctitle, final Properties props)1274 public PrintJob getPrintJob(final Frame frame, final String doctitle, 1275 final Properties props) { 1276 1277 if (frame == null) { 1278 throw new NullPointerException("frame must not be null"); 1279 } 1280 1281 PrintJob2D printJob = new PrintJob2D(frame, doctitle, props); 1282 1283 if (printJob.printDialog() == false) { 1284 printJob = null; 1285 } 1286 return printJob; 1287 } 1288 1289 @Override getPrintJob(final Frame frame, final String doctitle, final JobAttributes jobAttributes, final PageAttributes pageAttributes)1290 public PrintJob getPrintJob(final Frame frame, final String doctitle, 1291 final JobAttributes jobAttributes, 1292 final PageAttributes pageAttributes) 1293 { 1294 if (frame == null) { 1295 throw new NullPointerException("frame must not be null"); 1296 } 1297 1298 PrintJob2D printJob = new PrintJob2D(frame, doctitle, 1299 jobAttributes, pageAttributes); 1300 1301 if (printJob.printDialog() == false) { 1302 printJob = null; 1303 } 1304 1305 return printJob; 1306 } 1307 XSync()1308 static void XSync() { 1309 awtLock(); 1310 try { 1311 XlibWrapper.XSync(getDisplay(),0); 1312 } finally { 1313 awtUnlock(); 1314 } 1315 } 1316 1317 @Override getScreenResolution()1318 public int getScreenResolution() { 1319 long display = getDisplay(); 1320 awtLock(); 1321 try { 1322 return (int) ((XlibWrapper.DisplayWidth(display, 1323 XlibWrapper.DefaultScreen(display)) * 25.4) / 1324 XlibWrapper.DisplayWidthMM(display, 1325 XlibWrapper.DefaultScreen(display))); 1326 } finally { 1327 awtUnlock(); 1328 } 1329 } 1330 getDefaultXColormap()1331 static native long getDefaultXColormap(); 1332 1333 /** 1334 * Returns a new input method adapter descriptor for native input methods. 1335 */ 1336 @Override getInputMethodAdapterDescriptor()1337 public InputMethodDescriptor getInputMethodAdapterDescriptor() throws AWTException { 1338 return new XInputMethodDescriptor(); 1339 } 1340 1341 /** 1342 * Returns whether enableInputMethods should be set to true for peered 1343 * TextComponent instances on this platform. True by default. 1344 */ 1345 @Override enableInputMethodsForTextComponent()1346 public boolean enableInputMethodsForTextComponent() { 1347 return true; 1348 } 1349 getMultiClickTime()1350 static int getMultiClickTime() { 1351 if (awt_multiclick_time == 0) { 1352 initializeMultiClickTime(); 1353 } 1354 return awt_multiclick_time; 1355 } initializeMultiClickTime()1356 static void initializeMultiClickTime() { 1357 awtLock(); 1358 try { 1359 try { 1360 String multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(), "*", "multiClickTime"); 1361 if (multiclick_time_query != null) { 1362 awt_multiclick_time = (int)Long.parseLong(multiclick_time_query); 1363 } else { 1364 multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(), 1365 "OpenWindows", "MultiClickTimeout"); 1366 if (multiclick_time_query != null) { 1367 /* Note: OpenWindows.MultiClickTimeout is in tenths of 1368 a second, so we need to multiply by 100 to convert to 1369 milliseconds */ 1370 awt_multiclick_time = (int)Long.parseLong(multiclick_time_query) * 100; 1371 } else { 1372 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; 1373 } 1374 } 1375 } catch (NumberFormatException nf) { 1376 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; 1377 } catch (NullPointerException npe) { 1378 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; 1379 } 1380 } finally { 1381 awtUnlock(); 1382 } 1383 if (awt_multiclick_time == 0) { 1384 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME; 1385 } 1386 } 1387 1388 @Override isFrameStateSupported(int state)1389 public boolean isFrameStateSupported(int state) 1390 throws HeadlessException 1391 { 1392 if (state == Frame.NORMAL || state == Frame.ICONIFIED) { 1393 return true; 1394 } else { 1395 return XWM.getWM().supportsExtendedState(state); 1396 } 1397 } 1398 dumpPeers()1399 static void dumpPeers() { 1400 if (log.isLoggable(PlatformLogger.Level.FINE)) { 1401 log.fine("Mapped windows:"); 1402 winMap.forEach((k, v) -> { 1403 log.fine(k + "->" + v); 1404 if (v instanceof XComponentPeer) { 1405 Component target = (Component)((XComponentPeer)v).getTarget(); 1406 log.fine("\ttarget: " + target); 1407 } 1408 }); 1409 1410 SunToolkit.dumpPeers(log); 1411 1412 log.fine("Mapped special peers:"); 1413 specialPeerMap.forEach((k, v) -> { 1414 log.fine(k + "->" + v); 1415 }); 1416 1417 log.fine("Mapped dispatchers:"); 1418 winToDispatcher.forEach((k, v) -> { 1419 log.fine(k + "->" + v); 1420 }); 1421 } 1422 } 1423 1424 /* Protected with awt_lock. */ 1425 private static boolean initialized; 1426 private static boolean timeStampUpdated; 1427 private static long timeStamp; 1428 1429 private static final XEventDispatcher timeFetcher = 1430 new XEventDispatcher() { 1431 @Override 1432 public void dispatchEvent(XEvent ev) { 1433 switch (ev.get_type()) { 1434 case XConstants.PropertyNotify: 1435 XPropertyEvent xpe = ev.get_xproperty(); 1436 1437 awtLock(); 1438 try { 1439 timeStamp = xpe.get_time(); 1440 timeStampUpdated = true; 1441 awtLockNotifyAll(); 1442 } finally { 1443 awtUnlock(); 1444 } 1445 1446 break; 1447 } 1448 } 1449 }; 1450 1451 private static XAtom _XA_JAVA_TIME_PROPERTY_ATOM; 1452 getCurrentServerTime()1453 static long getCurrentServerTime() { 1454 awtLock(); 1455 try { 1456 try { 1457 if (!initialized) { 1458 XToolkit.addEventDispatcher(XBaseWindow.getXAWTRootWindow().getWindow(), 1459 timeFetcher); 1460 _XA_JAVA_TIME_PROPERTY_ATOM = XAtom.get("_SUNW_JAVA_AWT_TIME"); 1461 initialized = true; 1462 } 1463 timeStampUpdated = false; 1464 XlibWrapper.XChangeProperty(XToolkit.getDisplay(), 1465 XBaseWindow.getXAWTRootWindow().getWindow(), 1466 _XA_JAVA_TIME_PROPERTY_ATOM.getAtom(), XAtom.XA_ATOM, 32, 1467 XConstants.PropModeAppend, 1468 0, 0); 1469 XlibWrapper.XFlush(XToolkit.getDisplay()); 1470 1471 if (isToolkitThread()) { 1472 XEvent event = new XEvent(); 1473 try { 1474 XlibWrapper.XWindowEvent(XToolkit.getDisplay(), 1475 XBaseWindow.getXAWTRootWindow().getWindow(), 1476 XConstants.PropertyChangeMask, 1477 event.pData); 1478 timeFetcher.dispatchEvent(event); 1479 } 1480 finally { 1481 event.dispose(); 1482 } 1483 } 1484 else { 1485 while (!timeStampUpdated) { 1486 awtLockWait(); 1487 } 1488 } 1489 } catch (InterruptedException ie) { 1490 // Note: the returned timeStamp can be incorrect in this case. 1491 if (log.isLoggable(PlatformLogger.Level.FINE)) { 1492 log.fine("Catched exception, timeStamp may not be correct (ie = " + ie + ")"); 1493 } 1494 } 1495 } finally { 1496 awtUnlock(); 1497 } 1498 return timeStamp; 1499 } 1500 @Override initializeDesktopProperties()1501 protected void initializeDesktopProperties() { 1502 desktopProperties.put("DnD.Autoscroll.initialDelay", 1503 Integer.valueOf(50)); 1504 desktopProperties.put("DnD.Autoscroll.interval", 1505 Integer.valueOf(50)); 1506 desktopProperties.put("DnD.Autoscroll.cursorHysteresis", 1507 Integer.valueOf(5)); 1508 desktopProperties.put("Shell.shellFolderManager", 1509 "sun.awt.shell.ShellFolderManager"); 1510 // Don't want to call getMultiClickTime() if we are headless 1511 if (!GraphicsEnvironment.isHeadless()) { 1512 desktopProperties.put("awt.multiClickInterval", 1513 Integer.valueOf(getMultiClickTime())); 1514 desktopProperties.put("awt.mouse.numButtons", 1515 Integer.valueOf(getNumberOfButtons())); 1516 if(SunGraphicsEnvironment.isUIScaleEnabled()) { 1517 addPropertyChangeListener("gnome.Xft/DPI", evt -> 1518 localEnv.displayChanged()); 1519 } 1520 } 1521 } 1522 1523 /** 1524 * This method runs through the XPointer and XExtendedPointer array. 1525 * XExtendedPointer has priority because on some systems XPointer 1526 * (which is assigned to the virtual pointer) reports the maximum 1527 * capabilities of the mouse pointer (i.e. 32 physical buttons). 1528 */ getNumberOfButtonsImpl()1529 private native int getNumberOfButtonsImpl(); 1530 1531 @Override getNumberOfButtons()1532 public int getNumberOfButtons(){ 1533 awtLock(); 1534 try { 1535 if (numberOfButtons == 0) { 1536 numberOfButtons = getNumberOfButtonsImpl(); 1537 numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; 1538 //4th and 5th buttons are for wheel and shouldn't be reported as buttons. 1539 //If we have more than 3 physical buttons and a wheel, we report N-2 buttons. 1540 //If we have 3 physical buttons and a wheel, we report 3 buttons. 1541 //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively. 1542 if (numberOfButtons >=5) { 1543 numberOfButtons -= 2; 1544 } else if (numberOfButtons == 4 || numberOfButtons ==5){ 1545 numberOfButtons = 3; 1546 } 1547 } 1548 //Assume don't have to re-query the number again and again. 1549 return numberOfButtons; 1550 } finally { 1551 awtUnlock(); 1552 } 1553 } 1554 getNumberOfButtonsForMask()1555 static int getNumberOfButtonsForMask() { 1556 return Math.min(XConstants.MAX_BUTTONS, ((SunToolkit) (Toolkit.getDefaultToolkit())).getNumberOfButtons()); 1557 } 1558 1559 private static final String prefix = "DnD.Cursor."; 1560 private static final String postfix = ".32x32"; 1561 private static final String dndPrefix = "DnD."; 1562 1563 @Override lazilyLoadDesktopProperty(String name)1564 protected Object lazilyLoadDesktopProperty(String name) { 1565 if (name.startsWith(prefix)) { 1566 String cursorName = name.substring(prefix.length(), name.length()) + postfix; 1567 1568 try { 1569 return Cursor.getSystemCustomCursor(cursorName); 1570 } catch (AWTException awte) { 1571 throw new RuntimeException("cannot load system cursor: " + cursorName, awte); 1572 } 1573 } 1574 1575 if (name.equals("awt.dynamicLayoutSupported")) { 1576 return Boolean.valueOf(isDynamicLayoutSupported()); 1577 } 1578 1579 if (initXSettingsIfNeeded(name)) { 1580 return desktopProperties.get(name); 1581 } 1582 1583 return super.lazilyLoadDesktopProperty(name); 1584 } 1585 1586 @Override addPropertyChangeListener(String name, PropertyChangeListener pcl)1587 public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) { 1588 if (name == null) { 1589 // See JavaDoc for the Toolkit.addPropertyChangeListener() method 1590 return; 1591 } 1592 initXSettingsIfNeeded(name); 1593 super.addPropertyChangeListener(name, pcl); 1594 } 1595 1596 /** 1597 * Initializes XAWTXSettings if a property for a given property name is provided by 1598 * XSettings and they are not initialized yet. 1599 * 1600 * @return true if the method has initialized XAWTXSettings. 1601 */ initXSettingsIfNeeded(final String propName)1602 private boolean initXSettingsIfNeeded(final String propName) { 1603 if (!loadedXSettings && 1604 (propName.startsWith("gnome.") || 1605 propName.equals(SunToolkit.DESKTOPFONTHINTS) || 1606 propName.startsWith(dndPrefix))) 1607 { 1608 loadedXSettings = true; 1609 if (!GraphicsEnvironment.isHeadless()) { 1610 loadXSettings(); 1611 /* If no desktop font hint could be retrieved, check for 1612 * KDE running KWin and retrieve settings from fontconfig. 1613 * If that isn't found let SunToolkit will see if there's a 1614 * system property set by a user. 1615 */ 1616 if (desktopProperties.get(SunToolkit.DESKTOPFONTHINTS) == null) { 1617 if (XWM.isKDE2()) { 1618 Object hint = FontConfigManager.getFontConfigAAHint(); 1619 if (hint != null) { 1620 /* set the fontconfig/KDE property so that 1621 * getDesktopHints() below will see it 1622 * and set the public property. 1623 */ 1624 desktopProperties.put(UNIXToolkit.FONTCONFIGAAHINT, 1625 hint); 1626 } 1627 } 1628 desktopProperties.put(SunToolkit.DESKTOPFONTHINTS, 1629 SunToolkit.getDesktopFontHints()); 1630 } 1631 1632 return true; 1633 } 1634 } 1635 return false; 1636 } 1637 loadXSettings()1638 private void loadXSettings() { 1639 xs = new XAWTXSettings(); 1640 } 1641 1642 /** 1643 * Callback from the native side indicating some, or all, of the 1644 * desktop properties have changed and need to be reloaded. 1645 * {@code data} is the byte array directly from the x server and 1646 * may be in little endian format. 1647 * <p> 1648 * NB: This could be called from any thread if triggered by 1649 * {@code loadXSettings}. It is called from the System EDT 1650 * if triggered by an XSETTINGS change. 1651 */ parseXSettings(int screen_XXX_ignored,Map<String, Object> updatedSettings)1652 void parseXSettings(int screen_XXX_ignored,Map<String, Object> updatedSettings) { 1653 1654 if (updatedSettings == null || updatedSettings.isEmpty()) { 1655 return; 1656 } 1657 1658 Iterator<Map.Entry<String, Object>> i = updatedSettings.entrySet().iterator(); 1659 while (i.hasNext()) { 1660 Map.Entry<String, Object> e = i.next(); 1661 String name = e.getKey(); 1662 1663 name = "gnome." + name; 1664 setDesktopProperty(name, e.getValue()); 1665 if (log.isLoggable(PlatformLogger.Level.FINE)) { 1666 log.fine("name = " + name + " value = " + e.getValue()); 1667 } 1668 1669 // XXX: we probably want to do something smarter. In 1670 // particular, "Net" properties are of interest to the 1671 // "core" AWT itself. E.g. 1672 // 1673 // Net/DndDragThreshold -> ??? 1674 // Net/DoubleClickTime -> awt.multiClickInterval 1675 } 1676 1677 setDesktopProperty(SunToolkit.DESKTOPFONTHINTS, 1678 SunToolkit.getDesktopFontHints()); 1679 1680 Integer dragThreshold = null; 1681 synchronized (this) { 1682 dragThreshold = (Integer)desktopProperties.get("gnome.Net/DndDragThreshold"); 1683 } 1684 if (dragThreshold != null) { 1685 setDesktopProperty("DnD.gestureMotionThreshold", dragThreshold); 1686 } 1687 1688 } 1689 1690 1691 1692 static int altMask; 1693 static int metaMask; 1694 static int numLockMask; 1695 static int modeSwitchMask; 1696 static int modLockIsShiftLock; 1697 1698 /* Like XKeysymToKeycode, but ensures that keysym is the primary 1699 * symbol on the keycode returned. Returns zero otherwise. 1700 */ keysymToPrimaryKeycode(long sym)1701 static int keysymToPrimaryKeycode(long sym) { 1702 awtLock(); 1703 try { 1704 int code = XlibWrapper.XKeysymToKeycode(getDisplay(), sym); 1705 if (code == 0) { 1706 return 0; 1707 } 1708 long primary = XlibWrapper.XKeycodeToKeysym(getDisplay(), code, 0); 1709 if (sym != primary) { 1710 return 0; 1711 } 1712 return code; 1713 } finally { 1714 awtUnlock(); 1715 } 1716 } getModifierState( int jkc )1717 static boolean getModifierState( int jkc ) { 1718 int iKeyMask = 0; 1719 long ks = XKeysym.javaKeycode2Keysym( jkc ); 1720 int kc = XlibWrapper.XKeysymToKeycode(getDisplay(), ks); 1721 if (kc == 0) { 1722 return false; 1723 } 1724 awtLock(); 1725 try { 1726 XModifierKeymap modmap = new XModifierKeymap( 1727 XlibWrapper.XGetModifierMapping(getDisplay())); 1728 1729 int nkeys = modmap.get_max_keypermod(); 1730 1731 long map_ptr = modmap.get_modifiermap(); 1732 for( int k = 0; k < 8; k++ ) { 1733 for (int i = 0; i < nkeys; ++i) { 1734 int keycode = Native.getUByte(map_ptr, k * nkeys + i); 1735 if (keycode == 0) { 1736 continue; // ignore zero keycode 1737 } 1738 if (kc == keycode) { 1739 iKeyMask = 1 << k; 1740 break; 1741 } 1742 } 1743 if( iKeyMask != 0 ) { 1744 break; 1745 } 1746 } 1747 XlibWrapper.XFreeModifiermap(modmap.pData); 1748 if (iKeyMask == 0 ) { 1749 return false; 1750 } 1751 // Now we know to which modifier is assigned the keycode 1752 // correspondent to the keysym correspondent to the java 1753 // keycode. We are going to check a state of this modifier. 1754 // If a modifier is a weird one, we cannot help it. 1755 long window = 0; 1756 try{ 1757 // get any application window 1758 window = winMap.firstKey().longValue(); 1759 }catch(NoSuchElementException nex) { 1760 // get root window 1761 window = getDefaultRootWindow(); 1762 } 1763 boolean res = XlibWrapper.XQueryPointer(getDisplay(), window, 1764 XlibWrapper.larg1, //root 1765 XlibWrapper.larg2, //child 1766 XlibWrapper.larg3, //root_x 1767 XlibWrapper.larg4, //root_y 1768 XlibWrapper.larg5, //child_x 1769 XlibWrapper.larg6, //child_y 1770 XlibWrapper.larg7);//mask 1771 int mask = Native.getInt(XlibWrapper.larg7); 1772 return ((mask & iKeyMask) != 0); 1773 } finally { 1774 awtUnlock(); 1775 } 1776 } 1777 1778 /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5. 1779 * Only consider primary symbols on keycodes attached to modifiers. 1780 */ setupModifierMap()1781 static void setupModifierMap() { 1782 final int metaL = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_L); 1783 final int metaR = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_R); 1784 final int altL = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_L); 1785 final int altR = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_R); 1786 final int numLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Num_Lock); 1787 final int modeSwitch = keysymToPrimaryKeycode(XKeySymConstants.XK_Mode_switch); 1788 final int shiftLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Shift_Lock); 1789 final int capsLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Caps_Lock); 1790 1791 final int[] modmask = { XConstants.ShiftMask, XConstants.LockMask, XConstants.ControlMask, XConstants.Mod1Mask, 1792 XConstants.Mod2Mask, XConstants.Mod3Mask, XConstants.Mod4Mask, XConstants.Mod5Mask }; 1793 1794 log.fine("In setupModifierMap"); 1795 awtLock(); 1796 try { 1797 XModifierKeymap modmap = new XModifierKeymap( 1798 XlibWrapper.XGetModifierMapping(getDisplay())); 1799 1800 int nkeys = modmap.get_max_keypermod(); 1801 1802 long map_ptr = modmap.get_modifiermap(); 1803 1804 for (int modn = XConstants.Mod1MapIndex; 1805 modn <= XConstants.Mod5MapIndex; 1806 ++modn) 1807 { 1808 for (int i = 0; i < nkeys; ++i) { 1809 /* for each keycode attached to this modifier */ 1810 int keycode = Native.getUByte(map_ptr, modn * nkeys + i); 1811 1812 if (keycode == 0) { 1813 break; 1814 } 1815 if (metaMask == 0 && 1816 (keycode == metaL || keycode == metaR)) 1817 { 1818 metaMask = modmask[modn]; 1819 break; 1820 } 1821 if (altMask == 0 && (keycode == altL || keycode == altR)) { 1822 altMask = modmask[modn]; 1823 break; 1824 } 1825 if (numLockMask == 0 && keycode == numLock) { 1826 numLockMask = modmask[modn]; 1827 break; 1828 } 1829 if (modeSwitchMask == 0 && keycode == modeSwitch) { 1830 modeSwitchMask = modmask[modn]; 1831 break; 1832 } 1833 continue; 1834 } 1835 } 1836 modLockIsShiftLock = 0; 1837 for (int j = 0; j < nkeys; ++j) { 1838 int keycode = Native.getUByte(map_ptr, XConstants.LockMapIndex * nkeys + j); 1839 if (keycode == 0) { 1840 break; 1841 } 1842 if (keycode == shiftLock) { 1843 modLockIsShiftLock = 1; 1844 break; 1845 } 1846 if (keycode == capsLock) { 1847 break; 1848 } 1849 } 1850 XlibWrapper.XFreeModifiermap(modmap.pData); 1851 } finally { 1852 awtUnlock(); 1853 } 1854 if (log.isLoggable(PlatformLogger.Level.FINE)) { 1855 log.fine("metaMask = " + metaMask); 1856 log.fine("altMask = " + altMask); 1857 log.fine("numLockMask = " + numLockMask); 1858 log.fine("modeSwitchMask = " + modeSwitchMask); 1859 log.fine("modLockIsShiftLock = " + modLockIsShiftLock); 1860 } 1861 } 1862 1863 1864 private static SortedMap<Long, java.util.List<Runnable>> timeoutTasks; 1865 1866 /** 1867 * Removed the task from the list of waiting-to-be called tasks. 1868 * If the task has been scheduled several times removes only first one. 1869 */ remove(Runnable task)1870 static void remove(Runnable task) { 1871 if (task == null) { 1872 throw new NullPointerException("task is null"); 1873 } 1874 awtLock(); 1875 try { 1876 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) { 1877 timeoutTaskLog.finer("Removing task " + task); 1878 } 1879 if (timeoutTasks == null) { 1880 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) { 1881 timeoutTaskLog.finer("Task is not scheduled"); 1882 } 1883 return; 1884 } 1885 Collection<java.util.List<Runnable>> values = timeoutTasks.values(); 1886 Iterator<java.util.List<Runnable>> iter = values.iterator(); 1887 while (iter.hasNext()) { 1888 java.util.List<Runnable> list = iter.next(); 1889 boolean removed = false; 1890 if (list.contains(task)) { 1891 list.remove(task); 1892 if (list.isEmpty()) { 1893 iter.remove(); 1894 } 1895 break; 1896 } 1897 } 1898 } finally { 1899 awtUnlock(); 1900 } 1901 } 1902 wakeup_poll()1903 static native void wakeup_poll(); 1904 1905 /** 1906 * Registers a Runnable which {@code run()} method will be called 1907 * once on the toolkit thread when a specified interval of time elapses. 1908 * 1909 * @param task a Runnable which {@code run} method will be called 1910 * on the toolkit thread when {@code interval} milliseconds 1911 * elapse 1912 * @param interval an interal in milliseconds 1913 * 1914 * @throws NullPointerException if {@code task} is {@code null} 1915 * @throws IllegalArgumentException if {@code interval} is not positive 1916 */ schedule(Runnable task, long interval)1917 static void schedule(Runnable task, long interval) { 1918 if (task == null) { 1919 throw new NullPointerException("task is null"); 1920 } 1921 if (interval <= 0) { 1922 throw new IllegalArgumentException("interval " + interval + " is not positive"); 1923 } 1924 1925 awtLock(); 1926 try { 1927 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) { 1928 timeoutTaskLog.finer("XToolkit.schedule(): current time={0}" + 1929 "; interval={1}" + 1930 "; task being added={2}" + "; tasks before addition={3}", 1931 Long.valueOf(System.currentTimeMillis()), Long.valueOf(interval), task, timeoutTasks); 1932 } 1933 1934 if (timeoutTasks == null) { 1935 timeoutTasks = new TreeMap<>(); 1936 } 1937 1938 Long time = Long.valueOf(System.currentTimeMillis() + interval); 1939 java.util.List<Runnable> tasks = timeoutTasks.get(time); 1940 if (tasks == null) { 1941 tasks = new ArrayList<>(1); 1942 timeoutTasks.put(time, tasks); 1943 } 1944 tasks.add(task); 1945 1946 1947 if (timeoutTasks.get(timeoutTasks.firstKey()) == tasks && tasks.size() == 1) { 1948 // Added task became first task - poll won't know 1949 // about it so we need to wake it up 1950 wakeup_poll(); 1951 } 1952 } finally { 1953 awtUnlock(); 1954 } 1955 } 1956 getNextTaskTime()1957 private long getNextTaskTime() { 1958 awtLock(); 1959 try { 1960 if (timeoutTasks == null || timeoutTasks.isEmpty()) { 1961 return -1L; 1962 } 1963 return timeoutTasks.firstKey(); 1964 } finally { 1965 awtUnlock(); 1966 } 1967 } 1968 1969 /** 1970 * Executes mature timeout tasks registered with schedule(). 1971 * Called from run() under awtLock. 1972 */ callTimeoutTasks()1973 private static void callTimeoutTasks() { 1974 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) { 1975 timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" + 1976 "; tasks={1}", Long.valueOf(System.currentTimeMillis()), timeoutTasks); 1977 } 1978 1979 if (timeoutTasks == null || timeoutTasks.isEmpty()) { 1980 return; 1981 } 1982 1983 Long currentTime = Long.valueOf(System.currentTimeMillis()); 1984 Long time = timeoutTasks.firstKey(); 1985 1986 while (time.compareTo(currentTime) <= 0) { 1987 java.util.List<Runnable> tasks = timeoutTasks.remove(time); 1988 1989 for (Iterator<Runnable> iter = tasks.iterator(); iter.hasNext();) { 1990 Runnable task = iter.next(); 1991 1992 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) { 1993 timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" + 1994 "; about to run task={1}", Long.valueOf(currentTime), task); 1995 } 1996 1997 try { 1998 task.run(); 1999 } catch (ThreadDeath td) { 2000 throw td; 2001 } catch (Throwable thr) { 2002 processException(thr); 2003 } 2004 } 2005 2006 if (timeoutTasks.isEmpty()) { 2007 break; 2008 } 2009 time = timeoutTasks.firstKey(); 2010 } 2011 } 2012 isLeftMouseButton(MouseEvent me)2013 static boolean isLeftMouseButton(MouseEvent me) { 2014 switch (me.getID()) { 2015 case MouseEvent.MOUSE_PRESSED: 2016 case MouseEvent.MOUSE_RELEASED: 2017 return (me.getButton() == MouseEvent.BUTTON1); 2018 case MouseEvent.MOUSE_ENTERED: 2019 case MouseEvent.MOUSE_EXITED: 2020 case MouseEvent.MOUSE_CLICKED: 2021 case MouseEvent.MOUSE_DRAGGED: 2022 return ((me.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0); 2023 } 2024 return false; 2025 } 2026 isRightMouseButton(MouseEvent me)2027 static boolean isRightMouseButton(MouseEvent me) { 2028 int numButtons = ((Integer)getDefaultToolkit().getDesktopProperty("awt.mouse.numButtons")).intValue(); 2029 switch (me.getID()) { 2030 case MouseEvent.MOUSE_PRESSED: 2031 case MouseEvent.MOUSE_RELEASED: 2032 return ((numButtons == 2 && me.getButton() == MouseEvent.BUTTON2) || 2033 (numButtons > 2 && me.getButton() == MouseEvent.BUTTON3)); 2034 case MouseEvent.MOUSE_ENTERED: 2035 case MouseEvent.MOUSE_EXITED: 2036 case MouseEvent.MOUSE_CLICKED: 2037 case MouseEvent.MOUSE_DRAGGED: 2038 return ((numButtons == 2 && (me.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0) || 2039 (numButtons > 2 && (me.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)); 2040 } 2041 return false; 2042 } 2043 2044 static long reset_time_utc; 2045 static final long WRAP_TIME_MILLIS = 0x00000000FFFFFFFFL; 2046 2047 /* 2048 * This function converts between the X server time (number of milliseconds 2049 * since the last server reset) and the UTC time for the 'when' field of an 2050 * InputEvent (or another event type with a timestamp). 2051 */ nowMillisUTC_offset(long server_offset)2052 static long nowMillisUTC_offset(long server_offset) { 2053 // ported from awt_util.c 2054 /* 2055 * Because Time is of type 'unsigned long', it is possible that Time will 2056 * never wrap when using 64-bit Xlib. However, if a 64-bit client 2057 * connects to a 32-bit server, I suspect the values will still wrap. So 2058 * we should not attempt to remove the wrap checking even if _LP64 is 2059 * true. 2060 */ 2061 2062 long current_time_utc = System.currentTimeMillis(); 2063 if (log.isLoggable(PlatformLogger.Level.FINER)) { 2064 log.finer("reset_time=" + reset_time_utc + ", current_time=" + current_time_utc 2065 + ", server_offset=" + server_offset + ", wrap_time=" + WRAP_TIME_MILLIS); 2066 } 2067 2068 if ((current_time_utc - reset_time_utc) > WRAP_TIME_MILLIS) { 2069 reset_time_utc = System.currentTimeMillis() - getCurrentServerTime(); 2070 } 2071 2072 if (log.isLoggable(PlatformLogger.Level.FINER)) { 2073 log.finer("result = " + (reset_time_utc + server_offset)); 2074 } 2075 return reset_time_utc + server_offset; 2076 } 2077 2078 /** 2079 * @see sun.awt.SunToolkit#needsXEmbedImpl 2080 */ 2081 @Override needsXEmbedImpl()2082 protected boolean needsXEmbedImpl() { 2083 // XToolkit implements supports for XEmbed-client protocol and 2084 // requires the supports from the embedding host for it to work. 2085 return true; 2086 } 2087 2088 @Override isModalityTypeSupported(Dialog.ModalityType modalityType)2089 public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) { 2090 return (modalityType == null) || 2091 (modalityType == Dialog.ModalityType.MODELESS) || 2092 (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) || 2093 (modalityType == Dialog.ModalityType.APPLICATION_MODAL) || 2094 (modalityType == Dialog.ModalityType.TOOLKIT_MODAL); 2095 } 2096 2097 @Override isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType)2098 public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) { 2099 return (exclusionType == null) || 2100 (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) || 2101 (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) || 2102 (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); 2103 } 2104 getEventQueue(Object target)2105 static EventQueue getEventQueue(Object target) { 2106 AppContext appContext = targetToAppContext(target); 2107 if (appContext != null) { 2108 return (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY); 2109 } 2110 return null; 2111 } 2112 removeSourceEvents(EventQueue queue, Object source, boolean removeAllEvents)2113 static void removeSourceEvents(EventQueue queue, 2114 Object source, 2115 boolean removeAllEvents) { 2116 AWTAccessor.getEventQueueAccessor() 2117 .removeSourceEvents(queue, source, removeAllEvents); 2118 } 2119 2120 @Override isAlwaysOnTopSupported()2121 public boolean isAlwaysOnTopSupported() { 2122 for (XLayerProtocol proto : XWM.getWM().getProtocols(XLayerProtocol.class)) { 2123 if (proto.supportsLayer(XLayerProtocol.LAYER_ALWAYS_ON_TOP)) { 2124 return true; 2125 } 2126 } 2127 return false; 2128 } 2129 2130 @Override useBufferPerWindow()2131 public boolean useBufferPerWindow() { 2132 return XToolkit.getBackingStoreType() == XConstants.NotUseful; 2133 } 2134 2135 /** 2136 * Returns one of XConstants: NotUseful, WhenMapped or Always. 2137 * If backing store is not available on at least one screen, or 2138 * the string system property "sun.awt.backingStore" is neither "Always" 2139 * nor "WhenMapped", then the method returns XConstants.NotUseful. 2140 * Otherwise, if the system property "sun.awt.backingStore" is "WhenMapped", 2141 * then the method returns XConstants.WhenMapped. 2142 * Otherwise (i.e., if the system property "sun.awt.backingStore" is "Always"), 2143 * the method returns XConstants.Always. 2144 */ getBackingStoreType()2145 static int getBackingStoreType() { 2146 return backingStoreType; 2147 } 2148 setBackingStoreType()2149 private static void setBackingStoreType() { 2150 String prop = AccessController.doPrivileged( 2151 new sun.security.action.GetPropertyAction("sun.awt.backingStore")); 2152 2153 if (prop == null) { 2154 backingStoreType = XConstants.NotUseful; 2155 if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) { 2156 backingStoreLog.config("The system property sun.awt.backingStore is not set" + 2157 ", by default backingStore=NotUseful"); 2158 } 2159 return; 2160 } 2161 2162 if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) { 2163 backingStoreLog.config("The system property sun.awt.backingStore is " + prop); 2164 } 2165 prop = prop.toLowerCase(); 2166 if (prop.equals("always")) { 2167 backingStoreType = XConstants.Always; 2168 } else if (prop.equals("whenmapped")) { 2169 backingStoreType = XConstants.WhenMapped; 2170 } else { 2171 backingStoreType = XConstants.NotUseful; 2172 } 2173 2174 if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) { 2175 backingStoreLog.config("backingStore(as provided by the system property)=" + 2176 ( backingStoreType == XConstants.NotUseful ? "NotUseful" 2177 : backingStoreType == XConstants.WhenMapped ? 2178 "WhenMapped" : "Always") ); 2179 } 2180 2181 awtLock(); 2182 try { 2183 int screenCount = XlibWrapper.ScreenCount(getDisplay()); 2184 for (int i = 0; i < screenCount; i++) { 2185 if (XlibWrapper.DoesBackingStore(XlibWrapper.ScreenOfDisplay(getDisplay(), i)) 2186 == XConstants.NotUseful) { 2187 backingStoreType = XConstants.NotUseful; 2188 2189 if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) { 2190 backingStoreLog.config("Backing store is not available on the screen " + 2191 i + ", backingStore=NotUseful"); 2192 } 2193 2194 return; 2195 } 2196 } 2197 } finally { 2198 awtUnlock(); 2199 } 2200 } 2201 2202 /** 2203 * One of XConstants: NotUseful, WhenMapped or Always. 2204 */ 2205 private static int backingStoreType; 2206 2207 static final int XSUN_KP_BEHAVIOR = 1; 2208 static final int XORG_KP_BEHAVIOR = 2; 2209 static final int IS_SUN_KEYBOARD = 1; 2210 static final int IS_NONSUN_KEYBOARD = 2; 2211 static final int IS_KANA_KEYBOARD = 1; 2212 static final int IS_NONKANA_KEYBOARD = 2; 2213 2214 2215 static int awt_IsXsunKPBehavior = 0; 2216 static boolean awt_UseXKB = false; 2217 static boolean awt_UseXKB_Calls = false; 2218 static int awt_XKBBaseEventCode = 0; 2219 static int awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations 2220 // to XkbTranslateKeyCode 2221 static long awt_XKBDescPtr = 0; 2222 2223 /** 2224 * Check for Xsun convention regarding numpad keys. 2225 * Xsun and some other servers (i.e. derived from Xsun) 2226 * under certain conditions process numpad keys unlike Xorg. 2227 */ isXsunKPBehavior()2228 static boolean isXsunKPBehavior() { 2229 awtLock(); 2230 try { 2231 if( awt_IsXsunKPBehavior == 0 ) { 2232 if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) { 2233 awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR; 2234 }else{ 2235 awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR; 2236 } 2237 } 2238 return awt_IsXsunKPBehavior == XSUN_KP_BEHAVIOR ? true : false; 2239 } finally { 2240 awtUnlock(); 2241 } 2242 } 2243 2244 static int sunOrNotKeyboard = 0; 2245 static int kanaOrNotKeyboard = 0; resetKeyboardSniffer()2246 static void resetKeyboardSniffer() { 2247 sunOrNotKeyboard = 0; 2248 kanaOrNotKeyboard = 0; 2249 } isSunKeyboard()2250 static boolean isSunKeyboard() { 2251 if( sunOrNotKeyboard == 0 ) { 2252 if( XlibWrapper.IsSunKeyboard( getDisplay() )) { 2253 sunOrNotKeyboard = IS_SUN_KEYBOARD; 2254 }else{ 2255 sunOrNotKeyboard = IS_NONSUN_KEYBOARD; 2256 } 2257 } 2258 return (sunOrNotKeyboard == IS_SUN_KEYBOARD); 2259 } isKanaKeyboard()2260 static boolean isKanaKeyboard() { 2261 if( kanaOrNotKeyboard == 0 ) { 2262 if( XlibWrapper.IsKanaKeyboard( getDisplay() )) { 2263 kanaOrNotKeyboard = IS_KANA_KEYBOARD; 2264 }else{ 2265 kanaOrNotKeyboard = IS_NONKANA_KEYBOARD; 2266 } 2267 } 2268 return (kanaOrNotKeyboard == IS_KANA_KEYBOARD); 2269 } isXKBenabled()2270 static boolean isXKBenabled() { 2271 awtLock(); 2272 try { 2273 return awt_UseXKB; 2274 } finally { 2275 awtUnlock(); 2276 } 2277 } 2278 2279 /** 2280 Query XKEYBOARD extension. 2281 If possible, initialize xkb library. 2282 */ tryXKB()2283 static boolean tryXKB() { 2284 awtLock(); 2285 try { 2286 String name = "XKEYBOARD"; 2287 // First, if there is extension at all. 2288 awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3); 2289 if( awt_UseXKB ) { 2290 // There is a keyboard extension. Check if a client library is compatible. 2291 // If not, don't use xkb calls. 2292 // In this case we still may be Xkb-capable application. 2293 awt_UseXKB_Calls = XlibWrapper.XkbLibraryVersion( XlibWrapper.larg1, XlibWrapper.larg2); 2294 if( awt_UseXKB_Calls ) { 2295 awt_UseXKB_Calls = XlibWrapper.XkbQueryExtension( getDisplay(), XlibWrapper.larg1, XlibWrapper.larg2, 2296 XlibWrapper.larg3, XlibWrapper.larg4, XlibWrapper.larg5); 2297 if( awt_UseXKB_Calls ) { 2298 awt_XKBBaseEventCode = Native.getInt(XlibWrapper.larg2); 2299 XlibWrapper.XkbSelectEvents (getDisplay(), 2300 XConstants.XkbUseCoreKbd, 2301 XConstants.XkbNewKeyboardNotifyMask | 2302 XConstants.XkbMapNotifyMask ,//| 2303 //XConstants.XkbStateNotifyMask, 2304 XConstants.XkbNewKeyboardNotifyMask | 2305 XConstants.XkbMapNotifyMask );//| 2306 //XConstants.XkbStateNotifyMask); 2307 2308 XlibWrapper.XkbSelectEventDetails(getDisplay(), XConstants.XkbUseCoreKbd, 2309 XConstants.XkbStateNotify, 2310 XConstants.XkbGroupStateMask, 2311 XConstants.XkbGroupStateMask); 2312 //XXX ? XkbGroupLockMask last, XkbAllStateComponentsMask before last? 2313 awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(), 2314 XConstants.XkbKeyTypesMask | 2315 XConstants.XkbKeySymsMask | 2316 XConstants.XkbModifierMapMask | 2317 XConstants.XkbVirtualModsMask, 2318 XConstants.XkbUseCoreKbd); 2319 2320 XlibWrapper.XkbSetDetectableAutoRepeat(getDisplay(), true); 2321 } 2322 } 2323 } 2324 return awt_UseXKB; 2325 } finally { 2326 awtUnlock(); 2327 } 2328 } canUseXKBCalls()2329 static boolean canUseXKBCalls() { 2330 awtLock(); 2331 try { 2332 return awt_UseXKB_Calls; 2333 } finally { 2334 awtUnlock(); 2335 } 2336 } getXKBEffectiveGroup()2337 static int getXKBEffectiveGroup() { 2338 awtLock(); 2339 try { 2340 return awt_XKBEffectiveGroup; 2341 } finally { 2342 awtUnlock(); 2343 } 2344 } getXKBBaseEventCode()2345 static int getXKBBaseEventCode() { 2346 awtLock(); 2347 try { 2348 return awt_XKBBaseEventCode; 2349 } finally { 2350 awtUnlock(); 2351 } 2352 } getXKBKbdDesc()2353 static long getXKBKbdDesc() { 2354 awtLock(); 2355 try { 2356 return awt_XKBDescPtr; 2357 } finally { 2358 awtUnlock(); 2359 } 2360 } freeXKB()2361 void freeXKB() { 2362 awtLock(); 2363 try { 2364 if (awt_UseXKB_Calls && awt_XKBDescPtr != 0) { 2365 XlibWrapper.XkbFreeKeyboard(awt_XKBDescPtr, 0xFF, true); 2366 awt_XKBDescPtr = 0; 2367 } 2368 } finally { 2369 awtUnlock(); 2370 } 2371 } processXkbChanges(XEvent ev)2372 private void processXkbChanges(XEvent ev) { 2373 // mapping change --> refresh kbd map 2374 // state change --> get a new effective group; do I really need it 2375 // or that should be left for XkbTranslateKeyCode? 2376 XkbEvent xke = new XkbEvent( ev.getPData() ); 2377 int xkb_type = xke.get_any().get_xkb_type(); 2378 switch( xkb_type ) { 2379 case XConstants.XkbNewKeyboardNotify : 2380 if( awt_XKBDescPtr != 0 ) { 2381 freeXKB(); 2382 } 2383 awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(), 2384 XConstants.XkbKeyTypesMask | 2385 XConstants.XkbKeySymsMask | 2386 XConstants.XkbModifierMapMask | 2387 XConstants.XkbVirtualModsMask, 2388 XConstants.XkbUseCoreKbd); 2389 //System.out.println("XkbNewKeyboard:"+(xke.get_new_kbd())); 2390 break; 2391 case XConstants.XkbMapNotify : 2392 if (awt_XKBDescPtr != 0) { 2393 //TODO: provide a simple unit test. 2394 XlibWrapper.XkbGetUpdatedMap(getDisplay(), 2395 XConstants.XkbKeyTypesMask | 2396 XConstants.XkbKeySymsMask | 2397 XConstants.XkbModifierMapMask | 2398 XConstants.XkbVirtualModsMask, 2399 awt_XKBDescPtr); 2400 } 2401 //System.out.println("XkbMap:"+(xke.get_map())); 2402 break; 2403 case XConstants.XkbStateNotify : 2404 // May use it later e.g. to obtain an effective group etc. 2405 //System.out.println("XkbState:"+(xke.get_state())); 2406 break; 2407 default: 2408 //System.out.println("XkbEvent of xkb_type "+xkb_type); 2409 break; 2410 } 2411 } 2412 2413 private static long eventNumber; getEventNumber()2414 public static long getEventNumber() { 2415 awtLock(); 2416 try { 2417 return eventNumber; 2418 } finally { 2419 awtUnlock(); 2420 } 2421 } 2422 2423 private static XEventDispatcher oops_waiter; 2424 private static boolean oops_updated; 2425 private static int oops_position = 0; 2426 2427 /** 2428 * @inheritDoc 2429 */ 2430 @Override syncNativeQueue(final long timeout)2431 protected boolean syncNativeQueue(final long timeout) { 2432 if (timeout <= 0) { 2433 return false; 2434 } 2435 XBaseWindow win = XBaseWindow.getXAWTRootWindow(); 2436 2437 if (oops_waiter == null) { 2438 oops_waiter = new XEventDispatcher() { 2439 @Override 2440 public void dispatchEvent(XEvent e) { 2441 if (e.get_type() == XConstants.ConfigureNotify) { 2442 // OOPS ConfigureNotify event catched 2443 oops_updated = true; 2444 awtLockNotifyAll(); 2445 } 2446 } 2447 }; 2448 } 2449 2450 awtLock(); 2451 try { 2452 addEventDispatcher(win.getWindow(), oops_waiter); 2453 2454 oops_updated = false; 2455 long event_number = getEventNumber(); 2456 // Generate OOPS ConfigureNotify event 2457 XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(), 2458 win.scaleUp(++oops_position), 0); 2459 // Change win position each time to avoid system optimization 2460 if (oops_position > 50) { 2461 oops_position = 0; 2462 } 2463 2464 XSync(); 2465 2466 eventLog.finer("Generated OOPS ConfigureNotify event"); 2467 2468 long start = System.currentTimeMillis(); 2469 while (!oops_updated) { 2470 try { 2471 // Wait for OOPS ConfigureNotify event 2472 awtLockWait(timeout); 2473 } catch (InterruptedException e) { 2474 throw new RuntimeException(e); 2475 } 2476 // This "while" is a protection from spurious 2477 // wake-ups. However, we shouldn't wait for too long 2478 if ((System.currentTimeMillis() - start > timeout) && timeout >= 0) { 2479 throw new OperationTimedOut(Long.toString(System.currentTimeMillis() - start)); 2480 } 2481 } 2482 // Don't take into account OOPS ConfigureNotify event 2483 return getEventNumber() - event_number > 1; 2484 } finally { 2485 removeEventDispatcher(win.getWindow(), oops_waiter); 2486 eventLog.finer("Exiting syncNativeQueue"); 2487 awtUnlock(); 2488 } 2489 } 2490 @Override grab(Window w)2491 public void grab(Window w) { 2492 final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); 2493 if (peer != null) { 2494 ((XWindowPeer) peer).setGrab(true); 2495 } 2496 } 2497 2498 @Override ungrab(Window w)2499 public void ungrab(Window w) { 2500 final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); 2501 if (peer != null) { 2502 ((XWindowPeer) peer).setGrab(false); 2503 } 2504 } 2505 /** 2506 * Returns if the java.awt.Desktop class is supported on the current 2507 * desktop. 2508 * <p> 2509 * The methods of java.awt.Desktop class are supported on the Gnome desktop. 2510 * Check if the running desktop is Gnome by checking the window manager. 2511 */ 2512 @Override isDesktopSupported()2513 public boolean isDesktopSupported(){ 2514 return XDesktopPeer.isDesktopSupported(); 2515 } 2516 2517 @Override createDesktopPeer(Desktop target)2518 public DesktopPeer createDesktopPeer(Desktop target){ 2519 return new XDesktopPeer(); 2520 } 2521 2522 @Override isTaskbarSupported()2523 public boolean isTaskbarSupported(){ 2524 return XTaskbarPeer.isTaskbarSupported(); 2525 } 2526 2527 @Override createTaskbarPeer(Taskbar target)2528 public TaskbarPeer createTaskbarPeer(Taskbar target){ 2529 return new XTaskbarPeer(); 2530 } 2531 2532 @Override areExtraMouseButtonsEnabled()2533 public boolean areExtraMouseButtonsEnabled() throws HeadlessException { 2534 return areExtraMouseButtonsEnabled; 2535 } 2536 2537 @Override isWindowOpacitySupported()2538 public boolean isWindowOpacitySupported() { 2539 XNETProtocol net_protocol = XWM.getWM().getNETProtocol(); 2540 2541 if (net_protocol == null) { 2542 return false; 2543 } 2544 2545 return net_protocol.doOpacityProtocol(); 2546 } 2547 2548 @Override isWindowShapingSupported()2549 public boolean isWindowShapingSupported() { 2550 return XlibUtil.isShapingSupported(); 2551 } 2552 2553 @Override isWindowTranslucencySupported()2554 public boolean isWindowTranslucencySupported() { 2555 //NOTE: it may not be supported. The actual check is being performed 2556 // at java.awt.GraphicsDevice. In X11 we need to check 2557 // whether there's any translucency-capable GC available. 2558 return true; 2559 } 2560 2561 @Override isTranslucencyCapable(GraphicsConfiguration gc)2562 public boolean isTranslucencyCapable(GraphicsConfiguration gc) { 2563 if (!(gc instanceof X11GraphicsConfig)) { 2564 return false; 2565 } 2566 return ((X11GraphicsConfig)gc).isTranslucencyCapable(); 2567 } 2568 2569 /** 2570 * Returns the value of "sun.awt.disablegrab" property. Default 2571 * value is {@code false}. 2572 */ getSunAwtDisableGrab()2573 public static boolean getSunAwtDisableGrab() { 2574 return AccessController.doPrivileged(new GetBooleanAction("sun.awt.disablegrab")); 2575 } 2576 } 2577