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