From efe12a1b3fa9836888d13c6f71c41d9639a0a45c Mon Sep 17 00:00:00 2001 From: Artem Bochkarev Date: Fri, 19 Oct 2018 15:06:39 +0700 Subject: [PATCH] linux-menubar: fixes fixed IDEA-200379 linux Native menu bar on Ubuntu Linux: the View menu actions have incorrect state fixed IDEA-151200 Unity menu bar is not available for detached editor tabs and floating tool windows fixed IDEA-200724 IntelliJ IDEA does not fully start after update, ends with window with menubar and nothing else fixed IDEA-200374 Throwable at com.intellij.openapi.wm.impl.GlobalMenuLinux.lambda$handleEvent$4 fixed IDEA-200768 Start Splash window doesn't hide fixed IDEA-200822 Opening any Markdown file freezes recent IntelliJ Ultimate EAP 183.3795.13 fixed GLIB-WARN (child/parent mismatches) add traces return checking of registry key linux.native.menu fix loading of class GlobalMenuLib --- bin/linux/libdbm64.so | Bin 34328 -> 34504 bytes native/LinuxGlobalMenu/DbusMenuWrapper.c | 20 +- native/LinuxGlobalMenu/DbusMenuWrapper.h | 2 + .../openapi/wm/impl/GlobalMenuLinux.java | 285 +++++++++++------- .../intellij/openapi/wm/impl/IdeMenuBar.java | 4 +- 5 files changed, 201 insertions(+), 110 deletions(-) diff --git a/bin/linux/libdbm64.so b/bin/linux/libdbm64.so index e3368f40339c99a0617bbeca6ebd1d7f1315a690..f28323c7bd36a2bde85eb30383c9e33f520527bb 100755 GIT binary patch delta 10799 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 Qv8IMPRrfoEAJ`E4zw6Z&GXMYp delta 10457 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 zH~f<=linkedXids == NULL) { - wi->linkedXids = g_list_alloc(); - wi->linkedXids->data = windowXid; - } else - g_list_append(wi->linkedXids, windowXid); + // _logmsg(LOG_LEVEL_INFO, "bind new window 0x%lx", windowXid); + wi->linkedXids = g_list_append(wi->linkedXids, windowXid); } void unbindWindow(WndInfo * wi, long windowXid) { if (wi == NULL || wi->server == NULL || wi->menuPath == NULL) return; + // _logmsg(LOG_LEVEL_INFO, "unbind window 0x%lx", windowXid); _unregisterWindow(windowXid, wi->registrar); if (wi->linkedXids != NULL) - g_list_remove(wi->linkedXids, windowXid); + wi->linkedXids = g_list_remove(wi->linkedXids, windowXid); } static gboolean _execReleaseWindow(gpointer user_data) { @@ -536,6 +534,16 @@ void setItemShortcut(DbusmenuMenuitem *item, int jmodifiers, int jkeycode) { dbusmenu_menuitem_property_set_variant(item, DBUSMENU_MENUITEM_PROP_SHORTCUT, outsideArr); } +void toggleItemStateChecked(DbusmenuMenuitem *item, bool isChecked) { + const int nOn = DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED; + const int nOff = DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED; + const int ncheck = isChecked ? nOn : nOff; + if (dbusmenu_menuitem_property_get_int(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE) != ncheck) { + // _logmsg(LOG_LEVEL_INFO, "item %s changes checked-state: %d -> %d", _getItemLabel(item), dbusmenu_menuitem_property_get_int(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE), ncheck); + dbusmenu_menuitem_property_set_int(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, ncheck); + } +} + static gboolean _execJRunnable(gpointer user_data) { (*((jrunnable) user_data))(); return FALSE; diff --git a/native/LinuxGlobalMenu/DbusMenuWrapper.h b/native/LinuxGlobalMenu/DbusMenuWrapper.h index 1673ce94a121..1aa7b91a91d1 100644 --- a/native/LinuxGlobalMenu/DbusMenuWrapper.h +++ b/native/LinuxGlobalMenu/DbusMenuWrapper.h @@ -62,6 +62,8 @@ void setItemEnabled(DbusmenuMenuitem* item, bool isEnabled); void setItemIcon(DbusmenuMenuitem* item, const char * iconBytesPng, int iconBytesCount); void setItemShortcut(DbusmenuMenuitem *item, int jmodifiers, int jkeycode); +void toggleItemStateChecked(DbusmenuMenuitem *item, bool isChecked); + #ifdef __cplusplus } #endif 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 a55def588326..568ee58337b4 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 @@ -2,6 +2,7 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.impl.ActionMenu; import com.intellij.openapi.actionSystem.impl.ActionMenuItem; @@ -29,14 +30,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import java.text.SimpleDateFormat; import java.util.List; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.Date; interface GlobalMenuLib extends Library { void runDbusServer(JLogger jlogger, JRunnable onAppmenuServiceAppeared, JRunnable onAppmenuServiceVanished); @@ -46,8 +43,8 @@ interface GlobalMenuLib extends Library { Pointer registerWindow(long windowXid, EventHandler handler); void releaseWindowOnMainLoop(Pointer wi); - void bindNewWindow(Pointer wi, long windowXid); - void unbindWindow(Pointer wi, long windowXid); + 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) void clearRootMenu(Pointer wi); void clearMenu(Pointer dbmi); @@ -63,6 +60,8 @@ interface GlobalMenuLib extends Library { void setItemIcon(Pointer item, byte[] iconBytesPng, int iconBytesCount); void setItemShortcut(Pointer item, int jmodifiers, int jkeycode); + void toggleItemStateChecked(Pointer item, boolean isChecked); + interface EventHandler extends Callback { void handleEvent(int uid, int eventType); } @@ -98,16 +97,22 @@ interface GlobalMenuLib extends Library { public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { private static final SimpleDateFormat ourDtf = new SimpleDateFormat("hhmmss.SSS"); // for debug only - private static final boolean TRACE_SYSOUT = Registry.is("linux.native.menu.debug.trace.sysout", false); - private static final boolean TRACE_DISABLED = Registry.is("linux.native.menu.debug.trace.disabled", true); - private static final boolean TRACE_SYNC_STATS = Registry.is("linux.native.menu.debug.trace.sync-stats", false); - private static final boolean TRACE_EVENTS = Registry.is("linux.native.menu.debug.trace.events", false); - private static final boolean TRACE_EVENT_FILTER = Registry.is("linux.native.menu.debug.trace.event-filter", false); + private static final boolean TRACE_SYSOUT = Registry.is("linux.native.menu.debug.trace.sysout", false); + private static final boolean TRACE_DISABLED = Registry.is("linux.native.menu.debug.trace.disabled", true); + private static final boolean TRACE_SYNC_STATS = Registry.is("linux.native.menu.debug.trace.sync-stats", false); + private static final boolean TRACE_EVENTS = Registry.is("linux.native.menu.debug.trace.events", false); + private static final boolean TRACE_EVENT_FILTER = Registry.is("linux.native.menu.debug.trace.event-filter", false); + private static final boolean TRACE_CLEARING = Registry.is("linux.native.menu.debug.trace.clearing", false); + private static final boolean TRACE_HIERARCHY_MISMATCHES = Registry.is("linux.native.menu.debug.trace.hierarchy.mismatches", false); + private static final boolean SHOW_SWING_MENU = Registry.is("linux.native.menu.debug.show.frame.menu", false); private static final Logger LOG = Logger.getInstance(GlobalMenuLinux.class); private static final GlobalMenuLib ourLib; private static final GlobalMenuLib.JLogger ourGLogger; private static final Thread ourGlibMainLoopThread; + private static final GlobalMenuLib.JRunnable ourProcessQueue; + private static final GlobalMenuLib.JRunnable ourOnAppmenuServiceAppeared; + private static final GlobalMenuLib.JRunnable ourOnAppmenuServiceVanished; private static final Map ourInstances = new ConcurrentHashMap<>(); private static boolean ourIsServiceAvailable = false; @@ -124,18 +129,47 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { if (ourLib != null) { ourGLogger = (level, msg) -> { if (level == GlobalMenuLib.LOG_LEVEL_INFO) { - // System.out.println("INFO: " + msg); - LOG.info(msg); + if (TRACE_SYSOUT) + _trace(msg); + else + LOG.info(msg); } else { // System.out.println("ERROR: " + msg); LOG.error(msg); } }; - ourGlibMainLoopThread = new Thread(()->ourLib.runDbusServer(ourGLogger, GlobalMenuLinux::_onAppmenuServiceAppeared, GlobalMenuLinux::_onAppmenuServiceVanished), "Glib-main-loop"); + ourProcessQueue = () -> { + // exec at glib-thread + if (!ourIsServiceAvailable) + return; + + for (GlobalMenuLinux gml: ourInstances.values()) + gml._processRoots(); + }; + ourOnAppmenuServiceAppeared = () -> { + // exec at glib-thread + _trace("Appeared dbus-service 'com.canonical.AppMenu.Registrar'"); + ourIsServiceAvailable = true; + ourProcessQueue.run(); + }; + ourOnAppmenuServiceVanished = () -> { + // exec at glib-thread + _trace("Closed dbus-service 'com.canonical.AppMenu.Registrar'"); + ourIsServiceAvailable = false; + for (GlobalMenuLinux gml: ourInstances.values()) { + gml.myWindowHandle = null; + ApplicationManager.getApplication().invokeLater(()->gml.myFrame.getJMenuBar().setVisible(true)); + } + }; + + ourGlibMainLoopThread = new Thread(()->ourLib.runDbusServer(ourGLogger, ourOnAppmenuServiceAppeared, ourOnAppmenuServiceVanished), "Glib-main-loop"); ourGlibMainLoopThread.start(); } else { ourGLogger = null; ourGlibMainLoopThread = null; + ourProcessQueue = null; + ourOnAppmenuServiceAppeared = null; + ourOnAppmenuServiceVanished = null; } } @@ -163,17 +197,34 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } public void bindNewWindow(@NotNull Window frame) { + // exec at EDT final long xid = _getX11WindowXid(frame); - if (xid == 0) + if (xid == 0) { + LOG.warn("can't obtain XID of window: " + frame + ", skip global menu binding"); return; - ourLib.bindNewWindow(myWindowHandle, xid); + } + if (myWindowHandle != null) { + _trace("bind new window 0x%X", xid); + ourLib.bindNewWindow(myWindowHandle, xid); + if (frame instanceof JFrame) { + final JFrame jfr = (JFrame)frame; + if (jfr.getJMenuBar() != null) + jfr.getJMenuBar().setVisible(false); + } + } } - public void unbindNewWindow(@NotNull Window frame) { + public void unbindWindow(@NotNull Window frame) { + // exec at EDT final long xid = _getX11WindowXid(frame); - if (xid == 0) + if (xid == 0) { + LOG.warn("can't obtain XID of window: " + frame + ", skip global menu unbinding"); return; - ourLib.unbindWindow(myWindowHandle, xid); + } + if (myWindowHandle != null) { + _trace("unbind window 0x%X", xid); + ourLib.unbindWindow(myWindowHandle, xid); + } } public void setRoots(List roots) { @@ -187,8 +238,9 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { if (roots != null) { for (ActionMenu am: roots) { final int uid = System.identityHashCode(am); - final MenuItemInternal mi = new MenuItemInternal(newRoots.size(), uid, GlobalMenuLib.ITEM_SUBMENU, _buildMnemonicLabel(am), am.getText(), null, true, am.getAnAction()); + final MenuItemInternal mi = new MenuItemInternal(newRoots.size(), uid, GlobalMenuLib.ITEM_SUBMENU, am.getAnAction()); mi.jitem = am; + mi.setLabelFromSwingPeer(am); newRoots.add(mi); } } @@ -223,7 +275,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { for (MenuItemInternal mi: croots) mi.nativePeer = ourLib.addRootMenu(myWindowHandle, mi.uid, mi.txt); - if (!Registry.is("linux.native.menu.debug.show.frame.menu", false)) + if (!SHOW_SWING_MENU) ApplicationManager.getApplication().invokeLater(()->myFrame.getJMenuBar().setVisible(false)); } @@ -291,14 +343,14 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { MenuItemInternal result = null; if (each instanceof ActionMenuItem) { final ActionMenuItem ami = (ActionMenuItem)each; - result = new MenuItemInternal(-1, System.identityHashCode(ami), ami.isToggleable() ? GlobalMenuLib.ITEM_CHECK : GlobalMenuLib.ITEM_SIMPLE, ami.getText(), ami.getText(), _icon2png(ami.getIcon()), ami.isEnabled(), ami.getAnAction()); + result = new MenuItemInternal(-1, System.identityHashCode(ami), ami.isToggleable() ? GlobalMenuLib.ITEM_CHECK : GlobalMenuLib.ITEM_SIMPLE, ami.getAnAction()); result.jitem = ami; } else if (each instanceof ActionMenu) { final ActionMenu am2 = (ActionMenu)each; - result = new MenuItemInternal(-1, System.identityHashCode(am2), GlobalMenuLib.ITEM_SUBMENU, am2.getText(), am2.getText(), null, am2.isEnabled(), am2.getAnAction()); + result = new MenuItemInternal(-1, System.identityHashCode(am2), GlobalMenuLib.ITEM_SUBMENU, am2.getAnAction()); result.jitem = am2; } else if (each instanceof JSeparator) { - result = new MenuItemInternal(-1, System.identityHashCode(each), GlobalMenuLib.ITEM_SIMPLE, null, null, null, true, null); + result = new MenuItemInternal(-1, System.identityHashCode(each), GlobalMenuLib.ITEM_SIMPLE, null); } else if (each instanceof StubItem) { // System.out.println("skip StubItem"); } else { @@ -334,6 +386,8 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { if (cmi != null) { mi.children.add(cmi); if (stats != null) ++stats[STAT_CREATED]; + if (each instanceof JMenuItem) + cmi.updateBySwingPeer((JMenuItem)each); } } else { cmi.toDelete = false; @@ -359,11 +413,9 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { if (child.nativePeer != null) { if (child.toDelete) { ourLib.removeMenuItem(mi.nativePeer, child.nativePeer); + child.nativePeer = null; } else { - // update states and icons - // NOTE: probably it's better to use sync flags, to avoid frequent calls, to avoid applet destabilization) - ourLib.setItemEnabled(child.nativePeer, child.isEnabled); - ourLib.setItemIcon(child.nativePeer, child.iconPngBytes, child.iconPngBytes != null ? child.iconPngBytes.length : 0); + child.updateNative(); } } else { if (child.action == null) { @@ -372,11 +424,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } child.nativePeer = ourLib.addMenuItem(mi.nativePeer, child.uid, child.txt, child.type); - - if (!child.isEnabled) - ourLib.setItemEnabled(child.nativePeer, false); - if (child.iconPngBytes != null && child.iconPngBytes.length > 0) - ourLib.setItemIcon(child.nativePeer, child.iconPngBytes, child.iconPngBytes.length); + child.updateNative(); } _processChildren(child); @@ -416,7 +464,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { // ETD-start final JMenuItem jmi = mi.jitem; if (jmi == null) { - LOG.error("can't find corresponding (opening) ActionMenu, event source: " + mi + ", swing menu hierarchy:\n" + _dumpSwingHierarchy()); + if (TRACE_HIERARCHY_MISMATCHES) _trace("corresponding (opening) swing item is null, event source: " + mi + ", swing menu hierarchy:\n" + _dumpSwingHierarchy()); return; } if (!(jmi instanceof ActionMenu)) { @@ -437,26 +485,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { _processChildren(mi); } else if (eventType == GlobalMenuLib.EVENT_CLOSED) { // glib main-loop thread - final Timer timer = new Timer(100, (e) -> { - // ETD-start - final JMenuItem jmi = mi.jitem; - if (jmi == null) { - LOG.error("can't find corresponding (closing) ActionMenu, event source: " + mi + ", swing menu hierarchy:\n" + _dumpSwingHierarchy()); - return; - } - if (!(jmi instanceof ActionMenu)) { - LOG.error("corresponding (closing) swing item isn't instance of ActionMenu, class=" + jmi.getClass().getName() + ", event source: " + mi); - return; - } - - final ActionMenu am = (ActionMenu)jmi; - am.clearItems(); - mi.clearChildrenSwingRefs(); - }); - timer.setRepeats(false); - timer.start(); - - _trace("\t scheduled (100 ms later) to clear menu '%s'", mi.txt); + mi.scheduleClearSwing(); } return; @@ -483,22 +512,22 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { public static boolean isAvailable() { return ourLib != null; } private static GlobalMenuLib _loadLibrary() { - if (!SystemInfo.isLinux) + if (!SystemInfo.isLinux || !Registry.is("linux.native.menu")) return null; - UrlClassLoader.loadPlatformLibrary("dbm"); - - // Set JNA to convert java.lang.String to char* using UTF-8, and match that with - // the way we tell CF to interpret our char* - // May be removed if we use toStringViaUTF16 - System.setProperty("jna.encoding", "UTF8"); - - final Map options = new HashMap<>(); try { + UrlClassLoader.loadPlatformLibrary("dbm"); + + // Set JNA to convert java.lang.String to char* using UTF-8, and match that with + // the way we tell CF to interpret our char* + // May be removed if we use toStringViaUTF16 + System.setProperty("jna.encoding", "UTF8"); + + final Map options = new HashMap<>(); return Native.loadLibrary("dbm", GlobalMenuLib.class, options); } catch (UnsatisfiedLinkError ule) { - LOG.error(ule); - } catch (RuntimeException e) { + LOG.info("disable global-menu integration because some of shared libraries isn't installed: " + ule); + } catch (Throwable e) { LOG.error(e); } return null; @@ -514,28 +543,27 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { String txt; String originTxt; - boolean isEnabled; + boolean isEnabled = true; + boolean isChecked = false; byte[] iconPngBytes; JMenuItem jitem; Pointer nativePeer; boolean toDelete = false; - long lastOpenedMs = 0; long lastClosedMs = 0; - MenuItemInternal(int rootPos, int uid, int type, String txt, String originTxt, byte[] iconPngBytes, boolean isEnabled, AnAction action) { + Timer timerClearSwing; + + MenuItemInternal(int rootPos, int uid, int type, AnAction action) { this.rootPos = rootPos; this.uid = uid; this.type = type; - this.txt = txt; - this.originTxt = originTxt; - this.iconPngBytes = iconPngBytes; - this.isEnabled = isEnabled; this.action = action; } boolean isRoot() { return rootPos >= 0; } + boolean isToggleable() { return type == GlobalMenuLib.ITEM_CHECK || type == GlobalMenuLib.ITEM_RADIO; } void clearChildrenSwingRefs() { for (MenuItemInternal cmi: children) { @@ -545,16 +573,44 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } // returns true when changed - boolean updateBySwingPeer(JMenuItem peer) { + boolean updateBySwingPeer(@NotNull JMenuItem peer) { // exec at EDT jitem = peer; - // probably need to calc sync flags like: if (cmi.isEnabled != each.isEnabled()) cmi.needUpdate = true; + // NOTE: probably is's better to use sync flags like: if (cmi.isEnabled != each.isEnabled()) cmi.needUpdate = true; boolean res = isEnabled != peer.isEnabled(); isEnabled = peer.isEnabled(); - // TODO: update icons (text must be the same) + if (isToggleable()) { + if (isChecked != peer.isSelected()) res = true; + isChecked = peer.isSelected(); + } + if (!Objects.equals(originTxt, peer.getText())) { + // _trace("label changes: '%s' -> '%s'", originTxt, peer.getText()); + setLabelFromSwingPeer(peer); + res = true; + } + iconPngBytes = isToggleable() ? null : _icon2png(peer.getIcon()); return res; } + void setLabelFromSwingPeer(@NotNull JMenuItem peer) { + // exec at EDT + originTxt = peer.getText(); + txt = _buildMnemonicLabel(peer); + } + + void updateNative() { + // exec at glib-loop thread + // NOTE: probably it's better to use sync flags, to avoid frequent calls, to avoid applet destabilization) + if (nativePeer == null) + return; + + ourLib.setItemLabel(nativePeer, txt); + ourLib.setItemEnabled(nativePeer, isEnabled); + ourLib.setItemIcon(nativePeer, iconPngBytes, iconPngBytes != null ? iconPngBytes.length : 0); + if (isToggleable()) + ourLib.toggleItemStateChecked(nativePeer, isChecked); + } + MenuItemInternal findCorrespondingChild(@NotNull Component target) { if (target == null) return null; @@ -638,6 +694,55 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { res = res + " [toDelele]"; return res; } + + String toStringShort() { + String res = String.format("'%s'", txt); + if (toDelete) + res = res + " [D]"; + if (isRoot()) + res = "Root " + res; + else + res = "Submenu " + res; + return res; + } + + synchronized void scheduleClearSwing() { + // exec at glib main-loop thread + if (timerClearSwing != null) + timerClearSwing.stop(); + + timerClearSwing = new Timer(300, (e) -> { + _clearSwing(); + }); + timerClearSwing.setRepeats(false); + timerClearSwing.start(); + if (TRACE_CLEARING) _trace("\t scheduled (300 ms later) to clear '%s'", toStringShort()); + } + + synchronized void cancelClearSwing() { + // exec at glib main-loop thread + timerClearSwing = null; + } + + private void _clearSwing() { + // exec at ETD + if (timerClearSwing == null) + return; + + if (jitem == null) { + if (TRACE_CLEARING) _trace("corresponding (closing) swing item is null - nothing to clear, event source: ", this); + return; + } + if (!(jitem instanceof ActionMenu)) { + LOG.error("corresponding (closing) swing item isn't instance of ActionMenu, class=" + jitem.getClass().getName() + ", event source: " + toString()); + return; + } + + final ActionMenu am = (ActionMenu)jitem; + am.clearItems(); + clearChildrenSwingRefs(); + if (TRACE_CLEARING) _trace("\t cleared '%s'", toStringShort()); + } } private class EventFilter { @@ -666,6 +771,8 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { if (TRACE_EVENT_FILTER) _trace("EventFilter: start timer to process 'about-to-show' of first-root later"); return false; } + + myTimer = null; } else if (mi.rootPos > 0) { if ((timeMs - myLastFirstRootEventMs) < 50) { if (TRACE_EVENT_FILTER) _trace("EventFilter: skip fake 'about-to-show' of root[%d]%s", mi.rootPos, myTimer != null ? " (reset timer)" : ""); @@ -685,8 +792,6 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { } } - if (mi.rootPos == 0) - myTimer = null; return true; } } @@ -821,28 +926,4 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable { else LOG.info(msg); } - - private static final GlobalMenuLib.JRunnable ourProcessQueue = () -> { - // exec at glib-thread - if (!ourIsServiceAvailable) - return; - - for (GlobalMenuLinux gml: ourInstances.values()) - gml._processRoots(); - }; - - private static void _onAppmenuServiceAppeared() { - // exec at glib-thread - ourIsServiceAvailable = true; - ourProcessQueue.run(); - } - - private static void _onAppmenuServiceVanished() { - // exec at glib-thread - ourIsServiceAvailable = false; - for (GlobalMenuLinux gml: ourInstances.values()) { - gml.myWindowHandle = null; - ApplicationManager.getApplication().invokeLater(()->gml.myFrame.getJMenuBar().setVisible(true)); - } - } } \ No newline at end of file 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 955a29054ee9..1735b1840d47 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 @@ -16,7 +16,6 @@ import com.intellij.openapi.actionSystem.impl.WeakTimerListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.ui.FrameWrapper; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; @@ -575,8 +574,9 @@ public class IdeMenuBar extends JMenuBar implements IdeEventQueue.EventDispatche frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - frameMenuBar.myGlobalMenuLinux.unbindNewWindow(frame); + frameMenuBar.myGlobalMenuLinux.unbindWindow(frame); } + @Override public void windowOpened(WindowEvent e) { frameMenuBar.myGlobalMenuLinux.bindNewWindow(frame); }