JBR-2977 Opening a recent project in a new window doesn't bring this window to the front

(cherry picked from commit 2d9fb9e7b8)
This commit is contained in:
Dmitry Batrak
2020-12-24 16:32:29 +03:00
committed by alexey.ushakov@jetbrains.com
parent 72d10768f9
commit c93fcd1e63
3 changed files with 121 additions and 2 deletions

View File

@@ -166,6 +166,8 @@ public class XBaseWindow {
// Set WM_CLIENT_LEADER property
initClientLeader();
initUserTimeWindow();
}
/**
@@ -424,6 +426,13 @@ public class XBaseWindow {
}
}
private void initUserTimeWindow() {
XNETProtocol netProtocol = XWM.getWM().getNETProtocol();
if (netProtocol != null ) {
netProtocol.setupUserTimeWindow(this);
}
}
static XRootWindow getXAWTRootWindow() {
return XRootWindow.getInstance();
}
@@ -1271,8 +1280,8 @@ public class XBaseWindow {
globalUserTime = time;
}
XNETProtocol netProtocol = XWM.getWM().getNETProtocol();
if (netProtocol != null && netProtocol.active()) {
netProtocol.XA_NET_WM_USER_TIME.setCard32Property(this, time);
if (netProtocol != null) {
netProtocol.setUserTime(this, time);
}
}

View File

@@ -287,6 +287,7 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
XAtom XA_NET_WM_WINDOW_OPACITY = XAtom.get("_NET_WM_WINDOW_OPACITY");
XAtom XA_NET_WM_USER_TIME = XAtom.get("_NET_WM_USER_TIME");
XAtom XA_NET_WM_USER_TIME_WINDOW = XAtom.get("_NET_WM_USER_TIME_WINDOW");
/* For _NET_WM_STATE ClientMessage requests */
static final int _NET_WM_STATE_REMOVE =0; /* remove/unset property */
@@ -458,4 +459,21 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
XAtomList state = window.getNETWMState();
return (state != null && state.size() != 0 && state.contains(XA_NET_WM_STATE_HIDDEN));
}
private boolean isUserTimeWindowSupported() {
return checkProtocol(XA_NET_SUPPORTED, XA_NET_WM_USER_TIME_WINDOW);
}
void setupUserTimeWindow(XBaseWindow window) {
if (active() && isUserTimeWindowSupported()) {
XA_NET_WM_USER_TIME_WINDOW.setWindowProperty(window, XRootWindow.getInstance());
}
}
void setUserTime(XBaseWindow window, long time) {
if (active()) {
XBaseWindow target = isUserTimeWindowSupported() ? XRootWindow.getInstance() : window;
XA_NET_WM_USER_TIME.setCard32Property(target, time);
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2000-2020 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* @test
* @summary Regression test for JBR-2977 Opening a recent project in a new window doesn't bring this window to the front
* @key headful
*/
public class NewFrameAfterDialogTest {
private static final CompletableFuture<Boolean> success = new CompletableFuture<>();
private static Robot robot;
private static JFrame frame;
private static JDialog dialog;
private static JFrame frame2;
public static void main(String[] args) throws Exception {
robot = new Robot();
try {
SwingUtilities.invokeAndWait(NewFrameAfterDialogTest::initUI);
robot.delay(3000); // wait for the frame to appear
clickOn(frame);
robot.delay(3000); // wait for dialog to appear
clickOn(dialog);
robot.delay(3000); // wait for second frame to appear
clickOn(frame2);
success.get(10, TimeUnit.SECONDS);
} finally {
SwingUtilities.invokeAndWait(NewFrameAfterDialogTest::disposeUI);
}
}
private static void initUI() {
frame = new JFrame("NewFrameAfterDialogTest");
JButton button = new JButton("Open another frame");
button.addActionListener(e -> {
dialog = new JDialog(frame, true);
JButton b = new JButton("Confirm");
b.addActionListener(e2 -> dialog.dispose());
dialog.add(b);
dialog.setSize(300, 300);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
frame2 = new JFrame("Second frame");
JButton b2 = new JButton("Close");
b2.addActionListener(e3 -> success.complete(true));
frame2.add(b2);
frame2.setSize(300, 300);
frame2.setLocationRelativeTo(null);
frame2.setVisible(true);
});
frame.add(button);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static void disposeUI() {
if (frame != null) frame.dispose();
if (frame2 != null) frame2.dispose();
}
private static void clickAt(int x, int y) {
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
private static void clickOn(Component component) {
Point location = component.getLocationOnScreen();
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
}
}