GJS和GNOME Extension趟坑指南

通过了半个月的摸爬滚打,总算在写GNOME插件上走上了点正轨。这篇文章虽然是指南,其实就是一些抱怨(笑)javascript

概况

首先说说GNOME Extension是什么来的。html

2011年,GNOME释放了万众期待的大版本更新GNOME 3。据wiki描述,这个万众期待的大版本气得Linus Torvalds投向了xfce,而且把GNOME开发组狠狠地骂了一顿。不过在GNOME 3这么迭代了几个版本以后,他又用回了GNOME。前端

而GNOME Extension就是GNOME 3开始的,一种更加开放自由的方式提供给用户tweak本身的工做环境的方式。GNOME 3的桌面环境称做GNOME Shell,它负责Top Bar,还有Activites,Workspaces。整个GNOME Shell是由一种Javascript方言GJS和一大堆GTK+库Binding写成的。java

前端开发的同窗都知道,不管一个网页写成什么样子,我只要在控制台输入几行js代码,就能够魔改这个网页,也即没有所谓名字保护机制,任何部分均可以自由访问。GNOME Shell天然也是这样,因此每个插件上传都须要至关长的时间由工做人员Review以后才能释出。node

在终端输入gjs,你就能够开始用一个由GNOME倾情提供的js解释器了:git

$ gjs
gjs> print("Hello World!");
Hello World!
gjs> const Gtk = imports.gi.Gtk;
gjs> const GLib = imports.gi.GLib;
gjs> Gtk.init(null);

gjs> let mainloop = new GLib.MainLoop(null, null);
gjs> let w = new Gtk.Window();
gjs> w.show_all();
gjs> mainloop.run();

在你打完最后一句以后,应该会出来一个小窗口儿了。github

screenshot1

是否是有一种胜券在握的感受。有了这个gjs感受能够扔掉nodejs了(二者使用的JS引擎不一样,nodejs和QML使用Google的V8,而GJS使用Mozilla的SpiderMonkey,这两家真是世仇啊哈哈),甚至还能够10行之内开发Native GUI,还可使用由GTK+提供的全部库!是否是很爽。其实噩梦才刚刚开始。`shell

文档

首先,你碰到的第一个问题就是。你根本找不到文档。这么著名的GNOME项目竟然连文档都没有怎么可能。你不死心地Google了半天,只找到了一些零零散散的文档。这时你会在Stackoverflow看到有人问GJS的文档在哪里,答案就是很无奈的:你想一次过拿到一份完整的文档,是不可能的了(笑)。挖槽!编程

下面公布真相。能用的文档有两个:segmentfault

第一个是非官方的Seed文档,看起来还不错(Seed是GJS的一个兄弟,功能几乎同样,可是分开维护,老实说你们对此都很懵逼)。第二个是官方文档,看起来……喵喵喵喵喵????? 这也太随便了吧老实说。不过幸亏还能用。总的来讲就是。用到GTK家族的库的时候,以第二份为准,第一份备用参考(由于第二份很是不全),有时还要参考一下GTK+的C文档以了解详细状况。

接下来另外一个问题就是,怎么跟这该死的GNOME Shell互动了。上面两份文档里面都不包含任何GNOME的内容。可能还有很多人不知道GNOME和GTK+和GLib这些东西的关系。这种东西要认真纠结起来简直麻烦到上天。它们是这样的关系:

  • GLib是GTK+的一部分,用于在C上面布建一个面向对象编程和反射的架构(GObject)。

  • GTK+则是一个以界面库为中心的一大堆实用库,包括GLib, Gio, GTK,一开始是给GIMP作界面用的。咱们平时用+来代替“家”,好比Vocaloid=V+。不知是什么心有灵犀,总之GTK+就是整个这个实用库家族。更正:这个家族的库官方又称做GNOME平台库。

  • GTK(没有+)就是正真正銘的界面库了,按钮文本框标签什么的。更正:GTK是一个古老的界面库。GTK+同时也特指这一个界面库。仅为了区分,下面我全部的文字,但凡带+的,都是指整个家族,不带+的,都是特指这个界面库。

  • GNOME Foundation/GNOME Project后来相中了GTK+用它来开发桌面环境,后来把顺便它归入了本身旗下。如今GNOME基金会是GTK+老爸。

  • GNOME,本文特指GNOME 3,主要是指一个桌面环境(GNOME Shell)和一些应用程序(好比Nautilus,GNOME Terminal)。不带歧义时不少时候特指桌面环境。GNOME 2是彻底的C/C++写(libgnomeui),后来发展出了GObject Introspection、Vala和GJS这些基于GObject体系的东西,这样方便起见GNOME Shell很多业务逻辑就用脚本语言写了。

GNOME Shell的文档在哪儿呢?答案就是没有。也就是说,你必须去阅读GNOME Shell的代码。从 https://github.com/GNOME/gnom... 把代码下载下来读吧。所幸它的代码写得挺容易读,因此也不是件坏事。

其它的资料参考:

调试

为了方便调试GNOME很善意地提供了一个Looking Glass来做为GNOME的控制台。按<Alt-F2>运行lg便可进入。很惋惜这个东西不是通常的难用。进入了lg以后其它部分就不能再动了,因此你也不能开着它一遍写一遍调试。你也不能一大段代码复制进去运行。可能有人会问刚才不是有个gjs能在终端跑么,可是那个东西没办法干预到GNOME,由于它单单就是一个解释器,GNOME是运行在别的进程怎么可能能够访问。

GNOME的东西通讯都有个尿性,就是喜欢用DBus。当我用dbus-monitor监视DBus总线上的通讯时,不出所料,lg就是经过DBus发送内容给GNOME进程计算的。不过使人很恼火的是它发送的内容是加密过的,因此就不能利用了。查了一段时间资料以后,发现了一个Eval接口:

(1+1)*3=6!是否是很厉害

说到DBus就不能不说D-Feet和dbus-monitor了。前者是你在茫茫接口里寻宝的宝器,后者是用来监控DBus总线上的活动。若是你以为什么数据都能被监视很没安全感,那你就应该作点公钥加密,毕竟DBus接口作出来就是开放给公用的,包括命名管道,包括信箱也是,这些传统的IPC都是公用的。

经过它,咱们能够测试一些代码,来操做GNOME了。这里就要注意了:gnome-shell桌面跑在一个单线程,因此千万不要做死运行可能阻塞的代码,包括死循环,包括任何阻塞的东西,包括跑一个Gtk+窗口,这会瞬间弄崩你的GNOME。轻则service gdm restart,重则重启电脑才能解决。

每一次的Eval都是独立的Scope,因此上一次Eval时产生的变量,下一次Eval的时候就没有了。解决方法是将变量保存在global对象里,或者不用let/var这些定义变量,直接让它成为全局变量,不过小心名字污染。当你在调试的时候你可能会须要log(指global.log())一些信息,这些信息不会在Eval的时候直接返回给你。在:

$ journalctl -f /usr/bin/gnome-shell

能够找到日志。可是若是日志太大的话你就没这么愉快了。我第一次打开日志的时候,花了差很少10分钟才寻到文件末尾,两三年的日志加起来总共90多万行。用:

# journalctl --vacuum-time=2d

来将两天以前的日志删除。

GNOME Shell, Mutter和Clutter

GNOME Shell放弃了GNOME 2时代一直在用GTK,将界面绘制全面迁移到了Clutter库。Clutter也不是外家的东西,一样是基于GObject,也是GNOME项目组的一员。那为何要用它呢?由于它用OpenGL绘制界面,有硬件加速。

为了搞清楚这些乱七八糟的项目的前因后果,从Linux的X Window开始捋一捋。不严谨地说,是这样一个启动顺序:GDM首先由Systemd启动,而后GDM也就是显示管理器在登陆以后开启一个X Session,而且在这个X Session运行gnome-session会话管理器。GNOME Session会正式运行gnome-shell,至此咱们就看到熟悉的壁纸熟悉的桌面了。

GNOME Shell的中心,也就是窗口管理器Mutter,因此这就是*utter系列的第一个出场了。窗口管理器最主要的功能就是让X的窗口有标题栏(不知你们有没有见过那些没有标题栏的窗口,在重启GNOME Shell的间隙大概能见到),因而能最大化最小化移动,还能在工做区之间转换。在这些窗口里面有两个特殊的窗口:一个位于全部其它窗口的底部,它显示一张壁纸,兴许还有点图标;还有一个位于全部其它窗口的顶层,它显示Top Bar,Activities,Legacy Tray,兴许还有iBus输入法。

GNOME Shell做为桌面环境和Mutter其实已经难分难解。gnome-shell加载了libmutter.so,彷佛还有一说是gnome-shell已经被开发成了Mutter的插件这样的形式而存在,能够看出Mutter实际上是高可定制的。总而言之,窗口管理功能交给了Mutter以后,刚才说那两个特殊窗口,就是靠JS写出来的了,必定程度上咱们甚至能够认为GNOME Shell的本体其实也就只有那两个特殊窗口。

这两个特殊窗口的绘制,跟普通窗口并没有差异,反正到最后仍是会被解释成X11协议的显示命令被送到X Server。因此咱们能够自由地采用GTK,QT,或者Clutter。Clutter虽然没有GTK的历史长,可是也已经磨练了至关长的时间了(差很少10年了)。它引入了一个叫作Actor的概念(事实上至关于GtkWidget么),反正也就是盒模型,同时提供了CSS样式支持。很残念地,咱们如今须要为两个界面库维护两套CSS了。

与GTK不一样,Clutter自己不提供任何的控件,它只提供Actor,一个盒子。剩下的就靠你本身发挥想象力了。正如HTML自己也能够不提供控件(虽然它提供了),你只要经过本身写CSS和JS就能模拟出来按钮文本框标签。固然,这些事情不用咱们本身作,Shell Toolkit(ST)已经帮咱们封装好了一堆经常使用的控件。

不管是作什么,GNOME的动向都是方向明确的。它想要把一切都换成自家的,换成带硬件加速的,包括Xorg,也要换成Wayland。


就先抱怨到这里吧w。水平有限,如有纰漏欢迎指出。
在这里还要感谢 @mengzhuo 先生对插件的高效审校。

相关文章
相关标签/搜索