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