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