< prev index next >

src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java

Print this page




  40 import java.awt.im.InputMethodHighlight;
  41 import java.awt.im.spi.InputMethodDescriptor;
  42 import java.awt.image.ColorModel;
  43 import java.awt.peer.*;
  44 import java.beans.PropertyChangeListener;
  45 import java.security.AccessController;
  46 import java.security.PrivilegedAction;
  47 import java.util.*;
  48 import javax.swing.LookAndFeel;
  49 import javax.swing.UIDefaults;
  50 import sun.awt.*;
  51 import sun.awt.datatransfer.DataTransferer;
  52 import sun.font.FontConfigManager;
  53 import sun.java2d.SunGraphicsEnvironment;
  54 import sun.misc.*;
  55 import sun.awt.util.ThreadGroupUtils;
  56 import sun.print.PrintJob2D;
  57 import sun.security.action.GetPropertyAction;
  58 import sun.security.action.GetBooleanAction;
  59 import sun.util.logging.PlatformLogger;

  60 
  61 public final class XToolkit extends UNIXToolkit implements Runnable {
  62     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit");
  63     private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XToolkit");
  64     private static final PlatformLogger timeoutTaskLog = PlatformLogger.getLogger("sun.awt.X11.timeoutTask.XToolkit");
  65     private static final PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XToolkit");
  66     private static final PlatformLogger backingStoreLog = PlatformLogger.getLogger("sun.awt.X11.backingStore.XToolkit");
  67 
  68     //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME.
  69     //We use the same hardcoded constant.
  70     private static final int AWT_MULTICLICK_DEFAULT_TIME = 500;
  71 
  72     static final boolean PRIMARY_LOOP = false;
  73     static final boolean SECONDARY_LOOP = true;
  74 
  75     private static String awtAppClassName = null;
  76 
  77     // the system clipboard - CLIPBOARD selection
  78     XClipboard clipboard;
  79     // the system selection - PRIMARY selection


 405     /**
 406      * Returns whether there is last remembered cursor position.  The
 407      * position is remembered from X mouse events on our peers.  The
 408      * position is stored in <code>p</code>.
 409      * @return true, if there is remembered last cursor position,
 410      * false otherwise
 411      */
 412     boolean getLastCursorPos(Point p) {
 413         awtLock();
 414         try {
 415             if (lastCursorPos == null) {
 416                 return false;
 417             }
 418             p.setLocation(lastCursorPos);
 419             return true;
 420         } finally {
 421             awtUnlock();
 422         }
 423     }
 424 
 425     private void processGlobalMotionEvent(XEvent e) {
 426         // Only our windows guaranteely generate MotionNotify, so we
 427         // should track enter/leave, to catch the moment when to
 428         // switch to XQueryPointer
 429         if (e.get_type() == XConstants.MotionNotify) {
 430             XMotionEvent ev = e.get_xmotion();
 431             awtLock();
 432             try {
 433                 if (lastCursorPos == null) {
 434                     lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());

 435                 } else {
 436                     lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());

 437                 }
 438             } finally {
 439                 awtUnlock();
 440             }
 441         } else if (e.get_type() == XConstants.LeaveNotify) {
 442             // Leave from our window
 443             awtLock();
 444             try {
 445                 lastCursorPos = null;
 446             } finally {
 447                 awtUnlock();
 448             }
 449         } else if (e.get_type() == XConstants.EnterNotify) {
 450             // Entrance into our window
 451             XCrossingEvent ev = e.get_xcrossing();
 452             awtLock();
 453             try {
 454                 if (lastCursorPos == null) {
 455                     lastCursorPos = new Point(ev.get_x_root(), ev.get_y_root());

 456                 } else {
 457                     lastCursorPos.setLocation(ev.get_x_root(), ev.get_y_root());

 458                 }
 459             } finally {
 460                 awtUnlock();
 461             }
 462         }
 463     }
 464 
 465     public interface XEventListener {
 466         public void eventProcessed(XEvent e);
 467     }
 468 
 469     private Collection<XEventListener> listeners = new LinkedList<XEventListener>();
 470 
 471     public void addXEventListener(XEventListener listener) {
 472         synchronized (listeners) {
 473             listeners.add(listener);
 474         }
 475     }
 476 
 477     private void notifyListeners(XEvent xev) {
 478         synchronized (listeners) {
 479             if (listeners.size() == 0) return;
 480 
 481             XEvent copy = xev.clone();
 482             try {
 483                 for (XEventListener listener : listeners) {
 484                     listener.eventProcessed(copy);
 485                 }
 486             } finally {
 487                 copy.dispose();
 488             }
 489         }
 490     }
 491 
 492     private void dispatchEvent(XEvent ev) {
 493         final XAnyEvent xany = ev.get_xany();
 494 
 495         if (windowToXWindow(xany.get_window()) != null &&
 496              (ev.get_type() == XConstants.MotionNotify || ev.get_type() == XConstants.EnterNotify || ev.get_type() == XConstants.LeaveNotify))
 497         {
 498             processGlobalMotionEvent(ev);

 499         }
 500 
 501         if( ev.get_type() == XConstants.MappingNotify ) {
 502             // The 'window' field in this event is unused.
 503             // This application itself does nothing to initiate such an event
 504             // (no calls of XChangeKeyboardMapping etc.).
 505             // SunRay server sends this event to the application once on every
 506             // keyboard (not just layout) change which means, quite seldom.
 507             XlibWrapper.XRefreshKeyboardMapping(ev.pData);
 508             resetKeyboardSniffer();
 509             setupModifierMap();
 510         }
 511         XBaseWindow.dispatchToWindow(ev);
 512 
 513         Collection<XEventDispatcher> dispatchers = null;
 514         synchronized(winToDispatcher) {
 515             Long key = Long.valueOf(xany.get_window());
 516             dispatchers = winToDispatcher.get(key);
 517             if (dispatchers != null) { // Clone it to avoid synchronization during dispatching
 518                 dispatchers = new Vector<>(dispatchers);


 653                 }
 654             };
 655 
 656     static {
 657         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 658         if (ge instanceof SunGraphicsEnvironment) {
 659             ((SunGraphicsEnvironment) ge).addDisplayChangedListener(
 660                     displayChangedHandler);
 661         }
 662     }
 663 
 664     private static void initScreenSize() {
 665         if (screenWidth == -1 || screenHeight == -1) {
 666             awtLock();
 667             try {
 668                 XWindowAttributes pattr = new XWindowAttributes();
 669                 try {
 670                     XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
 671                                                      XToolkit.getDefaultRootWindow(),
 672                                                      pattr.pData);
 673                     screenWidth  = pattr.get_width();
 674                     screenHeight = pattr.get_height();
 675                 } finally {
 676                     pattr.dispose();
 677                 }
 678             } finally {
 679                 awtUnlock();
 680             }
 681         }
 682     }
 683 
 684     static int getDefaultScreenWidth() {
 685         initScreenSize();
 686         return screenWidth;
 687     }
 688 
 689     static int getDefaultScreenHeight() {
 690         initScreenSize();
 691         return screenHeight;
 692     }
 693 
 694     @Override
 695     protected int getScreenWidth() {
 696         return getDefaultScreenWidth();
 697     }
 698 
 699     @Override
 700     protected int getScreenHeight() {
 701         return getDefaultScreenHeight();
 702     }
 703 
 704     private static Rectangle getWorkArea(long root)
 705     {
 706         XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA");
 707 
 708         long native_ptr = Native.allocateLongArray(4);
 709         try
 710         {
 711             boolean workareaPresent = XA_NET_WORKAREA.getAtomData(root,
 712                 XAtom.XA_CARDINAL, native_ptr, 4);
 713             if (workareaPresent)
 714             {
 715                 int rootX = (int)Native.getLong(native_ptr, 0);
 716                 int rootY = (int)Native.getLong(native_ptr, 1);
 717                 int rootWidth = (int)Native.getLong(native_ptr, 2);
 718                 int rootHeight = (int)Native.getLong(native_ptr, 3);
 719 
 720                 return new Rectangle(rootX, rootY, rootWidth, rootHeight);



 721             }
 722         }
 723         finally
 724         {
 725             XlibWrapper.unsafe.freeMemory(native_ptr);
 726         }
 727 
 728         return null;
 729     }
 730 
 731     /*
 732      * If we're running in non-Xinerama environment and the current
 733      * window manager supports _NET protocol then the screen insets
 734      * are calculated using _NET_WM_WORKAREA property of the root
 735      * window.
 736      * Otherwise, i. e. if Xinerama is on or _NET_WM_WORKAREA is
 737      * not set, we try to calculate the insets ourselves using
 738      * getScreenInsetsManually method.
 739      */
 740     @Override
 741     public Insets getScreenInsets(GraphicsConfiguration gc)
 742     {
 743         XNETProtocol netProto = XWM.getWM().getNETProtocol();
 744         if ((netProto == null) || !netProto.active())
 745         {
 746             return super.getScreenInsets(gc);
 747         }
 748 
 749         XToolkit.awtLock();
 750         try
 751         {
 752             X11GraphicsConfig x11gc = (X11GraphicsConfig)gc;
 753             X11GraphicsDevice x11gd = (X11GraphicsDevice)x11gc.getDevice();
 754             long root = XlibUtil.getRootWindow(x11gd.getScreen());
 755             Rectangle rootBounds = XlibUtil.getWindowGeometry(root);

 756 
 757             X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment)
 758                 GraphicsEnvironment.getLocalGraphicsEnvironment();
 759             if (!x11ge.runningXinerama())
 760             {
 761                 Rectangle workArea = XToolkit.getWorkArea(root);
 762                 if (workArea != null)
 763                 {
 764                     return new Insets(workArea.y,
 765                                       workArea.x,
 766                                       rootBounds.height - workArea.height - workArea.y,
 767                                       rootBounds.width - workArea.width - workArea.x);
 768                 }
 769             }
 770 
 771             return getScreenInsetsManually(root, rootBounds, gc.getBounds());
 772         }
 773         finally
 774         {
 775             XToolkit.awtUnlock();
 776         }
 777     }
 778 
 779     /*
 780      * Manual calculation of screen insets: get all the windows with
 781      * _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL hints and add these
 782      * hints' values to screen insets.
 783      *
 784      * This method should be called under XToolkit.awtLock()
 785      */
 786     private Insets getScreenInsetsManually(long root, Rectangle rootBounds, Rectangle screenBounds)

 787     {
 788         /*
 789          * During the manual calculation of screen insets we iterate
 790          * all the X windows hierarchy starting from root window. This
 791          * constant is the max level inspected in this hierarchy.
 792          * 3 is a heuristic value: I suppose any the toolbar-like
 793          * window is a child of either root or desktop window.
 794          */
 795         final int MAX_NESTED_LEVEL = 3;
 796 
 797         XAtom XA_NET_WM_STRUT = XAtom.get("_NET_WM_STRUT");
 798         XAtom XA_NET_WM_STRUT_PARTIAL = XAtom.get("_NET_WM_STRUT_PARTIAL");
 799 
 800         Insets insets = new Insets(0, 0, 0, 0);
 801 
 802         java.util.List<Object> search = new LinkedList<>();
 803         search.add(root);
 804         search.add(0);
 805         while (!search.isEmpty())
 806         {


 814              * are not included to the screen insets.
 815              */
 816             if (XlibUtil.getWindowMapState(window) == XConstants.IsUnmapped)
 817             {
 818                 continue;
 819             }
 820 
 821             long native_ptr = Native.allocateLongArray(4);
 822             try
 823             {
 824                 // first, check if _NET_WM_STRUT or _NET_WM_STRUT_PARTIAL are present
 825                 // if both are set on the window, _NET_WM_STRUT_PARTIAL is used (see _NET spec)
 826                 boolean strutPresent = XA_NET_WM_STRUT_PARTIAL.getAtomData(window, XAtom.XA_CARDINAL, native_ptr, 4);
 827                 if (!strutPresent)
 828                 {
 829                     strutPresent = XA_NET_WM_STRUT.getAtomData(window, XAtom.XA_CARDINAL, native_ptr, 4);
 830                 }
 831                 if (strutPresent)
 832                 {
 833                     // second, verify that window is located on the proper screen
 834                     Rectangle windowBounds = XlibUtil.getWindowGeometry(window);

 835                     if (windowLevel > 1)
 836                     {
 837                         windowBounds = XlibUtil.translateCoordinates(window, root, windowBounds);


 838                     }
 839                     // if _NET_WM_STRUT_PARTIAL is present, we should use its values to detect
 840                     // if the struts area intersects with screenBounds, however some window
 841                     // managers don't set this hint correctly, so we just get intersection with windowBounds
 842                     if (windowBounds != null && windowBounds.intersects(screenBounds))
 843                     {
 844                         int left = (int)Native.getLong(native_ptr, 0);
 845                         int right = (int)Native.getLong(native_ptr, 1);
 846                         int top = (int)Native.getLong(native_ptr, 2);
 847                         int bottom = (int)Native.getLong(native_ptr, 3);
 848 
 849                         /*
 850                          * struts could be relative to root window bounds, so
 851                          * make them relative to the screen bounds in this case
 852                          */
 853                         left = rootBounds.x + left > screenBounds.x ?
 854                                 rootBounds.x + left - screenBounds.x : 0;
 855                         right = rootBounds.x + rootBounds.width - right <
 856                                 screenBounds.x + screenBounds.width ?
 857                                 screenBounds.x + screenBounds.width -
 858                                 (rootBounds.x + rootBounds.width - right) : 0;
 859                         top = rootBounds.y + top > screenBounds.y ?
 860                                 rootBounds.y + top - screenBounds.y : 0;
 861                         bottom = rootBounds.y + rootBounds.height - bottom <
 862                                 screenBounds.y + screenBounds.height ?
 863                                 screenBounds.y + screenBounds.height -
 864                                 (rootBounds.y + rootBounds.height - bottom) : 0;
 865 
 866                         insets.left = Math.max(left, insets.left);
 867                         insets.right = Math.max(right, insets.right);


2470         if (oops_waiter == null) {
2471             oops_waiter = new XEventDispatcher() {
2472                     @Override
2473                     public void dispatchEvent(XEvent e) {
2474                         if (e.get_type() == XConstants.ConfigureNotify) {
2475                             // OOPS ConfigureNotify event catched
2476                             oops_updated = true;
2477                             awtLockNotifyAll();
2478                         }
2479                     }
2480                 };
2481         }
2482 
2483         awtLock();
2484         try {
2485             addEventDispatcher(win.getWindow(), oops_waiter);
2486 
2487             oops_updated = false;
2488             long event_number = getEventNumber();
2489             // Generate OOPS ConfigureNotify event
2490             XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(), ++oops_position, 0);

2491             // Change win position each time to avoid system optimization
2492             if (oops_position > 50) {
2493                 oops_position = 0;
2494             }
2495 
2496             XSync();
2497 
2498             eventLog.finer("Generated OOPS ConfigureNotify event");
2499 
2500             long start = System.currentTimeMillis();
2501             while (!oops_updated) {
2502                 try {
2503                     // Wait for OOPS ConfigureNotify event
2504                     awtLockWait(timeout);
2505                 } catch (InterruptedException e) {
2506                     throw new RuntimeException(e);
2507                 }
2508                 // This "while" is a protection from spurious
2509                 // wake-ups.  However, we shouldn't wait for too long
2510                 if ((System.currentTimeMillis() - start > timeout) && timeout >= 0) {




  40 import java.awt.im.InputMethodHighlight;
  41 import java.awt.im.spi.InputMethodDescriptor;
  42 import java.awt.image.ColorModel;
  43 import java.awt.peer.*;
  44 import java.beans.PropertyChangeListener;
  45 import java.security.AccessController;
  46 import java.security.PrivilegedAction;
  47 import java.util.*;
  48 import javax.swing.LookAndFeel;
  49 import javax.swing.UIDefaults;
  50 import sun.awt.*;
  51 import sun.awt.datatransfer.DataTransferer;
  52 import sun.font.FontConfigManager;
  53 import sun.java2d.SunGraphicsEnvironment;
  54 import sun.misc.*;
  55 import sun.awt.util.ThreadGroupUtils;
  56 import sun.print.PrintJob2D;
  57 import sun.security.action.GetPropertyAction;
  58 import sun.security.action.GetBooleanAction;
  59 import sun.util.logging.PlatformLogger;
  60 import static sun.awt.X11.XlibUtil.scaleDown;
  61 
  62 public final class XToolkit extends UNIXToolkit implements Runnable {
  63     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit");
  64     private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XToolkit");
  65     private static final PlatformLogger timeoutTaskLog = PlatformLogger.getLogger("sun.awt.X11.timeoutTask.XToolkit");
  66     private static final PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XToolkit");
  67     private static final PlatformLogger backingStoreLog = PlatformLogger.getLogger("sun.awt.X11.backingStore.XToolkit");
  68 
  69     //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME.
  70     //We use the same hardcoded constant.
  71     private static final int AWT_MULTICLICK_DEFAULT_TIME = 500;
  72 
  73     static final boolean PRIMARY_LOOP = false;
  74     static final boolean SECONDARY_LOOP = true;
  75 
  76     private static String awtAppClassName = null;
  77 
  78     // the system clipboard - CLIPBOARD selection
  79     XClipboard clipboard;
  80     // the system selection - PRIMARY selection


 406     /**
 407      * Returns whether there is last remembered cursor position.  The
 408      * position is remembered from X mouse events on our peers.  The
 409      * position is stored in <code>p</code>.
 410      * @return true, if there is remembered last cursor position,
 411      * false otherwise
 412      */
 413     boolean getLastCursorPos(Point p) {
 414         awtLock();
 415         try {
 416             if (lastCursorPos == null) {
 417                 return false;
 418             }
 419             p.setLocation(lastCursorPos);
 420             return true;
 421         } finally {
 422             awtUnlock();
 423         }
 424     }
 425 
 426     private void processGlobalMotionEvent(XEvent e, XBaseWindow win) {
 427         // Only our windows guaranteely generate MotionNotify, so we
 428         // should track enter/leave, to catch the moment when to
 429         // switch to XQueryPointer
 430         if (e.get_type() == XConstants.MotionNotify) {
 431             XMotionEvent ev = e.get_xmotion();
 432             awtLock();
 433             try {
 434                 if (lastCursorPos == null) {
 435                     lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
 436                                               win.scaleDown(ev.get_y_root()));
 437                 } else {
 438                     lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
 439                                               win.scaleDown(ev.get_y_root()));
 440                 }
 441             } finally {
 442                 awtUnlock();
 443             }
 444         } else if (e.get_type() == XConstants.LeaveNotify) {
 445             // Leave from our window
 446             awtLock();
 447             try {
 448                 lastCursorPos = null;
 449             } finally {
 450                 awtUnlock();
 451             }
 452         } else if (e.get_type() == XConstants.EnterNotify) {
 453             // Entrance into our window
 454             XCrossingEvent ev = e.get_xcrossing();
 455             awtLock();
 456             try {
 457                 if (lastCursorPos == null) {
 458                     lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
 459                                               win.scaleDown(ev.get_y_root()));
 460                 } else {
 461                     lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
 462                                               win.scaleDown(ev.get_y_root()));
 463                 }
 464             } finally {
 465                 awtUnlock();
 466             }
 467         }
 468     }
 469 
 470     public interface XEventListener {
 471         public void eventProcessed(XEvent e);
 472     }
 473 
 474     private Collection<XEventListener> listeners = new LinkedList<XEventListener>();
 475 
 476     public void addXEventListener(XEventListener listener) {
 477         synchronized (listeners) {
 478             listeners.add(listener);
 479         }
 480     }
 481 
 482     private void notifyListeners(XEvent xev) {
 483         synchronized (listeners) {
 484             if (listeners.size() == 0) return;
 485 
 486             XEvent copy = xev.clone();
 487             try {
 488                 for (XEventListener listener : listeners) {
 489                     listener.eventProcessed(copy);
 490                 }
 491             } finally {
 492                 copy.dispose();
 493             }
 494         }
 495     }
 496 
 497     private void dispatchEvent(XEvent ev) {
 498         final XAnyEvent xany = ev.get_xany();
 499 
 500         XBaseWindow baseWindow = windowToXWindow(xany.get_window());
 501         if (baseWindow != null && (ev.get_type() == XConstants.MotionNotify
 502                 || ev.get_type() == XConstants.EnterNotify
 503                 || ev.get_type() == XConstants.LeaveNotify)) {
 504             processGlobalMotionEvent(ev, baseWindow);
 505         }
 506 
 507         if( ev.get_type() == XConstants.MappingNotify ) {
 508             // The 'window' field in this event is unused.
 509             // This application itself does nothing to initiate such an event
 510             // (no calls of XChangeKeyboardMapping etc.).
 511             // SunRay server sends this event to the application once on every
 512             // keyboard (not just layout) change which means, quite seldom.
 513             XlibWrapper.XRefreshKeyboardMapping(ev.pData);
 514             resetKeyboardSniffer();
 515             setupModifierMap();
 516         }
 517         XBaseWindow.dispatchToWindow(ev);
 518 
 519         Collection<XEventDispatcher> dispatchers = null;
 520         synchronized(winToDispatcher) {
 521             Long key = Long.valueOf(xany.get_window());
 522             dispatchers = winToDispatcher.get(key);
 523             if (dispatchers != null) { // Clone it to avoid synchronization during dispatching
 524                 dispatchers = new Vector<>(dispatchers);


 659                 }
 660             };
 661 
 662     static {
 663         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
 664         if (ge instanceof SunGraphicsEnvironment) {
 665             ((SunGraphicsEnvironment) ge).addDisplayChangedListener(
 666                     displayChangedHandler);
 667         }
 668     }
 669 
 670     private static void initScreenSize() {
 671         if (screenWidth == -1 || screenHeight == -1) {
 672             awtLock();
 673             try {
 674                 XWindowAttributes pattr = new XWindowAttributes();
 675                 try {
 676                     XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
 677                                                      XToolkit.getDefaultRootWindow(),
 678                                                      pattr.pData);
 679                     screenWidth  = config.scaleDown(pattr.get_width());
 680                     screenHeight = config.scaleDown(pattr.get_height());
 681                 } finally {
 682                     pattr.dispose();
 683                 }
 684             } finally {
 685                 awtUnlock();
 686             }
 687         }
 688     }
 689 
 690     static int getDefaultScreenWidth() {
 691         initScreenSize();
 692         return screenWidth;
 693     }
 694 
 695     static int getDefaultScreenHeight() {
 696         initScreenSize();
 697         return screenHeight;
 698     }
 699 
 700     @Override
 701     protected int getScreenWidth() {
 702         return getDefaultScreenWidth();
 703     }
 704 
 705     @Override
 706     protected int getScreenHeight() {
 707         return getDefaultScreenHeight();
 708     }
 709 
 710     private static Rectangle getWorkArea(long root, int scale)
 711     {
 712         XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA");
 713 
 714         long native_ptr = Native.allocateLongArray(4);
 715         try
 716         {
 717             boolean workareaPresent = XA_NET_WORKAREA.getAtomData(root,
 718                 XAtom.XA_CARDINAL, native_ptr, 4);
 719             if (workareaPresent)
 720             {
 721                 int rootX = (int)Native.getLong(native_ptr, 0);
 722                 int rootY = (int)Native.getLong(native_ptr, 1);
 723                 int rootWidth = (int)Native.getLong(native_ptr, 2);
 724                 int rootHeight = (int)Native.getLong(native_ptr, 3);
 725 
 726                 return new Rectangle(scaleDown(rootX, scale),
 727                                      scaleDown(rootY, scale),
 728                                      scaleDown(rootWidth, scale),
 729                                      scaleDown(rootHeight, scale));
 730             }
 731         }
 732         finally
 733         {
 734             XlibWrapper.unsafe.freeMemory(native_ptr);
 735         }
 736 
 737         return null;
 738     }
 739 
 740     /*
 741      * If we're running in non-Xinerama environment and the current
 742      * window manager supports _NET protocol then the screen insets
 743      * are calculated using _NET_WM_WORKAREA property of the root
 744      * window.
 745      * Otherwise, i. e. if Xinerama is on or _NET_WM_WORKAREA is
 746      * not set, we try to calculate the insets ourselves using
 747      * getScreenInsetsManually method.
 748      */
 749     @Override
 750     public Insets getScreenInsets(GraphicsConfiguration gc)
 751     {
 752         XNETProtocol netProto = XWM.getWM().getNETProtocol();
 753         if ((netProto == null) || !netProto.active())
 754         {
 755             return super.getScreenInsets(gc);
 756         }
 757 
 758         XToolkit.awtLock();
 759         try
 760         {
 761             X11GraphicsConfig x11gc = (X11GraphicsConfig)gc;
 762             X11GraphicsDevice x11gd = x11gc.getDevice();
 763             long root = XlibUtil.getRootWindow(x11gd.getScreen());
 764             int scale = x11gc.getScale();
 765             Rectangle rootBounds = XlibUtil.getWindowGeometry(root, scale);
 766 
 767             X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment)
 768                 GraphicsEnvironment.getLocalGraphicsEnvironment();
 769             if (!x11ge.runningXinerama())
 770             {
 771                 Rectangle workArea = XToolkit.getWorkArea(root, scale);
 772                 if (workArea != null)
 773                 {
 774                     return new Insets(workArea.y,
 775                                       workArea.x,
 776                                       rootBounds.height - workArea.height - workArea.y,
 777                                       rootBounds.width - workArea.width - workArea.x);
 778                 }
 779             }
 780 
 781             return getScreenInsetsManually(root, rootBounds, gc.getBounds(), scale);
 782         }
 783         finally
 784         {
 785             XToolkit.awtUnlock();
 786         }
 787     }
 788 
 789     /*
 790      * Manual calculation of screen insets: get all the windows with
 791      * _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL hints and add these
 792      * hints' values to screen insets.
 793      *
 794      * This method should be called under XToolkit.awtLock()
 795      */
 796     private Insets getScreenInsetsManually(long root, Rectangle rootBounds,
 797                                            Rectangle screenBounds, int scale)
 798     {
 799         /*
 800          * During the manual calculation of screen insets we iterate
 801          * all the X windows hierarchy starting from root window. This
 802          * constant is the max level inspected in this hierarchy.
 803          * 3 is a heuristic value: I suppose any the toolbar-like
 804          * window is a child of either root or desktop window.
 805          */
 806         final int MAX_NESTED_LEVEL = 3;
 807 
 808         XAtom XA_NET_WM_STRUT = XAtom.get("_NET_WM_STRUT");
 809         XAtom XA_NET_WM_STRUT_PARTIAL = XAtom.get("_NET_WM_STRUT_PARTIAL");
 810 
 811         Insets insets = new Insets(0, 0, 0, 0);
 812 
 813         java.util.List<Object> search = new LinkedList<>();
 814         search.add(root);
 815         search.add(0);
 816         while (!search.isEmpty())
 817         {


 825              * are not included to the screen insets.
 826              */
 827             if (XlibUtil.getWindowMapState(window) == XConstants.IsUnmapped)
 828             {
 829                 continue;
 830             }
 831 
 832             long native_ptr = Native.allocateLongArray(4);
 833             try
 834             {
 835                 // first, check if _NET_WM_STRUT or _NET_WM_STRUT_PARTIAL are present
 836                 // if both are set on the window, _NET_WM_STRUT_PARTIAL is used (see _NET spec)
 837                 boolean strutPresent = XA_NET_WM_STRUT_PARTIAL.getAtomData(window, XAtom.XA_CARDINAL, native_ptr, 4);
 838                 if (!strutPresent)
 839                 {
 840                     strutPresent = XA_NET_WM_STRUT.getAtomData(window, XAtom.XA_CARDINAL, native_ptr, 4);
 841                 }
 842                 if (strutPresent)
 843                 {
 844                     // second, verify that window is located on the proper screen
 845                     Rectangle windowBounds = XlibUtil.getWindowGeometry(window,
 846                                                                         scale);
 847                     if (windowLevel > 1)
 848                     {
 849                         windowBounds = XlibUtil.translateCoordinates(window, root,
 850                                                                      windowBounds,
 851                                                                      scale);
 852                     }
 853                     // if _NET_WM_STRUT_PARTIAL is present, we should use its values to detect
 854                     // if the struts area intersects with screenBounds, however some window
 855                     // managers don't set this hint correctly, so we just get intersection with windowBounds
 856                     if (windowBounds != null && windowBounds.intersects(screenBounds))
 857                     {
 858                         int left = scaleDown((int)Native.getLong(native_ptr, 0), scale);
 859                         int right = scaleDown((int)Native.getLong(native_ptr, 1), scale);
 860                         int top = scaleDown((int)Native.getLong(native_ptr, 2), scale);
 861                         int bottom = scaleDown((int)Native.getLong(native_ptr, 3), scale);
 862 
 863                         /*
 864                          * struts could be relative to root window bounds, so
 865                          * make them relative to the screen bounds in this case
 866                          */
 867                         left = rootBounds.x + left > screenBounds.x ?
 868                                 rootBounds.x + left - screenBounds.x : 0;
 869                         right = rootBounds.x + rootBounds.width - right <
 870                                 screenBounds.x + screenBounds.width ?
 871                                 screenBounds.x + screenBounds.width -
 872                                 (rootBounds.x + rootBounds.width - right) : 0;
 873                         top = rootBounds.y + top > screenBounds.y ?
 874                                 rootBounds.y + top - screenBounds.y : 0;
 875                         bottom = rootBounds.y + rootBounds.height - bottom <
 876                                 screenBounds.y + screenBounds.height ?
 877                                 screenBounds.y + screenBounds.height -
 878                                 (rootBounds.y + rootBounds.height - bottom) : 0;
 879 
 880                         insets.left = Math.max(left, insets.left);
 881                         insets.right = Math.max(right, insets.right);


2484         if (oops_waiter == null) {
2485             oops_waiter = new XEventDispatcher() {
2486                     @Override
2487                     public void dispatchEvent(XEvent e) {
2488                         if (e.get_type() == XConstants.ConfigureNotify) {
2489                             // OOPS ConfigureNotify event catched
2490                             oops_updated = true;
2491                             awtLockNotifyAll();
2492                         }
2493                     }
2494                 };
2495         }
2496 
2497         awtLock();
2498         try {
2499             addEventDispatcher(win.getWindow(), oops_waiter);
2500 
2501             oops_updated = false;
2502             long event_number = getEventNumber();
2503             // Generate OOPS ConfigureNotify event
2504             XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(),
2505                                     win.scaleUp(++oops_position), 0);
2506             // Change win position each time to avoid system optimization
2507             if (oops_position > 50) {
2508                 oops_position = 0;
2509             }
2510 
2511             XSync();
2512 
2513             eventLog.finer("Generated OOPS ConfigureNotify event");
2514 
2515             long start = System.currentTimeMillis();
2516             while (!oops_updated) {
2517                 try {
2518                     // Wait for OOPS ConfigureNotify event
2519                     awtLockWait(timeout);
2520                 } catch (InterruptedException e) {
2521                     throw new RuntimeException(e);
2522                 }
2523                 // This "while" is a protection from spurious
2524                 // wake-ups.  However, we shouldn't wait for too long
2525                 if ((System.currentTimeMillis() - start > timeout) && timeout >= 0) {


< prev index next >