在GTK/GJS应用程序和Gnome Shell扩展之间共享代码 [英] Sharing code between a GTK/GJS App and a Gnome Shell Extension
本文介绍了在GTK/GJS应用程序和Gnome Shell扩展之间共享代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
Gtk.Widget
到"侏儒外壳"面板图标的菜单。
我尝试使用clutter-gtk
中的GtkClutter.Actor
,但库似乎
过时了,在Wayland或X11 Gnome Shell中都不起作用,因为它
需要杂乱1.0
,但看到7
已加载。导入时
imports.gi.GtkClutter
在扩展中,Gnome Shell生成此错误:
Requiring GtkClutter, version none: Requiring namespace 'Clutter' version '1.0', but '7' is already loaded
。
clutter-gtk
实际工作的一些代码,如果直接
通过gjs
运行;可能是因为我可以在这里强制执行GTK 3.0。
gtkclutter.js:
imports.gi.versions.Gtk = '3.0' // fails if set to 4.0
const { Gtk, GLib, Clutter, GtkClutter } = imports.gi
// gtkUI returns a Gtk.Widget tree. This should be the reusable code.
function gtkUI() {
return new Gtk.Label({
label: '<span size="100000">🎉</span>',
use_markup: true,
})
}
// embedClutterActor returns a Gtk.Widget with an embedded Clutter.Actor.
function embedClutterActor(clutter_actor) {
let embed = new GtkClutter.Embed()
embed.get_stage().add_child(clutter_actor)
return embed
}
// embedGtkWidget returns a Clutter.Actor with an embedded Gtk.Widget.
function embedGtkWidget(gtk_widget) {
return new GtkClutter.Actor({ contents: gtk_widget })
}
class App {
constructor() {
this.title = 'GtkClutter'
GLib.set_prgname(this.title)
}
onActivate() { this.window.show_all() }
onStartup() { this.buildUI() }
run(ARGV=[]) {
this.app = new Gtk.Application()
this.app.connect('activate', () => this.onActivate())
this.app.connect('startup', () => this.onStartup())
this.app.run(ARGV)
}
buildUI() {
let w = this.window = new Gtk.ApplicationWindow({
application: this.app, title: this.title, icon_name: 'face-smile',
default_height: 160, default_width: 160, window_position: Gtk.WindowPosition.CENTER,
})
// Just to demonstrate that GtkClutter embedding works, we use both embeds here to create
// a Gtk.Widget from a Clutter.Actor from the actual Gtk.Widget that we want to show.
GtkClutter.init(null)
Clutter.init(null)
w.add(embedClutterActor(embedGtkWidget(gtkUI())))
// In the actual GTK App, we would just have used `w.add(gtkUI())`
// and not imported Clutter and GtkClutter at all.
}
}
new App().run(ARGV)
下面是GTK应用程序的配套扩展,正在尝试(但失败)
将GTK代码重用为GtkClutter.Actor
的contents
。
extsion.js:
const { Clutter, Gtk, Gio, St } = imports.gi
let GtkClutter = null // lazy import for debugging
const Main = imports.ui.main
const PanelMenu = imports.ui.panelMenu
const PopupMenu = imports.ui.popupMenu
const Me = imports.misc.extensionUtils.getCurrentExtension()
const VERSION = 'dev-version' // filled during install
const NAME = 'GtkClutterExt'
// gtkUI returns a Gtk.Widget tree. This should be the reusable code.
function gtkUI() {
return new Gtk.Button({ child: Gtk.Label({
label: `<span size="100000">🎉</span>`,
use_markup: true,
})})
}
// stUI returns an Gnome Shell widget tree that works only in Gnome Shell.
function stUI(icon_name='face-sad') {
return new St.Icon({ icon_name })
}
function statusIcon(icon_name) {
let box = new St.BoxLayout()
let icon = new St.Icon({ icon_name, style_class: 'system-status-icon emotes-icon' })
box.add_child(icon)
box.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM))
return box
}
class Ext {
constructor() { this.panel_widget = null }
enable() {
log(`enabling extension ${Me.uuid}`)
try {
// Use St only for the status icon and the menu container (not the menu content).
let btn = this.panel_widget = new PanelMenu.Button(0.0, NAME, false)
let item = new PopupMenu.PopupBaseMenuItem({ reactive: false, can_focus: false })
btn.menu.addMenuItem(item)
Main.panel.addToStatusArea(NAME, btn)
try { GtkClutter = imports.gi.GtkClutter }
catch (e) { log(`failed to load clutter-gtk, err=${e.message}`) }
if (GtkClutter) {
// Using St for the status icon is OK, since it is only used by the extension.
btn.add_child(statusIcon('face-happy'))
// But for the menu, I like to reuse my GTK code from the GTK app.
// That is what GtkClutter was designed for, I believe.
item.actor.add_child(new GtkClutter.Actor({ contents: gtkUI() }))
} else {
// As fallback we show our mood regarding GtkClutter support in Gnome Shell ;)
btn.add_child(statusIcon('face-sad'))
item.actor.add_child(stUI('face-angry'))
}
} catch (e) {
log(`failed to enable ${Me.uuid}, err=${e.message}`)
}
}
disable() {
debug(`disabling extension ${Me.uuid}`)
if (this.panel_widget == null) return
this.panel_widget.destroy()
this.panel_widget = null
}
}
function init() { return new Ext() }
我知道clutter-gtk
非常过时(请参阅https://gitlab.gnome.org/GNOME/clutter-gtk),
但我没有找到更好的方法将GTK提升到我的扩展中。
问题
- Gnome Shell是否提供与
GtkClutter.Actor
类似的功能,允许 扩展程序员重用他们的GJS/GTK代码? - 您看到了哪些重用GTK/GJS代码的替代方法?
- 如果GTK是如此通用的跨平台库,为什么Gnome Shell不 是否支持开箱即用?(奖金问题😉,更多出于好奇心)
推荐答案
tl;dr您不能在GNOME Shell扩展中使用GTK小工具。
GNOME Shell中使用的工具包是Clutter,而不是GTK。CLUTTER是Mutter的内部库,而GTK3仅在GNOME Shell中用于少数实用程序。
Clutter过去是一个独立库,但现在专门作为Mutter的合成器工具包开发。GTK是一个应用程序工具包,不适合在合成器中使用。独立的Clutter项目现在实际上没有维护,使得GtkClutter几乎相同。
这篇关于在GTK/GJS应用程序和Gnome Shell扩展之间共享代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文