--- old/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2018-09-10 14:46:48.000000000 -0700 +++ new/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java 2018-09-10 14:46:48.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,6 +215,12 @@ static long awt_defaultFg; // Pixel private static XMouseInfoPeer xPeer; + /** + * Should we check "_NET_WM_STRUT/_NET_WM_STRUT_PARTIAL" during insets + * calculation. + */ + private static Boolean checkSTRUT; + static { initSecurityWarning(); if (GraphicsEnvironment.isHeadless()) { @@ -826,13 +832,26 @@ } /* - * If we're running in non-Xinerama environment and the current - * window manager supports _NET protocol then the screen insets - * are calculated using _NET_WM_WORKAREA property of the root - * window. - * Otherwise, i. e. if Xinerama is on or _NET_WM_WORKAREA is - * not set, we try to calculate the insets ourselves using - * getScreenInsetsManually method. + * If the current window manager supports _NET protocol then the screen + * insets are calculated using _NET_WORKAREA property of the root window. + *

+ * Note that _NET_WORKAREA is a rectangular area and it does not work + * well in the Xinerama mode. + *

+ * We will trust the part of this rectangular area only if it starts at the + * requested graphics configuration. Below is an example when the + * _NET_WORKAREA intersects with the requested graphics configuration but + * produce wrong result. + * + * //<-x1,y1/////// + * // // //////////////// + * // SCREEN1 // // SCREEN2 // + * // ********** // // x2,y2->// + * //////////////// // // + * //////////////// + * + * When two screens are overlap and the first contain a dock(*****), then + * _NET_WORKAREA may start at point x1,y1 and ends at point x2,y2. */ @Override public Insets getScreenInsets(GraphicsConfiguration gc) @@ -846,30 +865,33 @@ XToolkit.awtLock(); try { - X11GraphicsConfig x11gc = (X11GraphicsConfig)gc; - X11GraphicsDevice x11gd = x11gc.getDevice(); - long root = XlibUtil.getRootWindow(x11gd.getScreen()); - int scale = x11gc.getScale(); - Rectangle rootBounds = XlibUtil.getWindowGeometry(root, scale); - X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment) - GraphicsEnvironment.getLocalGraphicsEnvironment(); - if (!x11ge.runningXinerama()) - { - Insets screenInsets = getInsets(root, rootBounds, scale); - if (screenInsets != null) return screenInsets; - } - - Insets insets = getScreenInsetsManually(root, rootBounds, - gc.getBounds(), scale); - if ((insets.left | insets.top | insets.bottom | insets.right) == 0 - && rootBounds != null ) { - root = XlibWrapper.RootWindow(XToolkit.getDisplay(), - x11gd.getScreen()); - Insets screenInsets = getInsets(root, rootBounds, scale); - if (screenInsets != null) return screenInsets; + GraphicsEnvironment.getLocalGraphicsEnvironment(); + X11GraphicsConfig x11gc = (X11GraphicsConfig) gc; + long root = XlibUtil.getRootWindow(x11gc.getDevice().getScreen()); + int scale = x11gc.getScale(); + if (x11ge.runningXinerama() && checkSTRUT()) { + // implementation based on _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL + Rectangle rootBounds = XlibUtil.getWindowGeometry(root, scale); + Insets insets = getScreenInsetsManually(root, rootBounds, + gc.getBounds(), scale); + if ((insets.left | insets.top | insets.bottom | insets.right) != 0 + || rootBounds == null) { + return insets; + } + } + Rectangle workArea = XToolkit.getWorkArea(root, scale); + Rectangle screen = gc.getBounds(); + if (workArea != null && screen.contains(workArea.getLocation())) { + workArea = workArea.intersection(screen); + int top = workArea.y - screen.y; + int left = workArea.x - screen.x; + int bottom = screen.height - workArea.height - top; + int right = screen.width - workArea.width - left; + return new Insets(top, left, bottom, right); } - return insets; + // Note that it is better to return zeros than inadequate values + return new Insets(0, 0, 0, 0); } finally { @@ -877,14 +899,16 @@ } } - private Insets getInsets(long root, Rectangle rootBounds, int scale) { - Rectangle workArea = XToolkit.getWorkArea(root, scale); - if (workArea == null) { - return null; + /** + * Returns the value of "sun.awt.X11.checkSTRUT" property. Default value is + * {@code false}. + */ + private static boolean checkSTRUT() { + if (checkSTRUT == null) { + checkSTRUT = AccessController.doPrivileged( + new GetBooleanAction("sun.awt.X11.checkSTRUT")); } - return new Insets(workArea.y, workArea.x, - rootBounds.height - workArea.height - workArea.y, - rootBounds.width - workArea.width - workArea.x); + return checkSTRUT; } /* @@ -893,6 +917,14 @@ * hints' values to screen insets. * * This method should be called under XToolkit.awtLock() + * + * This method is unused because of two reasons: + * - Iteration over windows may be extremely slow, and execution of + * getScreenInsets() can be x100 slower than in one monitor config. + * - _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL are hints for the applications. + * WM should take into account these hints when "_NET_WORKAREA" is + * calculated, but the system panels are not necessary contain these + * hints(Gnome 3 for example). */ private Insets getScreenInsetsManually(long root, Rectangle rootBounds, Rectangle screenBounds, int scale)