Skip to content
Permalink
Browse files
8076313: GraphicsEnvironment does not detect changes in count of moni…
…tors on Linux OS

Reviewed-by: kizune
  • Loading branch information
mrserb committed Feb 3, 2021
1 parent a47befc commit 98a76921ec782b720fe13f25f0e247b12fcbc638
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@@ -351,8 +351,7 @@ public void dispatchEvent(XEvent ev) {
awtUnlock();
try {
((X11GraphicsEnvironment)GraphicsEnvironment.
getLocalGraphicsEnvironment()).
displayChanged();
getLocalGraphicsEnvironment()).rebuildDevices();
} finally {
awtLock();
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@@ -329,19 +329,10 @@ public String toString() {
}

@Override
public Rectangle getBounds() {
Rectangle rect = pGetBounds(device.getScreen());
if (getScale() != 1) {
rect.x = scaleDown(rect.x);
rect.y = scaleDown(rect.y);
rect.width = scaleDown(rect.width);
rect.height = scaleDown(rect.height);
}
return rect;
public final Rectangle getBounds() {
return device.getBounds();
}

private native Rectangle pGetBounds(int screenNum);

private static class XDBECapabilities extends BufferCapabilities {
public XDBECapabilities() {
super(imageCaps, imageCaps, FlipContents.UNDEFINED);
@@ -42,6 +42,7 @@
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.loops.SurfaceType;
import sun.java2d.opengl.GLXGraphicsConfig;
import sun.java2d.pipe.Region;
import sun.java2d.xr.XRGraphicsConfig;

/**
@@ -53,7 +54,11 @@
*/
public final class X11GraphicsDevice extends GraphicsDevice
implements DisplayChangedListener {
int screen;
/**
* X11 screen number. This identifier can become non-valid at any time
* therefore methods, which is using this id should be ready to it.
*/
private volatile int screen;
HashMap<SurfaceType, Object> x11ProxyKeyMap = new HashMap<>();

private static AWTPermission fullScreenExclusivePermission;
@@ -105,6 +110,25 @@ public int getType() {
return TYPE_RASTER_SCREEN;
}

public int scaleUp(int x) {
return Region.clipRound(x * (double)getScaleFactor());
}

public int scaleDown(int x) {
return Region.clipRound(x / (double)getScaleFactor());
}

public Rectangle getBounds() {
Rectangle rect = pGetBounds(getScreen());
if (getScaleFactor() != 1) {
rect.x = scaleDown(rect.x);
rect.y = scaleDown(rect.y);
rect.width = scaleDown(rect.width);
rect.height = scaleDown(rect.height);
}
return rect;
}

/**
* Returns the identification string associated with this graphics
* device.
@@ -165,8 +189,8 @@ private void makeConfigurations() {
doubleBufferVisuals.contains(Integer.valueOf(visNum)));

if (xrenderSupported) {
ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth, getConfigColormap(i, screen),
doubleBuffer);
ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth,
getConfigColormap(i, screen), doubleBuffer);
} else {
ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,
getConfigColormap(i, screen),
@@ -271,8 +295,8 @@ private static native void enumDisplayModes(int screen,
private static native void configDisplayMode(int screen,
int width, int height,
int displayMode);
private static native void resetNativeData(int screen);
private static native double getNativeScaleFactor(int screen);
private native Rectangle pGetBounds(int screenNum);

/**
* Returns true only if:
@@ -514,7 +538,6 @@ public int getScaleFactor() {
}

public int getNativeScale() {
isXrandrExtensionSupported();
return (int)Math.round(getNativeScaleFactor(screen));
}

@@ -544,4 +567,8 @@ public void removeDisplayChangedListener(DisplayChangedListener client) {
public String toString() {
return ("X11GraphicsDevice[screen="+screen+"]");
}

public void invalidate(X11GraphicsDevice device) {
screen = device.screen;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@@ -27,17 +27,23 @@

import java.awt.AWTError;
import java.awt.GraphicsDevice;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import sun.awt.X11.XToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.SurfaceManagerFactory;
import sun.java2d.UnixSurfaceManagerFactory;
import sun.java2d.xr.XRSurfaceData;
import sun.util.logging.PlatformLogger;

/**
* This is an implementation of a GraphicsEnvironment object for the
@@ -49,11 +55,6 @@
*/
public final class X11GraphicsEnvironment extends SunGraphicsEnvironment {

private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11GraphicsEnvironment");
private static final PlatformLogger screenLog = PlatformLogger.getLogger("sun.awt.screen.X11GraphicsEnvironment");

private static Boolean xinerState;

static {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
@@ -169,32 +170,109 @@ public static boolean isXRenderVerbose() {
private static native String getDisplayString();
private Boolean isDisplayLocal;

/** Available X11 screens. */
private final Map<Integer, X11GraphicsDevice> devices = new HashMap<>(5);

/**
* The key in the {@link #devices} for the main screen.
*/
private int mainScreen;

// list of invalidated graphics devices (those which were removed)
private List<WeakReference<X11GraphicsDevice>> oldDevices = new ArrayList<>();

/**
* This should only be called from the static initializer, so no need for
* the synchronized keyword.
*/
private static native void initDisplay(boolean glxRequested);

protected native int getNumScreens();

private native int getDefaultScreenNum();

public X11GraphicsEnvironment() {
if (isHeadless()) {
return;
}

/* Populate the device table */
rebuildDevices();
}

protected native int getNumScreens();
/**
* Initialize the native list of devices.
*/
private static native void initNativeData();

protected GraphicsDevice makeScreenDevice(int screennum) {
return new X11GraphicsDevice(screennum);
/**
* Updates the list of devices and notify listeners.
*/
public void rebuildDevices() {
XToolkit.awtLock();
try {
initNativeData();
initDevices();
} finally {
XToolkit.awtUnlock();
}
displayChanged();
}

private native int getDefaultScreenNum();
/**
* Returns the default screen graphics device.
* (Re)create all X11GraphicsDevices, reuses a devices if it is possible.
*/
public GraphicsDevice getDefaultScreenDevice() {
GraphicsDevice[] screens = getScreenDevices();
if (screens.length == 0) {
private synchronized void initDevices() {
Map<Integer, X11GraphicsDevice> old = new HashMap<>(devices);
devices.clear();

int numScreens = getNumScreens();
if (numScreens == 0) {
throw new AWTError("no screen devices");
}
int index = getDefaultScreenNum();
return screens[0 < index && index < screens.length ? index : 0];
mainScreen = 0 < index && index < screens.length ? index : 0;

for (int id = 0; id < numScreens; ++id) {
devices.put(id, old.containsKey(id) ? old.remove(id) :
new X11GraphicsDevice(id));
}
// if a device was not reused it should be invalidated
for (X11GraphicsDevice gd : old.values()) {
oldDevices.add(new WeakReference<>(gd));
}
// Need to notify old devices, in case the user hold the reference to it
for (ListIterator<WeakReference<X11GraphicsDevice>> it =
oldDevices.listIterator(); it.hasNext(); ) {
X11GraphicsDevice gd = it.next().get();
if (gd != null) {
gd.invalidate(devices.get(mainScreen));
gd.displayChanged();
} else {
// no more references to this device, remove it
it.remove();
}
}
}

@Override
public synchronized GraphicsDevice getDefaultScreenDevice() {
return devices.get(mainScreen);
}

@Override
public synchronized GraphicsDevice[] getScreenDevices() {
return devices.values().toArray(new X11GraphicsDevice[0]);
}

public synchronized GraphicsDevice getScreenDevice(int screen) {
return devices.get(screen);
}

@Override
protected GraphicsDevice makeScreenDevice(int screennum) {
throw new UnsupportedOperationException("This method is unused and" +
"should not be called in this implementation");
}

public boolean isDisplayLocal() {
@@ -289,15 +367,7 @@ public String getDefaultFontFaceName() {
private static native boolean pRunningXinerama();

public boolean runningXinerama() {
if (xinerState == null) {
// pRunningXinerama() simply returns a global boolean variable,
// so there is no need to synchronize here
xinerState = Boolean.valueOf(pRunningXinerama());
if (screenLog.isLoggable(PlatformLogger.Level.FINER)) {
screenLog.finer("Running Xinerama: " + xinerState);
}
}
return xinerState.booleanValue();
return pRunningXinerama();
}

/**
Loading

0 comments on commit 98a7692

Please sign in to comment.