在 GTK/GJS 应用程序和 Gnome Shell 扩展之间共享代码

2024-02-10

我正在 GJS 中开发 GTK 应用程序,并且喜欢重用 GTK 的部分内容 Gnome Shell 扩展中的代码。但是我没有找到添加的方法Gtk.Widget到我的 Gnome Shell 面板图标的菜单。

我尝试使用GtkClutter.Actor from clutter-gtk,但图书馆似乎 已经过时了,并且在 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 代码重用为contents of a GtkClutter.Actor.

扩展.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 https://gitlab.gnome.org/GNOME/clutter-gtk), 但我没有找到更好的方法将 GTK 提升到我的扩展中。

问题

  1. Gnome Shell 是否提供类似的东西GtkClutter.Actor这允许 扩展程序员重用他们的 GJS/GTK 代码?
  2. 您认为重用 GTK/GJS 代码的替代方法是什么?
  3. 如果 GTK 是这样一个通用和跨平台的库,为什么 Gnome Shell 不是 支持开箱即用吗? (奖金问题????,更多出于好奇)

TL;DR您不能在 GNOME Shell 扩展中使用 GTK 小部件。

GNOME Shell 中使用的工具包是 Clutter,而不是 GTK。 Clutter 是 Mutter 的内部库,而 GTK3 仅在 GNOME Shell 中用于少数实用程序。

Clutter 曾经是一个独立的库,但现在专门作为 Mutter 的合成器工具包开发。 GTK 是一个应用程序工具包,不适合在合成器中使用。

独立的 Clutter 项目现在实际上已经不再维护,使得 GtkClutter 几乎没有变化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 GTK/GJS 应用程序和 Gnome Shell 扩展之间共享代码 的相关文章

  • 如何使用 GTK+ / Cairo 旋转图像

    我有一个简单的应用程序 应该使用每 x 毫秒旋转装饰轮这么多度GTK and Cairo 我下面有一些代码可以调用cairo rotate 来自计时器 然而 图像并没有改变 我是否必须使图像无效才能引发暴露事件 我对开罗很陌生 一个简单的例
  • 将主要参数传递给 gui 库的 init 函数

    当涉及到 Qt 和 GTK 等库中的库初始化时 您必须将主要参数传递到初始化库的函数中 为什么 图书馆用它们做什么 为了方便起见 Qt 和 GTK 都旨在响应某些命令行标志 两者也都响应各种环境变量 您不一定have将 argv 和 arg
  • 当我右键单击图标时出现无限 gtk 警告

    由此tuto http zetcode com tutorials gtktutorial firstprograms include
  • Gtk Ckipboard:使用自定义 URI 方案从源粘贴文件

    我正在尝试编写一个 GTK C 应用程序 将一些文件放在 Gtk 剪贴板上 以便使用 Nautilus 的用户能够粘贴它们 有一个好的stackoverflow 上 Gtk 剪贴板本地文件复制和粘贴的示例 https stackoverfl
  • 如何检查 GTK+3.0 中小部件的类型?

    I saw this https stackoverflow com questions 60112777 find type of gtk widgets帖子 但它是针对 Python 的 所以这对我没有太大帮助 我正在使用 C 进行编程
  • 如何使用 gtk 信号将多个变量作为数据传递

    我有一个小程序 其中 gtk 信号回调函数需要 2 或 3 个变量 我不想创建这些全局变量 该项目的整个目标是整洁 并且我不想创建整个结构 以便我可以将小部件和编译的正则表达式发送到函数 据我所见g signal connect只允许单个数
  • 更改 GdkPixbuf (GTK3) 中像素的颜色

    我在用着Gtk StatusIcon 并且想要改变某些像素的颜色 我有一段工作代码 它加载一个带有我想要设置的颜色的 1x1 像素 PNG 文件 然后将其复制到图标 Pixbuf 虽然这种方法有效 但它有一个明显的缺点 即必须为每种颜色创建
  • 为什么 DirectFB 没有在 GNU/Linux 中得到更广泛的应用?是否存在 X11 中不存在的严重限制?

    据我了解 DirectFB为多种显卡提供硬件加速 此外 它比 X11 更小 更快 并且占用的内存更少 那么 为什么它没有比现在更主流呢 我真正不确定的是 常见的 GTK Qt 程序是否需要移植到它 在 DirectFB 网站上 有一个将 F
  • C# Mono Linux - 抓取全局剪贴板的内容

    我试图简单地从剪贴板 抓取 文本并将其放入变量中 我在做这件事时遇到了很多麻烦 我尝试过使用 Gtk Clipboard Get Gdk Atom Intern PRIMARY true 到目前为止 我的代码只是将 Gtk Clipboar
  • 当行突出显示时设置 cellrenderertext 前景色

    当我有一个gtk CellRendererText 我可以关联它的foreground用树存储的一列着色 并设置foreground set属性设置为 True 以更改该列中文本的颜色 但是 当选择具有彩色列的行时 其颜色会消失 并且与任何
  • 如何在 gtk 中将小部件作为不同的线程加载? (瓦拉)

    我创建了这个类 出于效率原因 我想将缩略图作为不同的线程加载到图标视图中 因为如果我在同一个线程中执行此操作 GUI 加载速度会非常慢 但是当我创建线程时 它不起作用 它绘制了一些缩略图 然后它们就消失了 当我使用 join 时 它有效 这
  • 如何针对 gtk 3 库运行 javaFx 应用程序?

    如何强制 javaFx 应用程序使用 gtk3 库 我知道SWT允许设置SWT GTK3 1用于此目的的环境变量 javaFx 是否有类似的可能性 解决方法 新功能 8087516 对 Linux 上的 GTK 3 有条件支持 https
  • 如何在 C# 中使用 GtkBuilder 连接林间空地信号?

    在Python中 我可以这样做builder connect signals self C 中好像不存在这个方法 看了之后GtkBuilder 文档 http library gnome org devel gtkmm unstable c
  • GTK 中的延迟加载列表视图#

    我希望通过 GTK 中的列表视图显示大型数据集 而性能是这里的一个问题 我目前正在使用由 ListStore 支持的 TreeView 但将所有数据添加到 ListStore 需要很长时间 GTK 中是否有某种支持延迟加载数据的列表视图小部
  • mkbundle 和 GTK#

    我正在尝试使用 mkbundle 以便我可以分发 GTK 应用程序 而无需用户安装 NET Mono 或 GTK 我已经成功捆绑了一个使用 winforms 的应用程序 但由于某种原因 当我对 GTK 应用程序执行相同操作时 它无法工作 这
  • Python GTK 信号处理程序不工作

    我正在使用 GTK 为 GUI 编写一个 Python 应用程序 我注意到从终端使用 Ctrl C 关闭它不起作用 我发现这是因为一个错误 所以我尝试手动处理该信号 问题是 如果我将默认行为设置为默认行为 则会捕获信号并正确关闭应用程序 但
  • 重用 Java 方法的最佳方法

    我正在学习 Java 和 OOP 并且一直在做问题欧拉计划 http projecteuler net index php section problems用于练习 顺便说一句 很棒的网站 我发现自己一遍又一遍地做许多相同的事情 例如 检查
  • GTK 滚动窗口 - 将滚动条保持在底部

    我有一个使用 ScrolledWindow 的 GTK C 程序 我不断将数据添加到滚动窗口内的列表中 并且我想将注意力集中在最新的项目上 但我还想允许用户滚动数据以选择旧项目 有没有办法做到这一点 我到处都找过了 但什么也没找到 我不太清
  • Netbeans 8.1 Gnome 3 GTK+ UI 字体和选项卡高度

    我刚刚在运行 GNOME 3 桌面的 Ubuntu 16 04 上安装了 NetBeans 8 1 如果可能的话 我想继续使用 IDE 的 GTK 外观和感觉 但 UI 上的字体 尤其是选项卡中的字体 太小且重叠 我尝试添加 fontsiz
  • Python GTK + webkit - 在 gtk.main() 之后插入 JavaScript

    我在终端中尝试了这个 一切正常 但是如果我在脚本内运行这个 我无法在 gtk main 之后插入 JavaScript import gtk import webkit w gtk Window b webkit WebView w add

随机推荐

  • Visual Studio 2019 错误 - 无法加载文件或程序集或其依赖项之一

    我在运行我的项目时遇到一些问题 当我尝试运行时 出现以下错误 FileNotFoundException 无法加载文件或程序集 Dapper Version 2 0 0 0 Culture neutral PublicKeyToken nu
  • 删除c中数组的重复名称

    这就是我要做的 c 应该可以删除具有指定名称的动物 如果存在更多同名动物 则应删除所有同名动物 这是我的代码 void deleteAnimalByName char animalName int nrOfAnimals ANIMAL an
  • 执行代码块一定次数

    所以我想执行一些代码N次 N 是文本框的值 例如 12 我不知道如何实现这一点 但我的脑海里浮现出这样的事情 For Each i as 1 in textbox1 text some code Next or dim num1 as in
  • asciidoc宏

    我使用 asciidoc 来渲染文本 我很难理解宏 我的目标是进行简单的宏处理 就像在 LaTeX 中一样 我想写两个宏 FOO应替换为 bar MYTEXT xyz 应替换为 This is my text xyz 也许用不同的方式传递参
  • 如何从 Android 版 Google+ API 获取当前位置?

    我需要从 Android 版 Google API 获取当前位置 我已经在 Google API 控制台中完成了所有操作 并将我的应用程序与带有 SHA1 和包名称的客户端 ID 链接起来 我成功获取了有关用户名 个人资料图片 封面图片 电
  • 如何在python3中使用ldap3绑定(验证)用户

    我正在尝试将一些代码更新为 python3 使用ldap3 http ldap3 readthedocs org en latest quicktour html版本 0 9 7 4 https pypi python org pypi l
  • 如何在android apk中保存私有字符串值?

    我知道我可以将字符串保存在 res values strings xml 中 但是如果有人反汇编 dex 文件或 apk 文件 那么他将能够看到硬编码字符串或 res values strings xml 字符串 有没有办法存储反汇编后不会
  • 有没有办法让 Eclipse 报告一般“catch (Exception e)”作为错误/警告(在 java 中)?

    我试图鼓励在 Java 代码中不捕获一般异常的最佳实践 例如 try catch Exception e bad 有没有办法在 Eclipse 中将其标记为错误 警告 我知道 PMD 会注意到这一点 但我现在宁愿避免将其集成到每个人的构建环
  • Android 按钮 KeyDown - KeyUp |不同的按钮事件

    我有一个关于开发 Android 应用程序的简单问题 问题是不同类型的按钮 例如 当我的手指放在按钮上时 音乐就会播放 但是当我的手指放在按钮上时 音乐就会停止 我怎样才能做到这一点 这可能是不同类型的按钮事件 但我不知道 我用谷歌搜索 但
  • 如何在简单的 Kivy 应用程序中将 Pandas 数据框显示为表格?

    我想构建一个简单的 Kivy 应用程序 要求用户输入一个整数 MTP 要求用户输入延迟间隔 delay 用户按下提交按钮后查询 url 然后从 该查询创建一个显示的 pandas 数据框 就像 表 在 Kivy 应用程序的主屏幕上 然后输出
  • 如何将标签中的文本与右侧对齐?

    这是我的文件标签 如果标签太长 它就会超出屏幕 从而使我不得不滚动 我已经尝试了以下属性 单独的时间 RightToLeft as Yes ContentAlignment作为右下或右上 然而 它们都不起作用 什么是正确的属性 尝试设置Au
  • NSSortDescriptor 按核心数据对多关系中的项目数量进行排序

    使用 Core Data 多关系时 这是一个长期存在的问题 很难使用以下命令对获取请求进行排序NSSortDescriptor on a Parent基于实体的数量children与 a 处于一对多关系Child实体 这在与NSFetche
  • 如何对 xml 文件中的 IBM MobileFirst SQL 适配器用户名密码 url 和端口进行哈希处理?

    我正在使用 IBM MobileFirst SQL 适配器从 AWS Oracle RDS 获取数据 为了连接到 sql 适配器 我们需要提供用户名 密码 url 和端口 连接有效 但是 我应该如何散列它以便没有人可以读取它 这是为了使其更
  • 配置字符串的 winforms 连接属性对话框

    有没有办法在运行时显示用于连接字符串浏览 针对数据库 的连接属性对话框 因为我希望用户能够使用 GUI 连接到各种数据库 与我们在 Visual Studio 连接属性对话框中获得的相同 提前致谢 寻找this http pedotnet
  • 仅获取数组 mongoose 的最后一个元素

    我的文档中有数组 我尝试接收该数组的最后一个元素 我的代码是 Post find id postId comments slice 1 这给了我所有的对象 但注释数组仅包含最后一个元素 另一方面 Post find id postId co
  • Django South:如何在迁移中访问子包中的模型

    由于我们的应用程序有很多模型 因此我们将它们放置在 models 包的子包中 即Cheddar模型不会在models Cheddar 而是在models cheese Cheddar 看来我无法在南方数据迁移中访问这些模型 即使我创建了一个
  • Jooq中有没有办法通过示例进行查询?

    I ve a PersonPojo and PersonRecord由 Jooq 生成 现在我想做这样的事情 Person p new PersonPojo p setId 10 create selectFrom Tables PERSO
  • 如果多个线程尝试访问单例对象会发生什么

    不是在实例化期间 而是在单例对象实例化完成后 如果两个或多个线程尝试访问同一个单例对象 会发生什么情况 特别是在单例对象需要花费大量时间来处理请求的情况下 比如1分钟 在这种情况下 如果例如 5个线程尝试访问同一个单例对象 结果会是什么 附
  • 如何在 3D 绘图上设置平行透视

    我在 python 中有一段代码 用于在 python 中渲染一些球体 如下所示 matplotlib inline import numpy as np import matplotlib pyplot as plt import ran
  • 在 GTK/GJS 应用程序和 Gnome Shell 扩展之间共享代码

    我正在 GJS 中开发 GTK 应用程序 并且喜欢重用 GTK 的部分内容 Gnome Shell 扩展中的代码 但是我没有找到添加的方法Gtk Widget到我的 Gnome Shell 面板图标的菜单 我尝试使用GtkClutter A