feat: implement SSD support

This commit is contained in:
Johannes Frohnmeyer 2024-07-22 16:42:15 +02:00
parent 97f47569fd
commit 4ab1cc9a6b
Signed by: Johannes
GPG Key ID: E76429612C2929F4
4 changed files with 54 additions and 12 deletions

View File

@ -15,7 +15,6 @@ struct WLFrame {
void *pad5;
void *pad6;
void *pad7;
void *pad8;
jboolean toplevel;
union {
struct xdg_toplevel *xdg_toplevel;
@ -101,6 +100,10 @@ JNIEXPORT jlong JNICALL Java_io_gitlab_jfronny_globalmenu_Native_createDecoratio
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), "Not a toplevel");
return 0;
}
if (frame->xdg_toplevel == NULL) {
(*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/RuntimeException"), "No xdg_toplevel extracted");
return 0;
}
return (jlong) (intptr_t) zxdg_decoration_manager_v1_get_toplevel_decoration(zxdg_decoration_manager_v1, frame->xdg_toplevel);
}

View File

@ -4,6 +4,7 @@ import com.canonical.appmenu.Registrar
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.Application
import com.intellij.openapi.application.ApplicationActivationListener
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.wm.IdeFrame
import com.intellij.openapi.wm.impl.IdeFrameImpl
@ -16,6 +17,10 @@ import org.freedesktop.dbus.DBusPath
import org.freedesktop.dbus.connections.impl.DBusConnection
import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder
import org.freedesktop.dbus.types.UInt32
import java.awt.Dimension
import java.awt.Window
import javax.swing.FocusManager
import javax.swing.JFrame
import javax.swing.JMenuBar
class GlobalMenuService(private val app: Application) : ApplicationActivationListener {
@ -23,22 +28,44 @@ class GlobalMenuService(private val app: Application) : ApplicationActivationLis
super.applicationActivated(ideFrame)
if (!GlobalMenu.Native.isSupported) return
val peer: Peer
val menuBar: JMenuBar
val menuBar: JMenuBar?
val frame: JFrame
GlobalMenu.Log.warn(ideFrame.toString())
when (ideFrame) {
is ProjectFrameHelper -> {
peer = ideFrame.rootPane.peer
menuBar = ideFrame.rootPane.jMenuBar
frame = ideFrame.frame
}
is IdeFrameImpl -> {
peer = ideFrame.peer
menuBar = ideFrame.jMenuBar
frame = ideFrame
}
else -> return
}
if (GlobalMenu.Native.isMenuSupported && GMSettings.getInstance().state.menu) addGlobalMenu(menuBar, peer)
else connection?.unExportObject(DbusmenuImpl.getMenuPath(peer.nativePtr))
if (GlobalMenu.Native.isDecorationSupported && GMSettings.getInstance().state.decorations) {
onActivate(peer, frame, menuBar)
}
private fun onActivate(peer: Peer, frame: Window, menuBar: JMenuBar?) {
if (GlobalMenu.Native.isMenuSupported && GMSettings.getInstance().state.menu && menuBar != null) addGlobalMenu(menuBar, peer)
else connection?.unExportObject(DbusmenuImpl.getMenuPath(peer.nativePtr))
if (GlobalMenu.Native.isDecorationSupported && GMSettings.getInstance().state.decorations && peer is WLPeer) {
if (peer.decorated) {
// Disable client-side decorations and enable server-side decorations
peer.decorated = false
frame.size = Dimension(frame.width, frame.height + 1)
val decoration = GlobalMenu.Native.createDecoration(peer.nativePtr)
// Disposer.register(lastMenu!!) { GlobalMenu.Native.destroyDecoration(decoration)
GlobalMenu.Native.setDecoration(decoration, 2)
}
}
ApplicationManager.getApplication().invokeLater {
val frame1 = FocusManager.getCurrentManager().focusedWindow
if (frame != frame1) onActivate(frame1.peer, frame1, when (frame1) {
is JFrame -> frame1.jMenuBar
else -> null
})
}
}

View File

@ -1,14 +1,14 @@
package io.gitlab.jfronny.globalmenu
import java.util.function.BiConsumer
import java.util.function.BiFunction
import java.util.function.*
import java.util.function.Function
import java.util.function.Supplier
val <T, R> Function<T, R>.unchecked: Function<Any, R> get() = Function { it: Any -> apply(it as T) }
val <T> Consumer<T>.unchecked: Consumer<Any> get() = Consumer { accept(it as T) }
val <T1, T2> BiConsumer<T1, T2>.unchecked1: BiConsumer<Any, T2> get() = BiConsumer { t1: Any, t2: T2 -> accept(t1 as T1, t2) }
operator fun Runnable.invoke() = run()
operator fun <T> Supplier<T>.invoke() = get()
operator fun <T, R> Function<T, R>.invoke(t: T): R = apply(t)
operator fun <T1, T2, R> BiFunction<T1, T2, R>.invoke(t1: T1, t2: T2): R = apply(t1, t2)
operator fun <T1, T2> BiConsumer<T1, T2>.invoke(t1: T1, t2: T2) = accept(t1, t2)
operator fun <T1, T2> BiConsumer<T1, T2>.invoke(t1: T1, t2: T2) = accept(t1, t2)
operator fun <T> Consumer<T>.invoke(t: T) = accept(t)

View File

@ -3,6 +3,7 @@ package io.gitlab.jfronny.globalmenu
import io.gitlab.jfronny.commons.unsafe.reflect.Reflect
import io.gitlab.jfronny.commons.unsafe.reflect.impl.CoreReflect
import java.awt.Component
import java.awt.Insets
import java.lang.reflect.AccessibleObject
import java.lang.reflect.Field
@ -42,14 +43,25 @@ class WLPeer(private val inner: Any) : Peer {
fun performLocked(runnable: Runnable) {
performLockedMethod(inner, runnable)
}
fun registerCleaner(runnable: Runnable) {
GlobalMenu.Cleaner.register(this, runnable)
}
var decorated: Boolean
get() = containerPeerClass.isInstance(inner) && getInsetsMethod(inner).top > 0
set(value) {
val decoration = decorationField.get(inner)
isUndecoratedField.setBoolean(decoration, !value)
markRepaintNeededMethod(decoration)
}
companion object {
val componentPeerClass = Class.forName("sun.awt.wl.WLComponentPeer")
private val performLockedMethod = Reflect.instanceProcedure(componentPeerClass, "performLocked", Runnable::class.java).unchecked1
private val nativePtrField = componentPeerClass.getDeclaredField("nativePtr").apply { setAccessible(this) }
private val containerPeerClass = Class.forName("java.awt.peer.ContainerPeer")
private val getInsetsMethod = Reflect.instanceFunction(containerPeerClass, "getInsets", Insets::class.java).unchecked
private val decoratedPeerClass = Class.forName("sun.awt.wl.WLDecoratedPeer")
private val decorationField = decoratedPeerClass.getDeclaredField("decoration").apply { setAccessible(this) }
private val frameDecorationClass = Class.forName("sun.awt.wl.WLFrameDecoration")
private val markRepaintNeededMethod = Reflect.instanceProcedure(frameDecorationClass, "markRepaintNeeded").unchecked
private val isUndecoratedField = frameDecorationClass.getDeclaredField("isUndecorated").apply { setAccessible(this) }
}
}