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