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