mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
IDEA-240623: use separate glib-loop (in separate thread with thread-default context)
fixed IDEA-240623 KDE Global Menu does not work. But it's work with PhpStorm GitOrigin-RevId: 56b75d6ae4209a12dfc4fcbbc6e9486b07e868d2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5ed90ce495
commit
60272bba37
Binary file not shown.
@@ -23,15 +23,15 @@ endif (__DBUSMENU_HAVE_W_ALL)
|
||||
find_library(LIB_GLIB NAMES glib libglib libglib-2.0.so.0 PATHS /lib/x86_64-linux-gnu)
|
||||
MESSAGE("LIB_GLIB: " ${LIB_GLIB})
|
||||
|
||||
find_library(LIB_DBUSMENU NAMES libdbusmenu-glib.so PATHS /usr/lib/x86_64-linux-gnu)
|
||||
MESSAGE("LIB_DBUSMENU: " ${LIB_DBUSMENU})
|
||||
|
||||
find_library(LIB_GIO NAMES libgio-2.0.so.0 PATHS /usr/lib/x86_64-linux-gnu)
|
||||
MESSAGE("LIB_GIO: " ${LIB_GIO})
|
||||
|
||||
find_library(LIB_GOBJ NAMES libgobject-2.0.so.0 PATHS /usr/lib/x86_64-linux-gnu)
|
||||
MESSAGE("LIB_GOBJ: " ${LIB_GOBJ})
|
||||
|
||||
# use patched library
|
||||
set(LIB_DBUSMENU "${PROJECT_SOURCE_DIR}/libdbusmenu-glib.a")
|
||||
|
||||
set(GLIB_INCLUDE_DIRS /usr/include/glib-2.0 /usr/lib/x86_64-linux-gnu/glib-2.0/include)
|
||||
set(DBUSMENU_GLIB_INCLUDE_DIRS /usr/include/libdbusmenu-glib-0.4)
|
||||
|
||||
@@ -48,12 +48,16 @@ set(SOURCE_FILES DbusMenuWrapper.c)
|
||||
add_library(dbm SHARED ${SOURCE_FILES})
|
||||
target_link_libraries(dbm ${LIB_GLIB} ${LIB_GIO} ${LIB_DBUSMENU} ${LIB_GOBJ})
|
||||
|
||||
add_executable(dbmexec test.cc)
|
||||
target_link_libraries(dbmexec dbm ${LIB_GLIB} ${LIB_GIO} ${LIB_DBUSMENU} ${LIB_DBUSMENU_GTK} ${LIB_GOBJ} ${LIB_GTK} ${LIB_GDK})
|
||||
if (TESTS_ENABLED)
|
||||
find_library(LIB_GTK NAMES libgtk-3.so PATHS /usr/lib/x86_64-linux-gnu)
|
||||
MESSAGE("LIB_GTK: " ${LIB_GTK})
|
||||
|
||||
add_custom_command(TARGET dbm POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
$<TARGET_FILE:dbm> /home/parallels/projects/IDEA/community/bin/linux/libdbm64.so)
|
||||
add_custom_command(TARGET dbm POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
$<TARGET_FILE:dbm> /home/parallels/IdeaProjects/TestMenu/libdbm.so)
|
||||
set(GTK_INCLUDE_DIRS /usr/include/gtk-3.0)
|
||||
include_directories(${GTK_INCLUDE_DIRS} /usr/include/pango-1.0 /usr/include/harfbuzz /usr/include/cairo /usr/include/gdk-pixbuf-2.0 /usr/include/atk-1.0)
|
||||
|
||||
find_library(LIB_GDK NAMES libgdk-3.so PATHS /usr/lib/x86_64-linux-gnu) # needs to get xid from GtkWidget
|
||||
MESSAGE("LIB_GDK: " ${LIB_GDK})
|
||||
|
||||
add_executable(dbmexec test.cc)
|
||||
target_link_libraries(dbmexec dbm ${LIB_GLIB} ${LIB_GIO} ${LIB_DBUSMENU} ${LIB_DBUSMENU_GTK} ${LIB_GOBJ} ${LIB_GTK} ${LIB_GDK})
|
||||
endif(TESTS_ENABLED)
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
static jlogger _ourLogger = NULL;
|
||||
static jrunnable _ourOnServiceAppearedCallback = NULL;
|
||||
static jrunnable _ourOnServiceVanishedCallback = NULL;
|
||||
static guint _ourServiceNameWatcher = 0;
|
||||
|
||||
static GMainContext * glib_main_context = NULL;
|
||||
|
||||
typedef struct _WndInfo {
|
||||
guint32 xid;
|
||||
@@ -79,25 +80,20 @@ static void _onNameVanished(GDBusConnection *connection, const gchar *name, gpoi
|
||||
(*((jrunnable) _ourOnServiceVanishedCallback))();
|
||||
}
|
||||
|
||||
void startWatchDbus(jlogger jlog, jrunnable onAppmenuServiceAppeared, jrunnable onAppmenuServiceVanished) {
|
||||
// NOTE: main-loop is necessary for communication with dbus (via glib and it's signals)
|
||||
// It is started in java (see invocation com.sun.javafx.application.PlatformImpl.startup())
|
||||
_ourLogger = jlog;
|
||||
// NOTE: main-loop is necessary for communication with dbus (via glib and it's signals)
|
||||
void runMainLoop(jlogger jlogger, jrunnable onAppmenuServiceAppeared, jrunnable onAppmenuServiceVanished) {
|
||||
glib_main_context = g_main_context_new();
|
||||
g_main_context_push_thread_default(glib_main_context); // make this ctx default for current thread
|
||||
|
||||
_ourLogger = jlogger;
|
||||
_ourOnServiceAppearedCallback = onAppmenuServiceAppeared;
|
||||
_ourOnServiceVanishedCallback = onAppmenuServiceVanished;
|
||||
_ourServiceNameWatcher = g_bus_watch_name(G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_WATCHER_FLAGS_NONE, _onNameAppeared, _onNameVanished, NULL, NULL);
|
||||
g_bus_watch_name(G_BUS_TYPE_SESSION, DBUS_NAME, G_BUS_NAME_WATCHER_FLAGS_NONE, _onNameAppeared, _onNameVanished, NULL, NULL);
|
||||
// NOTE: Callbacks will be invoked in the thread-default main context of the thread you are calling g_bus_watch_name from.
|
||||
// _info("start watching for dbus name 'com.canonical.AppMenu.Registrar'");
|
||||
}
|
||||
|
||||
void stopWatchDbus() {
|
||||
g_bus_unwatch_name(_ourServiceNameWatcher);
|
||||
// _info("glib main loop is stopped");
|
||||
}
|
||||
|
||||
// used when javaFX can't be started
|
||||
void runMainLoop(jlogger jlogger, jrunnable onAppmenuServiceAppeared, jrunnable onAppmenuServiceVanished) {
|
||||
startWatchDbus(jlogger, onAppmenuServiceAppeared, onAppmenuServiceVanished);
|
||||
g_main_loop_run(g_main_loop_new(g_main_context_new(), FALSE));
|
||||
GMainLoop * main_loop = g_main_loop_new(glib_main_context, FALSE);
|
||||
g_main_loop_run(main_loop);
|
||||
}
|
||||
|
||||
static void _onDbusOwnerChange(GObject *gobject, GParamSpec *pspec, gpointer user_data) {
|
||||
@@ -199,8 +195,10 @@ static void _releaseWindow(WndInfo *wi) {
|
||||
if (wi->registrar != NULL) {
|
||||
_unregisterWindow(wi->xid, wi->registrar);
|
||||
if (wi->linkedXids != NULL) {
|
||||
for (GList* l = wi->linkedXids; l != NULL; l = l->next)
|
||||
_unregisterWindow((guint32)l->data, wi->registrar);
|
||||
for (GList* l = wi->linkedXids; l != NULL; l = l->next) {
|
||||
const guint32 xid = ((unsigned long)l->data) & 0xFFFFFFFF;
|
||||
_unregisterWindow(xid, wi->registrar);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref(wi->registrar);
|
||||
@@ -326,7 +324,7 @@ void bindNewWindow(WndInfo * wi, guint32 windowXid) {
|
||||
}
|
||||
|
||||
// _logmsg(LOG_LEVEL_INFO, "bind new window 0x%lx", windowXid);
|
||||
wi->linkedXids = g_list_append(wi->linkedXids, (gpointer)windowXid);
|
||||
wi->linkedXids = g_list_append(wi->linkedXids, (void *)(unsigned long)windowXid);
|
||||
}
|
||||
|
||||
void unbindWindow(WndInfo * wi, guint32 windowXid) {
|
||||
@@ -337,7 +335,7 @@ void unbindWindow(WndInfo * wi, guint32 windowXid) {
|
||||
_unregisterWindow(windowXid, wi->registrar);
|
||||
|
||||
if (wi->linkedXids != NULL)
|
||||
wi->linkedXids = g_list_remove(wi->linkedXids, (gpointer)windowXid);
|
||||
wi->linkedXids = g_list_remove(wi->linkedXids, (void *)(unsigned long)windowXid);
|
||||
}
|
||||
|
||||
static gboolean _execReleaseWindow(gpointer user_data) {
|
||||
@@ -510,7 +508,18 @@ static gboolean _showMenuItem(gpointer item) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void showMenuItem(DbusmenuMenuitem* item) { g_idle_add(_showMenuItem, item); }
|
||||
static guint
|
||||
execInMainContext(GSourceFunc func, gpointer data) {
|
||||
GSource *source = g_timeout_source_new(0);
|
||||
g_source_set_callback(source, func, data, NULL);
|
||||
guint result = g_source_attach(source, glib_main_context);
|
||||
g_source_unref(source);
|
||||
return result;
|
||||
}
|
||||
|
||||
void showMenuItem(DbusmenuMenuitem* item) {
|
||||
execInMainContext(_showMenuItem, item);
|
||||
}
|
||||
|
||||
void setItemLabel(DbusmenuMenuitem *item, const char *label) {
|
||||
dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, label);
|
||||
@@ -577,5 +586,10 @@ static gboolean _execJRunnable(gpointer user_data) {
|
||||
|
||||
void execOnMainLoop(jrunnable run) {
|
||||
// _info("scheduled execOnMain");
|
||||
g_idle_add(_execJRunnable, run);
|
||||
if (glib_main_context == NULL) {
|
||||
_logmsg(LOG_LEVEL_ERROR, "execOnMainLoop: glib_main_context wasn't initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
execInMainContext(_execJRunnable, run);
|
||||
}
|
||||
BIN
native/LinuxGlobalMenu/libdbusmenu-glib.a
Normal file
BIN
native/LinuxGlobalMenu/libdbusmenu-glib.a
Normal file
Binary file not shown.
@@ -7,7 +7,6 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
|
||||
static void _onDestroyWindow(void) {
|
||||
gtk_main_quit();
|
||||
return;
|
||||
@@ -30,23 +29,16 @@ int main (int argv, char ** argc) {
|
||||
WndInfo* wi = registerWindow(wndxid, &_testHandler);
|
||||
|
||||
// populate menu
|
||||
DbusmenuMenuitem* root1 = addRootMenu(wi, 1);
|
||||
setItemLabel(root1, "root1");
|
||||
DbusmenuMenuitem* root1 = addRootMenu(wi, 1, "root1");
|
||||
|
||||
FILE *f;
|
||||
char buffer[1024*1024];
|
||||
gsize length;
|
||||
|
||||
f = fopen ("../test.png", "r");
|
||||
length = fread (buffer, 1, sizeof(buffer), f);
|
||||
fclose (f);
|
||||
|
||||
DbusmenuMenuitem* item1 = addMenuItem(root1, 2, true);
|
||||
setItemLabel(item1, "item1");
|
||||
setItemIcon(item1, buffer, length);
|
||||
DbusmenuMenuitem* sub1 = addMenuItem(sub1, 3, false);
|
||||
setItemLabel(sub1, "sub1");
|
||||
setItemIcon(sub1, buffer, length);
|
||||
DbusmenuMenuitem* item1 = addMenuItem(root1, 2, "item1", ITEM_SIMPLE, 0);
|
||||
// setItemIcon(item1, buffer, length);
|
||||
DbusmenuMenuitem* sub1 = addMenuItem(item1, 3, "sub1", ITEM_SUBMENU, 0);
|
||||
// setItemIcon(sub1, buffer, length);
|
||||
|
||||
// run main loop
|
||||
gtk_main();
|
||||
|
||||
@@ -53,8 +53,6 @@ import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
interface GlobalMenuLib extends Library {
|
||||
void startWatchDbus(JLogger jlogger, JRunnable onAppmenuServiceAppeared, JRunnable onAppmenuServiceVanished);
|
||||
|
||||
void runMainLoop(JLogger jlogger, JRunnable onAppmenuServiceAppeared, JRunnable onAppmenuServiceVanished);
|
||||
|
||||
void execOnMainLoop(JRunnable run);
|
||||
@@ -218,19 +216,10 @@ public final class GlobalMenuLinux implements LinuxGlobalMenuEventHandler, Dispo
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: Linux implementation of JavaFX starts native main loop with GtkApplication._runLoop()
|
||||
try {
|
||||
Class<?> platformImpl = Class.forName("com.sun.javafx.application.PlatformImpl");
|
||||
Method startup = platformImpl.getMethod("startup", Runnable.class);
|
||||
Runnable r = () -> ourLib.startWatchDbus(ourGLogger, ourOnAppmenuServiceAppeared, ourOnAppmenuServiceVanished);
|
||||
startup.invoke(null, r);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.info("can't start main loop via JavaFX (will run it manually): " + e.getMessage());
|
||||
final Thread glibMain = new Thread(() -> ourLib.runMainLoop(ourGLogger, ourOnAppmenuServiceAppeared, ourOnAppmenuServiceVanished),
|
||||
"GlobalMenuLinux loop");
|
||||
glibMain.start();
|
||||
}
|
||||
final String threadName = "GlobalMenuLinux loop";
|
||||
new Thread(() -> ourLib.runMainLoop(ourGLogger, ourOnAppmenuServiceAppeared, ourOnAppmenuServiceVanished),
|
||||
threadName).start();
|
||||
LOG.info("Start glib main loop in thread: " + threadName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user