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