医院检讨书范文大全:Gnome 3 相关整理(二)

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 06:04:39

https://live.gnome.org/GnomeShell/CheatSheet

This page contains brief descriptions of many GNOME Shell features, such as keybindings, drag and drop capabilities, and special utilities. We are continuing to work on making all these features more discoverable, so this page can serve a dual purpose of describing these features to the early adopters and helping us keep track of the features that are not easily discoverable.

Many of the features relate to starting and switching between applications. Some of them are available in the current versions of GNOME and some are new. Other features are built-in utilities, such as a screencast recording tool and an integrated inspector tool and JavaScript console.

On the desktop

Alt+Tab switches between applications. Window previews of the applications with multiple windows are available as you cycle through. The previews show up after a short delay, but you can get them immediately by pressing the Down arrow key. You can move between the preview windows with the Right and Left arrow keys or with the mouse pointer. Previews of applications with a single window are only available when the Down arrow is explicitly hit. It is possible to switch to any window by moving to it with the mouse and clicking.

Alt+Shift+Tab cycles through applications in reverse direction.

Alt+[key above Tab] (eg, Alt+` on a US keyboard) switches between windows within an application. This can be used from within the Alt+Tab switcher, or from outside it (to open the switcher with the window previews for the current application already selected).

The applications running on other workspaces are displayed after a vertical separator. Including all applications in the Alt+Tab makes switching between tasks a single step process and provides the user with a full picture of what applications are running.

Alt+F2 allows entering a command to launch an application. If you want to launch a shell command in a new Terminal window press Ctrl+Enter.

Window maximizing and tiling: You can maximize a window by dragging it to the top edge of the screen. Alternatively, you can double-click the window title. To unmaximize, pull it down again. By dragging windows to the left and right edges of the screen you can tile them side by side.

The panel

The panel has the Activities button for switching to the overview, the name of the focused application (which will provide the application menu in the future), the current date, the notification icons, and the button with the user name that activates the user menu. The date in the panel has a pop-down with the calendar available on click. The user menu has System Preferences, Log Out and Shut Down options.

The Power Off... menu entry is hidden by default. You can make it visible by pressing the Alt key in the user menu.

— [Alt] ?>

Switching to and from the overview

Hot corner - moving the mouse pointer to the top left corner of the screen will take you to the overview or back to the desktop.

Activities button - clicking the Activities button which is in the top left corner of the screen will take you to the overview or back to the desktop.

System (Windows) key or Alt+F1 - these key combinations will take you to the overview or back to the desktop.

In the overview

The dash on the left side is where your favorite applications and your running applications are shown. The glow behind the application icon indicates if the application is running.

Clicking on the application icon will launch it if it is not running, and will open the last used window of that application if it is already running.

Middle clicking on the application icon will launch it on a new workspace.

Right clicking on the application icon for a running application will display a menu with window titles for selecting one of the windows. This menu also provides options to open a new window for that application and to remove or add that application to favorites depending on its current status.

Ctrl+Clicking on the application icon for a running application will open a new window of that application in the current workspace.

Running applications can be added to favorites with the help of the right click menu option. You can also drag an application from the application browsing pane to the favorites row to make it a favorite application.

Dragging an application icon within the dash moves its position. A trash can icon will appear at the bottom of the dash while dragging. If you drop the application icon on the trash can it will be removed from the dash.

Dragging an application icon to a particular workspace will open a new window for that application on that workspace. Unlike launching by clicking which results in leaving the overview mode and switching to the application immediately, launching by dragging does not leave the overview mode.

Search box allows searching for application names or their descriptions. It also has a section for preferences applets. The search box is focused on automatically when you are in the overview, so you can just start typing. You can navigate the search results with up and down arrows and hit Enter to launch them.

All open windows are shown on their corresponding workspaces. You can click on the window to switch to it and leave the overview. You can click on a workspace to switch to it an leave the overview. Switching to a workspace without selecting a specific window will just have the windows on it arranged the same way as when you last used that workspace.

Using a vertical scroll over a particular window zooms in on it by bringing it forward.

Windows can be dragged between workspaces. Workspaces are dynamically added and removed as needed. There's always one spare workspace.

Ctrl+Alt+Tab brings up the accessibility switcher, which can be used to select various parts of the shell UI and control them via the keyboard. This is not yet fully functional.

Escaping

Hitting Esc key escapes:

  • Alt+Tab
  • Alt+F2
  • menus / calendar
  • overview
  • search in the overview
  • Looking Glass

Screencast recording

Control+Shift+Alt+R keybinding starts and stops the recording. (Note: this functionality is currently missing in some distribution packages.) A red circle is displayed in the bottom right corner of the screen when the recording is in progress. After the recording is finished, a file named 'shell-%d%u-%c.webm' is saved in the home directory. In the filename, %d is the date, %u is a string that makes the filename unique, and %c is a counter that is incremented each time a recording is made within a single gnome-shell session.

Magnifier

Screen Magnification is built into GNOME Shell and provides various forms of screen enhancement. It can be launched and configured using the GConf Editor by modifying the /desktop/gnome/accessibility/magnifier settings. There is also a python script that implements a dialog for changing magnifier preferences.

More details are available on the GNOME Shell Magnification page.

Developer tools

Looking Glass is GNOME Shell's integrated inspector tool and JavaScript console useful for debugging. It can be run by typing 'lg' in the Alt+F2 prompt and can then be exited by pressing Esc. More details are here.

Typing 'r' or 'restart' in the Alt+F2 prompt will restart GNOME Shell. This is useful when you are make changes to the GNOME Shell code while working within the GNOME Shell. You don't need to compile anything if you only changed JavaScript code, but you need to run compilation as you would normally do for C code before restarting.

Typing 'rt' in the Alt+F2 prompt will reload the GNOME Shell theme. This is useful when you are a theme designer and want to test changes in your theme without restarting the whole shell. The theme file is share/gnome-shell/theme/gnome-shell.css.

Typing 'debugexit' in the Alt+F2 prompt will quit GNOME Shell. This is generally only useful when you are running a development version of GNOME Shell which you started from the command line; in a normal GNOME 3 session, gnome-session will just restart GNOME Shell if you exit it.

List of Keybindings

This is a place to document all the keybindings that GNOME Shell intercepts. Developers: if you add or change a keybinding, please update this list.

  • System (Windows) key: Switch between overview and desktop
  • Alt+F1: Switch between overview and desktop
  • Alt+F2: Pop up command dialog
  • Alt+Tab: Pop up application switcher
  • Alt+Shift+Tab: Cycle in reverse direction in the application switcher
  • Alt+[key above Tab]: Switch between windows of the same application in Alt+Tab

  • Ctrl+Alt+Tab: Pop up accessibility switcher

  • Ctrl+Shift+Alt+R: Start and end screencast recording
  • Ctrl+Alt+Up/Down arrow: Switch between workspaces
  • Ctrl+Alt+Shift+Up/Down arrow: Move the current window to a different workspace
  • Ctrl+Enter: Launch a shell command in a new Terminal window
Most keybindings can be viewed under the User Menu -> System Settings -> Keyboard -> Shortcuts
(一)中提到Gnome 3具有很炫的效果(视觉特效),这得益于其新的窗口管理器Mutter,可以使用图形硬件的优势(借助于基于Opengl的Clutter)。这也就给gnome3的应用带来一个前提,即显卡驱动必须支持。但Gnome3中负责管理窗口显示与交互(窗口切换、启动应用程序)的是Gnome Shell,Gnome Shell is the defining technology of the GNOME 3 user experience, is the core user interface of the GNOME desktop environment. The Shell acts as a compositing manager for the desktop, and displays both application windows and other objects in a Clutter scene graph. Much of the code of the shell is written in Javascript but uses Clutter and GNOME platform libraries via GObject Introspection and JavaScript bindings for GNOME. For window management and compositing, the shell builds off of a Metacity branch called Mutter, which adds Clutter-based compositing to Metacity.

除了这些特效之外,Gnome Shell的Power来自于其扩展性。尽管熟悉Gnome2桌面的用户在初次使用Gnome3时感觉变化很大,几乎看不到任何元素,一切都隐藏起来,相当bare,但Gnome Shell的扩展性却恰恰体现于此,用户可以根据其需要定制桌面!

8个最受欢迎的扩展:

Favourites Panel Extension

This extension puts all the shortcuts in the favourites panel on the top panel. This gives a quicker way to launch applications. However, the shorcuts cannot be added or removed from the top panel directly, you will have to do addition and deletion in the favourites panel only. This extension is a part of the zip file downloaded.

Favourites Panel at work

Shutdown Menu Extension

In Gnome Shell by default there is no option to Shutdown, Sleep, Standby or Hibernate the system directly. The power options can only be accessed after logging out of the Gnome Shell. This extension solves this annoyance by putting the shutdown option in the user menu.This extension is a part of the zip file downloaded.

Shut Down option in the usermenu

The Power options when clicked

Applications Menu Extension

This extension provides the Applications Menu by replacing the Activities on the Top left corner. Now we can forget that large tiled icons and browse the applications as we used to. This extension is a part of the zip file downloaded.

The Applications Menu Extension at work

Bottom Panel Extension

The Bottom panel extension creates a static panel at the bottom. This panel lists the open applications on that workspace in the left, and adds a workspace switcher on the right side. The Workspace shortcuts are also changed to Ctrl+Alt+left and right instead of up and down. This extension is a part of the zip file downloaded.

The Bottom Panel Extension at Work

Move Clock Extension

This extension moves the clock to the right side next to the User Menu. This doesn't give any kind of performance boost or productivity increase, but puts the final piece of our Gnome2 experience in place. And I confess that this is not a must have :)

Clock moved to the right

User Theme Extension

This extension helps you to choose the Gnome Shell themes using the Gnome Tweak Tool. With this extension enabled, the Gnome Tweak tool can list any Gnome Shell theme in ~/.themes or in /usr/share/themes. You can switch between the themes without reloading shell. Install it by running this in terminal:

sudo apt-get install gnome-shell-extensions-user-theme

Selecting Gnome Shell themes using the Gnome Tweak Tool

See our article Top 5 Gnome Shell Themes to try out really good shell themes.

Places and Bookmarks Extension

The Places and bookmarks extension adds the a MyPlaces menu to the top bar. This reduces the need to opening the file manager everytime and navigate to the required folders. You can download it here.

The result of Places and Bookmarks menu Extension

You can also download the same extension to produce a iconized menu  here.

Right Hot Corner Extension

This extension adds a extra hot corner to the right top corner which works similar to the left corner. This reduces the work of dragging the mouse from left corner to the right edge all the time to switch workspaces or move windows between workspaces. you can download it here.

If you are a bit uncomfortable with hot corners on both sides you can download this extension and shift the left corner to the right corner.


显示桌面图标:
  1. Go to Applications > Advanced Settings
  2. Select Desktop
  3. Set option “Have file manager handle the desktop” to ON

更为奇妙的是,可以通过extensions.gnome.org在线更新自己的桌面!

    

最后,最激动人心的是,你可以很方便的编写自己的扩展:

http://www.cnblogs.com/pmirhs0/archive/2011/10/27/2227138.html

GNOME Shell Extensions开发介绍

前两天看到这篇介绍gnome shell extensions 开发的文章,来自blog.fpmurphy.com 很不错,特转来留着。有兴趣的人看看吧。

GNOME Shell Extensions

The new GNOME Shell in GNOME 3 includes support for GNOME Shell extensions. What, you may ask, is a GNOME Shell extension? According to the GNOME web page on GNOME Shell extensions

the GNOME Shell extension design is designed to give a high degree of power to the parts of the GNOME interface managed by the shell, such as window management and application launching. It simply loads arbitrary JavaScript and CSS. This gives developers a way to make many kinds of changes and share those changes with others, without having to patch the original source code and recompile it, and somehow distribute the patched code.

In other ways, a GNOME Shell extension can be used to alter the existing functionality of the GNOME Shell or to provide additional functionality.

This post assumes that you are familiar with the GNOME 3 Shell provided in Fedora 15 and have a working knowledge of JavaScript. By means of a number of examples, it will introduce you to some of the key concepts required to write you own extension. As with a lot of my posts, this post will be a living document and will be edited from time to time to correct errors and add more examples.

So how should you go about creating a GNOME Shell extension? Let us dive in an create a simple extension and explain the concepts and theory as we go along. We will use gnome-shell-extension-tool for our first example. This tool is available in Fedora 15 Alpha. I am not sure whether it is available on other GNU/Linux distributions. There is no manpage for this tool but it is simple to use. Just answer a couple of questions and all the necessary files are created for you.

$ gnome-shell-extension-tool --help 
Usage: gnome-shell-extension-tool [options]
Options:
-h, --help show this help message and exit
--create-extension Create a new GNOME Shell extension

Example 1:

Suppose I use this gnome-shell-extension-tool to create an extension named helloworld with a UUID of helloworld@example.com and a description of My first GNOME 3 Shell extension. The tool, which is just a Python script, creates an appropriately named subdirectory (actually it is the uuid of the extension) under ~/.local/share/gnome-shell/extensions and populates that subdirectory with three files. Note that the UUID can be the classical 128 bit number, some other number or alphanumeric combination, or something more mundane like helloworld@example.com. So long as it can be used to create a subdirectory, it will be regarded as a valid UUID.

$ cd .local/share/gnome-shell/extensions  
$ find ./
./helloworld@example.com
./helloworld@example.com/stylesheet.css
./helloworld@example.com/extension.js
./helloworld@example.com/metadata.json
$ cd helloworld@example.com
$ ls -l
-rw-rw-r--. 1 fpm fpm 718 Mar 31 00:24 extension.js
-rw-rw-r--. 1 fpm fpm 137 Mar 31 00:23 metadata.json
-rw-rw-r--. 1 fpm fpm 177 Mar 31 00:23 stylesheet.css


Here are the contents of these three files:

0102030405060708091011121314151617181920212223242526272829303132333435363738394041$ cat metadata.json{   "shell-version": ["2.91.92"],   "uuid": "helloworld@example.com",   "name": "helloworld",   "description": "My first GNOME 3 Shell extension"} $ cat extension.js//// Sample extension code, makes clicking on the panel show a message// const St = imports.gi.St;const Mainloop = imports.mainloop;const Main = imports.ui.main; function _showHello() {    let text = new St.Label({ style_class: 'helloworld-label', text: "Hello, world!" });    let monitor = global.get_primary_monitor();    global.stage.add_actor(text);    text.set_position(Math.floor (monitor.width / 2 - text.width / 2),                      Math.floor(monitor.height / 2 - text.height / 2));    Mainloop.timeout_add(3000, function () { text.destroy(); });} // Put your extension initialization code herefunction main() {    Main.panel.actor.reactive = true;    Main.panel.actor.connect('button-release-event', _showHello);} $ cat stylesheet.css/* Example stylesheet */.helloworld-label {    font-size: 36px;    font-weight: bold;    color: #ffffff;    background-color: rgba(10,10,10,0.7);    border-radius: 5px;}


What is created is a very simple extension that display a message, Hello, world!, in the middle of your screen as shown below whenever you click the panel (the horizontal bar at the top of your screen in the GNOME 3 Shell) or a menu selection.

This extension is created under ~/.local/share/gnome-shell/extensions which is the designated location for per user extensions. Note that ~/.local is also used for other purposes, not just for per user extensions.

$ find .local 
.local
.local/share
.local/share/gnome-shell
.local/share/gnome-shell/extensions
.local/share/gnome-shell/extensions/helloworld@example.com
.local/share/gnome-shell/extensions/helloworld@example.com/stylesheet.css
.local/share/gnome-shell/extensions/helloworld@example.com/extension.js
.local/share/gnome-shell/extensions/helloworld@example.com/metadata.json
.local/share/gnome-shell/application_state .local/share/icc
.local/share/icc/edid-67c2e64687cb4fd59883902829614117.icc
.local/share/gsettings-data-convert


Global (system-wide) extensions should be placed in either /usr/share/gnome-shell/extensions or /usr/local/share/gnome-shell/extensions.

By the way I really wish the GNOME developers would stop creating more and more hidden subdirectories in a users home directory! It would be really nice if everything to do with GNOME 3 was located under, say, .gnome3.

Notice that the actual code for the extension is written in JavaScript and contained in a file called extension.js. This file is mandatory and is what gets loaded into GNOME Shell. At a minimum, it must contain a main() function which is invoked immediately after the extension is loaded by GNOME shell.

The JavaScript language version is 1.8 (which is a Mozilla extension to ECMAscript 262.) This is why non-standard JavaScript keywords like let are supported in shell extensions. The actual JavaScript engine (called gjs) is based on the Mozilla SpiderMonkey JavaScript engine and the GObject introspection framework.

Interestingly, a gjs shell is provided but unfortunately most of the shell functionality present in SpiderMonkey such as quit() does not appear to be supported in this particular JavaScript shell

$ gjs 
** (gjs:11363): DEBUG: Command line: gjs
** (gjs:11363): DEBUG: Creating new context to eval console script
gjs> help() ReferenceError: help is not defined
gjs> quit() ReferenceError: quit is not defined
gjs>


Persistent metadata for the extension is stored in the file metadate.json which uses the JSON file format. JSON was chosen because it is natively supported by JavaScript. Here is the current list of defined strings:

  • shell-version: A list of GNOME Shell versions compatible with the extension. For example ["2.91.92", "3.0.0"].
  • uuid: A unique UUID for the extension. This must be unique among any installed extensions as the UUID is used as the name of the subdirectory under which the files for the extension are located.
  • name: The name of the extension. This is displayed by the Looking Glass debugger when the extensions panel is displayed.
  • description: The description of the extension. This is also displayed by Looking Glass when the extensions panle is displayed.
  • url: [OPTIONAL] A valid URL pointing the the source code for the extension. Looking Glass uses this URL, if provided, to display a button which when pressed opens the source code file.
  • js-version: [OPTIONAL] This can be used to specify that a particular version of hjs is required by the extension.

There is nothing stopping you adding additional strings to this file. It some cases this may be useful as the contents of metadata.json is passed as an argument to the main() function in extension.js.

The third file is stylesheet.css. This contains all the CSS (Cascading Style Sheet) information for your extension. This file is not required if your particular extension does not require it’s own presentation markup.

Example 2:

What if we want to display localized message strings (always a good idea!) in our helloworld shell extension. In this case we need to modify entension.js to support message catalogs and we need to provide and install the relevant message catalogs in the appropriate directories.

The GNOME Shell uses the standard GNU/Linux gettext paradigm. I am going to assume that you are somewhat familiar with software localization and how to use gettext. A whole post could be devoted to the use of gettext but that is not the purpose of this post.

Fortunately the heavy lifting has been done for us by others and a JavaScript binding to gettext is available to us. We import the necessary JavaScript gettext module into the helloworld shell extension using imports and modify the code to use Gettext.gettext(“message string”) to retrieve the localized version of the message string if provided in a message catalog.

Normally compiled gettext message catalogs (.mo files) are placed under /usr/share/locale on GNU/Linux distributions. However I do not think that this is a good location for extension message catalogs as I believe that extensions should be as self-contained as possible to aid in their easy installation and removal. It also avoids the possibility of message catalog namespace collisions. For this reason, we place the message catalogs in a subdirectory called locale under the top directory of the extension.

By way of example, here is a listing of the files for our helloworld extension after it has been modified to support message localization and message catalogs for en_US and fr_FR locales provided.

./helloworld@example.com 
./helloworld@example.com/stylesheet.css
./helloworld@example.com/extension.js
./helloworld@example.com/locale
./helloworld@example.com/locale/fr_FR
./helloworld@example.com/locale/fr_FR/LC_MESSAGES
./helloworld@example.com/locale/fr_FR/LC_MESSAGES/helloworld.mo
./helloworld@example.com/locale/fr_FR/LC_MESSAGES/helloworld.po
./helloworld@example.com/locale/en_US ./helloworld@example.com/locale/en_US/LC_MESSAGES
./helloworld@example.com/locale/en_US/LC_MESSAGES/helloworld.mo
./helloworld@example.com/locale/en_US/LC_MESSAGES/helloworld.po
./helloworld@example.com/metadata.json


As you can see I have provided support for two locales, en_US for Americanese speakers and fr_FR for French speakers. The default message string Hello, world! will be displayed if neither of these two locales is set. Only the .mo files are necessary but I suggest that the corresponding .po files also reside there to make it easy to update a message catalog.

Here is our entension.js after it was modified to support message string localization:

010203040506070809101112131415161718192021222324252627const St = imports.gi.St;const Mainloop = imports.mainloop;const Main = imports.ui.main;const Gettext = imports.gettext; function _showHello() {    let text = new St.Label({ style_class: 'helloworld-label',                              text: Gettext.gettext("Hello, world!") });    let monitor = global.get_primary_monitor();     global.stage.add_actor(text);    text.set_position(Math.floor (monitor.width / 2 - text.width / 2),                      Math.floor(monitor.height / 2 - text.height / 2));     Mainloop.timeout_add(3000, function () { text.destroy(); });} function main(extensionMeta) {     let userExtensionLocalePath = extensionMeta.path + '/locale';     Gettext.bindtextdomain("helloworld", userExtensionLocalePath);    Gettext.textdomain("helloworld");     Main.panel.actor.reactive = true;    Main.panel.actor.connect('button-release-event', _showHello);}


Note that the main function now has one parameter extensionMeta. This is an object that contains all the information from the extension’s metadata.json file. This is the only parameter available to the main function in an extension. See the loadExtension function in /usr/share/gnome-shell/js/ui/extensionSystem.js for further details.

This parameter is used to build the path to the shell extension locale subdirectory. We then tell gettext that we want to use message catalogs from this subdirectory using bindtextdomain and specify the relevant message catalog, helloworld.mo, using textdomain.

Here is what is displayed when the locale is set to en_US:

and here is what is displayed when the locale set to fr_FR

If no suitable message catalog is found, the message string Hello, world! will be displayed.

Example 3:

This example shows you how modify our helloworld example extension to add a menu item to the Status Menu (the menu at the top right hand corner) of your primary display and output the Hello, world! message.

Here is the modified extensions.js:

0102030405060708091011121314151617181920212223242526272829303132333435const Main = imports.ui.main;const Shell = imports.gi.Shell;const Lang = imports.lang;const PopupMenu = imports.ui.popupMenu;const Gettext = imports.gettext; const _ = Gettext.gettext; function _showHello() {     let text = new St.Label({ style_class: 'helloworld-label', text: _("Hello, world!") });    let monitor = global.get_primary_monitor();     global.stage.add_actor(text);    text.set_position(Math.floor (monitor.width / 2 - text.width / 2),                      Math.floor(monitor.height / 2 - text.height / 2));     Mainloop.timeout_add(3000, function () { text.destroy(); });} function main(extensionMeta) {     let userExtensionLocalePath = extensionMeta.path + '/locale';    Gettext.bindtextdomain("helloworld", userExtensionLocalePath);    Gettext.textdomain("helloworld");     let statusMenu = Main.panel._statusmenu;    // use this in future:  let statusMenu = Main.panel._userMenu;    let item = new PopupMenu.PopupSeparatorMenuItem();    statusMenu.menu.addMenuItem(item);     item = new PopupMenu.PopupMenuItem(_("Hello"));    item.connect('activate', Lang.bind(this, this._showHello));    statusMenu.menu.addMenuItem(item);}


Note the use of const _ to make message strings note legible in the source code.

Notice how we increased the size of the message box. No code changes were required; we simply edited the relevant styling markup. Here is the new version of stylesheet.css

12345678.helloworld-label {    font-size: 36px;    font-weight: bold;    color: #ffffff;    background-color: rgba(10,10,10,0.7);    border-radius: 15px;    margin: 50px;    padding: 50px;

Example 4:

This example modifies the previous example to display a message in the GNOME Shell message tray.

Here is the modified extensions.js:

0102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950const St = imports.gi.St;const Mainloop = imports.mainloop;const Main = imports.ui.main;const Shell = imports.gi.Shell;const Lang = imports.lang;const PopupMenu = imports.ui.popupMenu;const Gettext = imports.gettext;const MessageTray = imports.ui.messageTray; const _ = Gettext.gettext; function _myNotify(text){    global.log("_myNotify called: " + text);     let source = new MessageTray.SystemNotificationSource();    Main.messageTray.add(source);    let notification = new MessageTray.Notification(source, text, null);    notification.setTransient(true);    source.notify(notification);} function _showHello() {    _myNotify(_("Hello, world!"))     let text = new St.Label({ style_class: 'helloworld-label', text: _("Hello, world!") });    let monitor = global.get_primary_monitor();     global.stage.add_actor(text);    text.set_position(Math.floor (monitor.width / 2 - text.width / 2),                      Math.floor(monitor.height / 2 - text.height / 2));     Mainloop.timeout_add(3000, function () { text.destroy(); });} function main(extensionMeta) {     let userExtensionLocalePath = extensionMeta.path + '/locale';    Gettext.bindtextdomain("helloworld", userExtensionLocalePath);    Gettext.textdomain("helloworld");     let statusMenu = Main.panel._statusmenu;    let item = new PopupMenu.PopupSeparatorMenuItem();    statusMenu.menu.addMenuItem(item);     item = new PopupMenu.PopupMenuItem(_("Hello, world!"));    item.connect('activate', Lang.bind(this, this._showHello));    statusMenu.menu.addMenuItem(item);}


Note the use of global.log to log a message to the error log. This log can be viewed in Looking Glass. This is useful when debugging an extension.

Example 5:

This example demonstrates how to modify our helloworld extension to add a button to the panel which when pressed displays a single option menu which when selected displays our Hello, world! message.

Here is the modified extensions.js:

0102030405060708091011121314151617181920212223242526272829303132333435363738394041424344454647484950515253const St = imports.gi.St;const Mainloop = imports.mainloop;const Main = imports.ui.main;const Shell = imports.gi.Shell;const Lang = imports.lang;const PopupMenu = imports.ui.popupMenu;const PanelMenu = imports.ui.panelMenu;const Gettext = imports.gettext;const MessageTray = imports.ui.messageTray; const _ = Gettext.gettext; function _myButton() {    this._init();} _myButton.prototype = {    __proto__: PanelMenu.Button.prototype,     _init: function() {        PanelMenu.Button.prototype._init.call(this, 0.0);        this._label = new St.Label({ style_class: 'panel-label', text: _("HelloWorld Button") });        this.actor.set_child(this._label);        Main.panel._centerBox.add(this.actor, { y_fill: true });         this._myMenu = new PopupMenu.PopupMenuItem(_('HelloWorld MenuItem'));        this.menu.addMenuItem(this._myMenu);        this._myMenu.connect('activate', Lang.bind(this, _showHello));    },     _onDestroy: function() {}}; function _showHello() {     let text = new St.Label({ style_class: 'helloworld-label', text: _("Hello, world!") });    let monitor = global.get_primary_monitor();     global.stage.add_actor(text);    text.set_position(Math.floor (monitor.width / 2 - text.width / 2),                      Math.floor(monitor.height / 2 - text.height / 2));     Mainloop.timeout_add(3000, function () { text.destroy(); });} function main(extensionMeta) {     let userExtensionLocalePath = extensionMeta.path + '/locale';    Gettext.bindtextdomain("helloworld", userExtensionLocalePath);    Gettext.textdomain("helloworld");     let _myPanelButton = new _myButton();}


Here is the modified stylesheet.css

010203040506070809101112131415.panel-label {    padding: .4em 1.75em;    font-size: 10.5pt;    color: #cccccc;    font-weight: bold;} .helloworld-label {    font-size: 36px;    font-weight: bold;    color: #ffffff;    background-color: rgba(10,10,10,0.7);    border-radius: 15px;    margin: 50px;    padding: 50px;

Example 6:

This example demonstrates how to modify our helloworld extension to change the hotspot button to display the Fedora logo in the upper left corner instead of the string Activities.

Here is the modified extensions.js. As you can see it contains only a few lines of JavaScript.

01020304050607080910111213const St = imports.gi.St;const Main = imports.ui.main; function main() {    hotCornerButton = Main.panel.button;    let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR, icon_size: hotCornerButton.height, icon_name: 'fedora-logo-icon' });   let box = new St.BoxLayout();   box.add_actor(logo);    Main.panel.button.set_child(box);}


No stylesheet.css is required as this particular extension is not using any presentation markup.

Example 7:

This example demonstrates how to remove the Computer Accessibility (AKA a11y icon and menu from the status tray in the panel.

Consider the following extensions.js. As you can see it contains only a few lines of JavaScript.

123456const Panel = imports.ui.panel; function main() {    Panel.STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['a11y'] = '';}


No stylesheet.css is required since the extension uses no presentation markup. This solution works. You no longer see the a11y status icon. However a SystemStatusButton object (see panelMenu.js ) is left dangling. A better approach is to do something like the following:

01020304050607080910const Panel = imports.ui.panel; function main() {     let index = Panel.STANDARD_TRAY_ICON_ORDER.indexOf('a11y');    if (index >= 0) {        Panel.STANDARD_TRAY_ICON_ORDER.splice(index, 1);    }    delete Panel.STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['a11y'];}


This extension is available as noa11y-1.0.tar.gz in the extensions area of my website.

Turning now to the question of how to determine which GNOME Shell extensions are loaded and what information is available about the state of such extensions. Currently no tool is provided in a distribution to list information about extensions.

Here is a small Python utility which lists the details of all your GNOME Shell extensions on the command line:

010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778#!/usr/bin/python## Copyright (c) 2011 Finnbarr P. Murphy## This utility is free software. You can redistribute it and/or# modify it under the terms of the GNU General Public License as# published by the Free Software Foundation, either version 2 of# the License, or (at your option) any later version.## This utility is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.## See for full text of the license.# import os.pathimport json from gi.repository import Giofrom gi.repository import GLib state = { 1:"enabled", 2:"disabled", 3:"error", 4:"out of date"}type  = { 1:"system", 2:"per user"} class GnomeShell:     def __init__(self):        d = Gio.bus_get_sync(Gio.BusType.SESSION, None)        self._proxy = Gio.DBusProxy.new_sync(                            d, 0, None,                            'org.gnome.Shell',                            '/org/gnome/Shell',                            'org.gnome.Shell',                            None)     def execute_javascript(self, js):        result, output = self._proxy.Eval('(s)', js)        if not result:            raise Exception(output)        return output     def list_extensions(self):        out = self.execute_javascript('const ExtensionSystem = imports.ui.extensionSystem; ExtensionSystem.extensionMeta')        return json.loads(out)     def get_shell_version(self):        out = self.execute_javascript('const Config = imports.misc.config; version = Config.PACKAGE_VERSION')        return out     def get_gjs_version(self):        out = self.execute_javascript('const Config = imports.misc.config; version = Config.GJS_VERSION')        return out if __name__ == "__main__":    s = GnomeShell()     print    print "Shell Version:", s.get_shell_version()    print "  GJS Version:",  s.get_gjs_version()    print     l = s.list_extensions()    for k, v in l.iteritems():        print 'Extension: %s' % k        print "-" * (len(k) + 11)        for k1, v1 in v.iteritems():            if k1 == 'state':                print '%15s: %s (%s)' % (k1, v1, state[v1])            elif k1 == 'type':                print '%15s: %s (%s)' % (k1, v1, type[v1])            elif k1 == 'shell-version':                print '%15s:' % k1,                print ", ".join(v1)            else:                print '%15s: %s' % (k1, v1)        print


Here is what is outputted for our HelloWorld example extension:

Shell Version: "3.0.0"  
GJS Version: "0.7.13"

Extension: helloworld@example.com
---------------------------------
description: My first GNOME 3 Shell extension
shell-version: 2.91.91, 2.91.92, 2.91.93
       name: helloworld
        url: http://example.com
      state: 1 (enabled)
       path: /home/fpm/.local/share/gnome-shell/extensions/helloworld@example.com
       type: 2 (per user)
       uuid: helloworld@example.com


You can also see which extensions are loaded using the Looking Glass debugger which is accessible via Alt-F2 lg. Unfortunately, the current version of Looking Glass displays very little information about extensions other than the fact that they are loaded, but that is easily remedied by adding a few lines of JavaScript to /usr/share/gnome-shell/js/ui/lookingGlass.js.

01020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546$ diff lookingGlass.js.org lookingGlass.js621a622,631>     _typeToString: function(extensionType) {>         switch (extensionType) {>             case ExtensionSystem.ExtensionType.SYSTEM:>                 return _("System");>             case ExtensionSystem.ExtensionType.PER_USER:>                 return _("Per User");>         }>         return 'Unknown';>     },>637a648>         let line1Box = new St.BoxLayout();640d650<         box.add(name, { expand: true });642,643c652,655<                                          text: meta.description });<         box.add(description, { expand: true });--->                                          text: "  " + meta.description });>         line1Box.add(name, { expand: false });>         line1Box.add(description, { expand: false });>         box.add(line1Box);645,647d656<         let metaBox = new St.BoxLayout();<         box.add(metaBox);<         let stateString = this._stateToString(meta.state);649c658,667<                                    text: this._stateToString(meta.state) });--->                                    text: "  State: " + this._stateToString(meta.state)+", " });>         let type = new St.Label({ style_class: 'lg-extension-state',>                                    text: "Type: " + this._typeToString(meta.type)+", " });>         let uuid = new St.Label({ style_class: 'lg-extension-state',>                                    text: "UUID: " + meta.uuid });>>         let metaDataBox = new St.BoxLayout();>         metaDataBox.add(state, { expand: false });>         metaDataBox.add(type, { expand: false });>         metaDataBox.add(uuid, { expand: false });650a669,670>         let metaBox = new St.BoxLayout();>         box.add(metaBox);666a687,690>         actionsBox.add(metaDataBox);


Here is what is displayed by the modified Looking Glass for our HelloWorld extension:

How do you disable or enable installed extensions? By default, all extensions are enabled provided they match the current GNOME Shell version number (and the gjs version number if one is provided in metadata.json.) You can disable extensions from the command line using the gsettings utility. You should also be able to disable extensions using dconf-editor but this utility is broken as of the date of this post (and seems to be always broken for some reason or other) so I cannot test it. At present there is no specific GUI-based utility to disable or enable extensions.

$ gsettings list-recursively  
org.gnome.shell org.gnome.shell command-history @as []
org.gnome.shell development-tools true
org.gnome.shell disabled-extensions @as []
org.gnome.shell disabled-open-search-providers @as []
org.gnome.shell enable-app-monitoring true
org.gnome.shell favorite-apps ['mozilla-firefox.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'openoffice.org-writer.desktop', 'nautilus.desktop']
org.gnome.shell looking-glass-history @as []
org.gnome.shell.calendar show-weekdate false
org.gnome.shell.clock show-date false
org.gnome.shell.clock show-seconds false
org.gnome.shell.recorder file-extension 'webm'
org.gnome.shell.recorder framerate 15
org.gnome.shell.recorder pipeline ''
[root@ultra noarch]#


The requisite key is disabled-extensions

$ gsettings get org.gnome.shell disabled-extensions 
@as []


The @as [] syntax is outputted whenever there are no disabled GNOME Shell extensions. This indicates a serialized GVariant. A GVariant is a variant datatype; it stores a value along with the type of that value.

To disable an extension, simply add the UUID of the extension to the disabled-extensions key, logout and log back in, or reload the GNOME Shell using Alt-F2 r. Note that disabling an extension does not stop it operating once it has been loaded into the GNOME Shell; it merely stops it being loaded in the first place.

$ gsettings set org.gnome.shell disabled-extensions "['helloworld@example.com']" 


By the way, gsettings does not handle incrementally adding an extensions’ UUID to the disabled-extensions key nor does it overwrite or remove existing values. You first have to reset the key and then set the key with the new values.

$ gsettngs reset org.gnome.shell disabled-extensions 
$ gsettings set org.gnome.shell disabled-extensions "['helloworld@gnome.org']"

Recently an official repository for GNOME Shell extensions was created by Giovanni Campagna. As of the date of this post it includes the following extensions:

  • alternate-tab: provides the classic GNOME Alt+Tab functionality.
  • alternative-status-menu: replaces the status menu with one featuring separate Suspend and Power Off menu options.
  • auto-move-windows: assigns a specific workspace to each application as soon as it creates a window, in a configurable manner.
  • dock: displays a docked task switcher on the right side of your screen.
  • example: a minimal example illustrating how to write extensions.
  • gajim: provides integration with Gajim, a Jabber/XMPP instant messaging client.
  • user-theme: loads a user specified shell theme.
  • windowsNavigator: enables keyboard selection of windows and workspaces in overlay mode.
  • xrandr-indicator: enable you to rotate your screen and access display preferences quickly.

Currently these extensions are not available as RPMs but I am sure that it will not take long before somebody does the necessary work to make this happen. If you want to build you own RPMs, here is a .spec file which packages the example shell extension. It assumes that the source files exist in gnome-shell-extensions.tar.gz in the build source directory. You can easily modify the file to use git archive –format=tar to pull the files directly from the extensions git repository and to build a package for other extensions.

Name:           gnome-shell-extensions 
Version: 2.91.6 Release: 1
License: GPLv2+
Group: User Interface/Desktops
Summary: A collection of extensions for the GNOME 3 Shell
Url: http://live.gnome.org/GnomeShell/Extensions
Source: %{name}.tar.gz
BuildRequires: gnome-common
BuildRequires: pkgconfig(gnome-desktop-3.0)
Requires: gnome-shell
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildArch: noarch

%description
GNOME Shell Extensions is a collection of extensions providing
additional optional functionality for the GNOME 3 Shell.

%prep
%setup -q -n %{name}
%build
# Needed because we build from a git checkout
[ -x autogen.sh ] && NOCONFIGURE=1 ./autogen.sh
%configure --enable-extensions="example" --prefix=$HOME/.local

%configure
make %{?_smp_mflags}
%install rm -rf $RPM_BUILD_ROOT
%make_install
%find_lang %{name}

%clean
%{?buildroot:%__rm -rf %{buildroot}}

%post

%postun
%files -f %{name}.lang
%defattr(-,root,root)
%doc README
%dir %{_datadir}/gnome-shell
%{_datadir}/gnome-shell/extensions/
%{_datadir}/glib-2.0/schemas/

%changelog
*Tue Mar 29 2011 1
-- Initial Build


I am going to assume that you know how to build RPMs. Since the GNOME Shell and, by extension (bad pun?), extensions are still a moving target at present, you will probably have to make minor changes to the above .spec file to meet your specific requirements and to conform to changes in the extensions repository. A word of caution however – if you build and install all the shell extensions that are in the repository at the one time, you will most certainly break GNOME Shell.

What are my thoughts on an architecture and framework for extensions? Based on my experience with developing extensions for Mozilla Firefox, WordPress and suchlike, I believe that:

  • Each extension should be packaged separately to allow for individual installation, updating or removal.
  • Extensions do not need to be packaged as RPMs but should be compressed into some kind of tarball or zip file. An extension installation tool i(possibly part of the GNOME Shell, should unpack the extension tarball, do some sanity checking, and then install the extension.
  • All files, including message catalogs, images, and icons, for an extension should live under the extension top directory.
  • There needs to be a GUI for listing, installing, disabling, enabling and removing extensions.
  • There needs to be a better version checking mechanism in extensionSystem.js. The current code is too restrictive and does not support range checking, i.e. minimum and maximum supported versions.
  • GNOME Shell needs to guarantee some set of public hooks (APIs) that extensions can depend upon.
  • There needs to be a basic validation/testsuite for extensions.
  • An ecosystem needs to be put in place around extensions. Something like addons.mozilla.org.
  • Whether an extension accepted or not should not depend on the whims of a single gatekeeper but solely depend on whether the extension met certain published guidelines.
  • Extensions should be disabled by default on installation to ensure stability of the Shell and require specific user action (white-list?) to enable.
  • There should be some mechanism in place to enable the order of loading of extensions to be specified.

The GNOME Shell is still under active development. It will probably be GNOME 3.2 before it stabilizes to the extent that serious effort will be expended developing an extensions ecosystem. A lot more documentation, tools and infrastructure need to be place before a formal reliable ecosystem for GNOME Shell extensions emerges.

As always, experiment and enjoy the experience!

P.S. If you have found this post via an Internet search, you might be interested to know that I have written a number of other posts in this blog about configuring and extending the GNOME 3 Shell. Most of the extensions that I have written are available here.


http://blog.fpmurphy.com/ 一个很好的关于gnome shell扩展的blog。