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