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