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