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