提交 c4cbf306 编写于 作者: S serb

8170937: Swing apps are slow if displaying from a remote source to many local displays

Reviewed-by: prr, aivanov
上级 9acd2c54
/* /*
* Copyright (c) 2002, 2014, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -114,6 +114,12 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -114,6 +114,12 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
static long awt_defaultFg; // Pixel static long awt_defaultFg; // Pixel
private static XMouseInfoPeer xPeer; private static XMouseInfoPeer xPeer;
/**
* Should we check "_NET_WM_STRUT/_NET_WM_STRUT_PARTIAL" during insets
* calculation.
*/
private static Boolean checkSTRUT;
static { static {
initSecurityWarning(); initSecurityWarning();
if (GraphicsEnvironment.isHeadless()) { if (GraphicsEnvironment.isHeadless()) {
...@@ -717,13 +723,26 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -717,13 +723,26 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
} }
/* /*
* If we're running in non-Xinerama environment and the current * If the current window manager supports _NET protocol then the screen
* window manager supports _NET protocol then the screen insets * insets are calculated using _NET_WORKAREA property of the root window.
* are calculated using _NET_WM_WORKAREA property of the root * <p>
* window. * Note that _NET_WORKAREA is a rectangular area and it does not work
* Otherwise, i. e. if Xinerama is on or _NET_WM_WORKAREA is * well in the Xinerama mode.
* not set, we try to calculate the insets ourselves using * <p>
* getScreenInsetsManually method. * 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
* produces wrong result.
*
* //<-x1,y1///////
* // // ////////////////
* // SCREEN1 // // SCREEN2 //
* // ********** // // x2,y2->//
* //////////////// // //
* ////////////////
*
* When two screens overlap and the first contains a dock(*****), then
* _NET_WORKAREA may start at point x1,y1 and end at point x2,y2.
*/ */
public Insets getScreenInsets(GraphicsConfiguration gc) public Insets getScreenInsets(GraphicsConfiguration gc)
{ {
...@@ -739,23 +758,30 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -739,23 +758,30 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
X11GraphicsConfig x11gc = (X11GraphicsConfig)gc; X11GraphicsConfig x11gc = (X11GraphicsConfig)gc;
X11GraphicsDevice x11gd = (X11GraphicsDevice)x11gc.getDevice(); X11GraphicsDevice x11gd = (X11GraphicsDevice)x11gc.getDevice();
long root = XlibUtil.getRootWindow(x11gd.getScreen()); long root = XlibUtil.getRootWindow(x11gd.getScreen());
Rectangle rootBounds = XlibUtil.getWindowGeometry(root);
X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment) X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment)
GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsEnvironment.getLocalGraphicsEnvironment();
if (!x11ge.runningXinerama()) if (x11ge.runningXinerama() && checkSTRUT()) {
{ // implementation based on _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL
Rectangle workArea = XToolkit.getWorkArea(root); Rectangle rootBounds = XlibUtil.getWindowGeometry(root);
if (workArea != null) Insets insets = getScreenInsetsManually(root, rootBounds,
{ gc.getBounds());
return new Insets(workArea.y, if ((insets.left | insets.top | insets.bottom | insets.right) != 0
workArea.x, || rootBounds == null) {
rootBounds.height - workArea.height - workArea.y, return insets;
rootBounds.width - workArea.width - workArea.x);
} }
} }
Rectangle workArea = XToolkit.getWorkArea(root);
return getScreenInsetsManually(root, rootBounds, gc.getBounds()); 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);
}
// Note that it is better to return zeros than inadequate values
return new Insets(0, 0, 0, 0);
} }
finally finally
{ {
...@@ -763,12 +789,32 @@ public final class XToolkit extends UNIXToolkit implements Runnable { ...@@ -763,12 +789,32 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
} }
} }
/**
* 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 checkSTRUT;
}
/* /*
* Manual calculation of screen insets: get all the windows with * Manual calculation of screen insets: get all the windows with
* _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL hints and add these * _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL hints and add these
* hints' values to screen insets. * hints' values to screen insets.
* *
* This method should be called under XToolkit.awtLock() * This method should be called under XToolkit.awtLock()
*
* This method is unused by default 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 do not necessarily contain these
* hints(Gnome 3 for example).
*/ */
private Insets getScreenInsetsManually(long root, Rectangle rootBounds, Rectangle screenBounds) private Insets getScreenInsetsManually(long root, Rectangle rootBounds, Rectangle screenBounds)
{ {
......
/* /*
* Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,8 +31,13 @@ ...@@ -31,8 +31,13 @@
@run main ScreenInsetsTest @run main ScreenInsetsTest
*/ */
import java.awt.*; import java.awt.Frame;
import java.awt.event.*; import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import test.java.awt.regtesthelpers.Util; import test.java.awt.regtesthelpers.Util;
...@@ -40,21 +45,33 @@ public class ScreenInsetsTest ...@@ -40,21 +45,33 @@ public class ScreenInsetsTest
{ {
public static void main(String[] args) public static void main(String[] args)
{ {
if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH))
{
// this state is used in the test - sorry
return;
}
boolean passed = true; boolean passed = true;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gds = ge.getScreenDevices(); GraphicsDevice[] gds = ge.getScreenDevices();
for (GraphicsDevice gd : gds) for (GraphicsDevice gd : gds) {
{
GraphicsConfiguration gc = gd.getDefaultConfiguration(); GraphicsConfiguration gc = gd.getDefaultConfiguration();
Rectangle gcBounds = gc.getBounds(); Rectangle gcBounds = gc.getBounds();
Insets gcInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); Insets gcInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
int left = gcInsets.left;
int right = gcInsets.right;
int bottom = gcInsets.bottom;
int top = gcInsets.top;
if (left < 0 || right < 0 || bottom < 0 || top < 0) {
throw new RuntimeException("Negative value: " + gcInsets);
}
int maxW = gcBounds.width / 3;
int maxH = gcBounds.height / 3;
if (left > maxW || right > maxW || bottom > maxH || top > maxH) {
throw new RuntimeException("Big value: " + gcInsets);
}
if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH))
{
// this state is used in the test - sorry
continue;
}
Frame f = new Frame("Test", gc); Frame f = new Frame("Test", gc);
f.setUndecorated(true); f.setUndecorated(true);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册