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