mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
linux-menu: fixed mnemonics processing under KDE
process key-events (for mnemonic shortcuts) within ide
This commit is contained in:
Binary file not shown.
@@ -65,7 +65,7 @@ static void _printWndInfo(const WndInfo *wi, char *out, int outLen) {
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(out, outLen, "xid=0x%X menuPath='%s' registrar=0x%p server=0x%p menuroot=0x%p", wi->xid, wi->menuPath,
|
||||
snprintf(out, (size_t)outLen, "xid=0x%X menuPath='%s' registrar=0x%p server=0x%p menuroot=0x%p", wi->xid, wi->menuPath,
|
||||
wi->registrar, wi->server, wi->menuroot);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ static void _releaseMenuItem(gpointer data) {
|
||||
}
|
||||
}
|
||||
|
||||
static void _unregisterWindow(long xid, GDBusProxy * registrar) {
|
||||
static void _unregisterWindow(guint32 xid, GDBusProxy * registrar) {
|
||||
// NOTE: sync call g_dbus_proxy_call_sync(wi->registrar, "UnregisterWindow", g_variant_new("(u)", wi->xid), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error)
|
||||
// under ubuntu18 (with GlobalMenu plugin) executes several minutes.
|
||||
// We make async call and don't care about results and errors (i.e. NULL callbacks)
|
||||
@@ -200,7 +200,7 @@ static void _releaseWindow(WndInfo *wi) {
|
||||
_unregisterWindow(wi->xid, wi->registrar);
|
||||
if (wi->linkedXids != NULL) {
|
||||
for (GList* l = wi->linkedXids; l != NULL; l = l->next)
|
||||
_unregisterWindow(l->data, wi->registrar);
|
||||
_unregisterWindow((guint32)l->data, wi->registrar);
|
||||
}
|
||||
|
||||
g_object_unref(wi->registrar);
|
||||
@@ -240,7 +240,7 @@ void createMenuRootForWnd(WndInfo *wi) {
|
||||
dbusmenu_server_set_root(wi->server, wi->menuroot);
|
||||
}
|
||||
|
||||
WndInfo *registerWindow(long windowXid, jeventcallback handler) {
|
||||
WndInfo *registerWindow(guint32 windowXid, jeventcallback handler) {
|
||||
// _info("register new window");
|
||||
|
||||
WndInfo *wi = (WndInfo *) malloc(sizeof(WndInfo));
|
||||
@@ -248,7 +248,7 @@ WndInfo *registerWindow(long windowXid, jeventcallback handler) {
|
||||
|
||||
wi->xid = (guint32) windowXid;
|
||||
wi->menuPath = malloc(64);
|
||||
sprintf(wi->menuPath, "/com/canonical/menu/0x%lx", windowXid);
|
||||
sprintf(wi->menuPath, "/com/canonical/menu/0x%x", windowXid);
|
||||
|
||||
wi->menuroot = dbusmenu_menuitem_new();
|
||||
if (wi->menuroot == NULL) {
|
||||
@@ -305,7 +305,7 @@ WndInfo *registerWindow(long windowXid, jeventcallback handler) {
|
||||
return wi;
|
||||
}
|
||||
|
||||
void bindNewWindow(WndInfo * wi, long windowXid) {
|
||||
void bindNewWindow(WndInfo * wi, guint32 windowXid) {
|
||||
if (wi == NULL || wi->server == NULL || wi->menuPath == NULL)
|
||||
return;
|
||||
|
||||
@@ -326,10 +326,10 @@ void bindNewWindow(WndInfo * wi, long windowXid) {
|
||||
}
|
||||
|
||||
// _logmsg(LOG_LEVEL_INFO, "bind new window 0x%lx", windowXid);
|
||||
wi->linkedXids = g_list_append(wi->linkedXids, windowXid);
|
||||
wi->linkedXids = g_list_append(wi->linkedXids, (gpointer)windowXid);
|
||||
}
|
||||
|
||||
void unbindWindow(WndInfo * wi, long windowXid) {
|
||||
void unbindWindow(WndInfo * wi, guint32 windowXid) {
|
||||
if (wi == NULL || wi->server == NULL || wi->menuPath == NULL)
|
||||
return;
|
||||
|
||||
@@ -337,7 +337,7 @@ void unbindWindow(WndInfo * wi, long windowXid) {
|
||||
_unregisterWindow(windowXid, wi->registrar);
|
||||
|
||||
if (wi->linkedXids != NULL)
|
||||
wi->linkedXids = g_list_remove(wi->linkedXids, windowXid);
|
||||
wi->linkedXids = g_list_remove(wi->linkedXids, (gpointer)windowXid);
|
||||
}
|
||||
|
||||
static gboolean _execReleaseWindow(gpointer user_data) {
|
||||
@@ -390,8 +390,9 @@ static const char *_type2str(int type) {
|
||||
return "sig-shown";
|
||||
case SIGNAL_CHILD_ADDED:
|
||||
return "sig-child-added";
|
||||
default:
|
||||
return "unknown event type";
|
||||
}
|
||||
return "unknown event type";
|
||||
}
|
||||
|
||||
static void _handleItemSignal(DbusmenuMenuitem *item, int type) {
|
||||
@@ -479,7 +480,7 @@ DbusmenuMenuitem *addMenuItem(DbusmenuMenuitem *parent, int uid, const char * la
|
||||
if (position < 0)
|
||||
dbusmenu_menuitem_child_append(parent, item);
|
||||
else
|
||||
dbusmenu_menuitem_child_add_position(parent, item, position);
|
||||
dbusmenu_menuitem_child_add_position(parent, item, (guint)position);
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -494,16 +495,23 @@ DbusmenuMenuitem* addSeparator(DbusmenuMenuitem * parent, int uid, int position)
|
||||
if (position < 0)
|
||||
dbusmenu_menuitem_child_append(parent, item);
|
||||
else
|
||||
dbusmenu_menuitem_child_add_position(parent, item, position);
|
||||
dbusmenu_menuitem_child_add_position(parent, item, (guint)position);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void reorderMenuItem(DbusmenuMenuitem * parent, DbusmenuMenuitem* item, int position) { dbusmenu_menuitem_child_reorder(parent, item, position); }
|
||||
void reorderMenuItem(DbusmenuMenuitem * parent, DbusmenuMenuitem* item, int position) { dbusmenu_menuitem_child_reorder(parent, item, (guint)position); }
|
||||
|
||||
void removeMenuItem(DbusmenuMenuitem * parent, DbusmenuMenuitem* item) { dbusmenu_menuitem_child_delete(parent, item); }
|
||||
|
||||
static gboolean _showMenuItem(gpointer item) {
|
||||
dbusmenu_menuitem_show_to_user(item, 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void showMenuItem(DbusmenuMenuitem* item) { g_idle_add(_showMenuItem, item); }
|
||||
|
||||
void setItemLabel(DbusmenuMenuitem *item, const char *label) {
|
||||
dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, label);
|
||||
}
|
||||
@@ -513,14 +521,8 @@ void setItemEnabled(DbusmenuMenuitem *item, bool isEnabled) {
|
||||
}
|
||||
|
||||
void setItemIcon(DbusmenuMenuitem *item, const char *iconBytesPng, int iconBytesCount) {
|
||||
const gboolean propreturn = dbusmenu_menuitem_property_set_byte_array(item, DBUSMENU_MENUITEM_PROP_ICON_DATA,
|
||||
(guchar *) iconBytesPng, iconBytesCount);
|
||||
dbusmenu_menuitem_property_set_byte_array(item, DBUSMENU_MENUITEM_PROP_ICON_DATA, (guchar*)iconBytesPng, (gsize)iconBytesCount);
|
||||
// NOTE: memory copied (try to call memset(iconBytesPng, 0, iconBytesCount) after)
|
||||
|
||||
// if (propreturn)
|
||||
// _logmsg(LOG_LEVEL_INFO, "\tset %d icon bytes for item %s", iconBytesCount, _getItemLabel(item));
|
||||
// else
|
||||
// _logmsg(LOG_LEVEL_ERROR, "\tcan't set %d icon bytes for item %s", iconBytesCount, _getItemLabel(item));
|
||||
}
|
||||
|
||||
// java modifiers
|
||||
@@ -530,7 +532,7 @@ static const int META_MASK = 1 << 2;
|
||||
static const int ALT_MASK = 1 << 3;
|
||||
|
||||
void setItemShortcut(DbusmenuMenuitem *item, int jmodifiers, int x11keycode) {
|
||||
char* xname = XKeysymToString(x11keycode);
|
||||
char* xname = XKeysymToString((KeySym)x11keycode);
|
||||
if (xname == NULL) {
|
||||
// _logmsg(LOG_LEVEL_ERROR, "XKeysymToString returns null for x11keycode=%d", x11keycode);
|
||||
return;
|
||||
|
||||
@@ -39,11 +39,11 @@ void runMainLoop(jlogger jlogger, jrunnable onAppmenuServiceAppeared, jrunnable
|
||||
|
||||
void execOnMainLoop(jrunnable run);
|
||||
|
||||
WndInfo* registerWindow(long windowXid, jeventcallback handler); // creates menu-server and binds to xid
|
||||
WndInfo* registerWindow(guint32 windowXid, jeventcallback handler); // creates menu-server and binds to xid
|
||||
void releaseWindowOnMainLoop(WndInfo* wi, jrunnable onReleased);
|
||||
|
||||
void bindNewWindow(WndInfo * wi, long windowXid);
|
||||
void unbindWindow(WndInfo * wi, long windowXid);
|
||||
void bindNewWindow(WndInfo * wi, guint32 windowXid);
|
||||
void unbindWindow(WndInfo * wi, guint32 windowXid);
|
||||
|
||||
void createMenuRootForWnd(WndInfo *wi);
|
||||
void clearRootMenu(WndInfo* wi);
|
||||
@@ -55,6 +55,7 @@ DbusmenuMenuitem* addSeparator(DbusmenuMenuitem * parent, int uid, int position)
|
||||
|
||||
void reorderMenuItem(DbusmenuMenuitem * parent, DbusmenuMenuitem* item, int position);
|
||||
void removeMenuItem(DbusmenuMenuitem * parent, DbusmenuMenuitem* item);
|
||||
void showMenuItem(DbusmenuMenuitem* item);
|
||||
|
||||
void setItemLabel(DbusmenuMenuitem* item, const char * label);
|
||||
void setItemEnabled(DbusmenuMenuitem* item, bool isEnabled);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.execution.util.ExecUtil;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
@@ -30,6 +31,7 @@ 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;
|
||||
@@ -63,6 +65,7 @@ interface GlobalMenuLib extends Library {
|
||||
|
||||
void reorderMenuItem(Pointer parent, Pointer item, int position);
|
||||
void removeMenuItem(Pointer parent, Pointer item);
|
||||
void showMenuItem(Pointer item);
|
||||
|
||||
void setItemLabel(Pointer item, String label);
|
||||
void setItemEnabled(Pointer item, boolean isEnabled);
|
||||
@@ -208,6 +211,37 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable {
|
||||
if (myIsDisposed)
|
||||
ourInstances.remove(myXid);
|
||||
};
|
||||
|
||||
if (SystemInfo.isKDE) {
|
||||
// root menu items doesn't catch mnemonic shortcuts (in KDE), so process them inside IDE
|
||||
IdeEventQueue.getInstance().addDispatcher(e -> {
|
||||
if (!(e instanceof KeyEvent))
|
||||
return false;
|
||||
|
||||
final KeyEvent event = (KeyEvent)e;
|
||||
if (!event.isAltDown())
|
||||
return false;
|
||||
|
||||
final Component src = event.getComponent();
|
||||
final Window wndParent = src instanceof Window ? (Window)src : SwingUtilities.windowForComponent(src);
|
||||
final char eventChar = Character.toUpperCase(event.getKeyChar());
|
||||
|
||||
for (GlobalMenuLinux gml: ourInstances.values()) {
|
||||
if (gml.myFrame == wndParent) {
|
||||
for (MenuItemInternal root : gml.myRoots) {
|
||||
if (eventChar == root.mnemonic) {
|
||||
ourLib.showMenuItem(root.nativePeer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}, this);
|
||||
}
|
||||
|
||||
ourInstances.put(myXid, this);
|
||||
}
|
||||
|
||||
@@ -652,6 +686,7 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable {
|
||||
|
||||
String txt;
|
||||
String originTxt;
|
||||
char mnemonic;
|
||||
boolean isEnabled = true;
|
||||
boolean isChecked = false;
|
||||
byte[] iconPngBytes;
|
||||
@@ -714,7 +749,19 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable {
|
||||
void setLabelFromSwingPeer(@NotNull JMenuItem peer) {
|
||||
// exec at EDT
|
||||
originTxt = peer.getText();
|
||||
txt = _buildMnemonicLabel(peer);
|
||||
txt = originTxt != null ? originTxt : "";
|
||||
mnemonic = 0;
|
||||
|
||||
if (originTxt != null && !originTxt.isEmpty()) {
|
||||
final int mnemonicCode = peer.getMnemonic();
|
||||
final int mnemonicIndex = peer.getDisplayedMnemonicIndex();
|
||||
if (mnemonicIndex >= 0 && mnemonicIndex < originTxt.length() && Character.toUpperCase(originTxt.charAt(mnemonicIndex)) == mnemonicCode) {
|
||||
final StringBuilder res = new StringBuilder(originTxt);
|
||||
res.insert(mnemonicIndex, '_');
|
||||
txt = res.toString();
|
||||
mnemonic = (char)mnemonicCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateNative() {
|
||||
@@ -900,27 +947,6 @@ public class GlobalMenuLinux implements GlobalMenuLib.EventHandler, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String _buildMnemonicLabel(JMenuItem jmenuitem) {
|
||||
String text = jmenuitem.getText();
|
||||
final int mnemonicCode = jmenuitem.getMnemonic();
|
||||
final int mnemonicIndex = jmenuitem.getDisplayedMnemonicIndex();
|
||||
if (text == null)
|
||||
text = "";
|
||||
final int index;
|
||||
if (mnemonicIndex >= 0 && mnemonicIndex < text.length() && Character.toUpperCase(text.charAt(mnemonicIndex)) == mnemonicCode) {
|
||||
index = mnemonicIndex;
|
||||
} else {
|
||||
// Mnemonic mismatch index
|
||||
index = -1;
|
||||
// LOG.error("Mnemonic code " + mnemonicCode + " mismatch index " + mnemonicIndex + " with txt: " + text);
|
||||
}
|
||||
|
||||
final StringBuilder res = new StringBuilder(text);
|
||||
if(index != -1)
|
||||
res.insert(index, '_');
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private static Object _getPeerField(@NotNull Component object) {
|
||||
try {
|
||||
Field field = Component.class.getDeclaredField("peer");
|
||||
|
||||
Reference in New Issue
Block a user