JBR-4618 Force window size update after display reconfiguration

- Re-create all GraphicsDevices on displayChanged()
This commit is contained in:
Nikita Gubarkov
2023-11-29 22:19:41 +01:00
committed by jbrbot
parent b033e3a618
commit 54d2fd80ac
8 changed files with 113 additions and 106 deletions

View File

@@ -218,11 +218,9 @@ public class Win32GraphicsConfig extends GraphicsConfiguration
return (super.toString()+"[dev="+device+",pixfmt="+visual+"]");
}
private native Rectangle getBounds(int screen);
@Override
public Rectangle getBounds() {
return getBounds(device.getScreen());
return device.getBounds();
}
@Override

View File

@@ -106,11 +106,12 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
private static native void initIDs();
native void initDevice(int screen);
native void initNativeScale(int screen);
native void setNativeScale(int screen, float scaleX, float scaleY);
native float getNativeScaleX(int screen);
native float getNativeScaleY(int screen);
private native void initDevice(int screen);
private static native void initNativeScale(int screen);
private static native void setNativeScale(int screen, float scaleX, float scaleY);
private static native float getNativeScaleX(int screen);
private static native float getNativeScaleY(int screen);
private static native Rectangle getBounds(int screen);
public Win32GraphicsDevice(int screennum) {
this.screen = screennum;
@@ -169,6 +170,10 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
}
}
public Rectangle getBounds() {
return getBounds(getScreen());
}
/**
* Returns whether this is a valid device. Device can become
* invalid as a result of device removal event.
@@ -256,7 +261,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
}
}
private native int getMaxConfigsImpl(int screen);
private static native int getMaxConfigsImpl(int screen);
/**
* Returns whether or not the PixelFormat indicated by index is
@@ -268,7 +273,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
* are disabled. Do not call this function with an index of 0.
* @param index a PixelFormat index
*/
private native boolean isPixFmtSupported(int index, int screen);
private static native boolean isPixFmtSupported(int index, int screen);
/**
* Returns the PixelFormatID of the default graphics configuration
@@ -287,7 +292,7 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
* Returns the default PixelFormat ID from GDI. Do not call if PixelFormats
* are disabled.
*/
private native int getDefaultPixIDImpl(int screen);
private static native int getDefaultPixIDImpl(int screen);
/**
* Returns the default graphics configuration
@@ -541,9 +546,8 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
dynamicColorModel = null;
defaultConfig = null;
configs = null;
initScaleFactors();
Rectangle screenBounds = getDefaultConfiguration().getBounds();
Rectangle screenBounds = getBounds();
resizeFSWindow(getFullScreenWindow(), screenBounds);
// pass on to all top-level windows on this display
@@ -577,8 +581,8 @@ public class Win32GraphicsDevice extends GraphicsDevice implements
/**
* Creates and returns the color model associated with this device
*/
private native ColorModel makeColorModel (int screen,
boolean dynamic);
private static native ColorModel makeColorModel(int screen,
boolean dynamic);
/**
* Returns a dynamic ColorModel which is updated when there

View File

@@ -31,6 +31,7 @@ import java.awt.GraphicsDevice;
import java.awt.peer.ComponentPeer;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;
import sun.awt.windows.WToolkit;
@@ -147,41 +148,23 @@ public final class Win32GraphicsEnvironment extends SunGraphicsEnvironment {
*/
@Override
public void displayChanged() {
if (screens != null) {
if (oldDevices == null) {
oldDevices = new ArrayList<>();
}
for (int i = 0; i < screens.length; i++) {
if (screens[i] instanceof Win32GraphicsDevice gd) {
oldDevices.add(new WeakReference<>(gd));
} else {
// REMIND: can we ever have anything other than Win32GD?
assert (false) : screens[i];
}
}
}
// create the new devices
// getNumScreens() will return the correct current number of screens
GraphicsDevice[] newDevices = new GraphicsDevice[getNumScreens()];
GraphicsDevice[] oldScreens = screens;
// go through the list of current devices and determine if they
// could be reused, or will have to be replaced
if (oldScreens != null) {
for (int i = 0; i < oldScreens.length; i++) {
if (!(screens[i] instanceof Win32GraphicsDevice)) {
// REMIND: can we ever have anything other than Win32GD?
assert (false) : oldScreens[i];
continue;
}
Win32GraphicsDevice gd = (Win32GraphicsDevice)oldScreens[i];
// devices may be invalidated from the native code when the
// display change happens (device add/removal also causes a
// display change)
if (!gd.isValid()) {
if (oldDevices == null) {
oldDevices =
new ArrayList<WeakReference<Win32GraphicsDevice>>();
}
oldDevices.add(new WeakReference<Win32GraphicsDevice>(gd));
} else if (i < newDevices.length) {
// reuse the device
newDevices[i] = gd;
}
}
oldScreens = null;
}
// create the new devices (those that weren't reused)
for (int i = 0; i < newDevices.length; i++) {
if (newDevices[i] == null) {
newDevices[i] = makeScreenDevice(i);
}
}
Arrays.setAll(newDevices, this::makeScreenDevice);
// install the new array of devices
// Note: no synchronization here, it doesn't matter if a thread gets
// a new or an old array this time around

View File

@@ -631,6 +631,14 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
AWTAccessor.getComponentAccessor().
setGraphicsConfiguration((Component)target, winGraphicsConfig);
// Windows may have already sent us WM_PAINT,
// which we have processed before updating the GC,
// so force full repaint just to be sure we don't leave damaged content.
if (oldDev != newDev) {
Rectangle b = getBounds();
handlePaint(0, 0, b.width, b.height);
}
}
/**

View File

@@ -214,6 +214,7 @@ BOOL Devices::UpdateInstance(JNIEnv *env)
}
for (i = 0; i < numScreens; ++i) {
rawDevices[i]->Initialize();
rawDevices[i]->InitDesktopScales();
}
{
CriticalSection::Lock l(arrayLock);

View File

@@ -912,6 +912,20 @@ void AwtToolkit::DestroyComponentHWND(HWND hwnd)
void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment);
#endif
static BOOL CALLBACK UpdateAllThreadWindowSizes(HWND hWnd, LPARAM)
{
TRY;
AwtComponent *c = AwtComponent::GetComponent(hWnd);
if (c) {
RECT r;
GetWindowRect(hWnd, &r);
c->WmSize(SIZENORMAL, r.right-r.left, r.bottom-r.top);
c->Invalidate(NULL);
}
return TRUE;
CATCH_BAD_ALLOC_RET(FALSE);
}
/*
* An AwtToolkit window is just a means of routing toolkit messages to here.
*/
@@ -1302,6 +1316,7 @@ LRESULT CALLBACK AwtToolkit::WndProc(HWND hWnd, UINT message,
case WM_DISPLAYCHANGE: {
// Reinitialize screens
initScreens(env);
::EnumThreadWindows(MainThread(), (WNDENUMPROC)UpdateAllThreadWindowSizes, 0);
// Notify Java side - call WToolkit.displayChanged()
jclass clazz = env->FindClass("sun/awt/windows/WToolkit");

View File

@@ -76,50 +76,3 @@ inline int shiftToMask(int numBits, int shift) {
mask = mask << shift;
return mask;
}
/*
* Class: sun_awt_Win32GraphicsConfig
* Method: getBounds
* Signature: ()Ljava/awt/Rectangle
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsConfig_getBounds(JNIEnv *env, jobject thisobj,
jint screen)
{
jclass clazz;
jmethodID mid;
jobject bounds = NULL;
clazz = env->FindClass("java/awt/Rectangle");
CHECK_NULL_RETURN(clazz, NULL);
mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
if (mid != 0) {
RECT rRW = {0, 0, 0, 0};
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {
int w = (device == NULL) ? rRW.right - rRW.left
: device->ScaleDownX(rRW.right - rRW.left);
int h = (device == NULL) ? rRW.bottom - rRW.top
: device->ScaleDownY(rRW.bottom - rRW.top);
bounds = env->NewObject(clazz, mid, rRW.left, rRW.top, w, h);
}
else {
// 4910760 - don't return a null bounds, return the bounds of the
// primary screen
int w = ::GetSystemMetrics(SM_CXSCREEN);
int h = ::GetSystemMetrics(SM_CYSCREEN);
bounds = env->NewObject(clazz, mid,
0, 0,
device == NULL ? w : device->ScaleDownX(w),
device == NULL ? h : device->ScaleDownY(h));
}
if (safe_ExceptionOccurred(env)) {
return 0;
}
}
return bounds;
}

View File

@@ -1017,7 +1017,7 @@ Java_sun_awt_Win32GraphicsDevice_initIDs(JNIEnv *env, jclass cls)
*/
JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl
(JNIEnv* jniEnv, jobject theThis, jint screen) {
(JNIEnv* jniEnv, jclass clazz, jint screen) {
TRY;
HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
@@ -1044,7 +1044,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl
*/
JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported
(JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) {
(JNIEnv* env, jclass clazz, jint pixFmtID, jint screen) {
TRY;
jboolean suppColor = JNI_TRUE;
HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
@@ -1086,7 +1086,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported
*/
JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl
(JNIEnv* env, jobject theThis, jint screen) {
(JNIEnv* env, jclass clazz, jint screen) {
TRY;
int pixFmtID = 0;
HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
@@ -1118,7 +1118,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl
}
if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported(
env, theThis, pixFmtID, screen)) {
env, clazz, pixFmtID, screen)) {
/* Can't find a suitable pixel format ID. Fall back on 0. */
pixFmtID = 0;
}
@@ -1415,7 +1415,7 @@ JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes
JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsDevice_makeColorModel
(JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic)
(JNIEnv *env, jclass clazz, jint screen, jboolean dynamic)
{
Devices::InstanceAccess devices;
return devices->GetDevice(screen)->GetColorModel(env, dynamic);
@@ -1428,10 +1428,10 @@ JNIEXPORT jobject JNICALL
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initDevice
(JNIEnv *env, jobject thisPtr, jint screen)
(JNIEnv *env, jobject graphicsDevice, jint screen)
{
Devices::InstanceAccess devices;
devices->GetDevice(screen)->SetJavaDevice(env, thisPtr);
devices->GetDevice(screen)->SetJavaDevice(env, graphicsDevice);
}
/*
@@ -1441,7 +1441,7 @@ JNIEXPORT void JNICALL
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_setNativeScale
(JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY)
(JNIEnv *env, jclass clazz, jint screen, jfloat scaleX, jfloat scaleY)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
@@ -1459,7 +1459,7 @@ JNIEXPORT void JNICALL
*/
JNIEXPORT jfloat JNICALL
Java_sun_awt_Win32GraphicsDevice_getNativeScaleX
(JNIEnv *env, jobject thisPtr, jint screen)
(JNIEnv *env, jclass clazz, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
@@ -1473,7 +1473,7 @@ JNIEXPORT jfloat JNICALL
*/
JNIEXPORT jfloat JNICALL
Java_sun_awt_Win32GraphicsDevice_getNativeScaleY
(JNIEnv *env, jobject thisPtr, jint screen)
(JNIEnv *env, jclass clazz, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
@@ -1487,7 +1487,7 @@ JNIEXPORT jfloat JNICALL
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initNativeScale
(JNIEnv *env, jobject thisPtr, jint screen)
(JNIEnv *env, jclass clazz, jint screen)
{
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
@@ -1496,3 +1496,48 @@ Java_sun_awt_Win32GraphicsDevice_initNativeScale
device->InitDesktopScales();
}
}
/*
* Class: sun_awt_Win32GraphicsDevice
* Method: getBounds
* Signature: (I)Ljava/awt/Rectangle
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsDevice_getBounds(JNIEnv *env, jclass clazz, jint screen)
{
jmethodID mid;
jobject bounds = NULL;
clazz = env->FindClass("java/awt/Rectangle");
CHECK_NULL_RETURN(clazz, NULL);
mid = env->GetMethodID(clazz, "<init>", "(IIII)V");
if (mid != 0) {
RECT rRW = {0, 0, 0, 0};
Devices::InstanceAccess devices;
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) {
int w = (device == NULL) ? rRW.right - rRW.left
: device->ScaleDownX(rRW.right - rRW.left);
int h = (device == NULL) ? rRW.bottom - rRW.top
: device->ScaleDownY(rRW.bottom - rRW.top);
bounds = env->NewObject(clazz, mid, rRW.left, rRW.top, w, h);
}
else {
// 4910760 - don't return a null bounds, return the bounds of the
// primary screen
int w = ::GetSystemMetrics(SM_CXSCREEN);
int h = ::GetSystemMetrics(SM_CYSCREEN);
bounds = env->NewObject(clazz, mid,
0, 0,
device == NULL ? w : device->ScaleDownX(w),
device == NULL ? h : device->ScaleDownY(h));
}
if (safe_ExceptionOccurred(env)) {
return 0;
}
}
return bounds;
}