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