From 0eee89e393c82198bd39021b8aff6ccc41f66c2c Mon Sep 17 00:00:00 2001 From: Artem Bochkarev Date: Wed, 14 Nov 2018 18:37:12 +0700 Subject: [PATCH] linux-menubar: show swing-menu in full screen mode fixed IDEA-201291 Linux Native menu bar: if 'windows-style' menu (i.e. located on the window title bar) is used, menu can't be used in the Full Screen mode --- bin/linux/libdbm64.so | Bin 39152 -> 39208 bytes native/LinuxGlobalMenu/DbusMenuWrapper.c | 9 +- native/LinuxGlobalMenu/DbusMenuWrapper.h | 2 +- .../openapi/wm/impl/GlobalMenuLinux.java | 86 ++++++++++++++---- .../openapi/wm/impl/IdeFrameDecorator.java | 5 + .../intellij/openapi/wm/impl/IdeMenuBar.java | 7 ++ 6 files changed, 90 insertions(+), 19 deletions(-) diff --git a/bin/linux/libdbm64.so b/bin/linux/libdbm64.so index 7fc851dcc1112708391218f5da7debb0d7cd4879..8d086450278368ad09fdb5ca370fcc074756dfb0 100755 GIT binary patch delta 7695 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 delta 7682 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 Yb=1o9n=(=DwN0b&R^+(SvW+SK4linkedXids = NULL; } + if (wi->onReleaseCallback != NULL) { + (*wi->onReleaseCallback)(); + wi->onReleaseCallback = NULL; + } free(wi); } @@ -340,8 +345,10 @@ static gboolean _execReleaseWindow(gpointer user_data) { return FALSE; } -void releaseWindowOnMainLoop(WndInfo *wi) { +void releaseWindowOnMainLoop(WndInfo *wi, jrunnable onReleased) { // _info("scheduled releaseWindowOnMainLoop"); + if (wi != NULL) + wi->onReleaseCallback = onReleased; g_idle_add(_execReleaseWindow, wi); } diff --git a/native/LinuxGlobalMenu/DbusMenuWrapper.h b/native/LinuxGlobalMenu/DbusMenuWrapper.h index f1b459d23292..42264b053749 100644 --- a/native/LinuxGlobalMenu/DbusMenuWrapper.h +++ b/native/LinuxGlobalMenu/DbusMenuWrapper.h @@ -40,7 +40,7 @@ void runMainLoop(jlogger jlogger, jrunnable onAppmenuServiceAppeared, jrunnable void execOnMainLoop(jrunnable run); WndInfo* registerWindow(long windowXid, jeventcallback handler); // creates menu-server and binds to xid -void releaseWindowOnMainLoop(WndInfo* wi); +void releaseWindowOnMainLoop(WndInfo* wi, jrunnable onReleased); void bindNewWindow(WndInfo * wi, long windowXid); void unbindWindow(WndInfo * wi, long windowXid); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java index d02c815b7517..f5d49caa2e85 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/GlobalMenuLinux.java @@ -24,7 +24,6 @@ import javax.imageio.ImageIO; import javax.swing.Timer; import javax.swing.*; import java.awt.*; -import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import java.awt.peer.ComponentPeer; import java.io.ByteArrayOutputStream; @@ -45,7 +44,7 @@ interface GlobalMenuLib extends Library { void execOnMainLoop(JRunnable run); Pointer registerWindow(long windowXid, EventHandler handler); - void releaseWindowOnMainLoop(Pointer wi); + void releaseWindowOnMainLoop(Pointer wi, JRunnable onReleased); void bindNewWindow(Pointer wi, long windowXid); // can be called from EDT (invokes only g_dbus_proxy_call, stateless) void unbindWindow(Pointer wi, long windowXid); // can be called from EDT (invokes only g_dbus_proxy_call, stateless) @@ -109,7 +108,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { private static final Logger LOG = Logger.getInstance(GlobalMenuLinux.class); private static final GlobalMenuLib ourLib; private static final GlobalMenuLib.JLogger ourGLogger; - private static final GlobalMenuLib.JRunnable ourProcessQueue; + private static final GlobalMenuLib.JRunnable ourUpdateAllRoots; private static final GlobalMenuLib.JRunnable ourOnAppmenuServiceAppeared; private static final GlobalMenuLib.JRunnable ourOnAppmenuServiceVanished; private static final Map ourInstances = new ConcurrentHashMap<>(); @@ -119,8 +118,11 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { private final @NotNull JFrame myFrame; private List myRoots; private Pointer myWindowHandle; - private boolean myIsProcessed = false; + private boolean myIsRootsUpdated = false; + private boolean myIsEnabled = true; + private boolean myIsDisposed = false; + private final GlobalMenuLib.JRunnable myOnWindowReleased; private final EventFilter myEventFilter = new EventFilter(); static { @@ -137,19 +139,19 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { LOG.error(msg); } }; - ourProcessQueue = () -> { + ourUpdateAllRoots = () -> { // exec at glib-thread if (!ourIsServiceAvailable) return; for (GlobalMenuLinux gml: ourInstances.values()) - gml._processRoots(); + gml._updateRoots(); }; ourOnAppmenuServiceAppeared = () -> { // exec at glib-thread LOG.info("Appeared dbus-service 'com.canonical.AppMenu.Registrar'"); ourIsServiceAvailable = true; - ourProcessQueue.run(); + ourUpdateAllRoots.run(); }; ourOnAppmenuServiceVanished = () -> { // exec at glib-thread @@ -177,7 +179,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } } else { ourGLogger = null; - ourProcessQueue = null; + ourUpdateAllRoots = null; ourOnAppmenuServiceAppeared = null; ourOnAppmenuServiceVanished = null; } @@ -192,22 +194,40 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { LOG.info("created instance of GlobalMenuLinux for xid=0x" + Long.toHexString(xid)); myXid = xid; myFrame = frame; + myOnWindowReleased = () -> { + // exec at glib-thread + myWindowHandle = null; + if (myRoots != null) { + for (MenuItemInternal root : myRoots) { + root.nativePeer = null; + root.children.clear(); + } + } + if (myIsDisposed) + ourInstances.remove(myXid); + }; ourInstances.put(myXid, this); } @Override public void dispose() { - if (ourLib == null) + // exec at EDT + if (ourLib == null || myIsDisposed) return; + myIsDisposed = true; + if (myWindowHandle != null) { - LOG.info("scheduled destroying of GlobalMenuLinux for xid=0x" + Long.toHexString(myXid)); - ourLib.releaseWindowOnMainLoop(myWindowHandle); + _trace("dispose frame, scheduled destroying of GlobalMenuLinux for xid=0x%X", myXid); + ourLib.releaseWindowOnMainLoop(myWindowHandle, myOnWindowReleased); } } public void bindNewWindow(@NotNull Window frame) { // exec at EDT + if (ourLib == null) + return; + final long xid = _getX11WindowXid(frame); if (xid == 0) { LOG.warn("can't obtain XID of window: " + frame + ", skip global menu binding"); @@ -221,6 +241,9 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { public void unbindWindow(@NotNull Window frame) { // exec at EDT + if (ourLib == null) + return; + final long xid = _getX11WindowXid(frame); if (xid == 0) { LOG.warn("can't obtain XID of window: " + frame + ", skip global menu unbinding"); @@ -233,6 +256,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } public void setRoots(List roots) { + // exec at EDT if (ourLib == null) return; @@ -252,16 +276,16 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { myRoots = newRoots; _trace("set new menu roots, count=%d", size); - myIsProcessed = false; - ourLib.execOnMainLoop(ourProcessQueue); + myIsRootsUpdated = false; + ourLib.execOnMainLoop(ourUpdateAllRoots); } - private void _processRoots() { + private void _updateRoots() { // exec at glib-thread - if (myIsProcessed) + if (myIsRootsUpdated || !myIsEnabled || myIsDisposed) return; - myIsProcessed = true; + myIsRootsUpdated = true; if (myWindowHandle == null) { myWindowHandle = ourLib.registerWindow(myXid, this); @@ -281,7 +305,35 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { mi.nativePeer = ourLib.addRootMenu(myWindowHandle, mi.uid, mi.txt); if (!SHOW_SWING_MENU) - ApplicationManager.getApplication().invokeLater(()->myFrame.getJMenuBar().setVisible(false)); + ApplicationManager.getApplication().invokeLater(()->{ + if (myIsEnabled) + myFrame.getJMenuBar().setVisible(false); + }); + } + + public void toggle(boolean enabled) { + if (ourLib == null || myIsDisposed) + return; + + if (myIsEnabled == enabled) + return; + + myIsEnabled = enabled; + + if (enabled) { + _trace("enable global-menu"); + myIsRootsUpdated = false; + ourLib.execOnMainLoop(ourUpdateAllRoots); + } else { + if (myWindowHandle != null) { + _trace("disable global menu, scheduled destroying of GlobalMenuLinux for xid=0x%X", myXid); + ourLib.releaseWindowOnMainLoop(myWindowHandle, myOnWindowReleased); + } + + final JMenuBar frameMenu = myFrame.getJMenuBar(); + if (frameMenu != null) + frameMenu.setVisible(true); + } } private MenuItemInternal _findMenuItem(int uid) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java index 411bc316c0ed..f82072fcf6aa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameDecorator.java @@ -152,6 +152,11 @@ public abstract class IdeFrameDecorator implements Disposable { if (myFrame != null) { myRequestedState = state; X11UiUtil.toggleFullScreenMode(myFrame); + + if (myFrame.getJMenuBar() instanceof IdeMenuBar) { + final IdeMenuBar frameMenuBar = (IdeMenuBar)myFrame.getJMenuBar(); + frameMenuBar.onToggleFullScreen(state); + } } return ActionCallback.DONE; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java index 4e74be871173..42f66e1e6235 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java @@ -600,6 +600,13 @@ public class IdeMenuBar extends JMenuBar implements IdeEventQueue.EventDispatche } } + public void onToggleFullScreen(boolean isFullScreen) { + if (myGlobalMenuLinux == null) + return; + + myGlobalMenuLinux.toggle(!isFullScreen); + } + private static class MyExitFullScreenButton extends JButton { private MyExitFullScreenButton() { setFocusable(false);