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