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