diff --git a/native/src/main/c/native.c b/native/src/main/c/native.c index f6d0895..8a0580b 100644 --- a/native/src/main/c/native.c +++ b/native/src/main/c/native.c @@ -13,7 +13,7 @@ struct WLFrame { struct org_kde_kwin_appmenu_manager *org_kde_kwin_appmenu_manager = NULL; static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { - if (strcmp(interface, "org_kde_kwin_appmenu_manager") == 0) { + if (strcmp(interface, org_kde_kwin_appmenu_manager_interface.name) == 0) { org_kde_kwin_appmenu_manager = wl_registry_bind(registry, name, &org_kde_kwin_appmenu_manager_interface, 1); } } @@ -42,7 +42,7 @@ JNIEXPORT void JNICALL Java_io_gitlab_jfronny_globalmenu_Native_init(JNIEnv *env } } -JNIEXPORT jlong JNICALL Java_io_gitlab_jfronny_globalmenu_Native_create(JNIEnv *env, jobject obj, jlong ptr) { +JNIEXPORT jlong JNICALL Java_io_gitlab_jfronny_globalmenu_Native_createMenu(JNIEnv *env, jobject obj, jlong ptr) { if (org_kde_kwin_appmenu_manager == NULL) { (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), "Appmenu manager not initialized"); return 0; @@ -51,13 +51,13 @@ JNIEXPORT jlong JNICALL Java_io_gitlab_jfronny_globalmenu_Native_create(JNIEnv * return (jlong) (intptr_t) org_kde_kwin_appmenu_manager_create(org_kde_kwin_appmenu_manager, frame->wl_surface); } -JNIEXPORT void JNICALL Java_io_gitlab_jfronny_globalmenu_Native_destroy(JNIEnv *env, jobject obj, jlong ptr) { +JNIEXPORT void JNICALL Java_io_gitlab_jfronny_globalmenu_Native_destroyMenu(JNIEnv *env, jobject obj, jlong ptr) { struct org_kde_kwin_appmenu *frame = (struct org_kde_kwin_appmenu *) ptr; org_kde_kwin_appmenu_release(frame); org_kde_kwin_appmenu_destroy(frame); } -JNIEXPORT void JNICALL Java_io_gitlab_jfronny_globalmenu_Native_setAddress(JNIEnv *env, jobject obj, jlong ptr, jstring serviceName, jstring objectPath) { +JNIEXPORT void JNICALL Java_io_gitlab_jfronny_globalmenu_Native_setMenuAddress(JNIEnv *env, jobject obj, jlong ptr, jstring serviceName, jstring objectPath) { struct org_kde_kwin_appmenu *frame = (struct org_kde_kwin_appmenu *) ptr; char *service_name = (*env)->GetStringUTFChars(env, serviceName, NULL); char *object_path = (*env)->GetStringUTFChars(env, objectPath, NULL); diff --git a/src/main/java/io/gitlab/jfronny/globalmenu/Native.java b/src/main/java/io/gitlab/jfronny/globalmenu/Native.java index 9911fd6..70210a5 100644 --- a/src/main/java/io/gitlab/jfronny/globalmenu/Native.java +++ b/src/main/java/io/gitlab/jfronny/globalmenu/Native.java @@ -7,9 +7,14 @@ import java.util.Optional; public class Native { public native void init(long displayPtr); - public native long create(long ptr); - public native void destroy(long ptr); - public native void setAddress(long ptr, String serviceName, String objectPath); + + public native long createMenu(long ptr); + public native void destroyMenu(long ptr); + public native void setMenuAddress(long ptr, String serviceName, String objectPath); + + public native long createDecoration(long ptr); + public native void destroyDecoration(long ptr); + public native void setDecoration(long ptr, int mode); // 0 = no preference, 1 = client side, 2 = server side private static final String problem; static { @@ -17,6 +22,8 @@ public class Native { problem = "Not running on Linux"; } else if (!System.getProperty("os.arch").equals("amd64")) { problem = "Not running on amd64"; + } else if (System.getProperty("io.gitlab.jfronny.globalmenu.disable") != null) { + problem = "Explicitly disabled"; } else { try (InputStream is = Native.class.getResourceAsStream("/libnative.so")) { Path path = Files.createTempFile("libnative", ".so"); diff --git a/src/main/kotlin/io/gitlab/jfronny/globalmenu/GlobalMenuService.kt b/src/main/kotlin/io/gitlab/jfronny/globalmenu/GlobalMenuService.kt index 5d26267..57a9c2e 100644 --- a/src/main/kotlin/io/gitlab/jfronny/globalmenu/GlobalMenuService.kt +++ b/src/main/kotlin/io/gitlab/jfronny/globalmenu/GlobalMenuService.kt @@ -22,11 +22,23 @@ class GlobalMenuService(private val app: Application) : ApplicationActivationLis override fun applicationActivated(ideFrame: IdeFrame) { super.applicationActivated(ideFrame) if (!GlobalMenu.Native.isSupported) return - if (!GMSettings.getInstance().state.menu) return - if (ideFrame is ProjectFrameHelper) { - visualize(ideFrame.rootPane.jMenuBar, ideFrame.rootPane.peer) - } else if (ideFrame is IdeFrameImpl) { - visualize(ideFrame.jMenuBar, ideFrame.peer) + val peer: Peer + val menuBar: JMenuBar + when (ideFrame) { + is ProjectFrameHelper -> { + peer = ideFrame.rootPane.peer + menuBar = ideFrame.rootPane.jMenuBar + } + is IdeFrameImpl -> { + peer = ideFrame.peer + menuBar = ideFrame.jMenuBar + } + else -> return + } + if (GMSettings.getInstance().state.menu) addGlobalMenu(menuBar, peer) + else connection?.unExportObject(DbusmenuImpl.getMenuPath(peer.nativePtr)) + if (GMSettings.getInstance().state.decorations) { + } } @@ -37,7 +49,7 @@ class GlobalMenuService(private val app: Application) : ApplicationActivationLis private var lastMenu: Disposable? = null private var connection: DBusConnection? = null - fun visualize(menu: JMenuBar, peer: Peer) = app.invokeLater { + private fun addGlobalMenu(menu: JMenuBar, peer: Peer) = app.invokeLater { lastMenu?.let { Disposer.dispose(it) } lastMenu = Disposer.newDisposable() @@ -51,6 +63,7 @@ class GlobalMenuService(private val app: Application) : ApplicationActivationLis } // menu.updateMenuActions(true) } + //TODO handle keybindings // IdeEventQueue.getInstance().addDispatcher({ e -> // if (e !is KeyEvent) false // else if (!e.isAltDown) false @@ -66,17 +79,20 @@ class GlobalMenuService(private val app: Application) : ApplicationActivationLis val windowPtr = peer.nativePtr val menu = DbusmenuImpl(windowPtr, menuHolder) - conn.unExportObject(menu.objectPath) + val objectPath = menu.objectPath conn.exportObject(menu) + Disposer.register(lastMenu!!) { conn.unExportObject(objectPath) } if (peer is WLPeer) { peer.performLocked { - val ptr = GlobalMenu.Native.create(windowPtr) - GlobalMenu.Native.setAddress(ptr, conn.uniqueName, menu.objectPath) + val ptr = GlobalMenu.Native.createMenu(windowPtr) + Disposer.register(lastMenu!!) { GlobalMenu.Native.destroyMenu(ptr) } + GlobalMenu.Native.setMenuAddress(ptr, conn.uniqueName, objectPath) } } else { val registrar = conn.getRemoteObject("org.canonical.AppMenu.Registrar", "/com/canonical/AppMenu/Registrar", Registrar::class.java) - registrar.RegisterWindow(UInt32(windowPtr), DBusPath(menu.objectPath)) + registrar.RegisterWindow(UInt32(windowPtr), DBusPath(objectPath)) + Disposer.register(lastMenu!!) { registrar.UnregisterWindow(UInt32(windowPtr)) } } } } \ No newline at end of file diff --git a/src/main/kotlin/io/gitlab/jfronny/globalmenu/proxy/DbusmenuImpl.kt b/src/main/kotlin/io/gitlab/jfronny/globalmenu/proxy/DbusmenuImpl.kt index b5907e7..e27ca18 100644 --- a/src/main/kotlin/io/gitlab/jfronny/globalmenu/proxy/DbusmenuImpl.kt +++ b/src/main/kotlin/io/gitlab/jfronny/globalmenu/proxy/DbusmenuImpl.kt @@ -7,7 +7,7 @@ import org.freedesktop.dbus.types.UInt32 import org.freedesktop.dbus.types.Variant class DbusmenuImpl(windowId: Long, private val menuHolder: MenuHolder) : Dbusmenu { - private val menuPath: String = "/com/canonical/menu0x${windowId.toString(16)}" + private val menuPath: String = getMenuPath(windowId) override fun getObjectPath(): String = menuPath // override fun getVersion(): UInt32 = UInt32(3) // override fun getTextDirection(): String = "none" @@ -97,4 +97,8 @@ class DbusmenuImpl(windowId: Long, private val menuHolder: MenuHolder) : Dbusmen } override fun AboutToShowGroup(ids: MutableList?): DPair, MutableList>? = null // not needed? + + companion object { + fun getMenuPath(windowId: Long): String = "/com/canonical/menu0x${windowId.toString(16)}" + } }