Compare commits
1 Commits
wip/gdbus-
...
osk
Author | SHA1 | Date | |
---|---|---|---|
fff607e1a4 |
23
.gitignore
vendored
@ -16,29 +16,11 @@ config.log
|
|||||||
config.status
|
config.status
|
||||||
config
|
config
|
||||||
configure
|
configure
|
||||||
data/50-gnome-shell-*.xml
|
|
||||||
data/gnome-shell.desktop
|
data/gnome-shell.desktop
|
||||||
data/gnome-shell.desktop.in
|
data/gnome-shell.desktop.in
|
||||||
data/gnome-shell-extension-prefs.desktop
|
|
||||||
data/gnome-shell-extension-prefs.desktop.in
|
|
||||||
data/gschemas.compiled
|
data/gschemas.compiled
|
||||||
data/org.gnome.shell.gschema.xml
|
data/org.gnome.shell.gschema.xml
|
||||||
data/org.gnome.shell.gschema.valid
|
data/org.gnome.shell.gschema.valid
|
||||||
data/org.gnome.shell.evolution.calendar.gschema.xml
|
|
||||||
data/org.gnome.shell.evolution.calendar.gschema.valid
|
|
||||||
docs/reference/*/*.args
|
|
||||||
docs/reference/*/*.bak
|
|
||||||
docs/reference/*/*.hierarchy
|
|
||||||
docs/reference/*/*.interfaces
|
|
||||||
docs/reference/*/*.prerequisites
|
|
||||||
docs/reference/*/*.sgml
|
|
||||||
docs/reference/*/*.signals
|
|
||||||
docs/reference/*/*.stamp
|
|
||||||
docs/reference/*/*.txt
|
|
||||||
docs/reference/*/*.types
|
|
||||||
docs/reference/*/html/
|
|
||||||
docs/reference/*/xml/
|
|
||||||
gtk-doc.make
|
|
||||||
js/misc/config.js
|
js/misc/config.js
|
||||||
intltool-extract.in
|
intltool-extract.in
|
||||||
intltool-merge.in
|
intltool-merge.in
|
||||||
@ -51,7 +33,6 @@ po/gnome-shell.pot
|
|||||||
po/*.header
|
po/*.header
|
||||||
po/*.sed
|
po/*.sed
|
||||||
po/*.sin
|
po/*.sin
|
||||||
po/.intltool-merge-cache
|
|
||||||
po/Makefile.in.in
|
po/Makefile.in.in
|
||||||
po/Makevars.template
|
po/Makevars.template
|
||||||
po/POTFILES
|
po/POTFILES
|
||||||
@ -64,17 +45,13 @@ src/*-enum-types.[ch]
|
|||||||
src/*-marshal.[ch]
|
src/*-marshal.[ch]
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/Makefile.in
|
src/Makefile.in
|
||||||
src/calendar-server/evolution-calendar.desktop
|
|
||||||
src/calendar-server/evolution-calendar.desktop.in
|
|
||||||
src/calendar-server/org.gnome.Shell.CalendarServer.service
|
src/calendar-server/org.gnome.Shell.CalendarServer.service
|
||||||
src/gnome-shell
|
src/gnome-shell
|
||||||
src/gnome-shell-calendar-server
|
src/gnome-shell-calendar-server
|
||||||
src/gnome-shell-extension-tool
|
src/gnome-shell-extension-tool
|
||||||
src/gnome-shell-extension-prefs
|
|
||||||
src/gnome-shell-hotplug-sniffer
|
src/gnome-shell-hotplug-sniffer
|
||||||
src/gnome-shell-jhbuild
|
src/gnome-shell-jhbuild
|
||||||
src/gnome-shell-perf-helper
|
src/gnome-shell-perf-helper
|
||||||
src/gnome-shell-perf-tool
|
|
||||||
src/gnome-shell-real
|
src/gnome-shell-real
|
||||||
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
|
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
|
||||||
src/run-js-test
|
src/run-js-test
|
||||||
|
331
HACKING
@ -1,331 +0,0 @@
|
|||||||
Coding guide
|
|
||||||
============
|
|
||||||
|
|
||||||
Our goal is to have all JavaScript code in GNOME follow a consistent style. In
|
|
||||||
a dynamic language like JavaScript, it is essential to be rigorous about style
|
|
||||||
(and unit tests), or you rapidly end up with a spaghetti-code mess.
|
|
||||||
|
|
||||||
A quick note
|
|
||||||
------------
|
|
||||||
|
|
||||||
Life isn't fun if you can't break the rules. If a rule seems unnecessarily
|
|
||||||
restrictive while you're coding, ignore it, and let the patch reviewer decide
|
|
||||||
what to do.
|
|
||||||
|
|
||||||
Indentation and whitespace
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Use four-space indents. Braces are on the same line as their associated
|
|
||||||
statements. You should only omit braces if *both* sides of the statement are
|
|
||||||
on one line.
|
|
||||||
|
|
||||||
* One space after the `function` keyword. No space between the function name
|
|
||||||
* in a declaration or a call. One space before the parens in the `if`
|
|
||||||
* statements, or `while`, or `for` loops.
|
|
||||||
|
|
||||||
function foo(a, b) {
|
|
||||||
let bar;
|
|
||||||
|
|
||||||
if (a > b)
|
|
||||||
bar = do_thing(a);
|
|
||||||
else
|
|
||||||
bar = do_thing(b);
|
|
||||||
|
|
||||||
if (var == 5) {
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
print(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print(20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Semicolons
|
|
||||||
----------
|
|
||||||
|
|
||||||
JavaScript allows omitting semicolons at the end of lines, but don't. Always
|
|
||||||
end statements with a semicolon.
|
|
||||||
|
|
||||||
js2-mode
|
|
||||||
--------
|
|
||||||
|
|
||||||
If using Emacs, do not use js2-mode. It is outdated and hasn't worked for a
|
|
||||||
while. emacs now has a built-in JavaScript mode, js-mode, based on
|
|
||||||
espresso-mode. It is the de facto emacs mode for JavaScript.
|
|
||||||
|
|
||||||
File naming and creation
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
For JavaScript files, use lowerCamelCase-style names, with a `.js` extension.
|
|
||||||
|
|
||||||
We only use C where gjs/gobject-introspection is not available for the task, or
|
|
||||||
where C would be cleaner. To work around limitations in
|
|
||||||
gjs/gobject-introspection itself, add a new method in `shell-util.[ch]`.
|
|
||||||
|
|
||||||
Like many other GNOME projects, we prefix our C source filenames with the
|
|
||||||
library name followed by a dash, e.g. `shell-app-system.c`. Create a
|
|
||||||
`-private.h` header when you want to share code internally in the
|
|
||||||
library. These headers are not installed, distributed or introspected.
|
|
||||||
|
|
||||||
Imports
|
|
||||||
-------
|
|
||||||
|
|
||||||
Use UpperCamelCase when importing modules to distinguish them from ordinary
|
|
||||||
variables, e.g.
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
|
|
||||||
Imports should be categorized into one of two places. The top-most import block
|
|
||||||
should contain only "environment imports". These are either modules from
|
|
||||||
gobject-introspection or modules added by gjs itself.
|
|
||||||
|
|
||||||
The second block of imports should contain only "application imports". These
|
|
||||||
are the JS code that is in the gnome-shell codebase,
|
|
||||||
e.g. `imports.ui.popupMenu`.
|
|
||||||
|
|
||||||
Each import block should be sorted alphabetically. Don't import modules you
|
|
||||||
don't use.
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
The alphabetical ordering should be done independently of the location of the
|
|
||||||
location. Never reference `imports` in actual code.
|
|
||||||
|
|
||||||
Constants
|
|
||||||
---------
|
|
||||||
|
|
||||||
We use CONSTANTS_CASE to define constants. All constants should be directly
|
|
||||||
under the imports:
|
|
||||||
|
|
||||||
const MY_DBUS_INTERFACE = 'org.my.Interface';
|
|
||||||
|
|
||||||
Variable declaration
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Always use either `const` or `let` when defining a variable.
|
|
||||||
|
|
||||||
// Iterating over an array
|
|
||||||
for (let i = 0; i < arr.length; ++i) {
|
|
||||||
let item = arr[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterating over an object's properties
|
|
||||||
for (let prop in someobj) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
If you use "var" then the variable is added to function scope, not block scope.
|
|
||||||
See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/New_in_JavaScript/1.7#Block_scope_with_let_%28Merge_into_let_Statement%29)
|
|
||||||
|
|
||||||
Classes
|
|
||||||
-------
|
|
||||||
|
|
||||||
There are many approaches to classes in JavaScript. We use our own class framework
|
|
||||||
(sigh), which is built in gjs. The advantage is that it supports inheriting from
|
|
||||||
GObjects, although this feature isn't used very often in the Shell itself.
|
|
||||||
|
|
||||||
const IconLabelMenuItem = new Lang.Class({
|
|
||||||
Name: 'IconLabelMenuItem',
|
|
||||||
Extends: PopupMenu.PopupMenuBaseItem,
|
|
||||||
|
|
||||||
_init: function(icon, label) {
|
|
||||||
this.parent({ reactive: false });
|
|
||||||
this.addActor(icon);
|
|
||||||
this.addActor(label);
|
|
||||||
},
|
|
||||||
|
|
||||||
open: function() {
|
|
||||||
log("menu opened!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
|
|
||||||
automatically inherit from Object.
|
|
||||||
|
|
||||||
* Leave a blank line between the "class header" (Name, Extends, and other
|
|
||||||
things) and the "class body" (methods). Leave a blank line between each
|
|
||||||
method.
|
|
||||||
|
|
||||||
* No space before the colon, one space after.
|
|
||||||
|
|
||||||
* No trailing comma after the last item.
|
|
||||||
|
|
||||||
* Make sure to use a semicolon after the closing paren to the class. It's
|
|
||||||
still a giant function call, even though it may resemble a more
|
|
||||||
conventional syntax.
|
|
||||||
|
|
||||||
GObject Introspection
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
GObject Introspection is a powerful feature that allows us to have native
|
|
||||||
bindings for almost any library built around GObject. If a library requires
|
|
||||||
you to inherit from a type to use it, you can do so:
|
|
||||||
|
|
||||||
const MyClutterActor = new Lang.Class({
|
|
||||||
Name: 'MyClutterActor',
|
|
||||||
Extends: Clutter.Actor,
|
|
||||||
|
|
||||||
vfunc_get_preferred_width: function(actor, forHeight) {
|
|
||||||
return [100, 100];
|
|
||||||
},
|
|
||||||
|
|
||||||
vfunc_get_preferred_height: function(actor, forWidth) {
|
|
||||||
return [100, 100];
|
|
||||||
},
|
|
||||||
|
|
||||||
vfunc_paint: function(actor) {
|
|
||||||
let alloc = this.get_allocation_box();
|
|
||||||
Cogl.set_source_color4ub(255, 0, 0, 255);
|
|
||||||
Cogl.rectangle(alloc.x1, alloc.y1,
|
|
||||||
alloc.x2, alloc.y2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Translatable strings, `environment.js`
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
We use gettext to translate the GNOME Shell into all the languages that GNOME
|
|
||||||
supports. The `gettext` function is aliased globally as `_`, you do not need to
|
|
||||||
explicitly import it. This is done through some magic in the
|
|
||||||
[environment.js](http://git.gnome.org/browse/gnome-shell/tree/js/ui/environment.js)
|
|
||||||
file. If you can't find a method that's used, it's probably either in gjs itself
|
|
||||||
or installed on the global object from the Environment.
|
|
||||||
|
|
||||||
Use 'single quotes' for programming strings that should not be translated
|
|
||||||
and "double quotes" for strings that the user may see. This allows us to
|
|
||||||
quickly find untranslated or mistranslated strings by grepping through the
|
|
||||||
sources for double quotes without a gettext call around them.
|
|
||||||
|
|
||||||
`actor` and `_delegate`
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
gjs allows us to set so-called "expando properties" on introspected objects,
|
|
||||||
allowing us to treat them like any other. Because the Shell was built before
|
|
||||||
you could inherit from GTypes natively in JS, we usually have a wrapper class
|
|
||||||
that has a property called `actor`. We call this wrapper class the "delegate".
|
|
||||||
|
|
||||||
We sometimes use expando properties to set a property called `_delegate` on
|
|
||||||
the actor itself:
|
|
||||||
|
|
||||||
const MyClass = new Lang.Class({
|
|
||||||
Name: 'MyClass',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.Button({ text: "This is a button" });
|
|
||||||
this.actor._delegate = this;
|
|
||||||
|
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onClicked: function(actor) {
|
|
||||||
actor.set_label("You clicked the button!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
The 'delegate' property is important for anything which trying to get the
|
|
||||||
delegate object from an associated actor. For instance, the drag and drop
|
|
||||||
system calls the `handleDragOver` function on the delegate of a "drop target"
|
|
||||||
when the user drags an item over it. If you do not set the `_delegate`
|
|
||||||
property, your actor will not be able to be dropped onto.
|
|
||||||
|
|
||||||
Functional style
|
|
||||||
----------------
|
|
||||||
|
|
||||||
JavaScript Array objects offer a lot of common functional programming
|
|
||||||
capabilities such as forEach, map, filter and so on. You can use these when
|
|
||||||
they make sense, but please don't have a spaghetti mess of function programming
|
|
||||||
messed in a procedural style. Use your best judgment.
|
|
||||||
|
|
||||||
Closures
|
|
||||||
--------
|
|
||||||
|
|
||||||
`this` will not be captured in a closure, it is relative to how the closure is
|
|
||||||
invoked, not to the value of this where the closure is created, because "this"
|
|
||||||
is a keyword with a value passed in at function invocation time, it is not a
|
|
||||||
variable that can be captured in closures.
|
|
||||||
|
|
||||||
All closures should be wrapped with a Lang.bind.
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
let closure = Lang.bind(this, function() { this._fnorbate(); });
|
|
||||||
|
|
||||||
A more realistic example would be connecting to a signal on a method of a
|
|
||||||
prototype:
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const FnorbLib = imports.fborbLib;
|
|
||||||
|
|
||||||
const MyClass = new Lang.Class({
|
|
||||||
_init: function() {
|
|
||||||
let fnorb = new FnorbLib.Fnorb();
|
|
||||||
fnorb.connect('frobate', Lang.bind(this, this._onFnorbFrobate));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onFnorbFrobate: function(fnorb) {
|
|
||||||
this._updateFnorb();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object literal syntax
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
In JavaScript, these are equivalent:
|
|
||||||
|
|
||||||
foo = { 'bar': 42 };
|
|
||||||
foo = { bar: 42 };
|
|
||||||
|
|
||||||
and so are these:
|
|
||||||
|
|
||||||
var b = foo['bar'];
|
|
||||||
var b = foo.bar;
|
|
||||||
|
|
||||||
If your usage of an object is like an object, then you're defining "member
|
|
||||||
variables." For member variables, use the no-quotes no-brackets syntax: `{ bar:
|
|
||||||
42 }` `foo.bar`.
|
|
||||||
|
|
||||||
If your usage of an object is like a hash table (and thus conceptually the keys
|
|
||||||
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
|
|
||||||
}`, `foo['bar']`.
|
|
||||||
|
|
||||||
Getters, setters, and Tweener
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Getters and setters should be used when you are dealing with an API that is
|
|
||||||
designed around setting properties, like Tweener. If you want to animate an
|
|
||||||
arbitrary property, create a getter and setter, and use Tweener to animate the
|
|
||||||
property.
|
|
||||||
|
|
||||||
const ANIMATION_TIME = 2000;
|
|
||||||
|
|
||||||
const MyClass = new Lang.Class({
|
|
||||||
Name: 'MyClass',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new St.BoxLayout();
|
|
||||||
this._position = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
get position() {
|
|
||||||
return this._position;
|
|
||||||
},
|
|
||||||
|
|
||||||
set position(value) {
|
|
||||||
this._position = value;
|
|
||||||
this.actor.set_position(value, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let myThing = new MyClass();
|
|
||||||
Tweener.addTween(myThing,
|
|
||||||
{ position: 100,
|
|
||||||
time: ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad' });
|
|
@ -1,7 +1,7 @@
|
|||||||
# Point to our macro directory and pick up user flags from the environment
|
# Point to our macro directory and pick up user flags from the environment
|
||||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
SUBDIRS = data js src browser-plugin tests po man docs
|
SUBDIRS = data js src tests po man
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.project \
|
.project \
|
||||||
@ -13,12 +13,9 @@ EXTRA_DIST = \
|
|||||||
DIST_EXCLUDE = \
|
DIST_EXCLUDE = \
|
||||||
.gitignore \
|
.gitignore \
|
||||||
gnome-shell.doap \
|
gnome-shell.doap \
|
||||||
HACKING \
|
|
||||||
MAINTAINERS \
|
MAINTAINERS \
|
||||||
tools/build/*
|
tools/build/*
|
||||||
|
|
||||||
distcheck-hook:
|
distcheck-hook:
|
||||||
@echo "Checking disted files against files in git"
|
@echo "Checking disted files against files in git"
|
||||||
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
|
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
mozillalibdir = $(BROWSER_PLUGIN_DIR)
|
|
||||||
|
|
||||||
mozillalib_LTLIBRARIES = libgnome-shell-browser-plugin.la
|
|
||||||
|
|
||||||
libgnome_shell_browser_plugin_la_LDFLAGS = -module -avoid-version -no-undefined
|
|
||||||
|
|
||||||
libgnome_shell_browser_plugin_la_LIBADD = \
|
|
||||||
$(BROWSER_PLUGIN_LIBS)
|
|
||||||
|
|
||||||
libgnome_shell_browser_plugin_la_SOURCES = \
|
|
||||||
browser-plugin.c \
|
|
||||||
npapi/npapi.h \
|
|
||||||
npapi/npfunctions.h \
|
|
||||||
npapi/npruntime.h \
|
|
||||||
npapi/nptypes.h
|
|
||||||
|
|
||||||
libgnome_shell_browser_plugin_la_CFLAGS = \
|
|
||||||
$(BROWSER_PLUGIN_CFLAGS) \
|
|
||||||
-DG_DISABLE_DEPRECATED \
|
|
||||||
-DG_LOG_DOMAIN=\"GnomeShellBrowserPlugin\"
|
|
@ -1,17 +0,0 @@
|
|||||||
The GNOME Shell Browser Plugin provides integration with gnome-shell and the
|
|
||||||
corresponding extensions repository, codenamed "SweetTooth". The plugin allows
|
|
||||||
the extensions repository to provide good integration, letting the website
|
|
||||||
know which extensions are enabled and disabled, and allowing the website to
|
|
||||||
enable, disable and install them.
|
|
||||||
|
|
||||||
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
|
|
||||||
product.
|
|
||||||
|
|
||||||
License
|
|
||||||
=======
|
|
||||||
The GNOME Shell Browser Plugin, like GNOME Shell itself is distributed under
|
|
||||||
the GNU General Public License, version 2 or later. The plugin also contains
|
|
||||||
header files from the "NPAPI SDK" project, tri-licensed under MPL 1.1, GPL 2.0
|
|
||||||
and LGPL 2.1. These headers are third-party sources and can be retrieved from:
|
|
||||||
|
|
||||||
http://code.google.com/p/npapi-sdk/
|
|
@ -1,893 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef npapi_h_
|
|
||||||
#define npapi_h_
|
|
||||||
|
|
||||||
#if defined(__OS2__)
|
|
||||||
#pragma pack(1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nptypes.h"
|
|
||||||
|
|
||||||
#if defined(__OS2__) || defined(OS2)
|
|
||||||
#ifndef XP_OS2
|
|
||||||
#define XP_OS2 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
|
||||||
#include <windef.h>
|
|
||||||
#ifndef XP_WIN
|
|
||||||
#define XP_WIN 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__SYMBIAN32__)
|
|
||||||
#ifndef XP_SYMBIAN
|
|
||||||
#define XP_SYMBIAN 1
|
|
||||||
#undef XP_WIN
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE_CC__) && !defined(XP_UNIX)
|
|
||||||
#ifndef XP_MACOSX
|
|
||||||
#define XP_MACOSX 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX) && defined(__LP64__)
|
|
||||||
#define NP_NO_QUICKDRAW
|
|
||||||
#define NP_NO_CARBON
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
|
||||||
#include <OpenGL/OpenGL.h>
|
|
||||||
#ifndef NP_NO_CARBON
|
|
||||||
#include <Carbon/Carbon.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_UNIX)
|
|
||||||
#include <stdio.h>
|
|
||||||
#if defined(MOZ_X11)
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xutil.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_SYMBIAN)
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QRegion>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* Plugin Version Constants */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#define NP_VERSION_MAJOR 0
|
|
||||||
#define NP_VERSION_MINOR 27
|
|
||||||
|
|
||||||
|
|
||||||
/* The OS/2 version of Netscape uses RC_DATA to define the
|
|
||||||
mime types, file extensions, etc that are required.
|
|
||||||
Use a vertical bar to separate types, end types with \0.
|
|
||||||
FileVersion and ProductVersion are 32bit ints, all other
|
|
||||||
entries are strings that MUST be terminated with a \0.
|
|
||||||
|
|
||||||
AN EXAMPLE:
|
|
||||||
|
|
||||||
RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
|
|
||||||
|
|
||||||
RCDATA NP_INFO_MIMEType { "video/x-video|",
|
|
||||||
"video/x-flick\0" }
|
|
||||||
RCDATA NP_INFO_FileExtents { "avi|",
|
|
||||||
"flc\0" }
|
|
||||||
RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
|
|
||||||
"MMOS2 Flc/Fli player(*.flc)\0" }
|
|
||||||
|
|
||||||
RCDATA NP_INFO_FileVersion { 1,0,0,1 }
|
|
||||||
RCDATA NP_INFO_CompanyName { "Netscape Communications\0" }
|
|
||||||
RCDATA NP_INFO_FileDescription { "NPAVI32 Extension DLL\0"
|
|
||||||
RCDATA NP_INFO_InternalName { "NPAVI32\0" )
|
|
||||||
RCDATA NP_INFO_LegalCopyright { "Copyright Netscape Communications \251 1996\0"
|
|
||||||
RCDATA NP_INFO_OriginalFilename { "NVAPI32.DLL" }
|
|
||||||
RCDATA NP_INFO_ProductName { "NPAVI32 Dynamic Link Library\0" }
|
|
||||||
*/
|
|
||||||
/* RC_DATA types for version info - required */
|
|
||||||
#define NP_INFO_ProductVersion 1
|
|
||||||
#define NP_INFO_MIMEType 2
|
|
||||||
#define NP_INFO_FileOpenName 3
|
|
||||||
#define NP_INFO_FileExtents 4
|
|
||||||
/* RC_DATA types for version info - used if found */
|
|
||||||
#define NP_INFO_FileDescription 5
|
|
||||||
#define NP_INFO_ProductName 6
|
|
||||||
/* RC_DATA types for version info - optional */
|
|
||||||
#define NP_INFO_CompanyName 7
|
|
||||||
#define NP_INFO_FileVersion 8
|
|
||||||
#define NP_INFO_InternalName 9
|
|
||||||
#define NP_INFO_LegalCopyright 10
|
|
||||||
#define NP_INFO_OriginalFilename 11
|
|
||||||
|
|
||||||
#ifndef RC_INVOKED
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* Definition of Basic Types */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
typedef unsigned char NPBool;
|
|
||||||
typedef int16_t NPError;
|
|
||||||
typedef int16_t NPReason;
|
|
||||||
typedef char* NPMIMEType;
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* Structures and definitions */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if !defined(__LP64__)
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
#pragma options align=mac68k
|
|
||||||
#endif
|
|
||||||
#endif /* __LP64__ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NPP is a plug-in's opaque instance handle
|
|
||||||
*/
|
|
||||||
typedef struct _NPP
|
|
||||||
{
|
|
||||||
void* pdata; /* plug-in private data */
|
|
||||||
void* ndata; /* netscape private data */
|
|
||||||
} NPP_t;
|
|
||||||
|
|
||||||
typedef NPP_t* NPP;
|
|
||||||
|
|
||||||
typedef struct _NPStream
|
|
||||||
{
|
|
||||||
void* pdata; /* plug-in private data */
|
|
||||||
void* ndata; /* netscape private data */
|
|
||||||
const char* url;
|
|
||||||
uint32_t end;
|
|
||||||
uint32_t lastmodified;
|
|
||||||
void* notifyData;
|
|
||||||
const char* headers; /* Response headers from host.
|
|
||||||
* Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
|
|
||||||
* Used for HTTP only; NULL for non-HTTP.
|
|
||||||
* Available from NPP_NewStream onwards.
|
|
||||||
* Plugin should copy this data before storing it.
|
|
||||||
* Includes HTTP status line and all headers,
|
|
||||||
* preferably verbatim as received from server,
|
|
||||||
* headers formatted as in HTTP ("Header: Value"),
|
|
||||||
* and newlines (\n, NOT \r\n) separating lines.
|
|
||||||
* Terminated by \n\0 (NOT \n\n\0). */
|
|
||||||
} NPStream;
|
|
||||||
|
|
||||||
typedef struct _NPByteRange
|
|
||||||
{
|
|
||||||
int32_t offset; /* negative offset means from the end */
|
|
||||||
uint32_t length;
|
|
||||||
struct _NPByteRange* next;
|
|
||||||
} NPByteRange;
|
|
||||||
|
|
||||||
typedef struct _NPSavedData
|
|
||||||
{
|
|
||||||
int32_t len;
|
|
||||||
void* buf;
|
|
||||||
} NPSavedData;
|
|
||||||
|
|
||||||
typedef struct _NPRect
|
|
||||||
{
|
|
||||||
uint16_t top;
|
|
||||||
uint16_t left;
|
|
||||||
uint16_t bottom;
|
|
||||||
uint16_t right;
|
|
||||||
} NPRect;
|
|
||||||
|
|
||||||
typedef struct _NPSize
|
|
||||||
{
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
} NPSize;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NPFocusNext = 0,
|
|
||||||
NPFocusPrevious = 1
|
|
||||||
} NPFocusDirection;
|
|
||||||
|
|
||||||
/* Return values for NPP_HandleEvent */
|
|
||||||
#define kNPEventNotHandled 0
|
|
||||||
#define kNPEventHandled 1
|
|
||||||
/* Exact meaning must be spec'd in event model. */
|
|
||||||
#define kNPEventStartIME 2
|
|
||||||
|
|
||||||
#if defined(XP_UNIX)
|
|
||||||
/*
|
|
||||||
* Unix specific structures and definitions
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback Structures.
|
|
||||||
*
|
|
||||||
* These are used to pass additional platform specific information.
|
|
||||||
*/
|
|
||||||
enum {
|
|
||||||
NP_SETWINDOW = 1,
|
|
||||||
NP_PRINT
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int32_t type;
|
|
||||||
} NPAnyCallbackStruct;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int32_t type;
|
|
||||||
#if defined(MOZ_X11)
|
|
||||||
Display* display;
|
|
||||||
Visual* visual;
|
|
||||||
Colormap colormap;
|
|
||||||
unsigned int depth;
|
|
||||||
#endif
|
|
||||||
} NPSetWindowCallbackStruct;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int32_t type;
|
|
||||||
FILE* fp;
|
|
||||||
} NPPrintCallbackStruct;
|
|
||||||
|
|
||||||
#endif /* XP_UNIX */
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
typedef enum {
|
|
||||||
#ifndef NP_NO_QUICKDRAW
|
|
||||||
NPDrawingModelQuickDraw = 0,
|
|
||||||
#endif
|
|
||||||
NPDrawingModelCoreGraphics = 1,
|
|
||||||
NPDrawingModelOpenGL = 2,
|
|
||||||
NPDrawingModelCoreAnimation = 3,
|
|
||||||
NPDrawingModelInvalidatingCoreAnimation = 4
|
|
||||||
} NPDrawingModel;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
#ifndef NP_NO_CARBON
|
|
||||||
NPEventModelCarbon = 0,
|
|
||||||
#endif
|
|
||||||
NPEventModelCocoa = 1
|
|
||||||
} NPEventModel;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following masks are applied on certain platforms to NPNV and
|
|
||||||
* NPPV selectors that pass around pointers to COM interfaces. Newer
|
|
||||||
* compilers on some platforms may generate vtables that are not
|
|
||||||
* compatible with older compilers. To prevent older plugins from
|
|
||||||
* not understanding a new browser's ABI, these masks change the
|
|
||||||
* values of those selectors on those platforms. To remain backwards
|
|
||||||
* compatible with different versions of the browser, plugins can
|
|
||||||
* use these masks to dynamically determine and use the correct C++
|
|
||||||
* ABI that the browser is expecting. This does not apply to Windows
|
|
||||||
* as Microsoft's COM ABI will likely not change.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NP_ABI_GCC3_MASK 0x10000000
|
|
||||||
/*
|
|
||||||
* gcc 3.x generated vtables on UNIX and OSX are incompatible with
|
|
||||||
* previous compilers.
|
|
||||||
*/
|
|
||||||
#if (defined(XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
|
|
||||||
#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
|
|
||||||
#else
|
|
||||||
#define _NP_ABI_MIXIN_FOR_GCC3 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
#define NP_ABI_MACHO_MASK 0x01000000
|
|
||||||
#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
|
|
||||||
#else
|
|
||||||
#define _NP_ABI_MIXIN_FOR_MACHO 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List of variable names for which NPP_GetValue shall be implemented
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
NPPVpluginNameString = 1,
|
|
||||||
NPPVpluginDescriptionString,
|
|
||||||
NPPVpluginWindowBool,
|
|
||||||
NPPVpluginTransparentBool,
|
|
||||||
NPPVjavaClass,
|
|
||||||
NPPVpluginWindowSize,
|
|
||||||
NPPVpluginTimerInterval,
|
|
||||||
NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
|
|
||||||
NPPVpluginScriptableIID = 11,
|
|
||||||
NPPVjavascriptPushCallerBool = 12,
|
|
||||||
NPPVpluginKeepLibraryInMemory = 13,
|
|
||||||
NPPVpluginNeedsXEmbed = 14,
|
|
||||||
|
|
||||||
/* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14.
|
|
||||||
*/
|
|
||||||
NPPVpluginScriptableNPObject = 15,
|
|
||||||
|
|
||||||
/* Get the plugin value (as \0-terminated UTF-8 string data) for
|
|
||||||
* form submission if the plugin is part of a form. Use
|
|
||||||
* NPN_MemAlloc() to allocate memory for the string data. Introduced
|
|
||||||
* in NPAPI minor version 15.
|
|
||||||
*/
|
|
||||||
NPPVformValue = 16,
|
|
||||||
|
|
||||||
NPPVpluginUrlRequestsDisplayedBool = 17,
|
|
||||||
|
|
||||||
/* Checks if the plugin is interested in receiving the http body of
|
|
||||||
* all http requests (including failed ones, http status != 200).
|
|
||||||
*/
|
|
||||||
NPPVpluginWantsAllNetworkStreams = 18,
|
|
||||||
|
|
||||||
/* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
|
|
||||||
NPPVpluginNativeAccessibleAtkPlugId = 19,
|
|
||||||
|
|
||||||
/* Checks to see if the plug-in would like the browser to load the "src" attribute. */
|
|
||||||
NPPVpluginCancelSrcStream = 20,
|
|
||||||
|
|
||||||
NPPVsupportsAdvancedKeyHandling = 21,
|
|
||||||
|
|
||||||
NPPVpluginUsesDOMForCursorBool = 22
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
/* Used for negotiating drawing models */
|
|
||||||
, NPPVpluginDrawingModel = 1000
|
|
||||||
/* Used for negotiating event models */
|
|
||||||
, NPPVpluginEventModel = 1001
|
|
||||||
/* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
|
|
||||||
, NPPVpluginCoreAnimationLayer = 1003
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
|
||||||
, NPPVpluginWindowlessLocalBool = 2002
|
|
||||||
#endif
|
|
||||||
} NPPVariable;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* List of variable names for which NPN_GetValue should be implemented.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
NPNVxDisplay = 1,
|
|
||||||
NPNVxtAppContext,
|
|
||||||
NPNVnetscapeWindow,
|
|
||||||
NPNVjavascriptEnabledBool,
|
|
||||||
NPNVasdEnabledBool,
|
|
||||||
NPNVisOfflineBool,
|
|
||||||
|
|
||||||
NPNVserviceManager = (10 | NP_ABI_MASK),
|
|
||||||
NPNVDOMElement = (11 | NP_ABI_MASK),
|
|
||||||
NPNVDOMWindow = (12 | NP_ABI_MASK),
|
|
||||||
NPNVToolkit = (13 | NP_ABI_MASK),
|
|
||||||
NPNVSupportsXEmbedBool = 14,
|
|
||||||
|
|
||||||
/* Get the NPObject wrapper for the browser window. */
|
|
||||||
NPNVWindowNPObject = 15,
|
|
||||||
|
|
||||||
/* Get the NPObject wrapper for the plugins DOM element. */
|
|
||||||
NPNVPluginElementNPObject = 16,
|
|
||||||
|
|
||||||
NPNVSupportsWindowless = 17,
|
|
||||||
|
|
||||||
NPNVprivateModeBool = 18,
|
|
||||||
|
|
||||||
NPNVsupportsAdvancedKeyHandling = 21
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
/* Used for negotiating drawing models */
|
|
||||||
, NPNVpluginDrawingModel = 1000
|
|
||||||
#ifndef NP_NO_QUICKDRAW
|
|
||||||
, NPNVsupportsQuickDrawBool = 2000
|
|
||||||
#endif
|
|
||||||
, NPNVsupportsCoreGraphicsBool = 2001
|
|
||||||
, NPNVsupportsOpenGLBool = 2002
|
|
||||||
, NPNVsupportsCoreAnimationBool = 2003
|
|
||||||
, NPNVsupportsInvalidatingCoreAnimationBool = 2004
|
|
||||||
#ifndef NP_NO_CARBON
|
|
||||||
, NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
|
|
||||||
#endif
|
|
||||||
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
|
|
||||||
, NPNVsupportsUpdatedCocoaTextInputBool = 3002 /* TRUE if the browser supports the updated
|
|
||||||
Cocoa text input specification. */
|
|
||||||
, NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
|
|
||||||
CA model compositing */
|
|
||||||
#endif
|
|
||||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
|
||||||
, NPNVSupportsWindowlessLocal = 2002
|
|
||||||
#endif
|
|
||||||
} NPNVariable;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NPNURLVCookie = 501,
|
|
||||||
NPNURLVProxy
|
|
||||||
} NPNURLVariable;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The type of Toolkit the widgets use
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
NPNVGtk12 = 1,
|
|
||||||
NPNVGtk2
|
|
||||||
} NPNToolkitType;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The type of a NPWindow - it specifies the type of the data structure
|
|
||||||
* returned in the window field.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
NPWindowTypeWindow = 1,
|
|
||||||
NPWindowTypeDrawable
|
|
||||||
} NPWindowType;
|
|
||||||
|
|
||||||
typedef struct _NPWindow
|
|
||||||
{
|
|
||||||
void* window; /* Platform specific window handle */
|
|
||||||
/* OS/2: x - Position of bottom left corner */
|
|
||||||
/* OS/2: y - relative to visible netscape window */
|
|
||||||
int32_t x; /* Position of top left corner relative */
|
|
||||||
int32_t y; /* to a netscape page. */
|
|
||||||
uint32_t width; /* Maximum window size */
|
|
||||||
uint32_t height;
|
|
||||||
NPRect clipRect; /* Clipping rectangle in port coordinates */
|
|
||||||
#if (defined(XP_UNIX) || defined(XP_SYMBIAN)) && !defined(XP_MACOSX)
|
|
||||||
void * ws_info; /* Platform-dependent additional data */
|
|
||||||
#endif /* XP_UNIX */
|
|
||||||
NPWindowType type; /* Is this a window or a drawable? */
|
|
||||||
} NPWindow;
|
|
||||||
|
|
||||||
typedef struct _NPImageExpose
|
|
||||||
{
|
|
||||||
char* data; /* image pointer */
|
|
||||||
int32_t stride; /* Stride of data image pointer */
|
|
||||||
int32_t depth; /* Depth of image pointer */
|
|
||||||
int32_t x; /* Expose x */
|
|
||||||
int32_t y; /* Expose y */
|
|
||||||
uint32_t width; /* Expose width */
|
|
||||||
uint32_t height; /* Expose height */
|
|
||||||
NPSize dataSize; /* Data buffer size */
|
|
||||||
float translateX; /* translate X matrix value */
|
|
||||||
float translateY; /* translate Y matrix value */
|
|
||||||
float scaleX; /* scale X matrix value */
|
|
||||||
float scaleY; /* scale Y matrix value */
|
|
||||||
} NPImageExpose;
|
|
||||||
|
|
||||||
typedef struct _NPFullPrint
|
|
||||||
{
|
|
||||||
NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
|
|
||||||
NPBool printOne; /* TRUE if plugin should print one copy to default
|
|
||||||
printer */
|
|
||||||
void* platformPrint; /* Platform-specific printing info */
|
|
||||||
} NPFullPrint;
|
|
||||||
|
|
||||||
typedef struct _NPEmbedPrint
|
|
||||||
{
|
|
||||||
NPWindow window;
|
|
||||||
void* platformPrint; /* Platform-specific printing info */
|
|
||||||
} NPEmbedPrint;
|
|
||||||
|
|
||||||
typedef struct _NPPrint
|
|
||||||
{
|
|
||||||
uint16_t mode; /* NP_FULL or NP_EMBED */
|
|
||||||
union
|
|
||||||
{
|
|
||||||
NPFullPrint fullPrint; /* if mode is NP_FULL */
|
|
||||||
NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
|
|
||||||
} print;
|
|
||||||
} NPPrint;
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
#ifndef NP_NO_CARBON
|
|
||||||
typedef EventRecord NPEvent;
|
|
||||||
#endif
|
|
||||||
#elif defined(XP_SYMBIAN)
|
|
||||||
typedef QEvent NPEvent;
|
|
||||||
#elif defined(XP_WIN)
|
|
||||||
typedef struct _NPEvent
|
|
||||||
{
|
|
||||||
uint16_t event;
|
|
||||||
uintptr_t wParam;
|
|
||||||
uintptr_t lParam;
|
|
||||||
} NPEvent;
|
|
||||||
#elif defined(XP_OS2)
|
|
||||||
typedef struct _NPEvent
|
|
||||||
{
|
|
||||||
uint32_t event;
|
|
||||||
uint32_t wParam;
|
|
||||||
uint32_t lParam;
|
|
||||||
} NPEvent;
|
|
||||||
#elif defined(XP_UNIX) && defined(MOZ_X11)
|
|
||||||
typedef XEvent NPEvent;
|
|
||||||
#else
|
|
||||||
typedef void* NPEvent;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
typedef void* NPRegion;
|
|
||||||
#ifndef NP_NO_QUICKDRAW
|
|
||||||
typedef RgnHandle NPQDRegion;
|
|
||||||
#endif
|
|
||||||
typedef CGPathRef NPCGRegion;
|
|
||||||
#elif defined(XP_WIN)
|
|
||||||
typedef HRGN NPRegion;
|
|
||||||
#elif defined(XP_UNIX) && defined(MOZ_X11)
|
|
||||||
typedef Region NPRegion;
|
|
||||||
#elif defined(XP_SYMBIAN)
|
|
||||||
typedef QRegion* NPRegion;
|
|
||||||
#else
|
|
||||||
typedef void *NPRegion;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct _NPNSString NPNSString;
|
|
||||||
typedef struct _NPNSWindow NPNSWindow;
|
|
||||||
typedef struct _NPNSMenu NPNSMenu;
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
typedef NPNSMenu NPMenu;
|
|
||||||
#else
|
|
||||||
typedef void *NPMenu;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NPCoordinateSpacePlugin = 1,
|
|
||||||
NPCoordinateSpaceWindow,
|
|
||||||
NPCoordinateSpaceFlippedWindow,
|
|
||||||
NPCoordinateSpaceScreen,
|
|
||||||
NPCoordinateSpaceFlippedScreen
|
|
||||||
} NPCoordinateSpace;
|
|
||||||
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
|
|
||||||
#ifndef NP_NO_QUICKDRAW
|
|
||||||
typedef struct NP_Port
|
|
||||||
{
|
|
||||||
CGrafPtr port;
|
|
||||||
int32_t portx; /* position inside the topmost window */
|
|
||||||
int32_t porty;
|
|
||||||
} NP_Port;
|
|
||||||
#endif /* NP_NO_QUICKDRAW */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
|
|
||||||
* as its drawing model.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct NP_CGContext
|
|
||||||
{
|
|
||||||
CGContextRef context;
|
|
||||||
void *window; /* A WindowRef under the Carbon event model. */
|
|
||||||
} NP_CGContext;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
|
|
||||||
* drawing model.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct NP_GLContext
|
|
||||||
{
|
|
||||||
CGLContextObj context;
|
|
||||||
#ifdef NP_NO_CARBON
|
|
||||||
NPNSWindow *window;
|
|
||||||
#else
|
|
||||||
void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */
|
|
||||||
#endif
|
|
||||||
} NP_GLContext;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NPCocoaEventDrawRect = 1,
|
|
||||||
NPCocoaEventMouseDown,
|
|
||||||
NPCocoaEventMouseUp,
|
|
||||||
NPCocoaEventMouseMoved,
|
|
||||||
NPCocoaEventMouseEntered,
|
|
||||||
NPCocoaEventMouseExited,
|
|
||||||
NPCocoaEventMouseDragged,
|
|
||||||
NPCocoaEventKeyDown,
|
|
||||||
NPCocoaEventKeyUp,
|
|
||||||
NPCocoaEventFlagsChanged,
|
|
||||||
NPCocoaEventFocusChanged,
|
|
||||||
NPCocoaEventWindowFocusChanged,
|
|
||||||
NPCocoaEventScrollWheel,
|
|
||||||
NPCocoaEventTextInput
|
|
||||||
} NPCocoaEventType;
|
|
||||||
|
|
||||||
typedef struct _NPCocoaEvent {
|
|
||||||
NPCocoaEventType type;
|
|
||||||
uint32_t version;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint32_t modifierFlags;
|
|
||||||
double pluginX;
|
|
||||||
double pluginY;
|
|
||||||
int32_t buttonNumber;
|
|
||||||
int32_t clickCount;
|
|
||||||
double deltaX;
|
|
||||||
double deltaY;
|
|
||||||
double deltaZ;
|
|
||||||
} mouse;
|
|
||||||
struct {
|
|
||||||
uint32_t modifierFlags;
|
|
||||||
NPNSString *characters;
|
|
||||||
NPNSString *charactersIgnoringModifiers;
|
|
||||||
NPBool isARepeat;
|
|
||||||
uint16_t keyCode;
|
|
||||||
} key;
|
|
||||||
struct {
|
|
||||||
CGContextRef context;
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
double width;
|
|
||||||
double height;
|
|
||||||
} draw;
|
|
||||||
struct {
|
|
||||||
NPBool hasFocus;
|
|
||||||
} focus;
|
|
||||||
struct {
|
|
||||||
NPNSString *text;
|
|
||||||
} text;
|
|
||||||
} data;
|
|
||||||
} NPCocoaEvent;
|
|
||||||
|
|
||||||
#ifndef NP_NO_CARBON
|
|
||||||
/* Non-standard event types that can be passed to HandleEvent */
|
|
||||||
enum NPEventType {
|
|
||||||
NPEventType_GetFocusEvent = (osEvt + 16),
|
|
||||||
NPEventType_LoseFocusEvent,
|
|
||||||
NPEventType_AdjustCursorEvent,
|
|
||||||
NPEventType_MenuCommandEvent,
|
|
||||||
NPEventType_ClippingChangedEvent,
|
|
||||||
NPEventType_ScrollingBeginsEvent = 1000,
|
|
||||||
NPEventType_ScrollingEndsEvent
|
|
||||||
};
|
|
||||||
#endif /* NP_NO_CARBON */
|
|
||||||
|
|
||||||
#endif /* XP_MACOSX */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Values for mode passed to NPP_New:
|
|
||||||
*/
|
|
||||||
#define NP_EMBED 1
|
|
||||||
#define NP_FULL 2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Values for stream type passed to NPP_NewStream:
|
|
||||||
*/
|
|
||||||
#define NP_NORMAL 1
|
|
||||||
#define NP_SEEK 2
|
|
||||||
#define NP_ASFILE 3
|
|
||||||
#define NP_ASFILEONLY 4
|
|
||||||
|
|
||||||
#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Flags for NPP_ClearSiteData.
|
|
||||||
*/
|
|
||||||
#define NP_CLEAR_ALL 0
|
|
||||||
#define NP_CLEAR_CACHE (1 << 0)
|
|
||||||
|
|
||||||
#if !defined(__LP64__)
|
|
||||||
#if defined(XP_MACOSX)
|
|
||||||
#pragma options align=reset
|
|
||||||
#endif
|
|
||||||
#endif /* __LP64__ */
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* Error and Reason Code definitions */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Values of type NPError:
|
|
||||||
*/
|
|
||||||
#define NPERR_BASE 0
|
|
||||||
#define NPERR_NO_ERROR (NPERR_BASE + 0)
|
|
||||||
#define NPERR_GENERIC_ERROR (NPERR_BASE + 1)
|
|
||||||
#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2)
|
|
||||||
#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3)
|
|
||||||
#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4)
|
|
||||||
#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5)
|
|
||||||
#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6)
|
|
||||||
#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7)
|
|
||||||
#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8)
|
|
||||||
#define NPERR_INVALID_PARAM (NPERR_BASE + 9)
|
|
||||||
#define NPERR_INVALID_URL (NPERR_BASE + 10)
|
|
||||||
#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11)
|
|
||||||
#define NPERR_NO_DATA (NPERR_BASE + 12)
|
|
||||||
#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13)
|
|
||||||
#define NPERR_TIME_RANGE_NOT_SUPPORTED (NPERR_BASE + 14)
|
|
||||||
#define NPERR_MALFORMED_SITE (NPERR_BASE + 15)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Values of type NPReason:
|
|
||||||
*/
|
|
||||||
#define NPRES_BASE 0
|
|
||||||
#define NPRES_DONE (NPRES_BASE + 0)
|
|
||||||
#define NPRES_NETWORK_ERR (NPRES_BASE + 1)
|
|
||||||
#define NPRES_USER_BREAK (NPRES_BASE + 2)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't use these obsolete error codes any more.
|
|
||||||
*/
|
|
||||||
#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
|
|
||||||
#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
|
|
||||||
#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Version feature information
|
|
||||||
*/
|
|
||||||
#define NPVERS_HAS_STREAMOUTPUT 8
|
|
||||||
#define NPVERS_HAS_NOTIFICATION 9
|
|
||||||
#define NPVERS_HAS_LIVECONNECT 9
|
|
||||||
#define NPVERS_68K_HAS_LIVECONNECT 11
|
|
||||||
#define NPVERS_HAS_WINDOWLESS 11
|
|
||||||
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
|
|
||||||
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
|
|
||||||
#define NPVERS_HAS_FORM_VALUES 15
|
|
||||||
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
|
|
||||||
#define NPVERS_HAS_RESPONSE_HEADERS 17
|
|
||||||
#define NPVERS_HAS_NPOBJECT_ENUM 18
|
|
||||||
#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
|
|
||||||
#define NPVERS_HAS_ALL_NETWORK_STREAMS 20
|
|
||||||
#define NPVERS_HAS_URL_AND_AUTH_INFO 21
|
|
||||||
#define NPVERS_HAS_PRIVATE_MODE 22
|
|
||||||
#define NPVERS_MACOSX_HAS_COCOA_EVENTS 23
|
|
||||||
#define NPVERS_HAS_ADVANCED_KEY_HANDLING 25
|
|
||||||
#define NPVERS_HAS_URL_REDIRECT_HANDLING 26
|
|
||||||
#define NPVERS_HAS_CLEAR_SITE_DATA 27
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
/* Function Prototypes */
|
|
||||||
/*----------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if defined(__OS2__)
|
|
||||||
#define NP_LOADDS _System
|
|
||||||
#else
|
|
||||||
#define NP_LOADDS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* NPP_* functions are provided by the plugin and called by the navigator. */
|
|
||||||
|
|
||||||
#if defined(XP_UNIX)
|
|
||||||
const char* NPP_GetMIMEDescription(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
|
|
||||||
uint16_t mode, int16_t argc, char* argn[],
|
|
||||||
char* argv[], NPSavedData* saved);
|
|
||||||
NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
|
|
||||||
NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
|
|
||||||
NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
|
|
||||||
NPStream* stream, NPBool seekable,
|
|
||||||
uint16_t* stype);
|
|
||||||
NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
|
|
||||||
NPReason reason);
|
|
||||||
int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
|
|
||||||
int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset,
|
|
||||||
int32_t len, void* buffer);
|
|
||||||
void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
|
|
||||||
const char* fname);
|
|
||||||
void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
|
|
||||||
int16_t NP_LOADDS NPP_HandleEvent(NPP instance, void* event);
|
|
||||||
void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
|
|
||||||
NPReason reason, void* notifyData);
|
|
||||||
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
|
|
||||||
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
|
|
||||||
NPBool NP_LOADDS NPP_GotFocus(NPP instance, NPFocusDirection direction);
|
|
||||||
void NP_LOADDS NPP_LostFocus(NPP instance);
|
|
||||||
void NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData);
|
|
||||||
NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge);
|
|
||||||
char** NP_LOADDS NPP_GetSitesWithData(void);
|
|
||||||
|
|
||||||
/* NPN_* functions are provided by the navigator and called by the plugin. */
|
|
||||||
void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
|
|
||||||
int* netscape_major, int* netscape_minor);
|
|
||||||
NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
|
|
||||||
const char* target, void* notifyData);
|
|
||||||
NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url,
|
|
||||||
const char* target);
|
|
||||||
NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
|
|
||||||
const char* target, uint32_t len,
|
|
||||||
const char* buf, NPBool file,
|
|
||||||
void* notifyData);
|
|
||||||
NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url,
|
|
||||||
const char* target, uint32_t len,
|
|
||||||
const char* buf, NPBool file);
|
|
||||||
NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
|
|
||||||
NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
|
|
||||||
const char* target, NPStream** stream);
|
|
||||||
int32_t NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len,
|
|
||||||
void* buffer);
|
|
||||||
NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream,
|
|
||||||
NPReason reason);
|
|
||||||
void NP_LOADDS NPN_Status(NPP instance, const char* message);
|
|
||||||
const char* NP_LOADDS NPN_UserAgent(NPP instance);
|
|
||||||
void* NP_LOADDS NPN_MemAlloc(uint32_t size);
|
|
||||||
void NP_LOADDS NPN_MemFree(void* ptr);
|
|
||||||
uint32_t NP_LOADDS NPN_MemFlush(uint32_t size);
|
|
||||||
void NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
|
|
||||||
NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable,
|
|
||||||
void *value);
|
|
||||||
NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable,
|
|
||||||
void *value);
|
|
||||||
void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
|
|
||||||
void NP_LOADDS NPN_InvalidateRegion(NPP instance,
|
|
||||||
NPRegion invalidRegion);
|
|
||||||
void NP_LOADDS NPN_ForceRedraw(NPP instance);
|
|
||||||
void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
|
|
||||||
void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
|
|
||||||
void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
|
|
||||||
void (*func) (void *),
|
|
||||||
void *userData);
|
|
||||||
NPError NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable,
|
|
||||||
const char *url, char **value,
|
|
||||||
uint32_t *len);
|
|
||||||
NPError NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable,
|
|
||||||
const char *url, const char *value,
|
|
||||||
uint32_t len);
|
|
||||||
NPError NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
|
|
||||||
const char *protocol,
|
|
||||||
const char *host, int32_t port,
|
|
||||||
const char *scheme,
|
|
||||||
const char *realm,
|
|
||||||
char **username, uint32_t *ulen,
|
|
||||||
char **password,
|
|
||||||
uint32_t *plen);
|
|
||||||
uint32_t NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
|
|
||||||
void NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
|
|
||||||
NPError NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
|
|
||||||
NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
|
|
||||||
NPBool NP_LOADDS NPN_HandleEvent(NPP instance, void *event, NPBool handled);
|
|
||||||
NPBool NP_LOADDS NPN_UnfocusInstance(NPP instance, NPFocusDirection direction);
|
|
||||||
void NP_LOADDS NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* end extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* RC_INVOKED */
|
|
||||||
#if defined(__OS2__)
|
|
||||||
#pragma pack()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* npapi_h_ */
|
|
@ -1,322 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* Netscape Communications Corporation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef npfunctions_h_
|
|
||||||
#define npfunctions_h_
|
|
||||||
|
|
||||||
#ifdef __OS2__
|
|
||||||
#pragma pack(1)
|
|
||||||
#define NP_LOADDS _System
|
|
||||||
#else
|
|
||||||
#define NP_LOADDS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "npapi.h"
|
|
||||||
#include "npruntime.h"
|
|
||||||
|
|
||||||
typedef NPError (* NP_LOADDS NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
|
|
||||||
typedef int32_t (* NP_LOADDS NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
|
|
||||||
typedef int32_t (* NP_LOADDS NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
|
|
||||||
typedef void (* NP_LOADDS NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname);
|
|
||||||
typedef void (* NP_LOADDS NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
|
|
||||||
typedef int16_t (* NP_LOADDS NPP_HandleEventProcPtr)(NPP instance, void* event);
|
|
||||||
typedef void (* NP_LOADDS NPP_URLNotifyProcPtr)(NPP instance, const char* url, NPReason reason, void* notifyData);
|
|
||||||
/* Any NPObjects returned to the browser via NPP_GetValue should be retained
|
|
||||||
by the plugin on the way out. The browser is responsible for releasing. */
|
|
||||||
typedef NPError (* NP_LOADDS NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value);
|
|
||||||
typedef NPBool (* NP_LOADDS NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction);
|
|
||||||
typedef void (* NP_LOADDS NPP_LostFocusPtr)(NPP instance);
|
|
||||||
typedef void (* NP_LOADDS NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData);
|
|
||||||
typedef NPError (* NP_LOADDS NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge);
|
|
||||||
typedef char** (* NP_LOADDS NPP_GetSitesWithDataPtr)(void);
|
|
||||||
|
|
||||||
typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
|
|
||||||
typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
|
|
||||||
typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* url, const char* window, void* notifyData);
|
|
||||||
typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData);
|
|
||||||
typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* url, const char* window);
|
|
||||||
typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file);
|
|
||||||
typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList);
|
|
||||||
typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream);
|
|
||||||
typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer);
|
|
||||||
typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
|
|
||||||
typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message);
|
|
||||||
/* Browser manages the lifetime of the buffer returned by NPN_UserAgent, don't
|
|
||||||
depend on it sticking around and don't free it. */
|
|
||||||
typedef const char* (*NPN_UserAgentProcPtr)(NPP instance);
|
|
||||||
typedef void* (*NPN_MemAllocProcPtr)(uint32_t size);
|
|
||||||
typedef void (*NPN_MemFreeProcPtr)(void* ptr);
|
|
||||||
typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size);
|
|
||||||
typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
|
|
||||||
typedef void* (*NPN_GetJavaEnvProcPtr)(void);
|
|
||||||
typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance);
|
|
||||||
typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect);
|
|
||||||
typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
|
|
||||||
typedef void (*NPN_ForceRedrawProcPtr)(NPP instance);
|
|
||||||
typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr)(const NPUTF8* name);
|
|
||||||
typedef void (*NPN_GetStringIdentifiersProcPtr)(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers);
|
|
||||||
typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr)(int32_t intid);
|
|
||||||
typedef bool (*NPN_IdentifierIsStringProcPtr)(NPIdentifier identifier);
|
|
||||||
typedef NPUTF8* (*NPN_UTF8FromIdentifierProcPtr)(NPIdentifier identifier);
|
|
||||||
typedef int32_t (*NPN_IntFromIdentifierProcPtr)(NPIdentifier identifier);
|
|
||||||
typedef NPObject* (*NPN_CreateObjectProcPtr)(NPP npp, NPClass *aClass);
|
|
||||||
typedef NPObject* (*NPN_RetainObjectProcPtr)(NPObject *obj);
|
|
||||||
typedef void (*NPN_ReleaseObjectProcPtr)(NPObject *obj);
|
|
||||||
typedef bool (*NPN_InvokeProcPtr)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
|
|
||||||
typedef bool (*NPN_InvokeDefaultProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
|
|
||||||
typedef bool (*NPN_EvaluateProcPtr)(NPP npp, NPObject *obj, NPString *script, NPVariant *result);
|
|
||||||
typedef bool (*NPN_GetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result);
|
|
||||||
typedef bool (*NPN_SetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value);
|
|
||||||
typedef bool (*NPN_RemovePropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
|
|
||||||
typedef bool (*NPN_HasPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
|
|
||||||
typedef bool (*NPN_HasMethodProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
|
|
||||||
typedef void (*NPN_ReleaseVariantValueProcPtr)(NPVariant *variant);
|
|
||||||
typedef void (*NPN_SetExceptionProcPtr)(NPObject *obj, const NPUTF8 *message);
|
|
||||||
typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp, NPBool enabled);
|
|
||||||
typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp);
|
|
||||||
typedef bool (*NPN_EnumerateProcPtr)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count);
|
|
||||||
typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, void (*func)(void *), void *userData);
|
|
||||||
typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
|
|
||||||
typedef NPError (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len);
|
|
||||||
typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len);
|
|
||||||
typedef NPError (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32_t port, const char *scheme, const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen);
|
|
||||||
typedef uint32_t (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
|
|
||||||
typedef void (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID);
|
|
||||||
typedef NPError (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu);
|
|
||||||
typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
|
|
||||||
typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled);
|
|
||||||
typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction);
|
|
||||||
typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow);
|
|
||||||
|
|
||||||
typedef struct _NPPluginFuncs {
|
|
||||||
uint16_t size;
|
|
||||||
uint16_t version;
|
|
||||||
NPP_NewProcPtr newp;
|
|
||||||
NPP_DestroyProcPtr destroy;
|
|
||||||
NPP_SetWindowProcPtr setwindow;
|
|
||||||
NPP_NewStreamProcPtr newstream;
|
|
||||||
NPP_DestroyStreamProcPtr destroystream;
|
|
||||||
NPP_StreamAsFileProcPtr asfile;
|
|
||||||
NPP_WriteReadyProcPtr writeready;
|
|
||||||
NPP_WriteProcPtr write;
|
|
||||||
NPP_PrintProcPtr print;
|
|
||||||
NPP_HandleEventProcPtr event;
|
|
||||||
NPP_URLNotifyProcPtr urlnotify;
|
|
||||||
void* javaClass;
|
|
||||||
NPP_GetValueProcPtr getvalue;
|
|
||||||
NPP_SetValueProcPtr setvalue;
|
|
||||||
NPP_GotFocusPtr gotfocus;
|
|
||||||
NPP_LostFocusPtr lostfocus;
|
|
||||||
NPP_URLRedirectNotifyPtr urlredirectnotify;
|
|
||||||
NPP_ClearSiteDataPtr clearsitedata;
|
|
||||||
NPP_GetSitesWithDataPtr getsiteswithdata;
|
|
||||||
} NPPluginFuncs;
|
|
||||||
|
|
||||||
typedef struct _NPNetscapeFuncs {
|
|
||||||
uint16_t size;
|
|
||||||
uint16_t version;
|
|
||||||
NPN_GetURLProcPtr geturl;
|
|
||||||
NPN_PostURLProcPtr posturl;
|
|
||||||
NPN_RequestReadProcPtr requestread;
|
|
||||||
NPN_NewStreamProcPtr newstream;
|
|
||||||
NPN_WriteProcPtr write;
|
|
||||||
NPN_DestroyStreamProcPtr destroystream;
|
|
||||||
NPN_StatusProcPtr status;
|
|
||||||
NPN_UserAgentProcPtr uagent;
|
|
||||||
NPN_MemAllocProcPtr memalloc;
|
|
||||||
NPN_MemFreeProcPtr memfree;
|
|
||||||
NPN_MemFlushProcPtr memflush;
|
|
||||||
NPN_ReloadPluginsProcPtr reloadplugins;
|
|
||||||
NPN_GetJavaEnvProcPtr getJavaEnv;
|
|
||||||
NPN_GetJavaPeerProcPtr getJavaPeer;
|
|
||||||
NPN_GetURLNotifyProcPtr geturlnotify;
|
|
||||||
NPN_PostURLNotifyProcPtr posturlnotify;
|
|
||||||
NPN_GetValueProcPtr getvalue;
|
|
||||||
NPN_SetValueProcPtr setvalue;
|
|
||||||
NPN_InvalidateRectProcPtr invalidaterect;
|
|
||||||
NPN_InvalidateRegionProcPtr invalidateregion;
|
|
||||||
NPN_ForceRedrawProcPtr forceredraw;
|
|
||||||
NPN_GetStringIdentifierProcPtr getstringidentifier;
|
|
||||||
NPN_GetStringIdentifiersProcPtr getstringidentifiers;
|
|
||||||
NPN_GetIntIdentifierProcPtr getintidentifier;
|
|
||||||
NPN_IdentifierIsStringProcPtr identifierisstring;
|
|
||||||
NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
|
|
||||||
NPN_IntFromIdentifierProcPtr intfromidentifier;
|
|
||||||
NPN_CreateObjectProcPtr createobject;
|
|
||||||
NPN_RetainObjectProcPtr retainobject;
|
|
||||||
NPN_ReleaseObjectProcPtr releaseobject;
|
|
||||||
NPN_InvokeProcPtr invoke;
|
|
||||||
NPN_InvokeDefaultProcPtr invokeDefault;
|
|
||||||
NPN_EvaluateProcPtr evaluate;
|
|
||||||
NPN_GetPropertyProcPtr getproperty;
|
|
||||||
NPN_SetPropertyProcPtr setproperty;
|
|
||||||
NPN_RemovePropertyProcPtr removeproperty;
|
|
||||||
NPN_HasPropertyProcPtr hasproperty;
|
|
||||||
NPN_HasMethodProcPtr hasmethod;
|
|
||||||
NPN_ReleaseVariantValueProcPtr releasevariantvalue;
|
|
||||||
NPN_SetExceptionProcPtr setexception;
|
|
||||||
NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
|
|
||||||
NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
|
|
||||||
NPN_EnumerateProcPtr enumerate;
|
|
||||||
NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
|
|
||||||
NPN_ConstructProcPtr construct;
|
|
||||||
NPN_GetValueForURLPtr getvalueforurl;
|
|
||||||
NPN_SetValueForURLPtr setvalueforurl;
|
|
||||||
NPN_GetAuthenticationInfoPtr getauthenticationinfo;
|
|
||||||
NPN_ScheduleTimerPtr scheduletimer;
|
|
||||||
NPN_UnscheduleTimerPtr unscheduletimer;
|
|
||||||
NPN_PopUpContextMenuPtr popupcontextmenu;
|
|
||||||
NPN_ConvertPointPtr convertpoint;
|
|
||||||
NPN_HandleEventPtr handleevent;
|
|
||||||
NPN_UnfocusInstancePtr unfocusinstance;
|
|
||||||
NPN_URLRedirectResponsePtr urlredirectresponse;
|
|
||||||
} NPNetscapeFuncs;
|
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
/*
|
|
||||||
* Mac OS X version(s) of NP_GetMIMEDescription(const char *)
|
|
||||||
* These can be called to retreive MIME information from the plugin dynamically
|
|
||||||
*
|
|
||||||
* Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way
|
|
||||||
* to get mime info from the plugin only on OSX and may not be supported
|
|
||||||
* in furture version -- use NP_GetMIMEDescription instead
|
|
||||||
*/
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kBPSupportedMIMETypesStructVers_1 = 1
|
|
||||||
};
|
|
||||||
typedef struct _BPSupportedMIMETypes
|
|
||||||
{
|
|
||||||
SInt32 structVersion; /* struct version */
|
|
||||||
Handle typeStrings; /* STR# formated handle, allocated by plug-in */
|
|
||||||
Handle infoStrings; /* STR# formated handle, allocated by plug-in */
|
|
||||||
} BPSupportedMIMETypes;
|
|
||||||
OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes *mimeInfo, UInt32 flags);
|
|
||||||
#define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription"
|
|
||||||
typedef const char* (*NP_GetMIMEDescriptionProcPtr)(void);
|
|
||||||
typedef OSErr (*BP_GetSupportedMIMETypesProcPtr)(BPSupportedMIMETypes*, UInt32);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define OSCALL WINAPI
|
|
||||||
#else
|
|
||||||
#if defined(__OS2__)
|
|
||||||
#define OSCALL _System
|
|
||||||
#else
|
|
||||||
#define OSCALL
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(XP_UNIX)
|
|
||||||
/* GCC 3.3 and later support the visibility attribute. */
|
|
||||||
#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
|
|
||||||
#define NP_VISIBILITY_DEFAULT __attribute__((visibility("default")))
|
|
||||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
|
||||||
#define NP_VISIBILITY_DEFAULT __global
|
|
||||||
#else
|
|
||||||
#define NP_VISIBILITY_DEFAULT
|
|
||||||
#endif
|
|
||||||
#define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined (__OS2__)
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
/* plugin meta member functions */
|
|
||||||
#if defined(__OS2__)
|
|
||||||
typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */
|
|
||||||
char *pMimeTypes;
|
|
||||||
char *pFileExtents;
|
|
||||||
char *pFileOpenTemplate;
|
|
||||||
char *pProductName;
|
|
||||||
char *pProductDescription;
|
|
||||||
unsigned long dwProductVersionMS;
|
|
||||||
unsigned long dwProductVersionLS;
|
|
||||||
} NPPluginData;
|
|
||||||
typedef NPError (*NP_GetPluginDataFunc)(NPPluginData*);
|
|
||||||
NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData);
|
|
||||||
#endif
|
|
||||||
typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
|
|
||||||
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs);
|
|
||||||
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*);
|
|
||||||
NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs);
|
|
||||||
typedef NPError (*NP_ShutdownFunc)(void);
|
|
||||||
NPError OSCALL NP_Shutdown(void);
|
|
||||||
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
|
|
||||||
const char* NP_GetMIMEDescription(void);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__OS2__)
|
|
||||||
#pragma pack()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef XP_UNIX
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
typedef char* (*NP_GetPluginVersionFunc)(void);
|
|
||||||
NP_EXPORT(char*) NP_GetPluginVersion(void);
|
|
||||||
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
|
|
||||||
NP_EXPORT(const char*) NP_GetMIMEDescription(void);
|
|
||||||
#ifdef XP_MACOSX
|
|
||||||
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*);
|
|
||||||
NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs);
|
|
||||||
typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
|
|
||||||
NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs);
|
|
||||||
#else
|
|
||||||
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*);
|
|
||||||
NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);
|
|
||||||
#endif
|
|
||||||
typedef NPError (*NP_ShutdownFunc)(void);
|
|
||||||
NP_EXPORT(NPError) NP_Shutdown(void);
|
|
||||||
typedef NPError (*NP_GetValueFunc)(void *, NPPVariable, void *);
|
|
||||||
NP_EXPORT(NPError) NP_GetValue(void *future, NPPVariable aVariable, void *aValue);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* npfunctions_h_ */
|
|
@ -1,393 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
|
|
||||||
* Foundation ("Mozilla") nor the names of their contributors may be used
|
|
||||||
* to endorse or promote products derived from this software without
|
|
||||||
* specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
|
|
||||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
|
|
||||||
* THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef _NP_RUNTIME_H_
|
|
||||||
#define _NP_RUNTIME_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "nptypes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
This API is used to facilitate binding code written in C to script
|
|
||||||
objects. The API in this header does not assume the presence of a
|
|
||||||
user agent. That is, it can be used to bind C code to scripting
|
|
||||||
environments outside of the context of a user agent.
|
|
||||||
|
|
||||||
However, the normal use of the this API is in the context of a
|
|
||||||
scripting environment running in a browser or other user agent.
|
|
||||||
In particular it is used to support the extended Netscape
|
|
||||||
script-ability API for plugins (NP-SAP). NP-SAP is an extension
|
|
||||||
of the Netscape plugin API. As such we have adopted the use of
|
|
||||||
the "NP" prefix for this API.
|
|
||||||
|
|
||||||
The following NP{N|P}Variables were added to the Netscape plugin
|
|
||||||
API (in npapi.h):
|
|
||||||
|
|
||||||
NPNVWindowNPObject
|
|
||||||
NPNVPluginElementNPObject
|
|
||||||
NPPVpluginScriptableNPObject
|
|
||||||
|
|
||||||
These variables are exposed through NPN_GetValue() and
|
|
||||||
NPP_GetValue() (respectively) and are used to establish the
|
|
||||||
initial binding between the user agent and native code. The DOM
|
|
||||||
objects in the user agent can be examined and manipulated using
|
|
||||||
the NPN_ functions that operate on NPObjects described in this
|
|
||||||
header.
|
|
||||||
|
|
||||||
To the extent possible the assumptions about the scripting
|
|
||||||
language used by the scripting environment have been minimized.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define NP_BEGIN_MACRO do {
|
|
||||||
#define NP_END_MACRO } while (0)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Objects (non-primitive data) passed between 'C' and script is
|
|
||||||
always wrapped in an NPObject. The 'interface' of an NPObject is
|
|
||||||
described by an NPClass.
|
|
||||||
*/
|
|
||||||
typedef struct NPObject NPObject;
|
|
||||||
typedef struct NPClass NPClass;
|
|
||||||
|
|
||||||
typedef char NPUTF8;
|
|
||||||
typedef struct _NPString {
|
|
||||||
const NPUTF8 *UTF8Characters;
|
|
||||||
uint32_t UTF8Length;
|
|
||||||
} NPString;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NPVariantType_Void,
|
|
||||||
NPVariantType_Null,
|
|
||||||
NPVariantType_Bool,
|
|
||||||
NPVariantType_Int32,
|
|
||||||
NPVariantType_Double,
|
|
||||||
NPVariantType_String,
|
|
||||||
NPVariantType_Object
|
|
||||||
} NPVariantType;
|
|
||||||
|
|
||||||
typedef struct _NPVariant {
|
|
||||||
NPVariantType type;
|
|
||||||
union {
|
|
||||||
bool boolValue;
|
|
||||||
int32_t intValue;
|
|
||||||
double doubleValue;
|
|
||||||
NPString stringValue;
|
|
||||||
NPObject *objectValue;
|
|
||||||
} value;
|
|
||||||
} NPVariant;
|
|
||||||
|
|
||||||
/*
|
|
||||||
NPN_ReleaseVariantValue is called on all 'out' parameters
|
|
||||||
references. Specifically it is to be called on variants that own
|
|
||||||
their value, as is the case with all non-const NPVariant*
|
|
||||||
arguments after a successful call to any methods (except this one)
|
|
||||||
in this API.
|
|
||||||
|
|
||||||
After calling NPN_ReleaseVariantValue, the type of the variant
|
|
||||||
will be NPVariantType_Void.
|
|
||||||
*/
|
|
||||||
void NPN_ReleaseVariantValue(NPVariant *variant);
|
|
||||||
|
|
||||||
#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void)
|
|
||||||
#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null)
|
|
||||||
#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
|
|
||||||
#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32)
|
|
||||||
#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double)
|
|
||||||
#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String)
|
|
||||||
#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object)
|
|
||||||
|
|
||||||
#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
|
|
||||||
#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue)
|
|
||||||
#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue)
|
|
||||||
#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue)
|
|
||||||
#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue)
|
|
||||||
|
|
||||||
#define VOID_TO_NPVARIANT(_v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Void; \
|
|
||||||
(_v).value.objectValue = NULL; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define NULL_TO_NPVARIANT(_v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Null; \
|
|
||||||
(_v).value.objectValue = NULL; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define BOOLEAN_TO_NPVARIANT(_val, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Bool; \
|
|
||||||
(_v).value.boolValue = !!(_val); \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define INT32_TO_NPVARIANT(_val, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Int32; \
|
|
||||||
(_v).value.intValue = _val; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define DOUBLE_TO_NPVARIANT(_val, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Double; \
|
|
||||||
(_v).value.doubleValue = _val; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define STRINGZ_TO_NPVARIANT(_val, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_String; \
|
|
||||||
NPString str = { _val, (uint32_t)(strlen(_val)) }; \
|
|
||||||
(_v).value.stringValue = str; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define STRINGN_TO_NPVARIANT(_val, _len, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_String; \
|
|
||||||
NPString str = { _val, (uint32_t)(_len) }; \
|
|
||||||
(_v).value.stringValue = str; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
#define OBJECT_TO_NPVARIANT(_val, _v) \
|
|
||||||
NP_BEGIN_MACRO \
|
|
||||||
(_v).type = NPVariantType_Object; \
|
|
||||||
(_v).value.objectValue = _val; \
|
|
||||||
NP_END_MACRO
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Type mappings (JavaScript types have been used for illustration
|
|
||||||
purposes):
|
|
||||||
|
|
||||||
JavaScript to C (NPVariant with type:)
|
|
||||||
undefined NPVariantType_Void
|
|
||||||
null NPVariantType_Null
|
|
||||||
Boolean NPVariantType_Bool
|
|
||||||
Number NPVariantType_Double or NPVariantType_Int32
|
|
||||||
String NPVariantType_String
|
|
||||||
Object NPVariantType_Object
|
|
||||||
|
|
||||||
C (NPVariant with type:) to JavaScript
|
|
||||||
NPVariantType_Void undefined
|
|
||||||
NPVariantType_Null null
|
|
||||||
NPVariantType_Bool Boolean
|
|
||||||
NPVariantType_Int32 Number
|
|
||||||
NPVariantType_Double Number
|
|
||||||
NPVariantType_String String
|
|
||||||
NPVariantType_Object Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void *NPIdentifier;
|
|
||||||
|
|
||||||
/*
|
|
||||||
NPObjects have methods and properties. Methods and properties are
|
|
||||||
identified with NPIdentifiers. These identifiers may be reflected
|
|
||||||
in script. NPIdentifiers can be either strings or integers, IOW,
|
|
||||||
methods and properties can be identified by either strings or
|
|
||||||
integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
|
|
||||||
compared using ==. In case of any errors, the requested
|
|
||||||
NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled
|
|
||||||
by the browser. Plugins do not need to worry about memory management
|
|
||||||
with regards to NPIdentifiers.
|
|
||||||
*/
|
|
||||||
NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
|
|
||||||
void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
|
|
||||||
NPIdentifier *identifiers);
|
|
||||||
NPIdentifier NPN_GetIntIdentifier(int32_t intid);
|
|
||||||
bool NPN_IdentifierIsString(NPIdentifier identifier);
|
|
||||||
|
|
||||||
/*
|
|
||||||
The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
|
|
||||||
*/
|
|
||||||
NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get the integer represented by identifier. If identifier is not an
|
|
||||||
integer identifier, the behaviour is undefined.
|
|
||||||
*/
|
|
||||||
int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
|
|
||||||
|
|
||||||
/*
|
|
||||||
NPObject behavior is implemented using the following set of
|
|
||||||
callback functions.
|
|
||||||
|
|
||||||
The NPVariant *result argument of these functions (where
|
|
||||||
applicable) should be released using NPN_ReleaseVariantValue().
|
|
||||||
*/
|
|
||||||
typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
|
|
||||||
typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj);
|
|
||||||
typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj);
|
|
||||||
typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name);
|
|
||||||
typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name,
|
|
||||||
const NPVariant *args, uint32_t argCount,
|
|
||||||
NPVariant *result);
|
|
||||||
typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj,
|
|
||||||
const NPVariant *args,
|
|
||||||
uint32_t argCount,
|
|
||||||
NPVariant *result);
|
|
||||||
typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
|
|
||||||
typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
|
|
||||||
NPVariant *result);
|
|
||||||
typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
|
|
||||||
const NPVariant *value);
|
|
||||||
typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
|
|
||||||
NPIdentifier name);
|
|
||||||
typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
|
|
||||||
uint32_t *count);
|
|
||||||
typedef bool (*NPConstructFunctionPtr)(NPObject *npobj,
|
|
||||||
const NPVariant *args,
|
|
||||||
uint32_t argCount,
|
|
||||||
NPVariant *result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
NPObjects returned by create, retain, invoke, and getProperty pass
|
|
||||||
a reference count to the caller. That is, the callee adds a
|
|
||||||
reference count which passes to the caller. It is the caller's
|
|
||||||
responsibility to release the returned object.
|
|
||||||
|
|
||||||
NPInvokeFunctionPtr function may return 0 to indicate a void
|
|
||||||
result.
|
|
||||||
|
|
||||||
NPInvalidateFunctionPtr is called by the scripting environment
|
|
||||||
when the native code is shutdown. Any attempt to message a
|
|
||||||
NPObject instance after the invalidate callback has been
|
|
||||||
called will result in undefined behavior, even if the native code
|
|
||||||
is still retaining those NPObject instances. (The runtime
|
|
||||||
will typically return immediately, with 0 or NULL, from an attempt
|
|
||||||
to dispatch to a NPObject, but this behavior should not be
|
|
||||||
depended upon.)
|
|
||||||
|
|
||||||
The NPEnumerationFunctionPtr function may pass an array of
|
|
||||||
NPIdentifiers back to the caller. The callee allocs the memory of
|
|
||||||
the array using NPN_MemAlloc(), and it's the caller's responsibility
|
|
||||||
to release it using NPN_MemFree().
|
|
||||||
*/
|
|
||||||
struct NPClass
|
|
||||||
{
|
|
||||||
uint32_t structVersion;
|
|
||||||
NPAllocateFunctionPtr allocate;
|
|
||||||
NPDeallocateFunctionPtr deallocate;
|
|
||||||
NPInvalidateFunctionPtr invalidate;
|
|
||||||
NPHasMethodFunctionPtr hasMethod;
|
|
||||||
NPInvokeFunctionPtr invoke;
|
|
||||||
NPInvokeDefaultFunctionPtr invokeDefault;
|
|
||||||
NPHasPropertyFunctionPtr hasProperty;
|
|
||||||
NPGetPropertyFunctionPtr getProperty;
|
|
||||||
NPSetPropertyFunctionPtr setProperty;
|
|
||||||
NPRemovePropertyFunctionPtr removeProperty;
|
|
||||||
NPEnumerationFunctionPtr enumerate;
|
|
||||||
NPConstructFunctionPtr construct;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NP_CLASS_STRUCT_VERSION 3
|
|
||||||
|
|
||||||
#define NP_CLASS_STRUCT_VERSION_ENUM 2
|
|
||||||
#define NP_CLASS_STRUCT_VERSION_CTOR 3
|
|
||||||
|
|
||||||
#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
|
|
||||||
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
|
|
||||||
|
|
||||||
#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \
|
|
||||||
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
|
|
||||||
|
|
||||||
struct NPObject {
|
|
||||||
NPClass *_class;
|
|
||||||
uint32_t referenceCount;
|
|
||||||
/*
|
|
||||||
* Additional space may be allocated here by types of NPObjects
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the class has an allocate function, NPN_CreateObject invokes
|
|
||||||
that function, otherwise a NPObject is allocated and
|
|
||||||
returned. This method will initialize the referenceCount member of
|
|
||||||
the NPObject to 1.
|
|
||||||
*/
|
|
||||||
NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Increment the NPObject's reference count.
|
|
||||||
*/
|
|
||||||
NPObject *NPN_RetainObject(NPObject *npobj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Decremented the NPObject's reference count. If the reference
|
|
||||||
count goes to zero, the class's destroy function is invoke if
|
|
||||||
specified, otherwise the object is freed directly.
|
|
||||||
*/
|
|
||||||
void NPN_ReleaseObject(NPObject *npobj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Functions to access script objects represented by NPObject.
|
|
||||||
|
|
||||||
Calls to script objects are synchronous. If a function returns a
|
|
||||||
value, it will be supplied via the result NPVariant
|
|
||||||
argument. Successful calls will return true, false will be
|
|
||||||
returned in case of an error.
|
|
||||||
|
|
||||||
Calls made from plugin code to script must be made from the thread
|
|
||||||
on which the plugin was initialized.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName,
|
|
||||||
const NPVariant *args, uint32_t argCount, NPVariant *result);
|
|
||||||
bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args,
|
|
||||||
uint32_t argCount, NPVariant *result);
|
|
||||||
bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script,
|
|
||||||
NPVariant *result);
|
|
||||||
bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
|
|
||||||
NPVariant *result);
|
|
||||||
bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
|
|
||||||
const NPVariant *value);
|
|
||||||
bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
|
|
||||||
bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
|
|
||||||
bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
|
|
||||||
bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
|
|
||||||
uint32_t *count);
|
|
||||||
bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
|
|
||||||
uint32_t argCount, NPVariant *result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
NPN_SetException may be called to trigger a script exception upon
|
|
||||||
return from entry points into NPObjects. Typical usage:
|
|
||||||
|
|
||||||
NPN_SetException (npobj, message);
|
|
||||||
*/
|
|
||||||
void NPN_SetException(NPObject *npobj, const NPUTF8 *message);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,121 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is mozilla.org code.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* mozilla.org.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Johnny Stenback <jst@mozilla.org> (Original author)
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
#ifndef nptypes_h_
|
|
||||||
#define nptypes_h_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Header file for ensuring that C99 types ([u]int32_t, [u]int64_t and bool) and
|
|
||||||
* true/false macros are available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(WIN32) || defined(OS2)
|
|
||||||
/*
|
|
||||||
* Win32 and OS/2 don't know C99, so define [u]int_16/32/64 here. The bool
|
|
||||||
* is predefined tho, both in C and C++.
|
|
||||||
*/
|
|
||||||
typedef short int16_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef int int32_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
typedef long long int64_t;
|
|
||||||
typedef unsigned long long uint64_t;
|
|
||||||
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
|
|
||||||
/*
|
|
||||||
* AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
|
|
||||||
* but not bool for C.
|
|
||||||
*/
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
|
|
||||||
/*
|
|
||||||
* BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and
|
|
||||||
* u_int32_t.
|
|
||||||
*/
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* BSD/OS ships no header that defines uint32_t, nor bool (for C)
|
|
||||||
*/
|
|
||||||
#if defined(bsdi)
|
|
||||||
typedef u_int32_t uint32_t;
|
|
||||||
typedef u_int64_t uint64_t;
|
|
||||||
|
|
||||||
#if !defined(__cplusplus)
|
|
||||||
typedef int bool;
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* FreeBSD and OpenBSD define uint32_t and bool.
|
|
||||||
*/
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#endif
|
|
||||||
#elif defined(BEOS)
|
|
||||||
#include <inttypes.h>
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* For those that ship a standard C99 stdint.h header file, include
|
|
||||||
* it. Can't do the same for stdbool.h tho, since some systems ship
|
|
||||||
* with a stdbool.h file that doesn't compile!
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
|
|
||||||
#include <stdbool.h>
|
|
||||||
#else
|
|
||||||
/*
|
|
||||||
* GCC 2.91 can't deal with a typedef for bool, but a #define
|
|
||||||
* works.
|
|
||||||
*/
|
|
||||||
#define bool int
|
|
||||||
#define true 1
|
|
||||||
#define false 0
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* nptypes_h_ */
|
|
132
configure.ac
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ(2.63)
|
AC_PREREQ(2.63)
|
||||||
AC_INIT([gnome-shell],[3.7.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
AC_INIT([gnome-shell],[3.1.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||||
@ -9,8 +9,8 @@ AC_CONFIG_AUX_DIR([config])
|
|||||||
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
|
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
|
||||||
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
|
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar foreign])
|
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
|
||||||
AM_MAINTAINER_MODE([enable])
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
@ -36,6 +36,10 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
|
|||||||
|
|
||||||
PKG_PROG_PKG_CONFIG([0.22])
|
PKG_PROG_PKG_CONFIG([0.22])
|
||||||
|
|
||||||
|
# GConf stuff
|
||||||
|
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||||
|
AM_GCONF_SOURCE_2
|
||||||
|
|
||||||
GLIB_GSETTINGS
|
GLIB_GSETTINGS
|
||||||
|
|
||||||
# Get a value to substitute into gnome-shell.in
|
# Get a value to substitute into gnome-shell.in
|
||||||
@ -44,50 +48,44 @@ AC_SUBST(PYTHON)
|
|||||||
|
|
||||||
# We need at least this, since gst_plugin_register_static() was added
|
# We need at least this, since gst_plugin_register_static() was added
|
||||||
# in 0.10.16, but nothing older than 0.10.21 has been tested.
|
# in 0.10.16, but nothing older than 0.10.21 has been tested.
|
||||||
GSTREAMER_MIN_VERSION=0.11.92
|
GSTREAMER_MIN_VERSION=0.10.16
|
||||||
|
|
||||||
recorder_modules=
|
recorder_modules=
|
||||||
build_recorder=false
|
build_recorder=false
|
||||||
AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
|
AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
|
||||||
if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then
|
if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
build_recorder=true
|
build_recorder=true
|
||||||
recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11 gtk+-3.0"
|
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 x11"
|
||||||
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes gl)
|
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes)
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||||
|
|
||||||
CLUTTER_MIN_VERSION=1.11.11
|
CLUTTER_MIN_VERSION=1.7.5
|
||||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||||
GJS_MIN_VERSION=1.33.2
|
GJS_MIN_VERSION=0.7.11
|
||||||
MUTTER_MIN_VERSION=3.7.1
|
MUTTER_MIN_VERSION=3.0.0
|
||||||
GTK_MIN_VERSION=3.3.9
|
GTK_MIN_VERSION=3.0.0
|
||||||
GIO_MIN_VERSION=2.35.0
|
GIO_MIN_VERSION=2.25.9
|
||||||
LIBECAL_MIN_VERSION=3.5.3
|
LIBECAL_MIN_VERSION=2.32.0
|
||||||
LIBEDATASERVER_MIN_VERSION=3.5.3
|
LIBEDATASERVER_MIN_VERSION=1.2.0
|
||||||
LIBEDATASERVERUI_MIN_VERSION=3.5.3
|
LIBEDATASERVERUI_MIN_VERSION=2.91.6
|
||||||
TELEPATHY_GLIB_MIN_VERSION=0.17.5
|
TELEPATHY_GLIB_MIN_VERSION=0.15.3
|
||||||
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
|
TELEPATHY_LOGGER_MIN_VERSION=0.2.4
|
||||||
POLKIT_MIN_VERSION=0.100
|
POLKIT_MIN_VERSION=0.100
|
||||||
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
STARTUP_NOTIFICATION_MIN_VERSION=0.11
|
||||||
GCR_MIN_VERSION=3.3.90
|
|
||||||
GNOME_DESKTOP_REQUIRED_VERSION=3.7.1
|
|
||||||
GNOME_MENUS_REQUIRED_VERSION=3.5.3
|
|
||||||
|
|
||||||
# Collect more than 20 libraries for a prize!
|
# Collect more than 20 libraries for a prize!
|
||||||
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
|
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
|
||||||
libxml-2.0
|
gio-unix-2.0 dbus-glib-1 libxml-2.0
|
||||||
gtk+-3.0 >= $GTK_MIN_VERSION
|
gtk+-3.0 >= $GTK_MIN_VERSION
|
||||||
atk-bridge-2.0
|
|
||||||
libmutter >= $MUTTER_MIN_VERSION
|
libmutter >= $MUTTER_MIN_VERSION
|
||||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||||
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
|
libgnome-menu $recorder_modules gconf-2.0
|
||||||
$recorder_modules
|
|
||||||
gdk-x11-3.0 libsoup-2.4
|
gdk-x11-3.0 libsoup-2.4
|
||||||
gl
|
|
||||||
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
|
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
|
||||||
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
|
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
|
||||||
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
|
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
|
||||||
@ -95,20 +93,25 @@ PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
|
|||||||
libcanberra
|
libcanberra
|
||||||
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
|
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
|
||||||
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
|
telepathy-logger-0.2 >= $TELEPATHY_LOGGER_MIN_VERSION
|
||||||
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
|
polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes)
|
||||||
libnm-glib libnm-util gnome-keyring-1
|
|
||||||
gcr-3 >= $GCR_MIN_VERSION)
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
|
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
|
||||||
|
|
||||||
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
|
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
|
||||||
|
|
||||||
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
|
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
|
||||||
|
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
|
||||||
GNOME_KEYBINDINGS_KEYSDIR=`$PKG_CONFIG --variable keysdir gnome-keybindings`
|
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
|
||||||
AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
|
|
||||||
|
|
||||||
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
|
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
|
||||||
|
JHBUILD_TYPELIBDIR="$INTROSPECTION_TYPELIBDIR"
|
||||||
|
# NM is the only typelib we use that we don't jhbuild
|
||||||
|
PKG_CHECK_EXISTS([libnm-glib >= 0.8.999],
|
||||||
|
[NM_TYPELIBDIR=`$PKG_CONFIG --variable=libdir libnm-glib`/girepository-1.0
|
||||||
|
if test "$INTROSPECTION_TYPELIBDIR" != "$NM_TYPELIBDIR"; then
|
||||||
|
JHBUILD_TYPELIBDIR="$JHBUILD_TYPELIBDIR:$NM_TYPELIBDIR"
|
||||||
|
fi])
|
||||||
|
AC_SUBST(JHBUILD_TYPELIBDIR)
|
||||||
|
|
||||||
saved_CFLAGS=$CFLAGS
|
saved_CFLAGS=$CFLAGS
|
||||||
saved_LIBS=$LIBS
|
saved_LIBS=$LIBS
|
||||||
@ -118,18 +121,17 @@ AC_CHECK_FUNCS(JS_NewGlobalObject XFixesCreatePointerBarrier)
|
|||||||
CFLAGS=$saved_CFLAGS
|
CFLAGS=$saved_CFLAGS
|
||||||
LIBS=$saved_LIBS
|
LIBS=$saved_LIBS
|
||||||
|
|
||||||
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
|
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 gnome-desktop-3.0 >= 2.90.0 x11)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||||
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
|
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
|
||||||
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.5.4)
|
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
|
||||||
|
|
||||||
AC_MSG_CHECKING([for bluetooth support])
|
AC_MSG_CHECKING([for bluetooth support])
|
||||||
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
|
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
|
||||||
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
|
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
|
||||||
BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
|
BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
|
||||||
AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
|
AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
|
||||||
AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
|
|
||||||
AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
|
AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
|
||||||
AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
|
AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
|
||||||
AC_SUBST([HAVE_BLUETOOTH],[1])
|
AC_SUBST([HAVE_BLUETOOTH],[1])
|
||||||
@ -138,37 +140,10 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
|
|||||||
AC_SUBST([HAVE_BLUETOOTH],[0])
|
AC_SUBST([HAVE_BLUETOOTH],[0])
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION gio-2.0)
|
PKG_CHECK_MODULES(CALENDAR_SERVER, libecal-1.2 >= $LIBECAL_MIN_VERSION libedataserver-1.2 >= $LIBEDATASERVER_MIN_VERSION libedataserverui-3.0 >= $LIBEDATASERVERUI_MIN_VERSION gio-2.0)
|
||||||
AC_SUBST(CALENDAR_SERVER_CFLAGS)
|
AC_SUBST(CALENDAR_SERVER_CFLAGS)
|
||||||
AC_SUBST(CALENDAR_SERVER_LIBS)
|
AC_SUBST(CALENDAR_SERVER_LIBS)
|
||||||
|
|
||||||
AC_ARG_WITH(systemd,
|
|
||||||
AS_HELP_STRING([--with-systemd],
|
|
||||||
[Add systemd support]),
|
|
||||||
[with_systemd=$withval], [with_systemd=auto])
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(SYSTEMD,
|
|
||||||
[libsystemd-login libsystemd-daemon],
|
|
||||||
[have_systemd=yes], [have_systemd=no])
|
|
||||||
|
|
||||||
if test "x$with_systemd" = "xauto" ; then
|
|
||||||
if test x$have_systemd = xno ; then
|
|
||||||
use_systemd=no
|
|
||||||
else
|
|
||||||
use_systemd=yes
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
use_systemd=$with_systemd
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$use_systemd" = "xyes"; then
|
|
||||||
if test "x$have_systemd" = "xno"; then
|
|
||||||
AC_MSG_ERROR([Systemd support explicitly required, but systemd not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_DEFINE(WITH_SYSTEMD, 1, [systemd support])
|
|
||||||
fi
|
|
||||||
|
|
||||||
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
|
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
|
||||||
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
|
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
|
||||||
AC_SUBST(MUTTER_GIR_DIR)
|
AC_SUBST(MUTTER_GIR_DIR)
|
||||||
@ -181,17 +156,6 @@ AC_CHECK_FUNCS(fdwalk)
|
|||||||
AC_CHECK_FUNCS(mallinfo)
|
AC_CHECK_FUNCS(mallinfo)
|
||||||
AC_CHECK_HEADERS([sys/resource.h])
|
AC_CHECK_HEADERS([sys/resource.h])
|
||||||
|
|
||||||
# _NL_TIME_FIRST_WEEKDAY is an enum and not a define
|
|
||||||
AC_MSG_CHECKING([for _NL_TIME_FIRST_WEEKDAY])
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <langinfo.h>]],
|
|
||||||
[[nl_langinfo(_NL_TIME_FIRST_WEEKDAY);]])],
|
|
||||||
[langinfo_ok=yes], [langinfo_ok=no])
|
|
||||||
AC_MSG_RESULT($langinfo_ok)
|
|
||||||
if test "$langinfo_ok" = "yes"; then
|
|
||||||
AC_DEFINE([HAVE__NL_TIME_FIRST_WEEKDAY], [1],
|
|
||||||
[Define if _NL_TIME_FIRST_WEEKDAY is available])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||||
AM_PATH_GLIB_2_0()
|
AM_PATH_GLIB_2_0()
|
||||||
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
|
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
|
||||||
@ -205,8 +169,6 @@ AC_SUBST(GIRDIR)
|
|||||||
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
|
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
|
||||||
AC_SUBST(TYPELIBDIR)
|
AC_SUBST(TYPELIBDIR)
|
||||||
|
|
||||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
|
|
||||||
|
|
||||||
# Stay command-line compatible with the gnome-common configure option. Here
|
# Stay command-line compatible with the gnome-common configure option. Here
|
||||||
# minimum/yes/maximum are the same, however.
|
# minimum/yes/maximum are the same, however.
|
||||||
AC_ARG_ENABLE(compile_warnings,
|
AC_ARG_ENABLE(compile_warnings,
|
||||||
@ -227,7 +189,7 @@ if test "$enable_compile_warnings" != no ; then
|
|||||||
if test "$enable_compile_warnings" = error ; then
|
if test "$enable_compile_warnings" = error ; then
|
||||||
case " $CFLAGS " in
|
case " $CFLAGS " in
|
||||||
*[\ \ ]-Werror[\ \ ]*) ;;
|
*[\ \ ]-Werror[\ \ ]*) ;;
|
||||||
*) CFLAGS="$CFLAGS -Werror -Wno-error=deprecated-declarations" ;;
|
*) CFLAGS="$CFLAGS -Werror" ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -235,25 +197,15 @@ fi
|
|||||||
changequote([,])dnl
|
changequote([,])dnl
|
||||||
|
|
||||||
AC_ARG_ENABLE(jhbuild-wrapper-script,
|
AC_ARG_ENABLE(jhbuild-wrapper-script,
|
||||||
AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
|
AS_HELP_STRING([--jhbuild-wrapper-script=yes],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
|
||||||
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
|
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
|
||||||
|
|
||||||
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
|
|
||||||
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
data/Makefile
|
data/Makefile
|
||||||
docs/Makefile
|
|
||||||
docs/reference/Makefile
|
|
||||||
docs/reference/shell/Makefile
|
|
||||||
docs/reference/shell/shell-docs.sgml
|
|
||||||
docs/reference/st/Makefile
|
|
||||||
docs/reference/st/st-docs.sgml
|
|
||||||
js/Makefile
|
js/Makefile
|
||||||
src/calendar-server/evolution-calendar.desktop.in
|
js/misc/config.js
|
||||||
src/Makefile
|
src/Makefile
|
||||||
browser-plugin/Makefile
|
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
man/Makefile
|
man/Makefile
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<KeyListEntries schema="org.gnome.shell.keybindings"
|
|
||||||
group="system"
|
|
||||||
_name="Screenshots"
|
|
||||||
wm_name="GNOME Shell"
|
|
||||||
package="gnome-shell">
|
|
||||||
|
|
||||||
<KeyListEntry name="toggle-recording"
|
|
||||||
_description="Record a screencast"/>
|
|
||||||
|
|
||||||
</KeyListEntries>
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<KeyListEntries schema="org.gnome.shell.keybindings"
|
|
||||||
group="system"
|
|
||||||
_name="System"
|
|
||||||
wm_name="GNOME Shell"
|
|
||||||
package="gnome-shell">
|
|
||||||
|
|
||||||
<KeyListEntry name="toggle-message-tray"
|
|
||||||
_description="Show the message tray"/>
|
|
||||||
|
|
||||||
<KeyListEntry name="toggle-application-view"
|
|
||||||
_description="Show all applications"/>
|
|
||||||
|
|
||||||
<KeyListEntry name="open-application-menu"
|
|
||||||
_description="Open the application menu"/>
|
|
||||||
|
|
||||||
</KeyListEntries>
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
desktopdir=$(datadir)/applications
|
desktopdir=$(datadir)/applications
|
||||||
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
desktop_DATA = gnome-shell.desktop
|
||||||
|
|
||||||
# We substitute in bindir so it works as an autostart
|
# We substitute in bindir so it works as an autostart
|
||||||
# file when built in a non-system prefix
|
# file when built in a non-system prefix
|
||||||
@ -8,20 +8,20 @@ desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
|
|||||||
-e "s|@VERSION[@]|$(VERSION)|" \
|
-e "s|@VERSION[@]|$(VERSION)|" \
|
||||||
$< > $@ || rm $@
|
$< > $@ || rm $@
|
||||||
|
|
||||||
@INTLTOOL_DESKTOP_RULE@
|
# Placeholder until we add intltool
|
||||||
|
%.desktop:%.desktop.in
|
||||||
|
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
||||||
|
|
||||||
introspectiondir = $(datadir)/dbus-1/interfaces
|
searchprovidersdir = $(pkgdatadir)/search_providers
|
||||||
introspection_DATA = org.gnome.ShellSearchProvider.xml
|
dist_searchproviders_DATA = \
|
||||||
|
search_providers/google.xml \
|
||||||
|
search_providers/wikipedia.xml
|
||||||
|
|
||||||
themedir = $(pkgdatadir)/theme
|
themedir = $(pkgdatadir)/theme
|
||||||
dist_theme_DATA = \
|
dist_theme_DATA = \
|
||||||
theme/calendar-arrow-left.svg \
|
theme/calendar-arrow-left.svg \
|
||||||
theme/calendar-arrow-right.svg \
|
theme/calendar-arrow-right.svg \
|
||||||
theme/calendar-today.svg \
|
theme/calendar-today.svg \
|
||||||
theme/checkbox-focused.svg \
|
|
||||||
theme/checkbox-off-focused.svg \
|
|
||||||
theme/checkbox-off.svg \
|
|
||||||
theme/checkbox.svg \
|
|
||||||
theme/close-window.svg \
|
theme/close-window.svg \
|
||||||
theme/close.svg \
|
theme/close.svg \
|
||||||
theme/corner-ripple-ltr.png \
|
theme/corner-ripple-ltr.png \
|
||||||
@ -30,38 +30,25 @@ dist_theme_DATA = \
|
|||||||
theme/filter-selected-ltr.svg \
|
theme/filter-selected-ltr.svg \
|
||||||
theme/filter-selected-rtl.svg \
|
theme/filter-selected-rtl.svg \
|
||||||
theme/gnome-shell.css \
|
theme/gnome-shell.css \
|
||||||
theme/logged-in-indicator.svg \
|
theme/panel-border.svg \
|
||||||
theme/message-tray-background.png \
|
|
||||||
theme/noise-texture.png \
|
|
||||||
theme/panel-button-border.svg \
|
theme/panel-button-border.svg \
|
||||||
theme/panel-button-highlight-narrow.svg \
|
theme/panel-button-highlight-narrow.svg \
|
||||||
theme/panel-button-highlight-wide.svg \
|
theme/panel-button-highlight-wide.svg \
|
||||||
theme/process-working.svg \
|
theme/process-working.svg \
|
||||||
theme/running-indicator.svg \
|
theme/running-indicator.svg \
|
||||||
|
theme/scroll-hhandle.svg \
|
||||||
|
theme/scroll-vhandle.svg \
|
||||||
theme/source-button-border.svg \
|
theme/source-button-border.svg \
|
||||||
theme/summary-counter.svg \
|
|
||||||
theme/toggle-off-us.svg \
|
theme/toggle-off-us.svg \
|
||||||
theme/toggle-off-intl.svg \
|
theme/toggle-off-intl.svg \
|
||||||
theme/toggle-on-us.svg \
|
theme/toggle-on-us.svg \
|
||||||
theme/toggle-on-intl.svg \
|
theme/toggle-on-intl.svg \
|
||||||
theme/ws-switch-arrow-up.png \
|
theme/ws-switch-arrow-up.svg \
|
||||||
theme/ws-switch-arrow-down.png
|
theme/ws-switch-arrow-down.svg
|
||||||
|
|
||||||
keysdir = @GNOME_KEYBINDINGS_KEYSDIR@
|
|
||||||
keys_in_files = \
|
|
||||||
50-gnome-shell-screenshot.xml.in \
|
|
||||||
50-gnome-shell-system.xml.in \
|
|
||||||
$(NULL)
|
|
||||||
keys_DATA = $(keys_in_files:.xml.in=.xml)
|
|
||||||
|
|
||||||
gsettings_SCHEMAS = org.gnome.shell.gschema.xml
|
gsettings_SCHEMAS = org.gnome.shell.gschema.xml
|
||||||
|
|
||||||
@INTLTOOL_XML_NOMERGE_RULE@
|
@INTLTOOL_XML_NOMERGE_RULE@
|
||||||
|
|
||||||
%.gschema.xml.in: %.gschema.xml.in.in Makefile
|
|
||||||
$(AM_V_GEN) sed -e 's|@GETTEXT_PACKAGE[@]|$(GETTEXT_PACKAGE)|g' \
|
|
||||||
$< > $@ || rm $@
|
|
||||||
|
|
||||||
@GSETTINGS_RULES@
|
@GSETTINGS_RULES@
|
||||||
|
|
||||||
# We need to compile schemas at make time
|
# We need to compile schemas at make time
|
||||||
@ -71,24 +58,30 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
|
|||||||
|
|
||||||
all-local: gschemas.compiled
|
all-local: gschemas.compiled
|
||||||
|
|
||||||
convertdir = $(datadir)/GConf/gsettings
|
|
||||||
convert_DATA = gnome-shell-overrides.convert
|
# GConf schemas: provide defaults for keys from Metacity we are overriding
|
||||||
|
gconfschemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||||
|
gconfschema_DATA = gnome-shell.schemas
|
||||||
|
|
||||||
|
shadersdir = $(pkgdatadir)/shaders
|
||||||
|
shaders_DATA = \
|
||||||
|
shaders/dim-window.glsl
|
||||||
|
|
||||||
|
install-data-local:
|
||||||
|
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(gconfschema_DATA)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
gnome-shell.desktop.in.in \
|
gnome-shell.desktop.in.in \
|
||||||
gnome-shell-extension-prefs.desktop.in.in \
|
|
||||||
$(introspection_DATA) \
|
|
||||||
$(menu_DATA) \
|
$(menu_DATA) \
|
||||||
$(convert_DATA) \
|
$(gconfschema_DATA) \
|
||||||
$(keys_in_files) \
|
$(shaders_DATA) \
|
||||||
org.gnome.shell.gschema.xml.in.in
|
org.gnome.shell.gschema.xml.in
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
gnome-shell.desktop.in \
|
gnome-shell.desktop.in \
|
||||||
gnome-shell-extension-prefs.in \
|
|
||||||
$(desktop_DATA) \
|
$(desktop_DATA) \
|
||||||
$(keys_DATA) \
|
|
||||||
$(gsettings_SCHEMAS) \
|
$(gsettings_SCHEMAS) \
|
||||||
gschemas.compiled \
|
gschemas.compiled
|
||||||
org.gnome.shell.gschema.valid \
|
|
||||||
org.gnome.shell.gschema.xml.in
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Type=Application
|
|
||||||
_Name=GNOME Shell Extension Preferences
|
|
||||||
_Comment=Configure GNOME Shell Extensions
|
|
||||||
Exec=@bindir@/gnome-shell-extension-prefs %u
|
|
||||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
|
||||||
X-GNOME-Bugzilla-Product=gnome-shell
|
|
||||||
X-GNOME-Bugzilla-Component=extensions
|
|
||||||
X-GNOME-Bugzilla-Version=@VERSION@
|
|
||||||
Categories=GNOME;GTK;
|
|
||||||
OnlyShowIn=GNOME;
|
|
||||||
NoDisplay=true
|
|
@ -1,5 +0,0 @@
|
|||||||
[org.gnome.shell.overrides]
|
|
||||||
attach-modal-dialogs = /desktop/gnome/shell/windows/attach_modal_dialogs
|
|
||||||
button-layout = /desktop/gnome/shell/windows/button_layout
|
|
||||||
edge-tiling = /desktop/gnome/shell/windows/edge_tiling
|
|
||||||
workspaces-only-on-primary = /desktop/gnome/shell/windows/workspaces_only_on_primary
|
|
@ -13,4 +13,4 @@ NoDisplay=true
|
|||||||
X-GNOME-Autostart-Phase=WindowManager
|
X-GNOME-Autostart-Phase=WindowManager
|
||||||
X-GNOME-Provides=panel;windowmanager;
|
X-GNOME-Provides=panel;windowmanager;
|
||||||
X-GNOME-Autostart-Notify=true
|
X-GNOME-Autostart-Notify=true
|
||||||
X-GNOME-AutoRestart=false
|
X-GNOME-AutoRestart=true
|
||||||
|
100
data/gnome-shell.schemas
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<gconfschemafile>
|
||||||
|
<schemalist>
|
||||||
|
|
||||||
|
<!-- Metacity overrides -->
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/windows/attach_modal_dialogs</key>
|
||||||
|
<applyto>/desktop/gnome/shell/windows/attach_modal_dialogs</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>true</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Attach modal dialog to the parent window</short>
|
||||||
|
<long>
|
||||||
|
This key overrides /apps/mutter/general/attach_modal_dialogs when
|
||||||
|
running GNOME Shell.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/windows/button_layout</key>
|
||||||
|
<applyto>/desktop/gnome/shell/windows/button_layout</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>string</type>
|
||||||
|
<default>:close</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Arrangement of buttons on the titlebar</short>
|
||||||
|
<long>
|
||||||
|
Arrangement of buttons on the titlebar. The
|
||||||
|
value should be a string, such as
|
||||||
|
"menu:minimize,maximize,spacer,close"; the colon separates the
|
||||||
|
left corner of the window from the right corner, and
|
||||||
|
the button names are comma-separated. Duplicate buttons
|
||||||
|
are not allowed. Unknown button names are silently ignored
|
||||||
|
so that buttons can be added in future gnome-shell versions
|
||||||
|
without breaking older versions.
|
||||||
|
A special spacer tag can be used to insert some space between
|
||||||
|
two adjacent buttons.
|
||||||
|
|
||||||
|
This key overrides /apps/metacity/general/button_layout when
|
||||||
|
running GNOME Shell.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/windows/edge_tiling</key>
|
||||||
|
<applyto>/desktop/gnome/shell/windows/edge_tiling</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>true</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>enable edge tiling when dropping windows on screen edges</short>
|
||||||
|
<long>
|
||||||
|
If enabled, dropping windows on vertical screen edges maximizes them
|
||||||
|
vertically and resizes them horizontally to cover half of the
|
||||||
|
available area. Dropping windows on the top screen edge maximizes them
|
||||||
|
completely.
|
||||||
|
|
||||||
|
This key overrides /apps/metacity/general/edge_tiling when
|
||||||
|
running GNOME Shell.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/windows/theme</key>
|
||||||
|
<applyto>/desktop/gnome/shell/windows/theme</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>string</type>
|
||||||
|
<default>Adwaita</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Current theme</short>
|
||||||
|
<long>
|
||||||
|
The theme determines the appearance of window borders,
|
||||||
|
titlebar, and so forth.
|
||||||
|
|
||||||
|
This key overrides /apps/metacity/general/theme when
|
||||||
|
running GNOME Shell.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema>
|
||||||
|
<key>/schemas/desktop/gnome/shell/windows/workspaces_only_on_primary</key>
|
||||||
|
<applyto>/desktop/gnome/shell/windows/workspaces_only_on_primary</applyto>
|
||||||
|
<owner>gnome-shell</owner>
|
||||||
|
<type>bool</type>
|
||||||
|
<default>true</default>
|
||||||
|
<locale name="C">
|
||||||
|
<short>Workspaces only on primary monitor</short>
|
||||||
|
<long>
|
||||||
|
This key overrides /apps/mutter/general/workspaces_only_on_primary when
|
||||||
|
running GNOME Shell.
|
||||||
|
</long>
|
||||||
|
</locale>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
</schemalist>
|
||||||
|
</gconfschemafile>
|
@ -1,147 +0,0 @@
|
|||||||
<!DOCTYPE node PUBLIC
|
|
||||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
|
|
||||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
|
|
||||||
<node>
|
|
||||||
<interface name="org.gnome.Shell.SearchProvider">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:description>
|
|
||||||
<doc:para>
|
|
||||||
The interface used for integrating into GNOME Shell's search
|
|
||||||
interface.
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
|
||||||
</doc:doc>
|
|
||||||
|
|
||||||
<method name="GetInitialResultSet">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:description>
|
|
||||||
<doc:para>
|
|
||||||
Called when the user first begins a search.
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
|
||||||
</doc:doc>
|
|
||||||
<arg type="as" direction="in">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
Array of search terms, which the provider should treat as
|
|
||||||
logical AND.
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
<arg type="as" direction="out">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
An array of result identifier strings representing items which
|
|
||||||
match the given search terms. Identifiers must be unique within
|
|
||||||
the provider's domain, but other than that may be chosen freely
|
|
||||||
by the provider.
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="GetSubsearchResultSet">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:description>
|
|
||||||
<doc:para>
|
|
||||||
Called when a search is performed which is a "subsearch" of
|
|
||||||
the previous search, e.g. the method may return less results, but
|
|
||||||
not more or different results.
|
|
||||||
|
|
||||||
This allows search providers to only search through the previous
|
|
||||||
result set, rather than possibly performing a full re-query.
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
|
||||||
</doc:doc>
|
|
||||||
<arg type="as" direction="in">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
Array of item identifiers
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
<arg type="as" direction="in">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
Array of updated search terms, which the provider should treat as
|
|
||||||
logical AND.
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
<arg type="as" direction="out">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
An array of result identifier strings representing items which
|
|
||||||
match the given search terms. Identifiers must be unique within
|
|
||||||
the provider's domain, but other than that may be chosen freely
|
|
||||||
by the provider.
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="GetResultMetas">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:description>
|
|
||||||
<doc:para>
|
|
||||||
Return an array of meta data used to display each given result
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
|
||||||
</doc:doc>
|
|
||||||
<arg type="as" direction="in">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
An array of result identifiers as returned by
|
|
||||||
GetInitialResultSet() or GetSubsearchResultSet()
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
<arg type="aa{sv}" direction="out">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
A dictionary describing the given search result, containing
|
|
||||||
'id', 'name' (both strings) and either 'icon' (a serialized
|
|
||||||
GIcon) or 'icon-data' (raw image data as (iiibiiay) - width,
|
|
||||||
height, rowstride, has-alpha, bits per sample, channels, data)
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="ActivateResult">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:description>
|
|
||||||
<doc:para>
|
|
||||||
Called when the users chooses a given result. The result should
|
|
||||||
be displayed in the application associated with the corresponding
|
|
||||||
provider.
|
|
||||||
</doc:para>
|
|
||||||
</doc:description>
|
|
||||||
</doc:doc>
|
|
||||||
<arg type="s" direction="in">
|
|
||||||
<doc:doc>
|
|
||||||
<doc:summary>
|
|
||||||
<doc:para>
|
|
||||||
A result identifier as returned by GetInitialResultSet() or
|
|
||||||
GetSubsearchResultSet()
|
|
||||||
</doc:para>
|
|
||||||
</doc:summary>
|
|
||||||
</doc:doc>
|
|
||||||
</arg>
|
|
||||||
</method>
|
|
||||||
</interface>
|
|
||||||
</node>
|
|
@ -11,14 +11,22 @@
|
|||||||
using the Alt-F2 dialog.
|
using the Alt-F2 dialog.
|
||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
|
<key name="disabled-extensions" type="as">
|
||||||
|
<default>[]</default>
|
||||||
|
<_summary>Uuids of extensions to disable</_summary>
|
||||||
|
<_description>
|
||||||
|
GNOME Shell extensions have a uuid property; this key lists extensions
|
||||||
|
which should not be loaded. This setting overrides enabled-extensions
|
||||||
|
for extensions that appear in both lists.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
<key name="enabled-extensions" type="as">
|
<key name="enabled-extensions" type="as">
|
||||||
<default>[]</default>
|
<default>[]</default>
|
||||||
<_summary>Uuids of extensions to enable</_summary>
|
<_summary>Uuids of extensions to enable</_summary>
|
||||||
<_description>
|
<_description>
|
||||||
GNOME Shell extensions have a uuid property; this key lists extensions
|
GNOME Shell extensions have a uuid property; this key lists extensions
|
||||||
which should be loaded. Any extension that wants to be loaded needs
|
which should be loaded. disabled-extensions overrides this setting for
|
||||||
to be in this list. You can also manipulate this list with the
|
extensions that appear in both lists.
|
||||||
EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
|
|
||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
<key name="enable-app-monitoring" type="b">
|
<key name="enable-app-monitoring" type="b">
|
||||||
@ -32,13 +40,17 @@
|
|||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
<key name="favorite-apps" type="as">
|
<key name="favorite-apps" type="as">
|
||||||
<default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
|
<default>[ 'mozilla-firefox.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'openoffice.org-writer.desktop', 'nautilus.desktop' ]</default>
|
||||||
<_summary>List of desktop file IDs for favorite applications</_summary>
|
<_summary>List of desktop file IDs for favorite applications</_summary>
|
||||||
<_description>
|
<_description>
|
||||||
The applications corresponding to these identifiers
|
The applications corresponding to these identifiers
|
||||||
will be displayed in the favorites area.
|
will be displayed in the favorites area.
|
||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
|
<key name="disabled-open-search-providers" type="as">
|
||||||
|
<default>[]</default>
|
||||||
|
<_summary>disabled OpenSearch providers</_summary>
|
||||||
|
</key>
|
||||||
<key name="command-history" type="as">
|
<key name="command-history" type="as">
|
||||||
<default>[]</default>
|
<default>[]</default>
|
||||||
<_summary>History for command (Alt-F2) dialog</_summary>
|
<_summary>History for command (Alt-F2) dialog</_summary>
|
||||||
@ -47,27 +59,9 @@
|
|||||||
<default>[]</default>
|
<default>[]</default>
|
||||||
<_summary>History for the looking glass dialog</_summary>
|
<_summary>History for the looking glass dialog</_summary>
|
||||||
</key>
|
</key>
|
||||||
<key name="saved-im-presence" type="i">
|
<child name="clock" schema="org.gnome.shell.clock"/>
|
||||||
<default>1</default>
|
|
||||||
<_summary>Internally used to store the last IM presence explicitly set by the user. The
|
|
||||||
value here is from the TpConnectionPresenceType enumeration.</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="saved-session-presence" type="i">
|
|
||||||
<default>0</default>
|
|
||||||
<_summary>Internally used to store the last session presence status for the user. The
|
|
||||||
value here is from the GsmPresenceStatus enumeration.</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="always-show-log-out" type="b">
|
|
||||||
<default>false</default>
|
|
||||||
<_summary>Always show the 'Log out' menuitem in the user menu.</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the automatic hiding of the 'Log out'
|
|
||||||
menuitem in single-user, single-session situations.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
<child name="calendar" schema="org.gnome.shell.calendar"/>
|
||||||
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
<child name="recorder" schema="org.gnome.shell.recorder"/>
|
||||||
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
|
|
||||||
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
|
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
@ -82,41 +76,15 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
|||||||
</key>
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
|
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
|
||||||
<key name="open-application-menu" type="as">
|
|
||||||
<default>["<Super>F10"]</default>
|
|
||||||
<_summary>Keybinding to open the application menu</_summary>
|
|
||||||
<_description>
|
|
||||||
Keybinding to open the application menu.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="toggle-application-view" type="as">
|
|
||||||
<default>["<Super>a"]</default>
|
|
||||||
<_summary>Keybinding to open the "Show Applications" view</_summary>
|
|
||||||
<_description>
|
|
||||||
Keybinding to open the "Show Applications" view of the Activities
|
|
||||||
Overview.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="toggle-message-tray" type="as">
|
|
||||||
<default>["<Super>m"]</default>
|
|
||||||
<_summary>Keybinding to toggle the visibility of the message tray</_summary>
|
|
||||||
<_description>
|
|
||||||
Keybinding to toggle the visibility of the message tray.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
<key name="toggle-recording" type="as">
|
|
||||||
<default><![CDATA[['<Control><Shift><Alt>r']]]></default>
|
|
||||||
<_summary>Keybinding to toggle the screen recorder</_summary>
|
|
||||||
<_description>
|
|
||||||
Keybinding to start/stop the builtin screen recorder.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
</schema>
|
|
||||||
|
|
||||||
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
gettext-domain="@GETTEXT_PACKAGE@">
|
||||||
|
<key name="show-keyboard" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<_summary>Show the onscreen keyboard</_summary>
|
||||||
|
<_description>
|
||||||
|
If true, display onscreen keyboard.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
<key name="keyboard-type" type="s">
|
<key name="keyboard-type" type="s">
|
||||||
<default>'touch'</default>
|
<default>'touch'</default>
|
||||||
<_summary>Which keyboard to use</_summary>
|
<_summary>Which keyboard to use</_summary>
|
||||||
@ -124,12 +92,44 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
|||||||
The type of keyboard to use.
|
The type of keyboard to use.
|
||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
|
<key name="enable-drag" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<_summary>Enable keyboard dragging</_summary>
|
||||||
|
<_description>
|
||||||
|
If true, enable keyboard dragging.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
|
<key name="enable-float" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<_summary>Enable floating keyboard</_summary>
|
||||||
|
<_description>
|
||||||
|
If true, enable floating keyboard.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema id="org.gnome.shell.clock" path="/org/gnome/shell/clock/"
|
||||||
|
gettext-domain="@GETTEXT_PACKAGE@">
|
||||||
|
<key name="show-seconds" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<_summary>Show time with seconds</_summary>
|
||||||
|
<_description>
|
||||||
|
If true, display seconds in time.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
|
<key name="show-date" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<_summary>Show date in clock</_summary>
|
||||||
|
<_description>
|
||||||
|
If true, display date in the clock, in addition to time.
|
||||||
|
</_description>
|
||||||
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
|
<schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
gettext-domain="@GETTEXT_PACKAGE@">
|
||||||
<key name="framerate" type="i">
|
<key name="framerate" type="i">
|
||||||
<default>30</default>
|
<default>15</default>
|
||||||
<_summary>Framerate used for recording screencasts.</_summary>
|
<_summary>Framerate used for recording screencasts.</_summary>
|
||||||
<_description>
|
<_description>
|
||||||
The framerate of the resulting screencast recordered
|
The framerate of the resulting screencast recordered
|
||||||
@ -148,7 +148,7 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
|||||||
take care of its own output - this might be used to send the output
|
take care of its own output - this might be used to send the output
|
||||||
to an icecast server via shout2send or similar. When unset or set
|
to an icecast server via shout2send or similar. When unset or set
|
||||||
to an empty value, the default pipeline will be used. This is currently
|
to an empty value, the default pipeline will be used. This is currently
|
||||||
'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux'
|
'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux'
|
||||||
and records to WEBM using the VP8 codec. %T is used as a placeholder
|
and records to WEBM using the VP8 codec. %T is used as a placeholder
|
||||||
for a guess at the optimal thread count on the system.
|
for a guess at the optimal thread count on the system.
|
||||||
</_description>
|
</_description>
|
||||||
@ -163,57 +163,4 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
|
|||||||
</_description>
|
</_description>
|
||||||
</key>
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
|
|
||||||
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
|
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
|
||||||
<key name="attach-modal-dialogs" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<_summary>Attach modal dialog to the parent window</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the key in org.gnome.mutter when running
|
|
||||||
GNOME Shell.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<key name="button-layout" type="s">
|
|
||||||
<default>":close"</default>
|
|
||||||
<_summary>Arrangement of buttons on the titlebar</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the key in org.gnome.desktop.wm.preferences when
|
|
||||||
running GNOME Shell.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<key name="edge-tiling" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<_summary>Enable edge tiling when dropping windows on screen edges</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the key in org.gnome.mutter when running GNOME Shell.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<key name="dynamic-workspaces" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<_summary>Workspaces are managed dynamically</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the key in org.gnome.mutter when running GNOME Shell.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<key name="workspaces-only-on-primary" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<_summary>Workspaces only on primary monitor</_summary>
|
|
||||||
<_description>
|
|
||||||
This key overrides the key in org.gnome.mutter when running GNOME Shell.
|
|
||||||
</_description>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
<key name="focus-change-on-pointer-rest" type="b">
|
|
||||||
<default>true</default>
|
|
||||||
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
|
|
||||||
<description>
|
|
||||||
This key overrides the key in org.gnome.mutter when running GNOME Shell.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
</schema>
|
|
||||||
</schemalist>
|
</schemalist>
|
7
data/search_providers/google.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
|
<ShortName>Google</ShortName>
|
||||||
|
<Description>Google Search</Description>
|
||||||
|
<InputEncoding>UTF-8</InputEncoding>
|
||||||
|
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
|
||||||
|
<Url type="text/html" method="GET" template="http://www.google.com/search?q={searchTerms}"/>
|
||||||
|
</OpenSearchDescription>
|
44
data/search_providers/wikipedia.xml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
|
<ShortName>Wikipedia</ShortName>
|
||||||
|
<Description>Wikipedia, the free encyclopedia</Description>
|
||||||
|
<InputEncoding>UTF-8</InputEncoding>
|
||||||
|
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</Image>
|
||||||
|
<Url type="text/html" method="GET" template="http://{language}.wikipedia.org/wiki/Special:Search?search={searchTerms}"/>
|
||||||
|
<!-- The criterion for being below is being listed with more than 100,000
|
||||||
|
articles on http://meta.wikimedia.org/wiki/List_of_Wikipedias -->
|
||||||
|
<Language>ar</Language>
|
||||||
|
<Language>bg</Language>
|
||||||
|
<Language>ca</Language>
|
||||||
|
<Language>cs</Language>
|
||||||
|
<Language>da</Language>
|
||||||
|
<Language>de</Language>
|
||||||
|
<Language>en</Language>
|
||||||
|
<Language>eo</Language>
|
||||||
|
<Language>es</Language>
|
||||||
|
<Language>fa</Language>
|
||||||
|
<Language>fi</Language>
|
||||||
|
<Language>fr</Language>
|
||||||
|
<Language>he</Language>
|
||||||
|
<Language>hu</Language>
|
||||||
|
<Language>id</Language>
|
||||||
|
<Language>it</Language>
|
||||||
|
<Language>ja</Language>
|
||||||
|
<Language>ko</Language>
|
||||||
|
<Language>lt</Language>
|
||||||
|
<Language>nl</Language>
|
||||||
|
<Language>no</Language>
|
||||||
|
<Language>pl</Language>
|
||||||
|
<Language>pt</Language>
|
||||||
|
<Language>ro</Language>
|
||||||
|
<Language>ru</Language>
|
||||||
|
<Language>sk</Language>
|
||||||
|
<Language>sl</Language>
|
||||||
|
<Language>sr</Language>
|
||||||
|
<Language>sv</Language>
|
||||||
|
<Language>tr</Language>
|
||||||
|
<Language>uk</Language>
|
||||||
|
<Language>vi</Language>
|
||||||
|
<Language>vo</Language>
|
||||||
|
<Language>war</Language>
|
||||||
|
<Language>zh</Language>
|
||||||
|
</OpenSearchDescription>
|
26
data/shaders/dim-window.glsl
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#version 110
|
||||||
|
uniform sampler2D sampler0;
|
||||||
|
uniform float fraction;
|
||||||
|
uniform float height;
|
||||||
|
const float c = -0.2;
|
||||||
|
const float border_max_height = 60.0;
|
||||||
|
|
||||||
|
mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0 + c, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0 + c, 0.0,
|
||||||
|
0.0, 0.0, 0.0, 1.0);
|
||||||
|
vec4 off = vec4(0.633, 0.633, 0.633, 0);
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 color = texture2D(sampler0, gl_TexCoord[0].st);
|
||||||
|
float y = height * gl_TexCoord[0][1];
|
||||||
|
|
||||||
|
// To reduce contrast, blend with a mid gray
|
||||||
|
gl_FragColor = color * contrast - off * c;
|
||||||
|
|
||||||
|
// We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
|
||||||
|
// when the fraction is 1.0. For other locations and fractions we linearly
|
||||||
|
// interpolate back to the original undimmed color.
|
||||||
|
gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0);
|
||||||
|
gl_FragColor = color + (gl_FragColor - color) * fraction;
|
||||||
|
}
|
@ -10,11 +10,11 @@
|
|||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
width="29"
|
width="28"
|
||||||
height="29"
|
height="25"
|
||||||
id="svg10621"
|
id="svg10621"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
inkscape:version="0.48.2 r9819"
|
inkscape:version="0.48.1 r9760"
|
||||||
sodipodi:docname="calendar-today.svg">
|
sodipodi:docname="calendar-today.svg">
|
||||||
<defs
|
<defs
|
||||||
id="defs10623">
|
id="defs10623">
|
||||||
@ -118,17 +118,6 @@
|
|||||||
fx="51"
|
fx="51"
|
||||||
fy="30"
|
fy="30"
|
||||||
r="42" />
|
r="42" />
|
||||||
<radialGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient34508-1-3"
|
|
||||||
id="radialGradient3113"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(0.72146227,0,0,0.27484277,14.205424,21.754717)"
|
|
||||||
cx="51"
|
|
||||||
cy="30"
|
|
||||||
fx="51"
|
|
||||||
fy="30"
|
|
||||||
r="42" />
|
|
||||||
</defs>
|
</defs>
|
||||||
<sodipodi:namedview
|
<sodipodi:namedview
|
||||||
id="base"
|
id="base"
|
||||||
@ -138,29 +127,20 @@
|
|||||||
inkscape:pageopacity="0"
|
inkscape:pageopacity="0"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="15.839192"
|
inkscape:zoom="15.839192"
|
||||||
inkscape:cx="20.652108"
|
inkscape:cx="8.3750933"
|
||||||
inkscape:cy="11.839084"
|
inkscape:cy="8.0837211"
|
||||||
inkscape:document-units="px"
|
inkscape:document-units="px"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
showgrid="true"
|
showgrid="false"
|
||||||
fit-margin-top="0"
|
fit-margin-top="0"
|
||||||
fit-margin-left="0"
|
fit-margin-left="0"
|
||||||
fit-margin-right="0"
|
fit-margin-right="0"
|
||||||
fit-margin-bottom="0"
|
fit-margin-bottom="0"
|
||||||
inkscape:window-width="1280"
|
inkscape:window-width="1440"
|
||||||
inkscape:window-height="741"
|
inkscape:window-height="843"
|
||||||
inkscape:window-x="0"
|
inkscape:window-x="0"
|
||||||
inkscape:window-y="27"
|
inkscape:window-y="26"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1" />
|
||||||
borderlayer="true">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid3109"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata10626">
|
id="metadata10626">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
@ -177,28 +157,31 @@
|
|||||||
inkscape:label="Layer 1"
|
inkscape:label="Layer 1"
|
||||||
inkscape:groupmode="layer"
|
inkscape:groupmode="layer"
|
||||||
id="layer1"
|
id="layer1"
|
||||||
transform="translate(-469.08263,-532.99307)">
|
transform="translate(-469.08263,-536.99307)">
|
||||||
<path
|
<g
|
||||||
sodipodi:type="arc"
|
id="g3003">
|
||||||
style="opacity:0.4625;color:#000000;fill:url(#radialGradient3113);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
<path
|
||||||
id="path34506-3"
|
inkscape:export-ydpi="90"
|
||||||
sodipodi:cx="51"
|
inkscape:export-xdpi="90"
|
||||||
sodipodi:cy="30"
|
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
|
||||||
sodipodi:rx="42"
|
transform="matrix(0.43692393,0,0,1.3783114,460.60467,517.48289)"
|
||||||
sodipodi:ry="16"
|
sodipodi:end="6.2831853"
|
||||||
d="M 9,29.999999 A 42,16 0 0 1 93,30 l -42,0 z"
|
sodipodi:start="3.1415927"
|
||||||
sodipodi:start="3.1415927"
|
d="M 9,29.999999 C 9.0000011,21.163443 27.804042,14 51.000002,14 74.195961,14 93,21.163444 93,30 l -42,0 z"
|
||||||
sodipodi:end="6.2831853"
|
sodipodi:ry="16"
|
||||||
transform="matrix(0.43692393,0,0,1.3783114,461.29951,517.6437)"
|
sodipodi:rx="42"
|
||||||
inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-shell-design/mockups/motion/textures/panel.png"
|
sodipodi:cy="30"
|
||||||
inkscape:export-xdpi="90"
|
sodipodi:cx="51"
|
||||||
inkscape:export-ydpi="90" />
|
id="path34506-3"
|
||||||
<rect
|
style="opacity:0.4625;color:#000000;fill:url(#radialGradient2997);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
style="fill:#ffffff;fill-opacity:0.50196078;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
sodipodi:type="arc" />
|
||||||
id="rect2996"
|
<rect
|
||||||
width="31"
|
y="558.85046"
|
||||||
height="3"
|
x="468.96878"
|
||||||
x="468.08264"
|
height="3.1425927"
|
||||||
y="558.99304" />
|
width="28.149134"
|
||||||
|
id="rect2996"
|
||||||
|
style="fill:#ffffff;fill-opacity:0.50196078;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.7 KiB |
@ -1,289 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="22"
|
|
||||||
id="svg3199"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="checkbox.svg">
|
|
||||||
<defs
|
|
||||||
id="defs3201">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient15404"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop15406"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#515151;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop15408"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#292929;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3207" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3187"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5872-5-1"
|
|
||||||
id="linearGradient5891-0-4"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
x1="205.84143"
|
|
||||||
y1="246.7094"
|
|
||||||
x2="206.74803"
|
|
||||||
y2="231.24142" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5872-5-1">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#0b2e52;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5874-4-4" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#1862af;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5876-0-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5837-4-6"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect14768"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5884-4-7"
|
|
||||||
is_visible="true" />
|
|
||||||
<linearGradient
|
|
||||||
y2="-388.72955"
|
|
||||||
x2="-93.031357"
|
|
||||||
y1="-396.34738"
|
|
||||||
x1="-93.031357"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient14219"
|
|
||||||
xlink:href="#linearGradient15404"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10013-4-63-6">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#333333;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10015-2-76-1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#292929;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10017-46-15-8" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10597-5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#16191a;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10599-2" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2b3133;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10601-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
y2="-322.16354"
|
|
||||||
x2="921.22498"
|
|
||||||
y1="-330.05121"
|
|
||||||
x1="921.32812"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15374"
|
|
||||||
xlink:href="#linearGradient10013-4-63-6"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
gradientTransform="translate(-1199.9852,216.38048)"
|
|
||||||
y2="-227.07961"
|
|
||||||
x2="1203.9177"
|
|
||||||
y1="-217.56708"
|
|
||||||
x1="1203.9177"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15376"
|
|
||||||
xlink:href="#linearGradient10597-5"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
y2="-388.72955"
|
|
||||||
x2="-93.031357"
|
|
||||||
y1="-396.34738"
|
|
||||||
x1="-93.031357"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient14219-6"
|
|
||||||
xlink:href="#linearGradient15404-9"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient15404-9"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop15406-6"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#515151;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop15408-7"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#292929;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#000000"
|
|
||||||
bordercolor="#2d2d2d"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="71.516955"
|
|
||||||
inkscape:cy="5.8710559"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1412"
|
|
||||||
inkscape:window-height="1067"
|
|
||||||
inkscape:window-x="2635"
|
|
||||||
inkscape:window-y="226"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
borderlayer="true"
|
|
||||||
inkscape:showpageshadow="false"
|
|
||||||
inkscape:snap-nodes="false"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
showborder="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid14843"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata3204">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-342.5,-521.36218)">
|
|
||||||
<g
|
|
||||||
transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
|
|
||||||
id="g14586-0"
|
|
||||||
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
|
|
||||||
id="g15291-9-6"
|
|
||||||
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
|
|
||||||
<g
|
|
||||||
transform="translate(877.50354,-102.83507)"
|
|
||||||
id="g16853-4-9"
|
|
||||||
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
|
|
||||||
<rect
|
|
||||||
transform="scale(1,-1)"
|
|
||||||
style="color:#000000;fill:url(#linearGradient14219-6);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
|
||||||
id="rect6506-6"
|
|
||||||
width="11.281681"
|
|
||||||
height="11.26221"
|
|
||||||
x="-409.59354"
|
|
||||||
y="-284.40115"
|
|
||||||
rx="1.0052766"
|
|
||||||
ry="1.0052764" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="translate(343.99999,987.99997)"
|
|
||||||
id="g5886-5"
|
|
||||||
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
|
|
||||||
id="g14586">
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
|
|
||||||
id="g15291-9"
|
|
||||||
style="display:inline;enable-background:new">
|
|
||||||
<g
|
|
||||||
transform="translate(877.50354,-102.83507)"
|
|
||||||
id="g16853-4"
|
|
||||||
style="enable-background:new" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="translate(343.99999,987.99997)"
|
|
||||||
id="g5886"
|
|
||||||
style="display:inline;enable-background:new">
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
|
|
||||||
id="path5835"
|
|
||||||
inkscape:path-effect="#path-effect5837-4-6"
|
|
||||||
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
|
|
||||||
inkscape:path-effect="#path-effect5837-4-6"
|
|
||||||
id="path5880"
|
|
||||||
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
|
|
||||||
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
|
|
||||||
id="path5882"
|
|
||||||
inkscape:path-effect="#path-effect5884-4-7"
|
|
||||||
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="csccc" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 11 KiB |
@ -1,198 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="22"
|
|
||||||
id="svg3199"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="checkbox-off.svg">
|
|
||||||
<defs
|
|
||||||
id="defs3201">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient15404"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop15406"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#515151;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop15408"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#292929;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3207" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3187"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5837-4-6"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect14768"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5884-4-7"
|
|
||||||
is_visible="true" />
|
|
||||||
<linearGradient
|
|
||||||
y2="-388.72955"
|
|
||||||
x2="-93.031357"
|
|
||||||
y1="-396.34738"
|
|
||||||
x1="-93.031357"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient14219"
|
|
||||||
xlink:href="#linearGradient15404"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10013-4-63-6">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#333333;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10015-2-76-1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#292929;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10017-46-15-8" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10597-5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#16191a;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10599-2" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2b3133;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10601-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
y2="-322.16354"
|
|
||||||
x2="921.22498"
|
|
||||||
y1="-330.05121"
|
|
||||||
x1="921.32812"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15374"
|
|
||||||
xlink:href="#linearGradient10013-4-63-6"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
gradientTransform="translate(-1199.9852,216.38048)"
|
|
||||||
y2="-227.07961"
|
|
||||||
x2="1203.9177"
|
|
||||||
y1="-217.56708"
|
|
||||||
x1="1203.9177"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15376"
|
|
||||||
xlink:href="#linearGradient10597-5"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#000000"
|
|
||||||
bordercolor="#2d2d2d"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="6.1225392"
|
|
||||||
inkscape:cy="3.6003241"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1412"
|
|
||||||
inkscape:window-height="1067"
|
|
||||||
inkscape:window-x="2116"
|
|
||||||
inkscape:window-y="261"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
borderlayer="true"
|
|
||||||
inkscape:showpageshadow="false"
|
|
||||||
inkscape:snap-nodes="false"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
showborder="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid14843"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata3204">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-342.5,-521.36218)">
|
|
||||||
<g
|
|
||||||
transform="matrix(0.80230061,0,0,0.80230061,-87.624044,-453.10297)"
|
|
||||||
id="g14586"
|
|
||||||
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none">
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
|
|
||||||
id="g15291-9"
|
|
||||||
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new">
|
|
||||||
<g
|
|
||||||
transform="translate(877.50354,-102.83507)"
|
|
||||||
id="g16853-4"
|
|
||||||
style="stroke-width:1.18754292;stroke-miterlimit:4;stroke-dasharray:none;enable-background:new">
|
|
||||||
<rect
|
|
||||||
transform="scale(1,-1)"
|
|
||||||
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.24833274;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
|
||||||
id="rect6506-6"
|
|
||||||
width="11.281681"
|
|
||||||
height="11.26221"
|
|
||||||
x="-409.59354"
|
|
||||||
y="-284.40115"
|
|
||||||
rx="1.0052766"
|
|
||||||
ry="1.0052764" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="translate(343.99999,987.99997)"
|
|
||||||
id="g5886"
|
|
||||||
style="stroke-width:2.3714385;stroke-miterlimit:4;stroke-dasharray:none;display:inline;enable-background:new" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 6.5 KiB |
@ -1,218 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="22"
|
|
||||||
id="svg3199"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="checkbox.svg">
|
|
||||||
<defs
|
|
||||||
id="defs3201">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient15404"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop15406"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#515151;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop15408"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#292929;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3207" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3187"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5872-5-1"
|
|
||||||
id="linearGradient5891-0-4"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
x1="205.84143"
|
|
||||||
y1="246.7094"
|
|
||||||
x2="206.74803"
|
|
||||||
y2="231.24142" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5872-5-1">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#0b2e52;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5874-4-4" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#1862af;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5876-0-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5837-4-6"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect14768"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5884-4-7"
|
|
||||||
is_visible="true" />
|
|
||||||
<linearGradient
|
|
||||||
y2="-388.72955"
|
|
||||||
x2="-93.031357"
|
|
||||||
y1="-396.34738"
|
|
||||||
x1="-93.031357"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient14219"
|
|
||||||
xlink:href="#linearGradient15404"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10013-4-63-6">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#333333;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10015-2-76-1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#292929;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10017-46-15-8" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10597-5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#16191a;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10599-2" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2b3133;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10601-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
y2="-322.16354"
|
|
||||||
x2="921.22498"
|
|
||||||
y1="-330.05121"
|
|
||||||
x1="921.32812"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15374"
|
|
||||||
xlink:href="#linearGradient10013-4-63-6"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
gradientTransform="translate(-1199.9852,216.38048)"
|
|
||||||
y2="-227.07961"
|
|
||||||
x2="1203.9177"
|
|
||||||
y1="-217.56708"
|
|
||||||
x1="1203.9177"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15376"
|
|
||||||
xlink:href="#linearGradient10597-5"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#000000"
|
|
||||||
bordercolor="#2d2d2d"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="4"
|
|
||||||
inkscape:cx="71.247925"
|
|
||||||
inkscape:cy="33.339093"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1412"
|
|
||||||
inkscape:window-height="1067"
|
|
||||||
inkscape:window-x="2116"
|
|
||||||
inkscape:window-y="261"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
borderlayer="true"
|
|
||||||
inkscape:showpageshadow="false"
|
|
||||||
inkscape:snap-nodes="false"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
showborder="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid14843"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata3204">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-342.5,-521.36218)">
|
|
||||||
<g
|
|
||||||
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
|
|
||||||
id="g14586">
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
|
|
||||||
id="g15291-9"
|
|
||||||
style="display:inline;enable-background:new">
|
|
||||||
<g
|
|
||||||
transform="translate(877.50354,-102.83507)"
|
|
||||||
id="g16853-4"
|
|
||||||
style="enable-background:new">
|
|
||||||
<rect
|
|
||||||
transform="scale(1,-1)"
|
|
||||||
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
|
||||||
id="rect6506-6"
|
|
||||||
width="11.281681"
|
|
||||||
height="11.26221"
|
|
||||||
x="-409.59354"
|
|
||||||
y="-284.40115"
|
|
||||||
rx="0.95632279"
|
|
||||||
ry="0.95632273" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="translate(343.99999,987.99997)"
|
|
||||||
id="g5886"
|
|
||||||
style="display:inline;enable-background:new" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 6.8 KiB |
@ -1,243 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="24"
|
|
||||||
height="22"
|
|
||||||
id="svg3199"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.1 r9760"
|
|
||||||
sodipodi:docname="checkbox-focused.svg">
|
|
||||||
<defs
|
|
||||||
id="defs3201">
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient15404"
|
|
||||||
inkscape:collect="always">
|
|
||||||
<stop
|
|
||||||
id="stop15406"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#515151;stop-opacity:1" />
|
|
||||||
<stop
|
|
||||||
id="stop15408"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#292929;stop-opacity:1" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 526.18109 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
|
||||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
|
||||||
id="perspective3207" />
|
|
||||||
<inkscape:perspective
|
|
||||||
id="perspective3187"
|
|
||||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
|
||||||
inkscape:vp_z="1 : 0.5 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_x="0 : 0.5 : 1"
|
|
||||||
sodipodi:type="inkscape:persp3d" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient5872-5-1"
|
|
||||||
id="linearGradient5891-0-4"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
x1="205.84143"
|
|
||||||
y1="246.7094"
|
|
||||||
x2="206.74803"
|
|
||||||
y2="231.24142" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient5872-5-1">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#0b2e52;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop5874-4-4" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#1862af;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop5876-0-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5837-4-6"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect14768"
|
|
||||||
is_visible="true" />
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="spiro"
|
|
||||||
id="path-effect5884-4-7"
|
|
||||||
is_visible="true" />
|
|
||||||
<linearGradient
|
|
||||||
y2="-388.72955"
|
|
||||||
x2="-93.031357"
|
|
||||||
y1="-396.34738"
|
|
||||||
x1="-93.031357"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.685418)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient14219"
|
|
||||||
xlink:href="#linearGradient15404"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10013-4-63-6">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#333333;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10015-2-76-1" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#292929;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10017-46-15-8" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient10597-5">
|
|
||||||
<stop
|
|
||||||
style="stop-color:#16191a;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop10599-2" />
|
|
||||||
<stop
|
|
||||||
style="stop-color:#2b3133;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop10601-5" />
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient
|
|
||||||
y2="-322.16354"
|
|
||||||
x2="921.22498"
|
|
||||||
y1="-330.05121"
|
|
||||||
x1="921.32812"
|
|
||||||
gradientTransform="matrix(1.5918367,0,0,0.85714285,-1456.5464,275.45191)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15374"
|
|
||||||
xlink:href="#linearGradient10013-4-63-6"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
<linearGradient
|
|
||||||
gradientTransform="translate(-1199.9852,216.38048)"
|
|
||||||
y2="-227.07961"
|
|
||||||
x2="1203.9177"
|
|
||||||
y1="-217.56708"
|
|
||||||
x1="1203.9177"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="linearGradient15376"
|
|
||||||
xlink:href="#linearGradient10597-5"
|
|
||||||
inkscape:collect="always" />
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#000000"
|
|
||||||
bordercolor="#2d2d2d"
|
|
||||||
borderopacity="1"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="1"
|
|
||||||
inkscape:cx="64.516955"
|
|
||||||
inkscape:cy="13.871056"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1412"
|
|
||||||
inkscape:window-height="1067"
|
|
||||||
inkscape:window-x="2635"
|
|
||||||
inkscape:window-y="226"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
borderlayer="true"
|
|
||||||
inkscape:showpageshadow="false"
|
|
||||||
inkscape:snap-nodes="false"
|
|
||||||
inkscape:snap-bbox="true"
|
|
||||||
showborder="false">
|
|
||||||
<inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid14843"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" />
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<metadata
|
|
||||||
id="metadata3204">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-342.5,-521.36218)">
|
|
||||||
<g
|
|
||||||
transform="matrix(0.84337,0,0,0.84337,-110.16632,-503.56182)"
|
|
||||||
id="g14586">
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="matrix(1.9969286,0,0,1.9969286,-397.05491,877.00482)"
|
|
||||||
id="g15291-9"
|
|
||||||
style="display:inline;enable-background:new">
|
|
||||||
<g
|
|
||||||
transform="translate(877.50354,-102.83507)"
|
|
||||||
id="g16853-4"
|
|
||||||
style="enable-background:new">
|
|
||||||
<rect
|
|
||||||
transform="scale(1,-1)"
|
|
||||||
style="color:#000000;fill:url(#linearGradient14219);fill-opacity:1;fill-rule:nonzero;stroke:#868686;stroke-width:0.59377144999999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
|
|
||||||
id="rect6506-6"
|
|
||||||
width="11.281681"
|
|
||||||
height="11.26221"
|
|
||||||
x="-409.59354"
|
|
||||||
y="-284.40115"
|
|
||||||
rx="0.95632279"
|
|
||||||
ry="0.95632273" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
inkscape:export-ydpi="90"
|
|
||||||
inkscape:export-xdpi="90"
|
|
||||||
inkscape:export-filename="/home/jimmac/SparkleShare/gnome-mockups/boxes/interactive/img/checkbox-on.png"
|
|
||||||
transform="translate(343.99999,987.99997)"
|
|
||||||
id="g5886"
|
|
||||||
style="display:inline;enable-background:new">
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:url(#linearGradient5891-0-4);stroke-width:7.11431503;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
|
|
||||||
id="path5835"
|
|
||||||
inkscape:path-effect="#path-effect5837-4-6"
|
|
||||||
inkscape:original-d="m 198.5,240 5.25,5.25 13.98616,-14.43081"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
inkscape:original-d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
|
|
||||||
inkscape:path-effect="#path-effect5837-4-6"
|
|
||||||
id="path5880"
|
|
||||||
d="m 198.5,240 5.25,5.25 13.91205,-14.31964"
|
|
||||||
style="fill:none;stroke:#4787c8;stroke-width:3.55715752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
sodipodi:nodetypes="ccc" />
|
|
||||||
<path
|
|
||||||
style="fill:none;stroke:#7ea7d3;stroke-width:1.18571913px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="m 197.45937,240.47455 c -0.17828,-0.29362 -0.20087,-0.67548 -0.0603,-0.98892 0.14055,-0.31344 0.43739,-0.54812 0.77144,-0.62817 0.33405,-0.08 0.69314,-0.01 0.99635,0.15175 0.30321,0.16144 0.55146,0.40727 0.79165,0.65284 l 3.66429,3.74643 12.87946,-12.98973 c 0.20796,-0.20974 0.42306,-0.41969 0.68548,-0.55522 0.26242,-0.13553 0.57293,-0.19052 0.85827,-0.11426 0.14267,0.0381 0.27708,0.10787 0.38874,0.20452 0.11167,0.0966 0.20021,0.22004 0.25479,0.35726 0.0546,0.13722 0.075,0.28793 0.0585,0.43468 -0.0165,0.14674 -0.07,0.28919 -0.15422,0.41052"
|
|
||||||
id="path5882"
|
|
||||||
inkscape:path-effect="#path-effect5884-4-7"
|
|
||||||
inkscape:original-d="m 197.45937,240.47455 c 0.65604,-0.56057 2.02485,-1.34847 2.49911,-0.8125 l 3.66429,3.74643 12.87946,-12.98973 c 0.6875,-0.6875 2.09152,0.7375 2.09152,0.7375"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="csccc" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 8.8 KiB |
@ -1,130 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="300"
|
|
||||||
height="80"
|
|
||||||
id="svg7355"
|
|
||||||
version="1.1"
|
|
||||||
inkscape:version="0.48.2 r9819"
|
|
||||||
sodipodi:docname="logged-in-indicator.svg">
|
|
||||||
<metadata
|
|
||||||
id="metadata4175">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<sodipodi:namedview
|
|
||||||
pagecolor="#2c1cff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1"
|
|
||||||
objecttolerance="10"
|
|
||||||
gridtolerance="10"
|
|
||||||
guidetolerance="10"
|
|
||||||
inkscape:pageopacity="1"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:window-width="1440"
|
|
||||||
inkscape:window-height="843"
|
|
||||||
id="namedview4173"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="2.8760889"
|
|
||||||
inkscape:cx="106.00403"
|
|
||||||
inkscape:cy="80.68078"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="27"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="g30864" />
|
|
||||||
<defs
|
|
||||||
id="defs7357">
|
|
||||||
<radialGradient
|
|
||||||
xlink:href="#linearGradient36429"
|
|
||||||
id="radialGradient7461"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(2.5919312,0,0,0.57582113,-20.687059,48.400487)"
|
|
||||||
cx="47.428951"
|
|
||||||
cy="167.16817"
|
|
||||||
fx="47.428951"
|
|
||||||
fy="167.16817"
|
|
||||||
r="37" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient36429">
|
|
||||||
<stop
|
|
||||||
id="stop36431"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
|
||||||
<stop
|
|
||||||
id="stop36433"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient
|
|
||||||
xlink:href="#linearGradient36471"
|
|
||||||
id="radialGradient7463"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
|
|
||||||
cx="49.067139"
|
|
||||||
cy="242.50381"
|
|
||||||
fx="49.067139"
|
|
||||||
fy="242.50381"
|
|
||||||
r="37.00671" />
|
|
||||||
<linearGradient
|
|
||||||
id="linearGradient36471">
|
|
||||||
<stop
|
|
||||||
id="stop36473"
|
|
||||||
offset="0"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
|
||||||
<stop
|
|
||||||
id="stop36475"
|
|
||||||
offset="1"
|
|
||||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient
|
|
||||||
r="37.00671"
|
|
||||||
fy="242.50381"
|
|
||||||
fx="49.067139"
|
|
||||||
cy="242.50381"
|
|
||||||
cx="49.067139"
|
|
||||||
gradientTransform="matrix(3.4218418,0,0,0.03365337,-61.309005,138.5071)"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
id="radialGradient7488"
|
|
||||||
xlink:href="#linearGradient36471" />
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
id="layer1"
|
|
||||||
transform="matrix(1.6213276,0,0,1.6213276,-431.6347,-272.5745)">
|
|
||||||
<g
|
|
||||||
style="display:inline"
|
|
||||||
id="g30864"
|
|
||||||
transform="translate(255.223,70.118091)">
|
|
||||||
<rect
|
|
||||||
ry="3.4593496"
|
|
||||||
rx="8.8641119"
|
|
||||||
y="76.159348"
|
|
||||||
x="12.596948"
|
|
||||||
height="71.116341"
|
|
||||||
width="182.22595"
|
|
||||||
id="rect14000"
|
|
||||||
style="opacity:0.371875;fill:url(#radialGradient7461);fill-opacity:1;stroke:none" />
|
|
||||||
<path
|
|
||||||
id="rect34520"
|
|
||||||
d="m 194.80022,146.83551 -182.559919,0"
|
|
||||||
style="opacity:0.35;fill:none;stroke:url(#radialGradient7488);stroke-width:0.61184424;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
|
||||||
connector-curvature="0"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
sodipodi:nodetypes="cc" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 78 KiB |
33
data/theme/panel-border.svg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="3"
|
||||||
|
height="10"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;stroke-width:0.43599999000000000;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
id="rect3779"
|
||||||
|
width="3"
|
||||||
|
height="10"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
<rect
|
||||||
|
style="fill:#536272;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
id="rect3796"
|
||||||
|
width="3"
|
||||||
|
height="1"
|
||||||
|
x="0"
|
||||||
|
y="9" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 787 B |
@ -9,7 +9,7 @@
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
width="17"
|
width="21"
|
||||||
height="10"
|
height="10"
|
||||||
id="svg2"
|
id="svg2"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
@ -66,9 +66,9 @@
|
|||||||
<rect
|
<rect
|
||||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke-width:0.43599999;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
id="rect3796"
|
id="rect3796"
|
||||||
width="7"
|
width="3"
|
||||||
height="2"
|
height="2"
|
||||||
x="5"
|
x="9"
|
||||||
y="8" />
|
y="8" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
64
data/theme/scroll-hhandle.svg
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="10"
|
||||||
|
height="4"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="scroll-hhandle.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
</defs>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||||
|
id="rect3592"
|
||||||
|
width="2"
|
||||||
|
height="4"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
rx="0"
|
||||||
|
ry="0" />
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#rect3592"
|
||||||
|
id="use2825"
|
||||||
|
transform="translate(8,0)"
|
||||||
|
width="10"
|
||||||
|
height="4" />
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#use2825"
|
||||||
|
id="use2827"
|
||||||
|
transform="translate(-4,0)"
|
||||||
|
width="10"
|
||||||
|
height="4" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
62
data/theme/scroll-vhandle.svg
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="4"
|
||||||
|
height="10"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="scroll-hhandle.svg">
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||||
|
id="rect3592"
|
||||||
|
width="2"
|
||||||
|
height="4"
|
||||||
|
x="0"
|
||||||
|
y="-4"
|
||||||
|
rx="0"
|
||||||
|
ry="0"
|
||||||
|
transform="matrix(0,1,-1,0,0,0)" />
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#rect3592"
|
||||||
|
id="use3705"
|
||||||
|
transform="translate(0,4)"
|
||||||
|
width="4"
|
||||||
|
height="10" />
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#use3705"
|
||||||
|
id="use3707"
|
||||||
|
transform="translate(0,4)"
|
||||||
|
width="4"
|
||||||
|
height="10" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -1,120 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
version="1.0"
|
|
||||||
id="Foreground"
|
|
||||||
x="0px"
|
|
||||||
y="0px"
|
|
||||||
width="32"
|
|
||||||
height="32"
|
|
||||||
viewBox="0 0 23.272727 23.272727"
|
|
||||||
enable-background="new 0 0 16 16"
|
|
||||||
xml:space="preserve"
|
|
||||||
sodipodi:version="0.32"
|
|
||||||
inkscape:version="0.48.2 r9819"
|
|
||||||
sodipodi:docname="summary-counter.svg"
|
|
||||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
|
||||||
id="metadata2399"><rdf:RDF><cc:Work
|
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
|
||||||
id="defs2397"><linearGradient
|
|
||||||
id="linearGradient3173"><stop
|
|
||||||
style="stop-color:#c4c4c4;stop-opacity:1;"
|
|
||||||
offset="0"
|
|
||||||
id="stop3175" /><stop
|
|
||||||
style="stop-color:#ffffff;stop-opacity:1;"
|
|
||||||
offset="1"
|
|
||||||
id="stop3177" /></linearGradient><inkscape:perspective
|
|
||||||
sodipodi:type="inkscape:persp3d"
|
|
||||||
inkscape:vp_x="0 : 8 : 1"
|
|
||||||
inkscape:vp_y="0 : 1000 : 0"
|
|
||||||
inkscape:vp_z="16 : 8 : 1"
|
|
||||||
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
|
||||||
id="perspective2401" /><filter
|
|
||||||
color-interpolation-filters="sRGB"
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="filter16494-4"
|
|
||||||
x="-0.20989846"
|
|
||||||
width="1.4197969"
|
|
||||||
y="-0.20903821"
|
|
||||||
height="1.4180764"><feGaussianBlur
|
|
||||||
inkscape:collect="always"
|
|
||||||
stdDeviation="1.3282637"
|
|
||||||
id="feGaussianBlur16496-8" /></filter><radialGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
xlink:href="#linearGradient16498-6"
|
|
||||||
id="radialGradient16504-1"
|
|
||||||
cx="7.6582627"
|
|
||||||
cy="5.8191104"
|
|
||||||
fx="7.6582627"
|
|
||||||
fy="5.8191104"
|
|
||||||
r="8.6928644"
|
|
||||||
gradientTransform="matrix(1.0474339,0,0,1.0517402,-0.3632615,-0.42032492)"
|
|
||||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
|
||||||
inkscape:collect="always"
|
|
||||||
id="linearGradient16498-6"><stop
|
|
||||||
style="stop-color:#9FD0FF;stop-opacity:1"
|
|
||||||
offset="0"
|
|
||||||
id="stop16500-8" /><stop
|
|
||||||
style="stop-color:#3465A4;stop-opacity:1"
|
|
||||||
offset="1"
|
|
||||||
id="stop16502-0" /></linearGradient></defs><sodipodi:namedview
|
|
||||||
inkscape:window-height="709"
|
|
||||||
inkscape:window-width="1366"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
guidetolerance="10.0"
|
|
||||||
gridtolerance="10.0"
|
|
||||||
objecttolerance="10.0"
|
|
||||||
borderopacity="1.0"
|
|
||||||
bordercolor="#666666"
|
|
||||||
pagecolor="#000000"
|
|
||||||
id="base"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="11.313708"
|
|
||||||
inkscape:cx="15.386407"
|
|
||||||
inkscape:cy="13.739577"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="1179"
|
|
||||||
inkscape:current-layer="g16402-8"
|
|
||||||
showguides="true"
|
|
||||||
inkscape:guide-bbox="true"
|
|
||||||
borderlayer="true"
|
|
||||||
inkscape:showpageshadow="false"
|
|
||||||
inkscape:window-maximized="1"><inkscape:grid
|
|
||||||
type="xygrid"
|
|
||||||
id="grid11246"
|
|
||||||
empspacing="5"
|
|
||||||
visible="true"
|
|
||||||
enabled="true"
|
|
||||||
snapvisiblegridlinesonly="true" /></sodipodi:namedview><g
|
|
||||||
style="display:inline"
|
|
||||||
id="g16402-8"
|
|
||||||
transform="translate(4.7533483,2.8238929)"><g
|
|
||||||
id="g3175-4"
|
|
||||||
transform="translate(-0.89995416,0.94028614)"><path
|
|
||||||
sodipodi:type="inkscape:offset"
|
|
||||||
inkscape:radius="0"
|
|
||||||
inkscape:original="M 7.65625 0.125 C 3.2589349 0.125 -0.3125 3.7070002 -0.3125 8.125 C -0.3125 12.543001 3.2589349 16.125 7.65625 16.125 C 12.053566 16.125 15.625 12.543001 15.625 8.125 C 15.625 3.7070002 12.053566 0.125 7.65625 0.125 z "
|
|
||||||
xlink:href="#path2394-32"
|
|
||||||
style="opacity:0.52994014;color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.18181825;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter16494-4);enable-background:accumulate"
|
|
||||||
id="path16480-5"
|
|
||||||
inkscape:href="#path2394-32"
|
|
||||||
d="m 7.65625,0.125 c -4.3973151,0 -7.96875,3.5820002 -7.96875,8 0,4.418001 3.5714349,8 7.96875,8 4.397316,0 7.96875,-3.581999 7.96875,-8 0,-4.4179998 -3.571434,-8 -7.96875,-8 z"
|
|
||||||
transform="translate(0,1.028519)" /><path
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="m -0.30428257,8.1237596 c 0,-4.4179998 3.56522987,-7.9999996 7.96254497,-7.9999996 4.3973156,0 7.9625456,3.5819998 7.9625456,7.9999996 0,4.4180014 -3.56523,8.0000004 -7.9625456,8.0000004 -4.3973151,0 -7.96254497,-3.581999 -7.96254497,-8.0000004 z"
|
|
||||||
id="path2394-32"
|
|
||||||
style="color:#000000;fill:url(#radialGradient16504-1);fill-opacity:1;fill-rule:nonzero;stroke:#eeeeec;stroke-width:1.4545455;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
|
||||||
sodipodi:nodetypes="csssc"
|
|
||||||
inkscape:connector-curvature="0" /><g
|
|
||||||
id="g3172-6" /></g></g></svg>
|
|
Before Width: | Height: | Size: 5.4 KiB |
@ -9,7 +9,7 @@
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
width="65"
|
width="64"
|
||||||
height="22"
|
height="22"
|
||||||
id="svg3273"
|
id="svg3273"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
@ -9,7 +9,7 @@
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
width="65"
|
width="64"
|
||||||
height="22"
|
height="22"
|
||||||
id="svg3012"
|
id="svg3012"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 850 B |
376
data/theme/ws-switch-arrow-down.svg
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg25070"
|
||||||
|
inkscape:version="0.48.0 r9654"
|
||||||
|
sodipodi:docname="ws-switch-arrow-down.svg">
|
||||||
|
<metadata
|
||||||
|
id="metadata3353">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="718"
|
||||||
|
inkscape:window-height="480"
|
||||||
|
id="namedview3351"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="2.6979167"
|
||||||
|
inkscape:cx="48"
|
||||||
|
inkscape:cy="48"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:current-layer="svg25070" />
|
||||||
|
<defs
|
||||||
|
id="defs25072">
|
||||||
|
<linearGradient
|
||||||
|
x1="-86.552246"
|
||||||
|
y1="185.439"
|
||||||
|
x2="-83.37072"
|
||||||
|
y2="197.31261"
|
||||||
|
id="linearGradient24957"
|
||||||
|
xlink:href="#linearGradient4034-0-4"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(6,0)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4034-0-4">
|
||||||
|
<stop
|
||||||
|
id="stop4036-5-7"
|
||||||
|
style="stop-color:#eeeeec;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4038-9-6"
|
||||||
|
style="stop-color:#babdb6;stop-opacity:1"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter24765">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix24767" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix24769" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
x1="-74.520325"
|
||||||
|
y1="169.06032"
|
||||||
|
x2="-74.520325"
|
||||||
|
y2="205.94189"
|
||||||
|
id="linearGradient24955"
|
||||||
|
xlink:href="#linearGradient4632-1-3-9-3-2"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(-5,0)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4632-1-3-9-3-2">
|
||||||
|
<stop
|
||||||
|
id="stop4634-1-8-3-9-0"
|
||||||
|
style="stop-color:#eeeeec;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4636-1-9-9-8-8"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0.0274937" />
|
||||||
|
<stop
|
||||||
|
id="stop4638-8-3-9-6-6"
|
||||||
|
style="stop-color:#f2f2f2;stop-opacity:1"
|
||||||
|
offset="0.274937" />
|
||||||
|
<stop
|
||||||
|
id="stop4640-8-5-7-8-9"
|
||||||
|
style="stop-color:#eeeeec;stop-opacity:1"
|
||||||
|
offset="0.38707438" />
|
||||||
|
<stop
|
||||||
|
id="stop4642-5-41-9-6-9"
|
||||||
|
style="stop-color:#d9dad8;stop-opacity:1"
|
||||||
|
offset="0.66528589" />
|
||||||
|
<stop
|
||||||
|
id="stop4644-5-2-7-9-2"
|
||||||
|
style="stop-color:#dfe0dd;stop-opacity:1"
|
||||||
|
offset="0.76745707" />
|
||||||
|
<stop
|
||||||
|
id="stop4646-3-2-3-7-3"
|
||||||
|
style="stop-color:#f0f0f0;stop-opacity:1"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
cx="-33.412369"
|
||||||
|
cy="185.74171"
|
||||||
|
r="2.3554697"
|
||||||
|
fx="-33.412369"
|
||||||
|
fy="185.74171"
|
||||||
|
id="radialGradient24959"
|
||||||
|
xlink:href="#linearGradient4869-4-1"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4869-4-1">
|
||||||
|
<stop
|
||||||
|
id="stop4871-6-2"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4879-7-4"
|
||||||
|
style="stop-color:#eeeeec;stop-opacity:1"
|
||||||
|
offset="0.31807542" />
|
||||||
|
<stop
|
||||||
|
id="stop4877-6-1"
|
||||||
|
style="stop-color:#c8c9c6;stop-opacity:1"
|
||||||
|
offset="0.74691135" />
|
||||||
|
<stop
|
||||||
|
id="stop4873-1-0"
|
||||||
|
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25011">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25013" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25015" />
|
||||||
|
</filter>
|
||||||
|
<radialGradient
|
||||||
|
cx="-33.412369"
|
||||||
|
cy="185.74171"
|
||||||
|
r="2.3554697"
|
||||||
|
fx="-33.412369"
|
||||||
|
fy="185.74171"
|
||||||
|
id="radialGradient24961"
|
||||||
|
xlink:href="#linearGradient4869-4-0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4869-4-0">
|
||||||
|
<stop
|
||||||
|
id="stop4871-6-8"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4879-7-5"
|
||||||
|
style="stop-color:#eeeeec;stop-opacity:1"
|
||||||
|
offset="0.31807542" />
|
||||||
|
<stop
|
||||||
|
id="stop4877-6-5"
|
||||||
|
style="stop-color:#c8c9c6;stop-opacity:1"
|
||||||
|
offset="0.74691135" />
|
||||||
|
<stop
|
||||||
|
id="stop4873-1-4"
|
||||||
|
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25023">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25025" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25027" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
x1="-39.858727"
|
||||||
|
y1="184.61784"
|
||||||
|
x2="-38.244785"
|
||||||
|
y2="188.84898"
|
||||||
|
id="linearGradient24963"
|
||||||
|
xlink:href="#linearGradient4941"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4941">
|
||||||
|
<stop
|
||||||
|
id="stop4943"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4945"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25033">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25035" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25037" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
x1="-39.858727"
|
||||||
|
y1="184.61784"
|
||||||
|
x2="-38.244785"
|
||||||
|
y2="188.84898"
|
||||||
|
id="linearGradient24965"
|
||||||
|
xlink:href="#linearGradient4941-7"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4941-7">
|
||||||
|
<stop
|
||||||
|
id="stop4943-2"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop4945-5"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25043">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25045" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25047" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25049">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25051" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25053" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
color-interpolation-filters="sRGB"
|
||||||
|
id="filter25055">
|
||||||
|
<feColorMatrix
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
values="1"
|
||||||
|
type="saturate"
|
||||||
|
id="feColorMatrix25057" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
id="feColorMatrix25059" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
transform="matrix(0,1,-1,0,48.0003,4.1307112e-7)"
|
||||||
|
id="layer1">
|
||||||
|
<g
|
||||||
|
transform="matrix(-2,0,0,2,-97.2497,-374.967)"
|
||||||
|
id="g4030-1-8"
|
||||||
|
style="stroke:#000000;stroke-opacity:1;display:inline">
|
||||||
|
<path
|
||||||
|
d="m -72.5,173.5 -14,14 14,14"
|
||||||
|
id="path3165-7-3"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
||||||
|
transform="matrix(-3.34328,0,0,3.34328,-89.2797,-623.176)"
|
||||||
|
id="path4050-2-7-9-4"
|
||||||
|
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
||||||
|
transform="matrix(-3.34328,0,0,3.34328,-111.2797,-623.176)"
|
||||||
|
id="path4050-2-7-9-4-8"
|
||||||
|
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
||||||
|
transform="matrix(-2.86565,0,0,2.86565,-70.8457,-534.143)"
|
||||||
|
id="path4050-2-7-9-4-0"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
|
||||||
|
transform="matrix(-2.86565,0,0,2.86565,-92.8457,-534.143)"
|
||||||
|
id="path4050-2-7-9-4-0-9"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m 47.87528,-34.0295 c 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25 -32.25,32.25 c -2.2253,2.2253 -6.2747,2.2253 -8.5,0 -2.2253,-2.22528 -2.2253,-6.2747 0,-8.5 l 23.75,-23.75 -23.75,-23.75 c -1.73168,-1.6731 -2.295,-4.44228 -1.3546,-6.65894 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 z"
|
||||||
|
id="path3165-7-3-1"
|
||||||
|
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
d="m 41.8316,28.09418 c -0.014,-1.58898 0.54158,-3.18406 1.66868,-4.31118 l 23.75,-23.75 m -25.1046,-30.40894 c 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25"
|
||||||
|
id="path3165-7-3-1-9"
|
||||||
|
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 841 B |
447
data/theme/ws-switch-arrow-up.svg
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="96"
|
||||||
|
height="96"
|
||||||
|
id="svg25070"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.0 r9654"
|
||||||
|
sodipodi:docname="ws-switch-arrow-up.svg">
|
||||||
|
<defs
|
||||||
|
id="defs25072">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 24 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="48 : 24 : 1"
|
||||||
|
inkscape:persp3d-origin="24 : 16 : 1"
|
||||||
|
id="perspective25078" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective24985"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4034-0-4"
|
||||||
|
id="linearGradient24957"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(6)"
|
||||||
|
x1="-86.552246"
|
||||||
|
y1="185.439"
|
||||||
|
x2="-83.37072"
|
||||||
|
y2="197.31261" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient4034-0-4">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4036-5-7" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(186, 189, 182); stop-opacity: 1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4038-9-6" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
id="filter24765"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix24767"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix24769"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4632-1-3-9-3-2"
|
||||||
|
id="linearGradient24955"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(-5)"
|
||||||
|
x1="-74.520325"
|
||||||
|
y1="169.06032"
|
||||||
|
x2="-74.520325"
|
||||||
|
y2="205.94189" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4632-1-3-9-3-2">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4634-1-8-3-9-0" />
|
||||||
|
<stop
|
||||||
|
id="stop4636-1-9-9-8-8"
|
||||||
|
offset="0.0274937"
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4638-8-3-9-6-6"
|
||||||
|
offset="0.274937"
|
||||||
|
style="stop-color: rgb(242, 242, 242); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4640-8-5-7-8-9"
|
||||||
|
offset="0.38707438"
|
||||||
|
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4642-5-41-9-6-9"
|
||||||
|
offset="0.66528589"
|
||||||
|
style="stop-color: rgb(217, 218, 216); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4644-5-2-7-9-2"
|
||||||
|
offset="0.76745707"
|
||||||
|
style="stop-color: rgb(223, 224, 221); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(240, 240, 240); stop-opacity: 1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4646-3-2-3-7-3" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4869-4-1"
|
||||||
|
id="radialGradient24959"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)"
|
||||||
|
cx="-33.412369"
|
||||||
|
cy="185.74171"
|
||||||
|
fx="-33.412369"
|
||||||
|
fy="185.74171"
|
||||||
|
r="2.3554697" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4869-4-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4871-6-2" />
|
||||||
|
<stop
|
||||||
|
id="stop4879-7-4"
|
||||||
|
offset="0.31807542"
|
||||||
|
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4877-6-1"
|
||||||
|
offset="0.74691135"
|
||||||
|
style="stop-color: rgb(200, 201, 198); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(211, 215, 207); stop-opacity: 1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4873-1-0" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
id="filter25011"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25013"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25015"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4869-4-0"
|
||||||
|
id="radialGradient24961"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)"
|
||||||
|
cx="-33.412369"
|
||||||
|
cy="185.74171"
|
||||||
|
fx="-33.412369"
|
||||||
|
fy="185.74171"
|
||||||
|
r="2.3554697" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4869-4-0">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4871-6-8" />
|
||||||
|
<stop
|
||||||
|
id="stop4879-7-5"
|
||||||
|
offset="0.31807542"
|
||||||
|
style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
id="stop4877-6-5"
|
||||||
|
offset="0.74691135"
|
||||||
|
style="stop-color: rgb(200, 201, 198); stop-opacity: 1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(211, 215, 207); stop-opacity: 1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4873-1-4" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
id="filter25023"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25025"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25027"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4941"
|
||||||
|
id="linearGradient24963"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-39.858727"
|
||||||
|
y1="184.61784"
|
||||||
|
x2="-38.244785"
|
||||||
|
y2="188.84898" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient4941">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4943" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4945" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
id="filter25033"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25035"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25037"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4941-7"
|
||||||
|
id="linearGradient24965"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-39.858727"
|
||||||
|
y1="184.61784"
|
||||||
|
x2="-38.244785"
|
||||||
|
y2="188.84898" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient4941-7">
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4943-2" />
|
||||||
|
<stop
|
||||||
|
style="stop-color: rgb(255, 255, 255); stop-opacity: 0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4945-5" />
|
||||||
|
</linearGradient>
|
||||||
|
<filter
|
||||||
|
id="filter25043"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25045"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25047"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
id="filter25049"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25051"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25053"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
<filter
|
||||||
|
id="filter25055"
|
||||||
|
inkscape:label="Invert"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="1"
|
||||||
|
height="1"
|
||||||
|
inkscape:menu="Color"
|
||||||
|
inkscape:menu-tooltip="Invert colors"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25057"
|
||||||
|
type="saturate"
|
||||||
|
values="1"
|
||||||
|
result="fbSourceGraphic" />
|
||||||
|
<feColorMatrix
|
||||||
|
id="feColorMatrix25059"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2.8284271"
|
||||||
|
inkscape:cx="-12.356322"
|
||||||
|
inkscape:cy="57.536221"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1200"
|
||||||
|
inkscape:window-height="840"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="26"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata25075">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0, 48)">
|
||||||
|
<g
|
||||||
|
id="g3181"
|
||||||
|
transform="matrix(0,1,-1,0,48.0003,-48)">
|
||||||
|
<g
|
||||||
|
style="stroke:#000000;stroke-opacity:1;display:inline"
|
||||||
|
transform="matrix(2,0,0,2,193.25,-374.967)"
|
||||||
|
id="g4030-1-8">
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
d="m -72.5,173.5 -14,14 14,14"
|
||||||
|
id="path3165-7-3"
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
transform="matrix(3.34328,0,0,3.34328,185.28,-623.176)"
|
||||||
|
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
|
||||||
|
sodipodi:ry="2.09375"
|
||||||
|
sodipodi:rx="2.09375"
|
||||||
|
sodipodi:cy="186.40625"
|
||||||
|
sodipodi:cx="-38.59375"
|
||||||
|
id="path4050-2-7-9-4"
|
||||||
|
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
transform="matrix(3.34328,0,0,3.34328,207.28,-623.176)"
|
||||||
|
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
|
||||||
|
sodipodi:ry="2.09375"
|
||||||
|
sodipodi:rx="2.09375"
|
||||||
|
sodipodi:cy="186.40625"
|
||||||
|
sodipodi:cx="-38.59375"
|
||||||
|
id="path4050-2-7-9-4-8"
|
||||||
|
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
transform="matrix(2.86565,0,0,2.86565,166.846,-534.143)"
|
||||||
|
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
|
||||||
|
sodipodi:ry="2.09375"
|
||||||
|
sodipodi:rx="2.09375"
|
||||||
|
sodipodi:cy="186.40625"
|
||||||
|
sodipodi:cx="-38.59375"
|
||||||
|
id="path4050-2-7-9-4-0"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
transform="matrix(2.86565,0,0,2.86565,188.846,-534.143)"
|
||||||
|
d="m -36.5,186.40625 c 0,1.15635 -0.937404,2.09375 -2.09375,2.09375 -1.156346,0 -2.09375,-0.9374 -2.09375,-2.09375 0,-1.15635 0.937404,-2.09375 2.09375,-2.09375 1.156346,0 2.09375,0.9374 2.09375,2.09375 z"
|
||||||
|
sodipodi:ry="2.09375"
|
||||||
|
sodipodi:rx="2.09375"
|
||||||
|
sodipodi:cy="186.40625"
|
||||||
|
sodipodi:cx="-38.59375"
|
||||||
|
id="path4050-2-7-9-4-0-9"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
transform="matrix(2,0,0,2,-586,-765.967)"
|
||||||
|
sodipodi:nodetypes="ccccscccsc"
|
||||||
|
id="path3165-7-3-1"
|
||||||
|
d="m 317.06251,365.96875 c -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 l -16.125,16.125 16.125,16.125 c 1.11265,1.11265 3.13735,1.11265 4.25,0 1.11265,-1.11264 1.11265,-3.13735 0,-4.25 l -11.875,-11.875 11.875,-11.875 c 0.86584,-0.83655 1.1475,-2.22114 0.6773,-3.32947 -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 z"
|
||||||
|
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
transform="matrix(2,0,0,2,-586,-765.967)"
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
id="path3165-7-3-1-9"
|
||||||
|
d="m 320.08435,397.03059 c 0.007,-0.79449 -0.27079,-1.59203 -0.83434,-2.15559 L 307.37501,383 m 12.5523,-15.20447 c -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 L 298.87501,383"
|
||||||
|
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 16 KiB |
@ -1 +0,0 @@
|
|||||||
SUBDIRS = reference
|
|
@ -1 +0,0 @@
|
|||||||
SUBDIRS = shell st
|
|
@ -1,117 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
# We require automake 1.6 at least.
|
|
||||||
AUTOMAKE_OPTIONS = 1.6
|
|
||||||
|
|
||||||
# This is a blank Makefile.am for using gtk-doc.
|
|
||||||
# Copy this to your project's API docs directory and modify the variables to
|
|
||||||
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
|
|
||||||
# of using the various options.
|
|
||||||
|
|
||||||
# The name of the module, e.g. 'glib'.
|
|
||||||
DOC_MODULE=shell
|
|
||||||
|
|
||||||
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
|
|
||||||
#DOC_MODULE_VERSION=2
|
|
||||||
|
|
||||||
|
|
||||||
# The top-level SGML file. You can change this if you want to.
|
|
||||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
|
||||||
|
|
||||||
# Directories containing the source code
|
|
||||||
# gtk-doc will search all .c and .h files beneath these paths
|
|
||||||
# for inline comments documenting functions and macros.
|
|
||||||
DOC_SOURCE_DIR=$(top_srcdir)/src
|
|
||||||
|
|
||||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
|
||||||
SCANGOBJ_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-scan.
|
|
||||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
|
||||||
SCAN_OPTIONS=--rebuild-types
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mkdb.
|
|
||||||
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
|
|
||||||
MKDB_OPTIONS=--xml-mode --output-format=xml
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mktmpl
|
|
||||||
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
|
|
||||||
MKTMPL_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mkhtml
|
|
||||||
MKHTML_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-fixref. Not normally needed.
|
|
||||||
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
|
|
||||||
FIXXREF_OPTIONS=
|
|
||||||
|
|
||||||
# Used for dependencies. The docs will be rebuilt if any of these change.
|
|
||||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
|
|
||||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
|
|
||||||
HFILE_GLOB=$(top_srcdir)/src/*.h
|
|
||||||
CFILE_GLOB=$(top_srcdir)/src/*.c
|
|
||||||
|
|
||||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
|
|
||||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
|
|
||||||
EXTRA_HFILES=
|
|
||||||
|
|
||||||
# Header files or dirs to ignore when scanning. Use base file/dir names
|
|
||||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
|
||||||
IGNORE_HFILES= \
|
|
||||||
calendar-server \
|
|
||||||
gvc \
|
|
||||||
hotplug-sniffer \
|
|
||||||
st \
|
|
||||||
tray \
|
|
||||||
gactionmuxer.h \
|
|
||||||
gactionobservable.h \
|
|
||||||
gactionobserver.h \
|
|
||||||
shell-recorder-src.h
|
|
||||||
|
|
||||||
if !BUILD_RECORDER
|
|
||||||
IGNORE_HFILES += shell-recorder.h
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Images to copy into HTML directory.
|
|
||||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
|
||||||
HTML_IMAGES=
|
|
||||||
|
|
||||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
|
||||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
|
||||||
content_files=
|
|
||||||
|
|
||||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
|
||||||
# These files must be listed here *and* in content_files
|
|
||||||
# e.g. expand_content_files=running.sgml
|
|
||||||
expand_content_files=
|
|
||||||
|
|
||||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
|
|
||||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
|
|
||||||
# signals and properties.
|
|
||||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
|
||||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
|
||||||
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
|
|
||||||
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
|
|
||||||
|
|
||||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
|
||||||
include $(top_srcdir)/gtk-doc.make
|
|
||||||
|
|
||||||
# Other files to distribute
|
|
||||||
# e.g. EXTRA_DIST += version.xml.in
|
|
||||||
EXTRA_DIST +=
|
|
||||||
|
|
||||||
# Files not to distribute
|
|
||||||
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
|
|
||||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
|
|
||||||
DISTCLEANFILES = $(DOC_MODULES).types
|
|
||||||
|
|
||||||
# Comment this out if you want 'make check' to test you doc status
|
|
||||||
# and run some sanity checks
|
|
||||||
if ENABLE_GTK_DOC
|
|
||||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
|
|
||||||
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
|
|
||||||
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
|
|
||||||
#TESTS = $(GTKDOC_CHECK)
|
|
||||||
endif
|
|
||||||
|
|
||||||
-include $(top_srcdir)/git.mk
|
|
@ -1,70 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
|
||||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
|
||||||
]>
|
|
||||||
<book id="index">
|
|
||||||
<bookinfo>
|
|
||||||
<title>Shell Reference Manual</title>
|
|
||||||
<releaseinfo>
|
|
||||||
for Shell @VERSION@.
|
|
||||||
<!--The latest version of this documentation can be found on-line at
|
|
||||||
<ulink role="online-location" url="http://[SERVER]/shell/index.html">http://[SERVER]/shell/</ulink>.-->
|
|
||||||
</releaseinfo>
|
|
||||||
</bookinfo>
|
|
||||||
|
|
||||||
<chapter>
|
|
||||||
<title>Actors</title>
|
|
||||||
<xi:include href="xml/shell-generic-container.xml"/>
|
|
||||||
<xi:include href="xml/shell-slicer.xml"/>
|
|
||||||
<xi:include href="xml/shell-stack.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter>
|
|
||||||
<title>Application tracking</title>
|
|
||||||
<xi:include href="xml/shell-app.xml"/>
|
|
||||||
<xi:include href="xml/shell-app-usage.xml"/>
|
|
||||||
<xi:include href="xml/shell-window-tracker.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter>
|
|
||||||
<title>Search</title>
|
|
||||||
<xi:include href="xml/shell-app-system.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter>
|
|
||||||
<title>Tray Icons</title>
|
|
||||||
<xi:include href="xml/shell-embedded-window.xml"/>
|
|
||||||
<xi:include href="xml/shell-gtk-embed.xml"/>
|
|
||||||
<xi:include href="xml/shell-tray-icon.xml"/>
|
|
||||||
<xi:include href="xml/shell-tray-manager.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter>
|
|
||||||
<title>Recorder</title>
|
|
||||||
<xi:include href="xml/shell-recorder.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter>
|
|
||||||
<title>Integration helpers and utilities</title>
|
|
||||||
<xi:include href="xml/shell-global.xml"/>
|
|
||||||
<xi:include href="xml/shell-wm.xml"/>
|
|
||||||
<xi:include href="xml/shell-xfixes-cursor.xml"/>
|
|
||||||
<xi:include href="xml/shell-util.xml"/>
|
|
||||||
<xi:include href="xml/shell-mount-operation.xml"/>
|
|
||||||
<xi:include href="xml/shell-mobile-providers.xml"/>
|
|
||||||
<xi:include href="xml/shell-network-agent.xml"/>
|
|
||||||
<xi:include href="xml/shell-polkit-authentication-agent.xml"/>
|
|
||||||
<xi:include href="xml/shell-tp-client.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter id="object-tree">
|
|
||||||
<title>Object Hierarchy</title>
|
|
||||||
<xi:include href="xml/tree_index.sgml"/>
|
|
||||||
</chapter>
|
|
||||||
<index id="api-index-full">
|
|
||||||
<title>API Index</title>
|
|
||||||
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
|
||||||
</index>
|
|
||||||
<index id="deprecated-api-index" role="deprecated">
|
|
||||||
<title>Index of deprecated API</title>
|
|
||||||
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
|
||||||
</index>
|
|
||||||
|
|
||||||
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
|
||||||
</book>
|
|
@ -1,104 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
# We require automake 1.6 at least.
|
|
||||||
AUTOMAKE_OPTIONS = 1.6
|
|
||||||
|
|
||||||
# This is a blank Makefile.am for using gtk-doc.
|
|
||||||
# Copy this to your project's API docs directory and modify the variables to
|
|
||||||
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
|
|
||||||
# of using the various options.
|
|
||||||
|
|
||||||
# The name of the module, e.g. 'glib'.
|
|
||||||
DOC_MODULE=st
|
|
||||||
|
|
||||||
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
|
|
||||||
#DOC_MODULE_VERSION=2
|
|
||||||
|
|
||||||
|
|
||||||
# The top-level SGML file. You can change this if you want to.
|
|
||||||
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
|
||||||
|
|
||||||
# Directories containing the source code
|
|
||||||
# gtk-doc will search all .c and .h files beneath these paths
|
|
||||||
# for inline comments documenting functions and macros.
|
|
||||||
DOC_SOURCE_DIR=$(top_srcdir)/src/st
|
|
||||||
|
|
||||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
|
||||||
SCANGOBJ_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-scan.
|
|
||||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
|
||||||
SCAN_OPTIONS=--rebuild-types --rebuild-sections
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mkdb.
|
|
||||||
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
|
|
||||||
MKDB_OPTIONS=--xml-mode --output-format=xml
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mktmpl
|
|
||||||
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
|
|
||||||
MKTMPL_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-mkhtml
|
|
||||||
MKHTML_OPTIONS=
|
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-fixref. Not normally needed.
|
|
||||||
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
|
|
||||||
FIXXREF_OPTIONS=
|
|
||||||
|
|
||||||
# Used for dependencies. The docs will be rebuilt if any of these change.
|
|
||||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
|
|
||||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
|
|
||||||
HFILE_GLOB=$(top_srcdir)/src/st/*.h
|
|
||||||
CFILE_GLOB=$(top_srcdir)/src/st/*.c
|
|
||||||
|
|
||||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
|
|
||||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
|
|
||||||
EXTRA_HFILES=
|
|
||||||
|
|
||||||
# Header files or dirs to ignore when scanning. Use base file/dir names
|
|
||||||
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
|
|
||||||
IGNORE_HFILES=st-private.h st-theme-node-private.h
|
|
||||||
|
|
||||||
# Images to copy into HTML directory.
|
|
||||||
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
|
|
||||||
HTML_IMAGES=
|
|
||||||
|
|
||||||
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
|
|
||||||
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
|
|
||||||
content_files=
|
|
||||||
|
|
||||||
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
|
|
||||||
# These files must be listed here *and* in content_files
|
|
||||||
# e.g. expand_content_files=running.sgml
|
|
||||||
expand_content_files=
|
|
||||||
|
|
||||||
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
|
|
||||||
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
|
|
||||||
# signals and properties.
|
|
||||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
|
||||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
|
||||||
GTKDOC_CFLAGS=
|
|
||||||
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la
|
|
||||||
|
|
||||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
|
||||||
include $(top_srcdir)/gtk-doc.make
|
|
||||||
|
|
||||||
# Other files to distribute
|
|
||||||
# e.g. EXTRA_DIST += version.xml.in
|
|
||||||
EXTRA_DIST +=
|
|
||||||
|
|
||||||
# Files not to distribute
|
|
||||||
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
|
|
||||||
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
|
|
||||||
DISTCLEANFILES = $(DOC_MODULE).types $(DOC_MODULE)-sections.txt
|
|
||||||
|
|
||||||
# Comment this out if you want 'make check' to test you doc status
|
|
||||||
# and run some sanity checks
|
|
||||||
if ENABLE_GTK_DOC
|
|
||||||
TESTS_ENVIRONMENT = cd $(srcdir) && \
|
|
||||||
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
|
|
||||||
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
|
|
||||||
#TESTS = $(GTKDOC_CHECK)
|
|
||||||
endif
|
|
||||||
|
|
||||||
-include $(top_srcdir)/git.mk
|
|
@ -1,64 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
|
||||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
|
||||||
]>
|
|
||||||
<book id="index">
|
|
||||||
<bookinfo>
|
|
||||||
<title>St Reference Manual</title>
|
|
||||||
<releaseinfo>
|
|
||||||
for St @VERSION@.
|
|
||||||
<!--The latest version of this documentation can be found on-line at
|
|
||||||
<ulink role="online-location" url="http://[SERVER]/st/index.html">http://[SERVER]/st/</ulink>.-->
|
|
||||||
</releaseinfo>
|
|
||||||
</bookinfo>
|
|
||||||
|
|
||||||
<part>
|
|
||||||
<title>API reference</title>
|
|
||||||
<chapter id="base">
|
|
||||||
<title>Abstract classes and Interfaces</title>
|
|
||||||
<xi:include href="xml/st-widget.xml"/>
|
|
||||||
<xi:include href="xml/st-widget-accessible.xml"/>
|
|
||||||
<xi:include href="xml/st-scrollable.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter id="widgets">
|
|
||||||
<title>Widgets</title>
|
|
||||||
<xi:include href="xml/st-button.xml"/>
|
|
||||||
<xi:include href="xml/st-drawing-area.xml"/>
|
|
||||||
<xi:include href="xml/st-entry.xml"/>
|
|
||||||
<xi:include href="xml/st-icon.xml"/>
|
|
||||||
<xi:include href="xml/st-label.xml"/>
|
|
||||||
</chapter>
|
|
||||||
<chapter id="containers">
|
|
||||||
<title>Containers</title>
|
|
||||||
<xi:include href="xml/st-bin.xml"/>
|
|
||||||
<xi:include href="xml/st-box-layout.xml"/>
|
|
||||||
<xi:include href="xml/st-scroll-view.xml"/>
|
|
||||||
<xi:include href="xml/st-table.xml"/>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="styling">
|
|
||||||
<title>Styling</title>
|
|
||||||
<xi:include href="xml/st-theme.xml"/>
|
|
||||||
<xi:include href="xml/st-theme-context.xml"/>
|
|
||||||
<xi:include href="xml/st-theme-node.xml"/>
|
|
||||||
<xi:include href="xml/st-theme-node-transition.xml"/>
|
|
||||||
<xi:include href="xml/st-texture-cache.xml"/>
|
|
||||||
</chapter>
|
|
||||||
</part>
|
|
||||||
<chapter id="object-tree">
|
|
||||||
<title>Object Hierarchy</title>
|
|
||||||
<xi:include href="xml/tree_index.sgml"/>
|
|
||||||
</chapter>
|
|
||||||
<index id="api-index-full">
|
|
||||||
<title>API Index</title>
|
|
||||||
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
|
||||||
</index>
|
|
||||||
<index id="deprecated-api-index" role="deprecated">
|
|
||||||
<title>Index of deprecated API</title>
|
|
||||||
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
|
|
||||||
</index>
|
|
||||||
|
|
||||||
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
|
|
||||||
</book>
|
|
@ -66,11 +66,4 @@ its dependencies to build from tarballs.</description>
|
|||||||
<gnome:userid>marinaz</gnome:userid>
|
<gnome:userid>marinaz</gnome:userid>
|
||||||
</foaf:Person>
|
</foaf:Person>
|
||||||
</maintainer>
|
</maintainer>
|
||||||
<maintainer>
|
|
||||||
<foaf:Person>
|
|
||||||
<foaf:name>Florian Müllner</foaf:name>
|
|
||||||
<foaf:mbox rdf:resource="mailto:fmuellner@gnome.org" />
|
|
||||||
<gnome:userid>fmuellner</gnome:userid>
|
|
||||||
</foaf:Person>
|
|
||||||
</maintainer>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,108 +1,73 @@
|
|||||||
NULL =
|
|
||||||
|
|
||||||
EXTRA_DIST = misc/config.js.in
|
|
||||||
CLEANFILES = misc/config.js
|
|
||||||
|
|
||||||
misc/config.js: misc/config.js.in Makefile
|
|
||||||
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \
|
|
||||||
sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \
|
|
||||||
-e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \
|
|
||||||
-e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \
|
|
||||||
-e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \
|
|
||||||
-e "s|[@]datadir@|$(datadir)|g" \
|
|
||||||
-e "s|[@]libexecdir@|$(libexecdir)|g" \
|
|
||||||
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \
|
|
||||||
$< > $@
|
|
||||||
|
|
||||||
jsdir = $(pkgdatadir)/js
|
jsdir = $(pkgdatadir)/js
|
||||||
|
|
||||||
nobase_dist_js_DATA = \
|
nobase_dist_js_DATA = \
|
||||||
gdm/batch.js \
|
|
||||||
gdm/fingerprint.js \
|
|
||||||
gdm/loginDialog.js \
|
|
||||||
gdm/powerMenu.js \
|
|
||||||
gdm/realmd.js \
|
|
||||||
gdm/util.js \
|
|
||||||
extensionPrefs/main.js \
|
|
||||||
misc/config.js \
|
misc/config.js \
|
||||||
misc/extensionUtils.js \
|
misc/docInfo.js \
|
||||||
misc/fileUtils.js \
|
misc/fileUtils.js \
|
||||||
|
misc/format.js \
|
||||||
misc/gnomeSession.js \
|
misc/gnomeSession.js \
|
||||||
misc/history.js \
|
misc/history.js \
|
||||||
misc/jsParse.js \
|
|
||||||
misc/loginManager.js \
|
|
||||||
misc/modemManager.js \
|
misc/modemManager.js \
|
||||||
misc/params.js \
|
misc/params.js \
|
||||||
|
misc/screenSaver.js \
|
||||||
misc/util.js \
|
misc/util.js \
|
||||||
perf/core.js \
|
perf/core.js \
|
||||||
ui/altTab.js \
|
ui/altTab.js \
|
||||||
ui/appDisplay.js \
|
ui/appDisplay.js \
|
||||||
ui/appFavorites.js \
|
ui/appFavorites.js \
|
||||||
|
ui/automountManager.js \
|
||||||
|
ui/autorunManager.js \
|
||||||
ui/boxpointer.js \
|
ui/boxpointer.js \
|
||||||
ui/calendar.js \
|
ui/calendar.js \
|
||||||
ui/checkBox.js \
|
ui/chrome.js \
|
||||||
ui/ctrlAltTab.js \
|
ui/ctrlAltTab.js \
|
||||||
ui/dash.js \
|
ui/dash.js \
|
||||||
ui/dateMenu.js \
|
ui/dateMenu.js \
|
||||||
ui/dnd.js \
|
ui/dnd.js \
|
||||||
|
ui/docDisplay.js \
|
||||||
ui/endSessionDialog.js \
|
ui/endSessionDialog.js \
|
||||||
ui/extensionSystem.js \
|
|
||||||
ui/extensionDownloader.js \
|
|
||||||
ui/environment.js \
|
ui/environment.js \
|
||||||
ui/flashspot.js \
|
ui/extensionSystem.js \
|
||||||
ui/ibusCandidatePopup.js\
|
|
||||||
ui/grabHelper.js \
|
|
||||||
ui/iconGrid.js \
|
ui/iconGrid.js \
|
||||||
ui/keyboard.js \
|
ui/keyboard.js \
|
||||||
ui/layout.js \
|
ui/layout.js \
|
||||||
ui/lightbox.js \
|
ui/lightbox.js \
|
||||||
|
ui/link.js \
|
||||||
ui/lookingGlass.js \
|
ui/lookingGlass.js \
|
||||||
ui/magnifier.js \
|
ui/magnifier.js \
|
||||||
ui/magnifierDBus.js \
|
ui/magnifierDBus.js \
|
||||||
ui/main.js \
|
ui/main.js \
|
||||||
ui/messageTray.js \
|
ui/messageTray.js \
|
||||||
ui/modalDialog.js \
|
ui/modalDialog.js \
|
||||||
ui/sessionMode.js \
|
|
||||||
ui/shellEntry.js \
|
|
||||||
ui/shellMountOperation.js \
|
ui/shellMountOperation.js \
|
||||||
ui/notificationDaemon.js \
|
ui/notificationDaemon.js \
|
||||||
ui/overview.js \
|
ui/overview.js \
|
||||||
ui/panel.js \
|
ui/panel.js \
|
||||||
ui/panelMenu.js \
|
ui/panelMenu.js \
|
||||||
ui/pointerWatcher.js \
|
ui/placeDisplay.js \
|
||||||
|
ui/polkitAuthenticationAgent.js \
|
||||||
ui/popupMenu.js \
|
ui/popupMenu.js \
|
||||||
ui/remoteSearch.js \
|
|
||||||
ui/runDialog.js \
|
ui/runDialog.js \
|
||||||
ui/screenShield.js \
|
|
||||||
ui/scripting.js \
|
ui/scripting.js \
|
||||||
ui/search.js \
|
ui/search.js \
|
||||||
ui/searchDisplay.js \
|
ui/searchDisplay.js \
|
||||||
ui/shellDBus.js \
|
ui/shellDBus.js \
|
||||||
|
ui/statusIconDispatcher.js \
|
||||||
|
ui/statusMenu.js \
|
||||||
ui/status/accessibility.js \
|
ui/status/accessibility.js \
|
||||||
ui/status/keyboard.js \
|
ui/status/keyboard.js \
|
||||||
ui/status/lockScreenMenu.js \
|
|
||||||
ui/status/network.js \
|
ui/status/network.js \
|
||||||
ui/status/power.js \
|
ui/status/power.js \
|
||||||
ui/status/volume.js \
|
ui/status/volume.js \
|
||||||
ui/status/bluetooth.js \
|
ui/status/bluetooth.js \
|
||||||
|
ui/telepathyClient.js \
|
||||||
ui/tweener.js \
|
ui/tweener.js \
|
||||||
ui/unlockDialog.js \
|
|
||||||
ui/userMenu.js \
|
|
||||||
ui/viewSelector.js \
|
ui/viewSelector.js \
|
||||||
ui/wanda.js \
|
|
||||||
ui/windowAttentionHandler.js \
|
ui/windowAttentionHandler.js \
|
||||||
ui/windowManager.js \
|
ui/windowManager.js \
|
||||||
ui/workspace.js \
|
ui/workspace.js \
|
||||||
ui/workspaceThumbnail.js \
|
ui/workspaceThumbnail.js \
|
||||||
ui/workspacesView.js \
|
ui/workspacesView.js \
|
||||||
ui/workspaceSwitcherPopup.js \
|
ui/workspaceSwitcherPopup.js \
|
||||||
ui/xdndHandler.js \
|
ui/xdndHandler.js
|
||||||
ui/components/__init__.js \
|
|
||||||
ui/components/autorunManager.js \
|
|
||||||
ui/components/automountManager.js \
|
|
||||||
ui/components/networkAgent.js \
|
|
||||||
ui/components/polkitAgent.js \
|
|
||||||
ui/components/recorder.js \
|
|
||||||
ui/components/telepathyClient.js \
|
|
||||||
ui/components/keyring.js \
|
|
||||||
$(NULL)
|
|
||||||
|
@ -1,280 +0,0 @@
|
|||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Gettext = imports.gettext;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const Format = imports.format;
|
|
||||||
|
|
||||||
const _ = Gettext.gettext;
|
|
||||||
|
|
||||||
const Config = imports.misc.config;
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
|
|
||||||
const GnomeShellIface = <interface name="org.gnome.Shell.Extensions">
|
|
||||||
<signal name="ExtensionStatusChanged">
|
|
||||||
<arg type="s" name="uuid"/>
|
|
||||||
<arg type="i" name="state"/>
|
|
||||||
<arg type="s" name="error"/>
|
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const GnomeShellProxy = new Gio.DBusProxyClass({
|
|
||||||
Name: 'GnomeShellProxy',
|
|
||||||
Interface: GnomeShellIface,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
|
||||||
g_name: 'org.gnome.Shell',
|
|
||||||
g_object_path: '/org/gnome/Shell' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function stripPrefix(string, prefix) {
|
|
||||||
if (string.slice(0, prefix.length) == prefix)
|
|
||||||
return string.slice(prefix.length);
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Application = new Lang.Class({
|
|
||||||
Name: 'Application',
|
|
||||||
_init: function() {
|
|
||||||
GLib.set_prgname('gnome-shell-extension-prefs');
|
|
||||||
this.application = new Gtk.Application({
|
|
||||||
application_id: 'org.gnome.shell.ExtensionPrefs',
|
|
||||||
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
|
|
||||||
});
|
|
||||||
|
|
||||||
this.application.connect('activate', Lang.bind(this, this._onActivate));
|
|
||||||
this.application.connect('command-line', Lang.bind(this, this._onCommandLine));
|
|
||||||
this.application.connect('startup', Lang.bind(this, this._onStartup));
|
|
||||||
|
|
||||||
this._extensionPrefsModules = {};
|
|
||||||
|
|
||||||
this._extensionIters = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildModel: function() {
|
|
||||||
this._model = new Gtk.ListStore();
|
|
||||||
this._model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]);
|
|
||||||
},
|
|
||||||
|
|
||||||
_extensionAvailable: function(uuid) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
|
|
||||||
if (!extension)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ExtensionUtils.isOutOfDate(extension))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!extension.dir.get_child('prefs.js').query_exists(null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_setExtensionInsensitive: function(layout, cell, model, iter, data) {
|
|
||||||
let uuid = model.get_value(iter, 0);
|
|
||||||
cell.set_sensitive(this._extensionAvailable(uuid));
|
|
||||||
},
|
|
||||||
|
|
||||||
_getExtensionPrefsModule: function(extension) {
|
|
||||||
let uuid = extension.metadata.uuid;
|
|
||||||
|
|
||||||
if (this._extensionPrefsModules.hasOwnProperty(uuid))
|
|
||||||
return this._extensionPrefsModules[uuid];
|
|
||||||
|
|
||||||
ExtensionUtils.installImporter(extension);
|
|
||||||
|
|
||||||
let prefsModule = extension.imports.prefs;
|
|
||||||
prefsModule.init(extension.metadata);
|
|
||||||
|
|
||||||
this._extensionPrefsModules[uuid] = prefsModule;
|
|
||||||
return prefsModule;
|
|
||||||
},
|
|
||||||
|
|
||||||
_selectExtension: function(uuid) {
|
|
||||||
if (!this._extensionAvailable(uuid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
let widget;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let prefsModule = this._getExtensionPrefsModule(extension);
|
|
||||||
widget = prefsModule.buildPrefsWidget();
|
|
||||||
} catch (e) {
|
|
||||||
widget = this._buildErrorUI(extension, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the current prefs widget, if it exists
|
|
||||||
if (this._extensionPrefsBin.get_child())
|
|
||||||
this._extensionPrefsBin.get_child().destroy();
|
|
||||||
|
|
||||||
this._extensionPrefsBin.add(widget);
|
|
||||||
this._extensionSelector.set_active_iter(this._extensionIters[uuid]);
|
|
||||||
},
|
|
||||||
|
|
||||||
_extensionSelected: function() {
|
|
||||||
let [success, iter] = this._extensionSelector.get_active_iter();
|
|
||||||
if (!success)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let uuid = this._model.get_value(iter, 0);
|
|
||||||
this._selectExtension(uuid);
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildErrorUI: function(extension, exc) {
|
|
||||||
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
|
||||||
let label = new Gtk.Label({
|
|
||||||
label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
|
|
||||||
});
|
|
||||||
box.add(label);
|
|
||||||
|
|
||||||
let errortext = '';
|
|
||||||
errortext += exc;
|
|
||||||
errortext += '\n\n';
|
|
||||||
errortext += 'Stack trace:\n';
|
|
||||||
|
|
||||||
// Indent stack trace.
|
|
||||||
errortext += exc.stack.split('\n').map(function(line) {
|
|
||||||
return ' ' + line;
|
|
||||||
}).join('\n');
|
|
||||||
|
|
||||||
let scroll = new Gtk.ScrolledWindow({ vexpand: true });
|
|
||||||
let buffer = new Gtk.TextBuffer({ text: errortext });
|
|
||||||
let textview = new Gtk.TextView({ buffer: buffer });
|
|
||||||
textview.override_font(Pango.font_description_from_string('monospace'));
|
|
||||||
scroll.add(textview);
|
|
||||||
box.add(scroll);
|
|
||||||
|
|
||||||
box.show_all();
|
|
||||||
return box;
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildUI: function(app) {
|
|
||||||
this._window = new Gtk.ApplicationWindow({ application: app,
|
|
||||||
window_position: Gtk.WindowPosition.CENTER,
|
|
||||||
title: _("GNOME Shell Extension Preferences") });
|
|
||||||
|
|
||||||
this._window.set_size_request(600, 400);
|
|
||||||
|
|
||||||
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
|
|
||||||
this._window.add(vbox);
|
|
||||||
|
|
||||||
let toolbar = new Gtk.Toolbar();
|
|
||||||
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR);
|
|
||||||
vbox.add(toolbar);
|
|
||||||
let toolitem;
|
|
||||||
|
|
||||||
let label = new Gtk.Label({ label: '<b>' + _("Extension") + '</b>',
|
|
||||||
use_markup: true });
|
|
||||||
toolitem = new Gtk.ToolItem({ child: label });
|
|
||||||
toolbar.add(toolitem);
|
|
||||||
|
|
||||||
this._extensionSelector = new Gtk.ComboBox({ model: this._model,
|
|
||||||
margin_left: 8,
|
|
||||||
hexpand: true });
|
|
||||||
this._extensionSelector.get_style_context().add_class(Gtk.STYLE_CLASS_RAISED);
|
|
||||||
|
|
||||||
let renderer = new Gtk.CellRendererText();
|
|
||||||
this._extensionSelector.pack_start(renderer, true);
|
|
||||||
this._extensionSelector.add_attribute(renderer, 'text', 1);
|
|
||||||
this._extensionSelector.set_cell_data_func(renderer, Lang.bind(this, this._setExtensionInsensitive));
|
|
||||||
this._extensionSelector.connect('changed', Lang.bind(this, this._extensionSelected));
|
|
||||||
|
|
||||||
toolitem = new Gtk.ToolItem({ child: this._extensionSelector });
|
|
||||||
toolitem.set_expand(true);
|
|
||||||
toolbar.add(toolitem);
|
|
||||||
|
|
||||||
this._extensionPrefsBin = new Gtk.Frame();
|
|
||||||
vbox.add(this._extensionPrefsBin);
|
|
||||||
|
|
||||||
let label = new Gtk.Label({
|
|
||||||
label: _("Select an extension to configure using the combobox above."),
|
|
||||||
vexpand: true
|
|
||||||
});
|
|
||||||
|
|
||||||
this._extensionPrefsBin.add(label);
|
|
||||||
|
|
||||||
this._shellProxy = new GnomeShellProxy();
|
|
||||||
this._shellProxy.init(null);
|
|
||||||
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
|
|
||||||
if (ExtensionUtils.extensions[uuid] !== undefined)
|
|
||||||
this._scanExtensions();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._window.show_all();
|
|
||||||
},
|
|
||||||
|
|
||||||
_scanExtensions: function() {
|
|
||||||
let finder = new ExtensionUtils.ExtensionFinder();
|
|
||||||
finder.connect('extension-found', Lang.bind(this, this._extensionFound));
|
|
||||||
finder.scanExtensions();
|
|
||||||
},
|
|
||||||
|
|
||||||
_extensionFound: function(signals, extension) {
|
|
||||||
let iter = this._model.append();
|
|
||||||
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
|
|
||||||
this._extensionIters[extension.uuid] = iter;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
_onActivate: function() {
|
|
||||||
this._window.present();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onStartup: function(app) {
|
|
||||||
this._buildModel();
|
|
||||||
this._buildUI(app);
|
|
||||||
this._scanExtensions();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCommandLine: function(app, commandLine) {
|
|
||||||
app.activate();
|
|
||||||
let args = commandLine.get_arguments();
|
|
||||||
if (args.length) {
|
|
||||||
let uuid = args[0];
|
|
||||||
|
|
||||||
// Strip off "extension:///" prefix which fakes a URI, if it exists
|
|
||||||
uuid = stripPrefix(uuid, "extension:///");
|
|
||||||
|
|
||||||
if (!this._extensionAvailable(uuid))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
this._selectExtension(uuid);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function initEnvironment() {
|
|
||||||
// Monkey-patch in a "global" object that fakes some Shell utilities
|
|
||||||
// that ExtensionUtils depends on.
|
|
||||||
window.global = {
|
|
||||||
log: function() {
|
|
||||||
print([].join.call(arguments, ', '));
|
|
||||||
},
|
|
||||||
|
|
||||||
logError: function(s) {
|
|
||||||
log('ERROR: ' + s);
|
|
||||||
},
|
|
||||||
|
|
||||||
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.format = Format.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
function main(argv) {
|
|
||||||
initEnvironment();
|
|
||||||
|
|
||||||
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
|
|
||||||
Gettext.textdomain(Config.GETTEXT_PACKAGE);
|
|
||||||
|
|
||||||
let app = new Application();
|
|
||||||
app.application.run(argv);
|
|
||||||
}
|
|
203
js/gdm/batch.js
@ -1,203 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
/*
|
|
||||||
* Copyright 2011 Red Hat, Inc
|
|
||||||
*
|
|
||||||
* This program 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, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const Task = new Lang.Class({
|
|
||||||
Name: 'Task',
|
|
||||||
|
|
||||||
_init: function(scope, handler) {
|
|
||||||
if (scope)
|
|
||||||
this.scope = scope;
|
|
||||||
else
|
|
||||||
this.scope = this;
|
|
||||||
|
|
||||||
this.handler = handler;
|
|
||||||
},
|
|
||||||
|
|
||||||
run: function() {
|
|
||||||
if (this.handler)
|
|
||||||
return this.handler.call(this.scope);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(Task.prototype);
|
|
||||||
|
|
||||||
const Hold = new Lang.Class({
|
|
||||||
Name: 'Hold',
|
|
||||||
Extends: Task,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent(this, function () {
|
|
||||||
return this;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._acquisitions = 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
acquire: function() {
|
|
||||||
if (this._acquisitions <= 0)
|
|
||||||
throw new Error("Cannot acquire hold after it's been released");
|
|
||||||
this._acquisitions++;
|
|
||||||
},
|
|
||||||
|
|
||||||
acquireUntilAfter: function(hold) {
|
|
||||||
if (!hold.isAcquired())
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.acquire();
|
|
||||||
let signalId = hold.connect('release', Lang.bind(this, function() {
|
|
||||||
hold.disconnect(signalId);
|
|
||||||
this.release();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
release: function() {
|
|
||||||
this._acquisitions--;
|
|
||||||
|
|
||||||
if (this._acquisitions == 0)
|
|
||||||
this.emit('release');
|
|
||||||
},
|
|
||||||
|
|
||||||
isAcquired: function() {
|
|
||||||
return this._acquisitions > 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(Hold.prototype);
|
|
||||||
|
|
||||||
const Batch = new Lang.Class({
|
|
||||||
Name: 'Batch',
|
|
||||||
Extends: Task,
|
|
||||||
|
|
||||||
_init: function(scope, tasks) {
|
|
||||||
this.parent();
|
|
||||||
|
|
||||||
this.tasks = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < tasks.length; i++) {
|
|
||||||
let task;
|
|
||||||
|
|
||||||
if (tasks[i] instanceof Task) {
|
|
||||||
task = tasks[i];
|
|
||||||
} else if (typeof tasks[i] == 'function') {
|
|
||||||
task = new Task(scope, tasks[i]);
|
|
||||||
} else {
|
|
||||||
throw new Error('Batch tasks must be functions or Task, Hold or Batch objects');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tasks.push(task);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
process: function() {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
},
|
|
||||||
|
|
||||||
runTask: function() {
|
|
||||||
if (!(this._currentTaskIndex in this.tasks)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.tasks[this._currentTaskIndex].run();
|
|
||||||
},
|
|
||||||
|
|
||||||
_finish: function() {
|
|
||||||
this.hold.release();
|
|
||||||
},
|
|
||||||
|
|
||||||
nextTask: function() {
|
|
||||||
this._currentTaskIndex++;
|
|
||||||
|
|
||||||
// if the entire batch of tasks is finished, release
|
|
||||||
// the hold and notify anyone waiting on the batch
|
|
||||||
if (this._currentTaskIndex >= this.tasks.length) {
|
|
||||||
this._finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.process();
|
|
||||||
},
|
|
||||||
|
|
||||||
_start: function() {
|
|
||||||
// acquire a hold to get released when the entire
|
|
||||||
// batch of tasks is finished
|
|
||||||
this.hold = new Hold();
|
|
||||||
this._currentTaskIndex = 0;
|
|
||||||
this.process();
|
|
||||||
},
|
|
||||||
|
|
||||||
run: function() {
|
|
||||||
this._start();
|
|
||||||
|
|
||||||
// hold may be destroyed at this point
|
|
||||||
// if we're already done running
|
|
||||||
return this.hold;
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function() {
|
|
||||||
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(Batch.prototype);
|
|
||||||
|
|
||||||
const ConcurrentBatch = new Lang.Class({
|
|
||||||
Name: 'ConcurrentBatch',
|
|
||||||
Extends: Batch,
|
|
||||||
|
|
||||||
process: function() {
|
|
||||||
let hold = this.runTask();
|
|
||||||
|
|
||||||
if (hold) {
|
|
||||||
this.hold.acquireUntilAfter(hold);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regardless of the state of the just run task,
|
|
||||||
// fire off the next one, so all the tasks can run
|
|
||||||
// concurrently.
|
|
||||||
this.nextTask();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(ConcurrentBatch.prototype);
|
|
||||||
|
|
||||||
const ConsecutiveBatch = new Lang.Class({
|
|
||||||
Name: 'ConsecutiveBatch',
|
|
||||||
Extends: Batch,
|
|
||||||
|
|
||||||
process: function() {
|
|
||||||
let hold = this.runTask();
|
|
||||||
|
|
||||||
if (hold && hold.isAcquired()) {
|
|
||||||
// This task is inhibiting the batch. Wait on it
|
|
||||||
// before processing the next one.
|
|
||||||
let signalId = hold.connect('release',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
hold.disconnect(signalId);
|
|
||||||
this.nextTask();
|
|
||||||
}));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// This task finished, process the next one
|
|
||||||
this.nextTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(ConsecutiveBatch.prototype);
|
|
@ -1,24 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
|
|
||||||
<method name='GetDefaultDevice'>
|
|
||||||
<arg type='o' direction='out' />
|
|
||||||
</method>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const FprintManager = new Gio.DBusProxyClass({
|
|
||||||
Name: 'FprintManager',
|
|
||||||
Interface: FprintManagerIface,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'net.reactivated.Fprint',
|
|
||||||
g_object_path: '/net/reactivated/Fprint/Manager',
|
|
||||||
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,153 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
/*
|
|
||||||
* Copyright 2011 Red Hat, Inc
|
|
||||||
*
|
|
||||||
* This program 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, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const LoginManager = imports.misc.loginManager;
|
|
||||||
|
|
||||||
const GdmUtil = imports.gdm.util;
|
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
|
||||||
|
|
||||||
const PowerMenuButton = new Lang.Class({
|
|
||||||
Name: 'PowerMenuButton',
|
|
||||||
Extends: PanelMenu.SystemStatusButton,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
/* Translators: accessible name of the power menu in the login screen */
|
|
||||||
this.parent('system-shutdown-symbolic', _("Power"));
|
|
||||||
|
|
||||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
|
||||||
this._loginManager = manager;
|
|
||||||
|
|
||||||
this._updateHaveShutdown();
|
|
||||||
this._updateHaveRestart();
|
|
||||||
this._updateHaveSuspend();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._settings = new Gio.Settings({ schema: GdmUtil.LOGIN_SCREEN_SCHEMA });
|
|
||||||
this._settings.connect('changed::disable-restart-buttons',
|
|
||||||
Lang.bind(this, this._updateVisibility));
|
|
||||||
|
|
||||||
this._createSubMenu();
|
|
||||||
|
|
||||||
// ConsoleKit doesn't send notifications when shutdown/reboot
|
|
||||||
// are disabled, so we update the menu item each time the menu opens
|
|
||||||
this.menu.connect('open-state-changed', Lang.bind(this,
|
|
||||||
function(menu, open) {
|
|
||||||
if (open) {
|
|
||||||
this._updateHaveShutdown();
|
|
||||||
this._updateHaveRestart();
|
|
||||||
this._updateHaveSuspend();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
this._updateHaveShutdown();
|
|
||||||
this._updateHaveRestart();
|
|
||||||
this._updateHaveSuspend();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateVisibility: function() {
|
|
||||||
let shouldBeVisible = (this._haveSuspend || this._haveShutdown || this._haveRestart);
|
|
||||||
this.actor.visible = shouldBeVisible && !this._settings.get_boolean('disable-restart-buttons');
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateHaveShutdown: function() {
|
|
||||||
if (!this._loginManager) {
|
|
||||||
this._haveShutdown = false;
|
|
||||||
this._powerOffItem.actor.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._loginManager.canPowerOff(Lang.bind(this, function(result) {
|
|
||||||
this._haveShutdown = result;
|
|
||||||
this._powerOffItem.actor.visible = this._haveShutdown;
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateHaveRestart: function() {
|
|
||||||
if (!this._loginManager) {
|
|
||||||
this._haveRestart = false;
|
|
||||||
this._restartItem.actor.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._loginManager.canReboot(Lang.bind(this, function(result) {
|
|
||||||
this._haveRestart = result;
|
|
||||||
this._restartItem.actor.visible = this._haveRestart;
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateHaveSuspend: function() {
|
|
||||||
if (!this._loginManager) {
|
|
||||||
this._haveSuspend = false;
|
|
||||||
this._suspendItem.actor.visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._loginManager.canSuspend(Lang.bind(this, function(result) {
|
|
||||||
this._haveSuspend = result;
|
|
||||||
this._suspendItem.actor.visible = this._haveSuspend;
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_createSubMenu: function() {
|
|
||||||
let item;
|
|
||||||
|
|
||||||
item = new PopupMenu.PopupMenuItem(_("Suspend"));
|
|
||||||
item.connect('activate', Lang.bind(this, this._onActivateSuspend));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
this._suspendItem = item;
|
|
||||||
|
|
||||||
item = new PopupMenu.PopupMenuItem(_("Restart"));
|
|
||||||
item.connect('activate', Lang.bind(this, this._onActivateRestart));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
this._restartItem = item;
|
|
||||||
|
|
||||||
item = new PopupMenu.PopupMenuItem(_("Power Off"));
|
|
||||||
item.connect('activate', Lang.bind(this, this._onActivatePowerOff));
|
|
||||||
this.menu.addMenuItem(item);
|
|
||||||
this._powerOffItem = item;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onActivateSuspend: function() {
|
|
||||||
if (!this._haveSuspend)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._loginManager.suspend();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onActivateRestart: function() {
|
|
||||||
if (!this._haveRestart)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._loginManager.reboot();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onActivatePowerOff: function() {
|
|
||||||
if (!this._haveShutdown)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._loginManager.powerOff();
|
|
||||||
}
|
|
||||||
});
|
|
173
js/gdm/realmd.js
@ -1,173 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const ProviderIface = <interface name='org.freedesktop.realmd.Provider'>
|
|
||||||
<property name="Name" type="s" access="read"/>
|
|
||||||
<property name="Version" type="s" access="read"/>
|
|
||||||
<property name="Realms" type="ao" access="read"/>
|
|
||||||
<method name="Discover">
|
|
||||||
<arg name="string" type="s" direction="in"/>
|
|
||||||
<arg name="options" type="a{sv}" direction="in"/>
|
|
||||||
<arg name="relevance" type="i" direction="out"/>
|
|
||||||
<arg name="realm" type="ao" direction="out"/>
|
|
||||||
</method>
|
|
||||||
</interface>;
|
|
||||||
const Provider = new Gio.DBusProxyClass({
|
|
||||||
Name: 'RealmdProvider',
|
|
||||||
Interface: ProviderIface,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.realmd',
|
|
||||||
g_object_path: '/org/freedesktop/realmd' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ServiceIface = <interface name="org.freedesktop.realmd.Service">
|
|
||||||
<method name="Cancel">
|
|
||||||
<arg name="operation" type="s" direction="in"/>
|
|
||||||
</method>
|
|
||||||
<method name="Release" />
|
|
||||||
<method name="SetLocale">
|
|
||||||
<arg name="locale" type="s" direction="in"/>
|
|
||||||
</method>
|
|
||||||
<signal name="Diagnostics">
|
|
||||||
<arg name="data" type="s"/>
|
|
||||||
<arg name="operation" type="s"/>
|
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
const Service = new Gio.DBusProxyClass({
|
|
||||||
Name: 'RealmdService',
|
|
||||||
Interface: ServiceIface,
|
|
||||||
|
|
||||||
_init: function(service) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.realmd',
|
|
||||||
g_object_path: service });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const RealmIface = <interface name="org.freedesktop.realmd.Realm">
|
|
||||||
<property name="Name" type="s" access="read"/>
|
|
||||||
<property name="Configured" type="s" access="read"/>
|
|
||||||
<property name="Details" type="a(ss)" access="read"/>
|
|
||||||
<property name="LoginFormats" type="as" access="read"/>
|
|
||||||
<property name="LoginPolicy" type="s" access="read"/>
|
|
||||||
<property name="PermittedLogins" type="as" access="read"/>
|
|
||||||
<property name="SupportedInterfaces" type="as" access="read"/>
|
|
||||||
<method name="ChangeLoginPolicy">
|
|
||||||
<arg name="login_policy" type="s" direction="in"/>
|
|
||||||
<arg name="permitted_add" type="as" direction="in"/>
|
|
||||||
<arg name="permitted_remove" type="as" direction="in"/>
|
|
||||||
<arg name="options" type="a{sv}" direction="in"/>
|
|
||||||
</method>
|
|
||||||
<method name="Deconfigure">
|
|
||||||
<arg name="options" type="a{sv}" direction="in"/>
|
|
||||||
</method>
|
|
||||||
</interface>;
|
|
||||||
const Realm = new Gio.DBusProxyClass({
|
|
||||||
Name: 'RealmdRealm',
|
|
||||||
Interface: RealmIface,
|
|
||||||
|
|
||||||
_init: function(realm) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.realmd',
|
|
||||||
g_object_path: realm });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Manager = new Lang.Class({
|
|
||||||
Name: 'Manager',
|
|
||||||
|
|
||||||
_init: function(parentActor) {
|
|
||||||
this._aggregateProvider = new Provider();
|
|
||||||
this._realms = {};
|
|
||||||
|
|
||||||
this._aggregateProvider.connect('g-properties-changed',
|
|
||||||
Lang.bind(this, function(proxy, properties) {
|
|
||||||
if ('Realms' in properties.deep_unpack())
|
|
||||||
this._reloadRealms();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._aggregateProvider.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
} catch(e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._reloadRealms();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_reloadRealms: function() {
|
|
||||||
let realmPaths = this._aggregateProvider.Realms;
|
|
||||||
|
|
||||||
if (!realmPaths)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let i = 0; i < realmPaths.length; i++) {
|
|
||||||
let realm = new Realm(realmPaths[i]);
|
|
||||||
realm.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, this._onRealmLoaded));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_reloadRealm: function(realm) {
|
|
||||||
if (!realm.Configured) {
|
|
||||||
if (this._realms[realm.get_object_path()])
|
|
||||||
delete this._realms[realm.get_object_path()];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._realms[realm.get_object_path()] = realm;
|
|
||||||
|
|
||||||
this._updateLoginFormat();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onRealmLoaded: function(realm, result) {
|
|
||||||
try {
|
|
||||||
realm.init_finish(result);
|
|
||||||
} catch(e) { return; }
|
|
||||||
|
|
||||||
this._reloadRealm(realm);
|
|
||||||
|
|
||||||
realm.connect('g-properties-changed',
|
|
||||||
Lang.bind(this, function(proxy, properties) {
|
|
||||||
if ('Configured' in properties.deep_unpack())
|
|
||||||
this._reloadRealm();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateLoginFormat: function() {
|
|
||||||
let newLoginFormat;
|
|
||||||
|
|
||||||
for (let realmPath in this._realms) {
|
|
||||||
let realm = this._realms[realmPath];
|
|
||||||
if (realm.LoginFormats && realm.LoginFormats.length > 0) {
|
|
||||||
newLoginFormat = realm.LoginFormats[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._loginFormat != newLoginFormat) {
|
|
||||||
this._loginFormat = newLoginFormat;
|
|
||||||
this.emit('login-format-changed', newLoginFormat);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get loginFormat() {
|
|
||||||
if (this._loginFormat !== undefined)
|
|
||||||
return this._loginFormat;
|
|
||||||
|
|
||||||
this._updateLoginFormat();
|
|
||||||
|
|
||||||
return this._loginFormat;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(Manager.prototype)
|
|
376
js/gdm/util.js
@ -1,376 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const Batch = imports.gdm.batch;
|
|
||||||
const Fprint = imports.gdm.fingerprint;
|
|
||||||
const Realmd = imports.gdm.realmd;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const PASSWORD_SERVICE_NAME = 'gdm-password';
|
|
||||||
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
|
|
||||||
const FADE_ANIMATION_TIME = 0.16;
|
|
||||||
|
|
||||||
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
|
|
||||||
const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
|
|
||||||
const BANNER_MESSAGE_KEY = 'banner-message-enable';
|
|
||||||
const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
|
|
||||||
const ALLOWED_FAILURES_KEY = 'allowed-failures';
|
|
||||||
|
|
||||||
const LOGO_KEY = 'logo';
|
|
||||||
|
|
||||||
function fadeInActor(actor) {
|
|
||||||
if (actor.opacity == 255 && actor.visible)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
let hold = new Batch.Hold();
|
|
||||||
actor.show();
|
|
||||||
let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
|
|
||||||
|
|
||||||
actor.opacity = 0;
|
|
||||||
actor.set_height(0);
|
|
||||||
Tweener.addTween(actor,
|
|
||||||
{ opacity: 255,
|
|
||||||
height: naturalHeight,
|
|
||||||
time: FADE_ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: function() {
|
|
||||||
this.set_height(-1);
|
|
||||||
hold.release();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return hold;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fadeOutActor(actor) {
|
|
||||||
if (!actor.visible || actor.opacity == 0) {
|
|
||||||
actor.opacity = 0;
|
|
||||||
actor.hide();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let hold = new Batch.Hold();
|
|
||||||
Tweener.addTween(actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
height: 0,
|
|
||||||
time: FADE_ANIMATION_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: function() {
|
|
||||||
this.hide();
|
|
||||||
this.set_height(-1);
|
|
||||||
hold.release();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return hold;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ShellUserVerifier = new Lang.Class({
|
|
||||||
Name: 'ShellUserVerifier',
|
|
||||||
|
|
||||||
_init: function(client, params) {
|
|
||||||
params = Params.parse(params, { reauthenticationOnly: false });
|
|
||||||
this._reauthOnly = params.reauthenticationOnly;
|
|
||||||
|
|
||||||
this._client = client;
|
|
||||||
|
|
||||||
this._settings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
|
|
||||||
|
|
||||||
this._fprintManager = new Fprint.FprintManager();
|
|
||||||
this._fprintManager.init(null);
|
|
||||||
|
|
||||||
this._realmManager = new Realmd.Manager();
|
|
||||||
|
|
||||||
this._failCounter = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
begin: function(userName, hold) {
|
|
||||||
this._cancellable = new Gio.Cancellable();
|
|
||||||
this._hold = hold;
|
|
||||||
this._userName = userName;
|
|
||||||
|
|
||||||
this._checkForFingerprintReader();
|
|
||||||
|
|
||||||
if (userName) {
|
|
||||||
// If possible, reauthenticate an already running session,
|
|
||||||
// so any session specific credentials get updated appropriately
|
|
||||||
this._client.open_reauthentication_channel(userName, this._cancellable,
|
|
||||||
Lang.bind(this, this._reauthenticationChannelOpened));
|
|
||||||
} else {
|
|
||||||
this._client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function() {
|
|
||||||
if (this._cancellable)
|
|
||||||
this._cancellable.cancel();
|
|
||||||
|
|
||||||
if (this._userVerifier)
|
|
||||||
this._userVerifier.call_cancel_sync(null);
|
|
||||||
},
|
|
||||||
|
|
||||||
clear: function() {
|
|
||||||
if (this._cancellable) {
|
|
||||||
this._cancellable.cancel();
|
|
||||||
this._cancellable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._userVerifier) {
|
|
||||||
this._userVerifier.run_dispose();
|
|
||||||
this._userVerifier = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
answerQuery: function(serviceName, answer) {
|
|
||||||
// Clear any previous message
|
|
||||||
this.emit('show-message', null, null);
|
|
||||||
|
|
||||||
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
_checkForFingerprintReader: function() {
|
|
||||||
this._haveFingerprintReader = false;
|
|
||||||
|
|
||||||
if (!this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._fprintManager.GetDefaultDeviceRemote(this._cancellable, Lang.bind(this, function(manager, result) {
|
|
||||||
try {
|
|
||||||
let device = manager.GetDefaultDeviceFinish(result);
|
|
||||||
this._haveFingerprintReader = !!device;
|
|
||||||
} catch(e) {
|
|
||||||
this._haveFingerprintReader = false;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_reportInitError: function(where, error) {
|
|
||||||
logError(error, where);
|
|
||||||
this._hold.release();
|
|
||||||
|
|
||||||
this.emit('show-message', _("Authentication error"), 'login-dialog-message-warning');
|
|
||||||
this._verificationFailed(false);
|
|
||||||
},
|
|
||||||
|
|
||||||
_reauthenticationChannelOpened: function(client, result) {
|
|
||||||
try {
|
|
||||||
this._userVerifier = client.open_reauthentication_channel_finish(result);
|
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
|
||||||
return;
|
|
||||||
} catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
|
|
||||||
!this._reauthOnly) {
|
|
||||||
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is
|
|
||||||
// no session to reauthenticate. Fall back to performing verification
|
|
||||||
// from this login session
|
|
||||||
client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
|
|
||||||
return;
|
|
||||||
} catch(e) {
|
|
||||||
this._reportInitError('Failed to open reauthentication channel', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._connectSignals();
|
|
||||||
this._beginVerification();
|
|
||||||
this._hold.release();
|
|
||||||
},
|
|
||||||
|
|
||||||
_userVerifierGot: function(client, result) {
|
|
||||||
try {
|
|
||||||
this._userVerifier = client.get_user_verifier_finish(result);
|
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
|
||||||
return;
|
|
||||||
} catch(e) {
|
|
||||||
this._reportInitError('Failed to obtain user verifier', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._connectSignals();
|
|
||||||
this._beginVerification();
|
|
||||||
this._hold.release();
|
|
||||||
},
|
|
||||||
|
|
||||||
_connectSignals: function() {
|
|
||||||
this._userVerifier.connect('info', Lang.bind(this, this._onInfo));
|
|
||||||
this._userVerifier.connect('problem', Lang.bind(this, this._onProblem));
|
|
||||||
this._userVerifier.connect('info-query', Lang.bind(this, this._onInfoQuery));
|
|
||||||
this._userVerifier.connect('secret-info-query', Lang.bind(this, this._onSecretInfoQuery));
|
|
||||||
this._userVerifier.connect('conversation-stopped', Lang.bind(this, this._onConversationStopped));
|
|
||||||
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
|
||||||
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
|
|
||||||
},
|
|
||||||
|
|
||||||
_beginVerification: function() {
|
|
||||||
this._hold.acquire();
|
|
||||||
|
|
||||||
if (this._userName) {
|
|
||||||
this._userVerifier.call_begin_verification_for_user(PASSWORD_SERVICE_NAME,
|
|
||||||
this._userName,
|
|
||||||
this._cancellable,
|
|
||||||
Lang.bind(this, function(obj, result) {
|
|
||||||
try {
|
|
||||||
obj.call_begin_verification_for_user_finish(result);
|
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
|
||||||
return;
|
|
||||||
} catch(e) {
|
|
||||||
this._reportInitError('Failed to start verification for user', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._hold.release();
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (this._haveFingerprintReader) {
|
|
||||||
this._hold.acquire();
|
|
||||||
|
|
||||||
this._userVerifier.call_begin_verification_for_user(FINGERPRINT_SERVICE_NAME,
|
|
||||||
this._userName,
|
|
||||||
this._cancellable,
|
|
||||||
Lang.bind(this, function(obj, result) {
|
|
||||||
try {
|
|
||||||
obj.call_begin_verification_for_user_finish(result);
|
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
|
||||||
return;
|
|
||||||
} catch(e) {
|
|
||||||
this._reportInitError('Failed to start fingerprint verification for user', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._hold.release();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._userVerifier.call_begin_verification(PASSWORD_SERVICE_NAME,
|
|
||||||
this._cancellable,
|
|
||||||
Lang.bind(this, function(obj, result) {
|
|
||||||
try {
|
|
||||||
obj.call_begin_verification_finish(result);
|
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
|
||||||
return;
|
|
||||||
} catch(e) {
|
|
||||||
this._reportInitError('Failed to start verification', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._hold.release();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onInfo: function(client, serviceName, info) {
|
|
||||||
// We don't display fingerprint messages, because they
|
|
||||||
// have words like UPEK in them. Instead we use the messages
|
|
||||||
// as a cue to display our own message.
|
|
||||||
if (serviceName == FINGERPRINT_SERVICE_NAME &&
|
|
||||||
this._haveFingerprintReader) {
|
|
||||||
|
|
||||||
// Translators: this message is shown below the password entry field
|
|
||||||
// to indicate the user can swipe their finger instead
|
|
||||||
this.emit('show-login-hint', _("(or swipe finger)"));
|
|
||||||
} else if (serviceName == PASSWORD_SERVICE_NAME) {
|
|
||||||
this.emit('show-message', info, 'login-dialog-message-info');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onProblem: function(client, serviceName, problem) {
|
|
||||||
// we don't want to show auth failed messages to
|
|
||||||
// users who haven't enrolled their fingerprint.
|
|
||||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
|
||||||
return;
|
|
||||||
this.emit('show-message', problem, 'login-dialog-message-warning');
|
|
||||||
},
|
|
||||||
|
|
||||||
_showRealmLoginHint: function() {
|
|
||||||
if (this._realmManager.loginFormat) {
|
|
||||||
let hint = this._realmManager.loginFormat;
|
|
||||||
|
|
||||||
hint = hint.replace(/%U/g, 'user');
|
|
||||||
hint = hint.replace(/%D/g, 'DOMAIN');
|
|
||||||
hint = hint.replace(/%[^UD]/g, '');
|
|
||||||
|
|
||||||
// Translators: this message is shown below the username entry field
|
|
||||||
// to clue the user in on how to login to the local network realm
|
|
||||||
this.emit('show-login-hint',
|
|
||||||
_("(e.g., user or %s)").format(hint));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onInfoQuery: function(client, serviceName, question) {
|
|
||||||
// We only expect questions to come from the main auth service
|
|
||||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._showRealmLoginHint();
|
|
||||||
this._realmLoginHintSignalId = this._realmManager.connect('login-format-changed',
|
|
||||||
Lang.bind(this, this._showRealmLoginHint));
|
|
||||||
|
|
||||||
this.emit('ask-question', serviceName, question, '');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
|
|
||||||
// We only expect secret requests to come from the main auth service
|
|
||||||
if (serviceName != PASSWORD_SERVICE_NAME)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onReset: function() {
|
|
||||||
this.clear();
|
|
||||||
|
|
||||||
// Clear previous attempts to authenticate
|
|
||||||
this._failCounter = 0;
|
|
||||||
|
|
||||||
this.emit('reset');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onVerificationComplete: function() {
|
|
||||||
this.emit('verification-complete');
|
|
||||||
},
|
|
||||||
|
|
||||||
_verificationFailed: function(retry) {
|
|
||||||
// For Not Listed / enterprise logins, immediately reset
|
|
||||||
// the dialog
|
|
||||||
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
|
|
||||||
// go back to the welcome screen.
|
|
||||||
|
|
||||||
this._failCounter++;
|
|
||||||
let canRetry = retry && this._userName &&
|
|
||||||
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
|
|
||||||
|
|
||||||
if (canRetry) {
|
|
||||||
this.clear();
|
|
||||||
this.begin(this._userName, new Batch.Hold());
|
|
||||||
} else {
|
|
||||||
// Allow some time to see the message, then reset everything
|
|
||||||
Mainloop.timeout_add(3000, Lang.bind(this, function() {
|
|
||||||
this.cancel();
|
|
||||||
|
|
||||||
this._onReset();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('verification-failed');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onConversationStopped: function(client, serviceName) {
|
|
||||||
// if the password service fails, then cancel everything.
|
|
||||||
// But if, e.g., fingerprint fails, still give
|
|
||||||
// password authentication a chance to succeed
|
|
||||||
if (serviceName == PASSWORD_SERVICE_NAME) {
|
|
||||||
this._verificationFailed(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('hide-login-hint');
|
|
||||||
|
|
||||||
if (this._realmLoginHintSignalId) {
|
|
||||||
this._realmManager.disconnect(this._realmLoginHintSignalId);
|
|
||||||
this._realmLoginHintSignalId = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(ShellUserVerifier.prototype);
|
|
@ -1,15 +1,10 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
|
||||||
|
|
||||||
/* The name of this package (not localized) */
|
/* The name of this package (not localized) */
|
||||||
const PACKAGE_NAME = '@PACKAGE_NAME@';
|
const PACKAGE_NAME = '@PACKAGE_NAME@';
|
||||||
/* The version of this package */
|
/* The version of this package */
|
||||||
const PACKAGE_VERSION = '@PACKAGE_VERSION@';
|
const PACKAGE_VERSION = '@PACKAGE_VERSION@';
|
||||||
|
/* The version of GJS we're linking to */
|
||||||
|
const GJS_VERSION = '@GJS_VERSION@';
|
||||||
/* 1 if gnome-bluetooth is available, 0 otherwise */
|
/* 1 if gnome-bluetooth is available, 0 otherwise */
|
||||||
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
|
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
|
||||||
/* gettext package */
|
|
||||||
const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
|
|
||||||
/* locale dir */
|
|
||||||
const LOCALEDIR = '@datadir@/locale';
|
|
||||||
/* other standard directories */
|
|
||||||
const LIBEXECDIR = '@libexecdir@';
|
|
||||||
const SYSCONFDIR = '@sysconfdir@';
|
|
||||||
|
140
js/misc/docInfo.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
|
||||||
|
const THUMBNAIL_ICON_MARGIN = 2;
|
||||||
|
|
||||||
|
function DocInfo(recentInfo) {
|
||||||
|
this._init(recentInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
DocInfo.prototype = {
|
||||||
|
_init : function(recentInfo) {
|
||||||
|
this.recentInfo = recentInfo;
|
||||||
|
// We actually used get_modified() instead of get_visited()
|
||||||
|
// here, as GtkRecentInfo doesn't updated get_visited()
|
||||||
|
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
|
||||||
|
this.timestamp = recentInfo.get_modified();
|
||||||
|
this.name = recentInfo.get_display_name();
|
||||||
|
this._lowerName = this.name.toLowerCase();
|
||||||
|
this.uri = recentInfo.get_uri();
|
||||||
|
this.mimeType = recentInfo.get_mime_type();
|
||||||
|
},
|
||||||
|
|
||||||
|
createIcon : function(size) {
|
||||||
|
return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
|
||||||
|
},
|
||||||
|
|
||||||
|
launch : function(workspaceIndex) {
|
||||||
|
Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex);
|
||||||
|
},
|
||||||
|
|
||||||
|
matchTerms: function(terms) {
|
||||||
|
let mtype = Search.MatchType.NONE;
|
||||||
|
for (let i = 0; i < terms.length; i++) {
|
||||||
|
let term = terms[i];
|
||||||
|
let idx = this._lowerName.indexOf(term);
|
||||||
|
if (idx == 0) {
|
||||||
|
mtype = Search.MatchType.PREFIX;
|
||||||
|
} else if (idx > 0) {
|
||||||
|
if (mtype == Search.MatchType.NONE)
|
||||||
|
mtype = Search.MatchType.SUBSTRING;
|
||||||
|
} else {
|
||||||
|
return Search.MatchType.NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mtype;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var docManagerInstance = null;
|
||||||
|
|
||||||
|
function getDocManager() {
|
||||||
|
if (docManagerInstance == null)
|
||||||
|
docManagerInstance = new DocManager();
|
||||||
|
return docManagerInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DocManager wraps the DocSystem, primarily to expose DocInfo objects.
|
||||||
|
*/
|
||||||
|
function DocManager() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
DocManager.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this._docSystem = Shell.DocSystem.get_default();
|
||||||
|
this._infosByTimestamp = [];
|
||||||
|
this._infosByUri = {};
|
||||||
|
this._docSystem.connect('changed', Lang.bind(this, this._reload));
|
||||||
|
this._reload();
|
||||||
|
},
|
||||||
|
|
||||||
|
_reload: function() {
|
||||||
|
let docs = this._docSystem.get_all();
|
||||||
|
this._infosByTimestamp = [];
|
||||||
|
this._infosByUri = {};
|
||||||
|
for (let i = 0; i < docs.length; i++) {
|
||||||
|
let recentInfo = docs[i];
|
||||||
|
|
||||||
|
let docInfo = new DocInfo(recentInfo);
|
||||||
|
this._infosByTimestamp.push(docInfo);
|
||||||
|
this._infosByUri[docInfo.uri] = docInfo;
|
||||||
|
}
|
||||||
|
this.emit('changed');
|
||||||
|
},
|
||||||
|
|
||||||
|
getTimestampOrderedInfos: function() {
|
||||||
|
return this._infosByTimestamp;
|
||||||
|
},
|
||||||
|
|
||||||
|
getInfosByUri: function() {
|
||||||
|
return this._infosByUri;
|
||||||
|
},
|
||||||
|
|
||||||
|
lookupByUri: function(uri) {
|
||||||
|
return this._infosByUri[uri];
|
||||||
|
},
|
||||||
|
|
||||||
|
queueExistenceCheck: function(count) {
|
||||||
|
return this._docSystem.queue_existence_check(count);
|
||||||
|
},
|
||||||
|
|
||||||
|
_searchDocs: function(items, terms) {
|
||||||
|
let multiplePrefixMatches = [];
|
||||||
|
let prefixMatches = [];
|
||||||
|
let multipleSubtringMatches = [];
|
||||||
|
let substringMatches = [];
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
let item = items[i];
|
||||||
|
let mtype = item.matchTerms(terms);
|
||||||
|
if (mtype == Search.MatchType.MULTIPLE_PREFIX)
|
||||||
|
multiplePrefixMatches.push(item.uri);
|
||||||
|
else if (mtype == Search.MatchType.PREFIX)
|
||||||
|
prefixMatches.push(item.uri);
|
||||||
|
else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING)
|
||||||
|
multipleSubtringMatches.push(item.uri);
|
||||||
|
else if (mtype == Search.MatchType.SUBSTRING)
|
||||||
|
substringMatches.push(item.uri);
|
||||||
|
}
|
||||||
|
return multiplePrefixMatches.concat(prefixMatches.concat(multipleSubtringMatches.concat(substringMatches)));
|
||||||
|
},
|
||||||
|
|
||||||
|
initialSearch: function(terms) {
|
||||||
|
return this._searchDocs(this._infosByTimestamp, terms);
|
||||||
|
},
|
||||||
|
|
||||||
|
subsearch: function(previousResults, terms) {
|
||||||
|
return this._searchDocs(previousResults.map(Lang.bind(this,
|
||||||
|
function(url) {
|
||||||
|
return this._infosByUri[url];
|
||||||
|
})), terms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Signals.addSignalMethods(DocManager.prototype);
|
@ -1,202 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
// Common utils for the extension system and the extension
|
|
||||||
// preferences tool
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const ShellJS = imports.gi.ShellJS;
|
|
||||||
|
|
||||||
const Config = imports.misc.config;
|
|
||||||
|
|
||||||
const ExtensionType = {
|
|
||||||
SYSTEM: 1,
|
|
||||||
PER_USER: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// Maps uuid -> metadata object
|
|
||||||
const extensions = {};
|
|
||||||
|
|
||||||
function getCurrentExtension() {
|
|
||||||
let stack = (new Error()).stack;
|
|
||||||
|
|
||||||
// Assuming we're importing this directly from an extension (and we shouldn't
|
|
||||||
// ever not be), its UUID should be directly in the path here.
|
|
||||||
let extensionStackLine = stack.split('\n')[1];
|
|
||||||
if (!extensionStackLine)
|
|
||||||
throw new Error('Could not find current extension');
|
|
||||||
|
|
||||||
// The stack line is like:
|
|
||||||
// init([object Object])@/home/user/data/gnome-shell/extensions/u@u.id/prefs.js:8
|
|
||||||
//
|
|
||||||
// In the case that we're importing from
|
|
||||||
// module scope, the first field is blank:
|
|
||||||
// @/home/user/data/gnome-shell/extensions/u@u.id/prefs.js:8
|
|
||||||
let match = new RegExp('@(.+):\\d+').exec(extensionStackLine);
|
|
||||||
if (!match)
|
|
||||||
throw new Error('Could not find current extension');
|
|
||||||
|
|
||||||
let path = match[1];
|
|
||||||
let file = Gio.File.new_for_path(path);
|
|
||||||
|
|
||||||
// Walk up the directory tree, looking for an extesion with
|
|
||||||
// the same UUID as a directory name.
|
|
||||||
while (file != null) {
|
|
||||||
let extension = extensions[file.get_basename()];
|
|
||||||
if (extension !== undefined)
|
|
||||||
return extension;
|
|
||||||
file = file.get_parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error('Could not find current extension');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* versionCheck:
|
|
||||||
* @required: an array of versions we're compatible with
|
|
||||||
* @current: the version we have
|
|
||||||
*
|
|
||||||
* Check if a component is compatible for an extension.
|
|
||||||
* @required is an array, and at least one version must match.
|
|
||||||
* @current must be in the format <major>.<minor>.<point>.<micro>
|
|
||||||
* <micro> is always ignored
|
|
||||||
* <point> is ignored if <minor> is even (so you can target the
|
|
||||||
* whole stable release)
|
|
||||||
* <minor> and <major> must match
|
|
||||||
* Each target version must be at least <major> and <minor>
|
|
||||||
*/
|
|
||||||
function versionCheck(required, current) {
|
|
||||||
let currentArray = current.split('.');
|
|
||||||
let major = currentArray[0];
|
|
||||||
let minor = currentArray[1];
|
|
||||||
let point = currentArray[2];
|
|
||||||
for (let i = 0; i < required.length; i++) {
|
|
||||||
let requiredArray = required[i].split('.');
|
|
||||||
if (requiredArray[0] == major &&
|
|
||||||
requiredArray[1] == minor &&
|
|
||||||
(requiredArray[2] == point ||
|
|
||||||
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isOutOfDate(extension) {
|
|
||||||
if (!versionCheck(extension.metadata['shell-version'], Config.PACKAGE_VERSION))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createExtensionObject(uuid, dir, type) {
|
|
||||||
let info;
|
|
||||||
|
|
||||||
let metadataFile = dir.get_child('metadata.json');
|
|
||||||
if (!metadataFile.query_exists(null)) {
|
|
||||||
throw new Error('Missing metadata.json');
|
|
||||||
}
|
|
||||||
|
|
||||||
let metadataContents, success, tag;
|
|
||||||
try {
|
|
||||||
[success, metadataContents, tag] = metadataFile.load_contents(null);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error('Failed to load metadata.json: ' + e);
|
|
||||||
}
|
|
||||||
let meta;
|
|
||||||
try {
|
|
||||||
meta = JSON.parse(metadataContents);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error('Failed to parse metadata.json: ' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
|
|
||||||
for (let i = 0; i < requiredProperties.length; i++) {
|
|
||||||
let prop = requiredProperties[i];
|
|
||||||
if (!meta[prop]) {
|
|
||||||
throw new Error('missing "' + prop + '" property in metadata.json');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uuid != meta.uuid) {
|
|
||||||
throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
let extension = {};
|
|
||||||
|
|
||||||
extension.metadata = meta;
|
|
||||||
extension.uuid = meta.uuid;
|
|
||||||
extension.type = type;
|
|
||||||
extension.dir = dir;
|
|
||||||
extension.path = dir.get_path();
|
|
||||||
extension.error = '';
|
|
||||||
extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
|
|
||||||
|
|
||||||
extensions[uuid] = extension;
|
|
||||||
|
|
||||||
return extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
var _extension = null;
|
|
||||||
|
|
||||||
function installImporter(extension) {
|
|
||||||
_extension = extension;
|
|
||||||
ShellJS.add_extension_importer('imports.misc.extensionUtils._extension', 'imports', extension.path);
|
|
||||||
_extension = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ExtensionFinder = new Lang.Class({
|
|
||||||
Name: 'ExtensionFinder',
|
|
||||||
|
|
||||||
_scanExtensionsInDirectory: function(dir, type) {
|
|
||||||
let fileEnum;
|
|
||||||
let file, info;
|
|
||||||
try {
|
|
||||||
fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
} catch(e) {
|
|
||||||
if (e.domain != Gio.io_error_quark() || e.code != Gio.IOErrorEnum.NOT_FOUND)
|
|
||||||
logError(e, 'Could not enumerate extensions directory');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((info = fileEnum.next_file(null)) != null) {
|
|
||||||
let fileType = info.get_file_type();
|
|
||||||
if (fileType != Gio.FileType.DIRECTORY)
|
|
||||||
continue;
|
|
||||||
let uuid = info.get_name();
|
|
||||||
let extensionDir = dir.get_child(uuid);
|
|
||||||
|
|
||||||
let existing = extensions[uuid];
|
|
||||||
if (existing) {
|
|
||||||
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let extension;
|
|
||||||
try {
|
|
||||||
extension = createExtensionObject(uuid, extensionDir, type);
|
|
||||||
} catch(e) {
|
|
||||||
logError(e, 'Could not load extension %s'.format(uuid));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.emit('extension-found', extension);
|
|
||||||
}
|
|
||||||
fileEnum.close(null);
|
|
||||||
},
|
|
||||||
|
|
||||||
scanExtensions: function() {
|
|
||||||
let userExtensionsDir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions']));
|
|
||||||
this._scanExtensionsInDirectory(userExtensionsDir, ExtensionType.PER_USER);
|
|
||||||
|
|
||||||
let systemDataDirs = GLib.get_system_data_dirs();
|
|
||||||
for (let i = 0; i < systemDataDirs.length; i++) {
|
|
||||||
let dirPath = GLib.build_filenamev([systemDataDirs[i], 'gnome-shell', 'extensions']);
|
|
||||||
let dir = Gio.file_new_for_path(dirPath);
|
|
||||||
if (dir.query_exists(null))
|
|
||||||
this._scanExtensionsInDirectory(dir, ExtensionType.SYSTEM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(ExtensionFinder.prototype);
|
|
@ -1,5 +1,3 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
|
|
||||||
@ -22,46 +20,3 @@ function listDirAsync(file, callback) {
|
|||||||
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
|
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteGFile(file) {
|
|
||||||
// Work around 'delete' being a keyword in JS.
|
|
||||||
return file['delete'](null);
|
|
||||||
}
|
|
||||||
|
|
||||||
function recursivelyDeleteDir(dir, deleteParent) {
|
|
||||||
let children = dir.enumerate_children('standard::name,standard::type',
|
|
||||||
Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
|
|
||||||
let info, child;
|
|
||||||
while ((info = children.next_file(null)) != null) {
|
|
||||||
let type = info.get_file_type();
|
|
||||||
let child = dir.get_child(info.get_name());
|
|
||||||
if (type == Gio.FileType.REGULAR)
|
|
||||||
deleteGFile(child);
|
|
||||||
else if (type == Gio.FileType.DIRECTORY)
|
|
||||||
recursivelyDeleteDir(child, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deleteParent)
|
|
||||||
deleteGFile(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function recursivelyMoveDir(srcDir, destDir) {
|
|
||||||
let children = srcDir.enumerate_children('standard::name,standard::type',
|
|
||||||
Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
|
|
||||||
if (!destDir.query_exists(null))
|
|
||||||
destDir.make_directory_with_parents(null);
|
|
||||||
|
|
||||||
let info, child;
|
|
||||||
while ((info = children.next_file(null)) != null) {
|
|
||||||
let type = info.get_file_type();
|
|
||||||
let srcChild = srcDir.get_child(info.get_name());
|
|
||||||
let destChild = destDir.get_child(info.get_name());
|
|
||||||
log([srcChild.get_path(), destChild.get_path()]);
|
|
||||||
if (type == Gio.FileType.REGULAR)
|
|
||||||
srcChild.move(destChild, Gio.FileCopyFlags.NONE, null, null);
|
|
||||||
else if (type == Gio.FileType.DIRECTORY)
|
|
||||||
recursivelyMoveDir(srcChild, destChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
60
js/misc/format.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is intended to extend the String object and provide
|
||||||
|
* an String.format API for string formatting.
|
||||||
|
* It has to be set up using String.prototype.format = Format.format;
|
||||||
|
* Usage:
|
||||||
|
* "somestring %s %d".format('hello', 5);
|
||||||
|
* It supports %s, %d, %x and %f, for %f it also support precisions like
|
||||||
|
* "%.2f".format(1.526). All specifiers can be prefixed with a minimum
|
||||||
|
* field width, e.g. "%5s".format("foo"). Unless the width is prefixed
|
||||||
|
* with '0', the formatted string will be padded with spaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function format() {
|
||||||
|
let str = this;
|
||||||
|
let i = 0;
|
||||||
|
let args = arguments;
|
||||||
|
|
||||||
|
return str.replace(/%([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, widthGroup, precisionGroup, genericGroup) {
|
||||||
|
|
||||||
|
if (precisionGroup != '' && genericGroup != 'f')
|
||||||
|
throw new Error("Precision can only be specified for 'f'");
|
||||||
|
|
||||||
|
let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
|
||||||
|
let width = parseInt(widthGroup, 10) || 0;
|
||||||
|
|
||||||
|
function fillWidth(s, c, w) {
|
||||||
|
let fill = '';
|
||||||
|
for (let i = 0; i < w; i++)
|
||||||
|
fill += c;
|
||||||
|
return fill.substr(s.length) + s;
|
||||||
|
}
|
||||||
|
|
||||||
|
let s = '';
|
||||||
|
switch (genericGroup) {
|
||||||
|
case '%':
|
||||||
|
return '%';
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
s = args[i++].toString();
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
s = parseInt(args[i++]).toString();
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
s = parseInt(args[i++]).toString(16);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (precisionGroup == '')
|
||||||
|
s = parseFloat(args[i++]).toString();
|
||||||
|
else
|
||||||
|
s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported conversion character %' + genericGroup);
|
||||||
|
}
|
||||||
|
return fillWidth(s, fillChar, width);
|
||||||
|
});
|
||||||
|
}
|
@ -1,18 +1,20 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const DBus = imports.dbus;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
|
const PresenceIface = {
|
||||||
<method name="SetStatus">
|
name: 'org.gnome.SessionManager.Presence',
|
||||||
<arg type="u" direction="in"/>
|
methods: [{ name: 'SetStatus',
|
||||||
</method>
|
inSignature: 'u',
|
||||||
<property name="status" type="u" access="readwrite"/>
|
outSignature: '' }],
|
||||||
<signal name="StatusChanged">
|
properties: [{ name: 'status',
|
||||||
<arg type="u" direction="out"/>
|
signature: 'u',
|
||||||
</signal>
|
access: 'readwrite' }],
|
||||||
</interface>;
|
signals: [{ name: 'StatusChanged',
|
||||||
|
inSignature: 'u' }]
|
||||||
|
};
|
||||||
|
|
||||||
const PresenceStatus = {
|
const PresenceStatus = {
|
||||||
AVAILABLE: 0,
|
AVAILABLE: 0,
|
||||||
@ -21,70 +23,104 @@ const PresenceStatus = {
|
|||||||
IDLE: 3
|
IDLE: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
const Presence = new Gio.DBusProxyClass({
|
function Presence() {
|
||||||
Name: 'GnomeSessionPresence',
|
this._init();
|
||||||
Interface: PresenceIface,
|
}
|
||||||
|
|
||||||
|
Presence.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
|
||||||
g_name: 'org.gnome.SessionManager',
|
},
|
||||||
g_object_path: '/org/gnome/SessionManager/Presence' });
|
|
||||||
|
getStatus: function(callback) {
|
||||||
|
this.GetRemote('status', Lang.bind(this,
|
||||||
|
function(status, ex) {
|
||||||
|
if (!ex)
|
||||||
|
callback(this, status);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
setStatus: function(status) {
|
||||||
|
this.SetStatusRemote(status);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
DBus.proxifyPrototype(Presence.prototype, PresenceIface);
|
||||||
|
|
||||||
// Note inhibitors are immutable objects, so they don't
|
// Note inhibitors are immutable objects, so they don't
|
||||||
// change at runtime (changes always come in the form
|
// change at runtime (changes always come in the form
|
||||||
// of new inhibitors)
|
// of new inhibitors)
|
||||||
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
|
const InhibitorIface = {
|
||||||
<method name="GetAppId">
|
name: 'org.gnome.SessionManager.Inhibitor',
|
||||||
<arg type="s" direction="out" />
|
properties: [{ name: 'app_id',
|
||||||
</method>
|
signature: 's',
|
||||||
<method name="GetReason">
|
access: 'readonly' },
|
||||||
<arg type="s" direction="out" />
|
{ name: 'client_id',
|
||||||
</method>
|
signature: 's',
|
||||||
</interface>;
|
access: 'readonly' },
|
||||||
|
{ name: 'reason',
|
||||||
|
signature: 's',
|
||||||
|
access: 'readonly' },
|
||||||
|
{ name: 'flags',
|
||||||
|
signature: 'u',
|
||||||
|
access: 'readonly' },
|
||||||
|
{ name: 'toplevel_xid',
|
||||||
|
signature: 'u',
|
||||||
|
access: 'readonly' },
|
||||||
|
{ name: 'cookie',
|
||||||
|
signature: 'u',
|
||||||
|
access: 'readonly' }],
|
||||||
|
};
|
||||||
|
|
||||||
const Inhibitor = new Gio.DBusProxyClass({
|
function Inhibitor(objectPath) {
|
||||||
Name: 'GnomeSessionInhibitor',
|
this._init(objectPath);
|
||||||
Interface: InhibitorIface,
|
}
|
||||||
|
|
||||||
|
Inhibitor.prototype = {
|
||||||
|
_init: function(objectPath) {
|
||||||
|
DBus.session.proxifyObject(this,
|
||||||
|
"org.gnome.SessionManager",
|
||||||
|
objectPath);
|
||||||
|
this.isLoaded = false;
|
||||||
|
this._loadingPropertiesCount = InhibitorIface.properties.length;
|
||||||
|
for (let i = 0; i < InhibitorIface.properties.length; i++) {
|
||||||
|
let propertyName = InhibitorIface.properties[i].name;
|
||||||
|
this.GetRemote(propertyName, Lang.bind(this,
|
||||||
|
function(value, exception) {
|
||||||
|
if (exception)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this[propertyName] = value;
|
||||||
|
this._loadingPropertiesCount--;
|
||||||
|
|
||||||
|
if (this._loadingPropertiesCount == 0) {
|
||||||
|
this.isLoaded = true;
|
||||||
|
this.emit("is-loaded");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
|
||||||
|
Signals.addSignalMethods(Inhibitor.prototype);
|
||||||
|
|
||||||
_init: function(inhibitor) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
|
||||||
g_name: 'org.gnome.SessionManager',
|
|
||||||
g_object_path: inhibitor });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Not the full interface, only the methods we use
|
// Not the full interface, only the methods we use
|
||||||
const SessionManagerIface = <interface name="org.gnome.SessionManager">
|
const SessionManagerIface = {
|
||||||
<method name="Logout">
|
name: 'org.gnome.SessionManager',
|
||||||
<arg type="u" direction="in" />
|
methods: [
|
||||||
</method>
|
{ name: 'Logout', inSignature: 'u', outSignature: '' },
|
||||||
<method name="Shutdown" />
|
{ name: 'Shutdown', inSignature: '', outSignature: '' },
|
||||||
<method name="Reboot" />
|
{ name: 'CanShutdown', inSignature: '', outSignature: 'b' }
|
||||||
<method name="CanShutdown">
|
]
|
||||||
<arg type="b" direction="out" />
|
};
|
||||||
</method>
|
|
||||||
<method name="IsInhibited">
|
|
||||||
<arg type="u" direction="in" />
|
|
||||||
<arg type="b" direction="out" />
|
|
||||||
</method>
|
|
||||||
<signal name="InhibitorAdded">
|
|
||||||
<arg type="o" direction="out"/>
|
|
||||||
</signal>
|
|
||||||
<signal name="InhibitorRemoved">
|
|
||||||
<arg type="o" direction="out"/>
|
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const SessionManager = new Gio.DBusProxyClass({
|
function SessionManager() {
|
||||||
Name: 'GnomeSessionManager',
|
this._init();
|
||||||
Interface: SessionManagerIface,
|
}
|
||||||
|
|
||||||
|
SessionManager.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
|
||||||
g_name: 'org.gnome.SessionManager',
|
}
|
||||||
g_object_path: '/org/gnome/SessionManager' });
|
};
|
||||||
},
|
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);
|
||||||
});
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
@ -7,9 +7,11 @@ const Params = imports.misc.params;
|
|||||||
|
|
||||||
const DEFAULT_LIMIT = 512;
|
const DEFAULT_LIMIT = 512;
|
||||||
|
|
||||||
const HistoryManager = new Lang.Class({
|
function HistoryManager(params) {
|
||||||
Name: 'HistoryManager',
|
this._init(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
HistoryManager.prototype = {
|
||||||
_init: function(params) {
|
_init: function(params) {
|
||||||
params = Params.parse(params, { gsettingsKey: null,
|
params = Params.parse(params, { gsettingsKey: null,
|
||||||
limit: DEFAULT_LIMIT,
|
limit: DEFAULT_LIMIT,
|
||||||
@ -41,26 +43,24 @@ const HistoryManager = new Lang.Class({
|
|||||||
this._historyIndex = this._history.length;
|
this._historyIndex = this._history.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
_setPrevItem: function(text) {
|
prevItem: function(text) {
|
||||||
if (this._historyIndex <= 0)
|
if (this._historyIndex <= 0)
|
||||||
return false;
|
return text;
|
||||||
|
|
||||||
if (text)
|
if (text)
|
||||||
this._history[this._historyIndex] = text;
|
this._history[this._historyIndex] = text;
|
||||||
this._historyIndex--;
|
this._historyIndex--;
|
||||||
this._indexChanged();
|
return this._indexChanged();
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_setNextItem: function(text) {
|
nextItem: function(text) {
|
||||||
if (this._historyIndex >= this._history.length)
|
if (this._historyIndex >= this._history.length)
|
||||||
return false;
|
return text;
|
||||||
|
|
||||||
if (text)
|
if (text)
|
||||||
this._history[this._historyIndex] = text;
|
this._history[this._historyIndex] = text;
|
||||||
this._historyIndex++;
|
this._historyIndex++;
|
||||||
this._indexChanged();
|
return this._indexChanged();
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
lastItem: function() {
|
lastItem: function() {
|
||||||
@ -85,9 +85,11 @@ const HistoryManager = new Lang.Class({
|
|||||||
_onEntryKeyPress: function(entry, event) {
|
_onEntryKeyPress: function(entry, event) {
|
||||||
let symbol = event.get_key_symbol();
|
let symbol = event.get_key_symbol();
|
||||||
if (symbol == Clutter.KEY_Up) {
|
if (symbol == Clutter.KEY_Up) {
|
||||||
return this._setPrevItem(entry.get_text());
|
this.prevItem(entry.get_text());
|
||||||
|
return true;
|
||||||
} else if (symbol == Clutter.KEY_Down) {
|
} else if (symbol == Clutter.KEY_Down) {
|
||||||
return this._setNextItem(entry.get_text());
|
this.nextItem(entry.get_text());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@ -98,6 +100,8 @@ const HistoryManager = new Lang.Class({
|
|||||||
|
|
||||||
if (this._entry)
|
if (this._entry)
|
||||||
this._entry.set_text(current);
|
this._entry.set_text(current);
|
||||||
|
|
||||||
|
return current;
|
||||||
},
|
},
|
||||||
|
|
||||||
_save: function() {
|
_save: function() {
|
||||||
@ -107,5 +111,5 @@ const HistoryManager = new Lang.Class({
|
|||||||
if (this._key)
|
if (this._key)
|
||||||
global.settings.set_strv(this._key, this._history);
|
global.settings.set_strv(this._key, this._history);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(HistoryManager.prototype);
|
Signals.addSignalMethods(HistoryManager.prototype);
|
||||||
|
@ -1,246 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
// Returns a list of potential completions for text. Completions either
|
|
||||||
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
|
|
||||||
// commandHeader is prefixed on any expression before it is eval'ed. It will most likely
|
|
||||||
// consist of global constants that might not carry over from the calling environment.
|
|
||||||
//
|
|
||||||
// This function is likely the one you want to call from external modules
|
|
||||||
function getCompletions(text, commandHeader, globalCompletionList) {
|
|
||||||
let methods = [];
|
|
||||||
let expr, base;
|
|
||||||
let attrHead = '';
|
|
||||||
if (globalCompletionList == null) {
|
|
||||||
globalCompletionList = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
let offset = getExpressionOffset(text, text.length - 1);
|
|
||||||
if (offset >= 0) {
|
|
||||||
text = text.slice(offset);
|
|
||||||
|
|
||||||
// Look for expressions like "Main.panel.foo" and match Main.panel and foo
|
|
||||||
let matches = text.match(/(.*)\.(.*)/);
|
|
||||||
if (matches) {
|
|
||||||
[expr, base, attrHead] = matches;
|
|
||||||
|
|
||||||
methods = getPropertyNamesFromExpression(base, commandHeader).filter(function(attr) {
|
|
||||||
return attr.slice(0, attrHead.length) == attrHead;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the empty expression or partially entered words
|
|
||||||
// not proceeded by a dot and match them against global constants
|
|
||||||
matches = text.match(/^(\w*)$/);
|
|
||||||
if (text == '' || matches) {
|
|
||||||
[expr, attrHead] = matches;
|
|
||||||
methods = globalCompletionList.filter(function(attr) {
|
|
||||||
return attr.slice(0, attrHead.length) == attrHead;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [methods, attrHead];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// A few functions for parsing strings of javascript code.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Identify characters that delimit an expression. That is,
|
|
||||||
// if we encounter anything that isn't a letter, '.', ')', or ']',
|
|
||||||
// we should stop parsing.
|
|
||||||
function isStopChar(c) {
|
|
||||||
return !c.match(/[\w\.\)\]]/);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given the ending position of a quoted string, find where it starts
|
|
||||||
function findMatchingQuote(expr, offset) {
|
|
||||||
let quoteChar = expr.charAt(offset);
|
|
||||||
for (let i = offset - 1; i >= 0; --i) {
|
|
||||||
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given the ending position of a regex, find where it starts
|
|
||||||
function findMatchingSlash(expr, offset) {
|
|
||||||
for (let i = offset - 1; i >= 0; --i) {
|
|
||||||
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If expr.charAt(offset) is ')' or ']',
|
|
||||||
// return the position of the corresponding '(' or '[' bracket.
|
|
||||||
// This function does not check for syntactic correctness. e.g.,
|
|
||||||
// findMatchingBrace("[(])", 3) returns 1.
|
|
||||||
function findMatchingBrace(expr, offset) {
|
|
||||||
let closeBrace = expr.charAt(offset);
|
|
||||||
let openBrace = ({')': '(', ']': '['})[closeBrace];
|
|
||||||
|
|
||||||
function findTheBrace(expr, offset) {
|
|
||||||
if (offset < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expr.charAt(offset) == openBrace) {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
if (expr.charAt(offset).match(/['"]/)) {
|
|
||||||
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
|
|
||||||
}
|
|
||||||
if (expr.charAt(offset) == '/') {
|
|
||||||
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
|
|
||||||
}
|
|
||||||
if (expr.charAt(offset) == closeBrace) {
|
|
||||||
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return findTheBrace(expr, offset - 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return findTheBrace(expr, offset - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Walk expr backwards from offset looking for the beginning of an
|
|
||||||
// expression suitable for passing to eval.
|
|
||||||
// There is no guarantee of correct javascript syntax between the return
|
|
||||||
// value and offset. This function is meant to take a string like
|
|
||||||
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
|
|
||||||
function getExpressionOffset(expr, offset) {
|
|
||||||
while (offset >= 0) {
|
|
||||||
let currChar = expr.charAt(offset);
|
|
||||||
|
|
||||||
if (isStopChar(currChar)){
|
|
||||||
return offset + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currChar.match(/[\)\]]/)) {
|
|
||||||
offset = findMatchingBrace(expr, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
--offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Things with non-word characters or that start with a number
|
|
||||||
// are not accessible via .foo notation and so aren't returned
|
|
||||||
function isValidPropertyName(w) {
|
|
||||||
return !(w.match(/\W/) || w.match(/^\d/));
|
|
||||||
}
|
|
||||||
|
|
||||||
// To get all properties (enumerable and not), we need to walk
|
|
||||||
// the prototype chain ourselves
|
|
||||||
function getAllProps(obj) {
|
|
||||||
if (obj === null || obj === undefined) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a string _expr_, returns all methods
|
|
||||||
// that can be accessed via '.' notation.
|
|
||||||
// e.g., expr="({ foo: null, bar: null, 4: null })" will
|
|
||||||
// return ["foo", "bar", ...] but the list will not include "4",
|
|
||||||
// since methods accessed with '.' notation must star with a letter or _.
|
|
||||||
function getPropertyNamesFromExpression(expr, commandHeader) {
|
|
||||||
if (commandHeader == null) {
|
|
||||||
commandHeader = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {};
|
|
||||||
if (!isUnsafeExpression(expr)) {
|
|
||||||
try {
|
|
||||||
obj = eval(commandHeader + expr);
|
|
||||||
} catch (e) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
let propsUnique = {};
|
|
||||||
if (typeof obj === 'object'){
|
|
||||||
let allProps = getAllProps(obj);
|
|
||||||
// Get only things we are allowed to complete following a '.'
|
|
||||||
allProps = allProps.filter( isValidPropertyName );
|
|
||||||
|
|
||||||
// Make sure propsUnique contains one key for every
|
|
||||||
// property so we end up with a unique list of properties
|
|
||||||
allProps.map(function(p){ propsUnique[p] = null; });
|
|
||||||
}
|
|
||||||
return Object.keys(propsUnique).sort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a list of words, returns the longest prefix they all have in common
|
|
||||||
function getCommonPrefix(words) {
|
|
||||||
let word = words[0];
|
|
||||||
for (let i = 0; i < word.length; i++) {
|
|
||||||
for (let w = 1; w < words.length; w++) {
|
|
||||||
if (words[w].charAt(i) != word.charAt(i))
|
|
||||||
return word.slice(0, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return word;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if there is reason to think that eval(str)
|
|
||||||
// will modify the global scope
|
|
||||||
function isUnsafeExpression(str) {
|
|
||||||
// Remove any blocks that are quoted or are in a regex
|
|
||||||
function removeLiterals(str) {
|
|
||||||
if (str.length == 0) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
let currChar = str.charAt(str.length - 1);
|
|
||||||
if (currChar == '"' || currChar == '\'') {
|
|
||||||
return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
|
|
||||||
} else if (currChar == '/') {
|
|
||||||
return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for any sort of assignment
|
|
||||||
// The strategy used is dumb: remove any quotes
|
|
||||||
// or regexs and comparison operators and see if there is an '=' character.
|
|
||||||
// If there is, it might be an unsafe assignment.
|
|
||||||
|
|
||||||
let prunedStr = removeLiterals(str);
|
|
||||||
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
|
|
||||||
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
|
|
||||||
|
|
||||||
if (prunedStr.match(/=/)) {
|
|
||||||
return true;
|
|
||||||
} else if (prunedStr.match(/;/)) {
|
|
||||||
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a list of global keywords derived from str
|
|
||||||
function getDeclaredConstants(str) {
|
|
||||||
let ret = [];
|
|
||||||
str.split(';').forEach(function(s) {
|
|
||||||
let base, keyword;
|
|
||||||
let match = s.match(/const\s+(\w+)\s*=/);
|
|
||||||
if (match) {
|
|
||||||
[base, keyword] = match;
|
|
||||||
ret.push(keyword);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
@ -1,391 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const UPowerGlib = imports.gi.UPowerGlib;
|
|
||||||
|
|
||||||
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
|
|
||||||
<method name='PowerOff'>
|
|
||||||
<arg type='b' direction='in'/>
|
|
||||||
</method>
|
|
||||||
<method name='Reboot'>
|
|
||||||
<arg type='b' direction='in'/>
|
|
||||||
</method>
|
|
||||||
<method name='Suspend'>
|
|
||||||
<arg type='b' direction='in'/>
|
|
||||||
</method>
|
|
||||||
<method name='CanPowerOff'>
|
|
||||||
<arg type='s' direction='out'/>
|
|
||||||
</method>
|
|
||||||
<method name='CanReboot'>
|
|
||||||
<arg type='s' direction='out'/>
|
|
||||||
</method>
|
|
||||||
<method name='CanSuspend'>
|
|
||||||
<arg type='s' direction='out'/>
|
|
||||||
</method>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
|
|
||||||
<signal name='Lock' />
|
|
||||||
<signal name='Unlock' />
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const SystemdLoginManager = new Gio.DBusProxyClass({
|
|
||||||
Name: 'SystemdLoginManager',
|
|
||||||
Interface: SystemdLoginManagerIface,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.login1',
|
|
||||||
g_object_path: '/org/freedesktop/login1' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const SystemdLoginSession = new Gio.DBusProxyClass({
|
|
||||||
Name: 'SystemdLoginSession',
|
|
||||||
Interface: SystemdLoginSessionIface,
|
|
||||||
|
|
||||||
_init: function(session) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.login1',
|
|
||||||
g_object_path: session });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
|
|
||||||
<method name='CanRestart'>
|
|
||||||
<arg type='b' direction='out'/>
|
|
||||||
</method>
|
|
||||||
<method name='CanStop'>
|
|
||||||
<arg type='b' direction='out'/>
|
|
||||||
</method>
|
|
||||||
<method name='Restart' />
|
|
||||||
<method name='Stop' />
|
|
||||||
<method name='GetCurrentSession'>
|
|
||||||
<arg type='o' direction='out' />
|
|
||||||
</method>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'>
|
|
||||||
<method name='IsActive'>
|
|
||||||
<arg type='b' direction='out' />
|
|
||||||
</method>
|
|
||||||
<signal name='ActiveChanged'>
|
|
||||||
<arg type='b' direction='out' />
|
|
||||||
</signal>
|
|
||||||
<signal name='Lock' />
|
|
||||||
<signal name='Unlock' />
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const ConsoleKitSession = new Gio.DBusProxyClass({
|
|
||||||
Name: 'ConsoleKitSession',
|
|
||||||
Interface: ConsoleKitSessionIface,
|
|
||||||
|
|
||||||
_init: function(session) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.ConsoleKit',
|
|
||||||
g_object_path: session });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const ConsoleKitManager = new Gio.DBusProxyClass({
|
|
||||||
Name: 'ConsoleKitManager',
|
|
||||||
Interface: ConsoleKitManagerIface,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.ConsoleKit',
|
|
||||||
g_object_path: '/org/freedesktop/ConsoleKit/Manager' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function haveSystemd() {
|
|
||||||
return GLib.access("/sys/fs/cgroup/systemd", 0) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let _loginManager = null;
|
|
||||||
let _pendingAsyncCallbacks = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LoginManager:
|
|
||||||
* An abstraction over systemd/logind and ConsoleKit.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function getLoginManager(asyncCallback) {
|
|
||||||
if (_loginManager == null) {
|
|
||||||
if (_pendingAsyncCallbacks.length == 0) {
|
|
||||||
let manager;
|
|
||||||
|
|
||||||
if (haveSystemd())
|
|
||||||
manager = new LoginManagerSystemd();
|
|
||||||
else
|
|
||||||
manager = new LoginManagerConsoleKit();
|
|
||||||
|
|
||||||
manager.initAsync(null, function(obj, result) {
|
|
||||||
obj.initFinish(result);
|
|
||||||
|
|
||||||
_loginManager = manager;
|
|
||||||
|
|
||||||
_pendingAsyncCallbacks.forEach(function (f) { f(obj) });
|
|
||||||
_pendingAsyncCallbacks = [];
|
|
||||||
});
|
|
||||||
|
|
||||||
_pendingAsyncCallbacks = [asyncCallback];
|
|
||||||
} else {
|
|
||||||
_pendingAsyncCallbacks.push(asyncCallback);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GLib.idle_add(GLib.PRIORITY_DEFAULT, function() {
|
|
||||||
asyncCallback(_loginManager);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoginManagerSystemd = new Lang.Class({
|
|
||||||
Name: 'LoginManagerSystemd',
|
|
||||||
Extends: GObject.Object,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent();
|
|
||||||
|
|
||||||
this._proxy = new SystemdLoginManager();
|
|
||||||
},
|
|
||||||
|
|
||||||
initAsync: function(cancellable, asyncCallback) {
|
|
||||||
let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null);
|
|
||||||
simpleResult.set_check_cancellable(cancellable);
|
|
||||||
|
|
||||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
|
|
||||||
if (cancellable && cancellable.is_cancelled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._fetchCurrentSession(cancellable, simpleResult);
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
simpleResult.set_from_error(e);
|
|
||||||
simpleResult.complete();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
initFinish: function(simpleResult) {
|
|
||||||
if (!simpleResult.propagate_error())
|
|
||||||
return simpleResult.get_op_res_gboolean();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_fetchCurrentSession: function(cancellable, simpleResult) {
|
|
||||||
this._currentSession = new SystemdLoginSession('/org/freedesktop/login1/session/' +
|
|
||||||
GLib.getenv('XDG_SESSION_ID'));
|
|
||||||
|
|
||||||
this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
|
|
||||||
simpleResult.set_op_res_gboolean(true);
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
simpleResult.set_from_error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
simpleResult.complete();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
|
||||||
// session objects have different interfaces - but in both cases there are
|
|
||||||
// Lock/Unlock signals, and that's all we count upon at the moment.
|
|
||||||
//
|
|
||||||
// This is only valid after async initialization
|
|
||||||
getCurrentSessionProxy: function() {
|
|
||||||
return this._currentSession;
|
|
||||||
},
|
|
||||||
|
|
||||||
get sessionActive() {
|
|
||||||
return Shell.session_is_active_for_systemd();
|
|
||||||
},
|
|
||||||
|
|
||||||
canPowerOff: function(asyncCallback) {
|
|
||||||
this._proxy.CanPowerOffRemote(null, function(proxy, result) {
|
|
||||||
let val = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
val = proxy.CanPowerOffFinish(result)[0] != 'no';
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
asyncCallback(val);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
canReboot: function(asyncCallback) {
|
|
||||||
this._proxy.CanRebootRemote(null, function(proxy, result) {
|
|
||||||
let val = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
val = proxy.CanRebootFinish(result)[0] != 'no';
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
asyncCallback(val);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
canSuspend: function(asyncCallback) {
|
|
||||||
this._proxy.CanSuspendRemote(null, function(proxy, result) {
|
|
||||||
let val = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
val = proxy.CanRebootFinish(result)[0] != 'no';
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
asyncCallback(val);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
powerOff: function() {
|
|
||||||
this._proxy.PowerOffRemote(true, null, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
reboot: function() {
|
|
||||||
this._proxy.RebootRemote(true, null, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
suspend: function() {
|
|
||||||
this._proxy.SuspendRemote(true, null, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const LoginManagerConsoleKit = new Lang.Class({
|
|
||||||
Name: 'LoginManagerConsoleKit',
|
|
||||||
Extends: GObject.Object,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent();
|
|
||||||
|
|
||||||
this._proxy = new ConsoleKitManager();
|
|
||||||
this._upClient = new UPowerGlib.Client();
|
|
||||||
},
|
|
||||||
|
|
||||||
initAsync: function(cancellable, asyncCallback) {
|
|
||||||
let simpleResult = Gio.SimpleAsyncResult.new(this, asyncCallback, null);
|
|
||||||
simpleResult.set_check_cancellable(cancellable);
|
|
||||||
|
|
||||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
|
|
||||||
if (cancellable && cancellable.is_cancelled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._fetchCurrentSession(cancellable, simpleResult);
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
simpleResult.set_from_error(e);
|
|
||||||
simpleResult.complete();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
initFinish: function(simpleResult) {
|
|
||||||
if (!simpleResult.propagate_error())
|
|
||||||
return simpleResult.get_op_res_gboolean();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_fetchCurrentSession: function(cancellable, simpleResult) {
|
|
||||||
this._proxy.GetCurrentSessionRemote(cancellable, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
let [currentSessionId] = proxy.GetCurrentSessionFinish(result);
|
|
||||||
|
|
||||||
if (cancellable && cancellable.is_cancelled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._createSessionProxy(currentSessionId, cancellable, simpleResult);
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
simpleResult.set_from_error(e);
|
|
||||||
simpleResult.complete();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_createSessionProxy: function(currentSessionId, cancellable, simpleResult) {
|
|
||||||
this._currentSession = new ConsoleKitSession(currentSessionId);
|
|
||||||
this._currentSession.init_async(GLib.PRIORITY_DEFAULT, cancellable, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
|
|
||||||
simpleResult.set_op_res_gboolean(true);
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
simpleResult.set_from_error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
simpleResult.complete();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
// Having this function is a bit of a hack since the Systemd and ConsoleKit
|
|
||||||
// session objects have different interfaces - but in both cases there are
|
|
||||||
// Lock/Unlock signals, and that's all we count upon at the moment.
|
|
||||||
getCurrentSessionProxy: function() {
|
|
||||||
return this._currentSession;
|
|
||||||
},
|
|
||||||
|
|
||||||
get sessionActive() {
|
|
||||||
if (this._sessionActive !== undefined)
|
|
||||||
return this._sessionActive;
|
|
||||||
|
|
||||||
let session = this.getCurrentSessionProxy();
|
|
||||||
session.connectSignal('ActiveChanged', Lang.bind(this, function(object, senderName, [isActive]) {
|
|
||||||
this._sessionActive = isActive;
|
|
||||||
}));
|
|
||||||
[this._sessionActive] = session.IsActiveSync(null);
|
|
||||||
|
|
||||||
return this._sessionActive;
|
|
||||||
},
|
|
||||||
|
|
||||||
canPowerOff: function(asyncCallback) {
|
|
||||||
this._proxy.CanStopRemote(null, function(proxy, result) {
|
|
||||||
let val = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
[val] = proxy.CanStopFinish(result);
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
asyncCallback(val);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
canReboot: function(asyncCallback) {
|
|
||||||
this._proxy.CanRestartRemote(null, function(proxy, result) {
|
|
||||||
let val = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
[val] = proxy.CanRestartFinish(result);
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
asyncCallback(val);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
canSuspend: function(asyncCallback) {
|
|
||||||
Mainloop.idle_add(Lang.bind(this, function() {
|
|
||||||
asyncCallback(this._upClient.get_can_suspend());
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
powerOff: function() {
|
|
||||||
this._proxy.StopRemote(null, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
reboot: function() {
|
|
||||||
this._proxy.RestartRemote(null, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
suspend: function() {
|
|
||||||
this._upClient.suspend_sync(null);
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,7 +1,6 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
const DBus = imports.dbus;
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
@ -9,57 +8,33 @@ const Signals = imports.signals;
|
|||||||
// The following are not the complete interfaces, just the methods we need
|
// The following are not the complete interfaces, just the methods we need
|
||||||
// (or may need in the future)
|
// (or may need in the future)
|
||||||
|
|
||||||
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
|
const ModemGsmNetworkInterface = {
|
||||||
<method name="GetRegistrationInfo">
|
name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
|
||||||
<arg type="(uss)" direction="out" />
|
methods: [
|
||||||
</method>
|
{ name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
|
||||||
<method name="GetSignalQuality">
|
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
|
||||||
<arg type="u" direction="out" />
|
],
|
||||||
</method>
|
properties: [
|
||||||
<property name="AccessTechnology" type="u" access="read" />
|
{ name: 'AccessTechnology', signature: 'u', access: 'read' }
|
||||||
<signal name="SignalQuality">
|
],
|
||||||
<arg type="u" direction="out" />
|
signals: [
|
||||||
</signal>
|
{ name: 'SignalQuality', inSignature: 'u' },
|
||||||
<signal name="RegistrationInfo">
|
{ name: 'RegistrationInfo', inSignature: 'uss' }
|
||||||
<arg type="u" direction="out" />
|
]
|
||||||
<arg type="s" direction="out" />
|
};
|
||||||
<arg type="s" direction="out" />
|
const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const ModemGsmNetworkProxy = new Gio.DBusProxyClass({
|
const ModemCdmaInterface = {
|
||||||
Name: 'ModemGsmNetworkProxy',
|
name: 'org.freedesktop.ModemManager.Modem.Cdma',
|
||||||
Interface: ModemGsmNetworkInterface,
|
methods: [
|
||||||
|
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
|
||||||
_init: function(modem) {
|
{ name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
],
|
||||||
g_name: 'org.freedesktop.ModemManager',
|
signals: [
|
||||||
g_object_path: modem });
|
{ name: 'SignalQuality', inSignature: 'u' }
|
||||||
}
|
]
|
||||||
});
|
};
|
||||||
|
const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
|
||||||
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
|
|
||||||
<method name="GetSignalQuality">
|
|
||||||
<arg type="u" direction="out" />
|
|
||||||
</method>
|
|
||||||
<method name="GetServingSystem">
|
|
||||||
<arg type="(usu)" direction="out" />
|
|
||||||
</method>
|
|
||||||
<signal name="SignalQuality">
|
|
||||||
<arg type="u" direction="out" />
|
|
||||||
</signal>
|
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const ModemCdmaProxy = new Gio.DBusProxyClass({
|
|
||||||
Name: 'ModemCdmaProxy',
|
|
||||||
Interface: ModemCdmaInterface,
|
|
||||||
|
|
||||||
_init: function(modem) {
|
|
||||||
this.parent({ g_bus_type: Gio.BusType.SYSTEM,
|
|
||||||
g_name: 'org.freedesktop.ModemManager',
|
|
||||||
g_object_path: modem });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
let _providersTable;
|
let _providersTable;
|
||||||
function _getProvidersTable() {
|
function _getProvidersTable() {
|
||||||
@ -69,44 +44,44 @@ function _getProvidersTable() {
|
|||||||
return _providersTable = providers;
|
return _providersTable = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModemGsm = new Lang.Class({
|
function ModemGsm() {
|
||||||
Name: 'ModemGsm',
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemGsm.prototype = {
|
||||||
_init: function(path) {
|
_init: function(path) {
|
||||||
this._proxy = new ModemGsmNetworkProxy(path);
|
this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
|
||||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(obj, result) {
|
|
||||||
obj.init_finish(result);
|
|
||||||
|
|
||||||
this._finishInit();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.signal_quality = 0;
|
this.signal_quality = 0;
|
||||||
this.operator_name = null;
|
this.operator_name = null;
|
||||||
},
|
|
||||||
|
|
||||||
_finishInit: function() {
|
|
||||||
// Code is duplicated because the function have different signatures
|
// Code is duplicated because the function have different signatures
|
||||||
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
|
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
|
||||||
this.signal_quality = quality;
|
this.signal_quality = quality;
|
||||||
this.emit('notify::signal-quality');
|
this.emit('notify::signal-quality');
|
||||||
}));
|
}));
|
||||||
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
|
this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
|
||||||
this.operator_name = this._findOperatorName(name, code);
|
this.operator_name = this._findOperatorName(name, code);
|
||||||
this.emit('notify::operator-name');
|
this.emit('notify::operator-name');
|
||||||
}));
|
}));
|
||||||
this._proxy.GetRegistrationInfoRemote(null, Lang.bind(this, function(proxy, result) {
|
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function(result, err) {
|
||||||
let [status, code, name] = proxy.GetRegistrationInfoFinish(result);
|
if (err) {
|
||||||
this.operator_name = this._findOperatorName(name, code);
|
log(err);
|
||||||
this.emit('notify::operator-name');
|
return;
|
||||||
}));
|
|
||||||
this._proxy.GetSignalQualityRemote(null, Lang.bind(this, function(proxy, result) {
|
|
||||||
try {
|
|
||||||
[this.signal_quality] = proxy.GetSignalQualityFinish(result);
|
|
||||||
} catch(e) {
|
|
||||||
// it will return an error if the device is not connected
|
|
||||||
this.signal_quality = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let [status, code, name] = result;
|
||||||
|
this.operator_name = this._findOperatorName(name, code);
|
||||||
|
this.emit('notify::operator-name');
|
||||||
|
}));
|
||||||
|
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||||
|
if (err) {
|
||||||
|
// it will return an error if the device is not connected
|
||||||
|
this.signal_quality = 0;
|
||||||
|
} else {
|
||||||
|
let [quality] = result;
|
||||||
|
this.signal_quality = quality;
|
||||||
|
}
|
||||||
this.emit('notify::signal-quality');
|
this.emit('notify::signal-quality');
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -171,27 +146,21 @@ const ModemGsm = new Lang.Class({
|
|||||||
|
|
||||||
return name3 || name2 || null;
|
return name3 || name2 || null;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
Signals.addSignalMethods(ModemGsm.prototype);
|
Signals.addSignalMethods(ModemGsm.prototype);
|
||||||
|
|
||||||
const ModemCdma = new Lang.Class({
|
function ModemCdma() {
|
||||||
Name: 'ModemCdma',
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
ModemCdma.prototype = {
|
||||||
_init: function(path) {
|
_init: function(path) {
|
||||||
this._proxy = new ModemCdmaProxy(path);
|
this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
|
||||||
this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(obj, result) {
|
|
||||||
obj.init_finish(result);
|
|
||||||
|
|
||||||
this._finishInit();
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.signal_quality = 0;
|
this.signal_quality = 0;
|
||||||
this.operator_name = null;
|
this.operator_name = null;
|
||||||
},
|
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
|
||||||
|
this.signal_quality = quality;
|
||||||
_finishInit: function() {
|
|
||||||
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
|
|
||||||
this.signal_quality = params[0];
|
|
||||||
this.emit('notify::signal-quality');
|
this.emit('notify::signal-quality');
|
||||||
|
|
||||||
// receiving this signal means the device got activated
|
// receiving this signal means the device got activated
|
||||||
@ -199,31 +168,30 @@ const ModemCdma = new Lang.Class({
|
|||||||
if (this.operator_name == null)
|
if (this.operator_name == null)
|
||||||
this._refreshServingSystem();
|
this._refreshServingSystem();
|
||||||
}));
|
}));
|
||||||
this._proxy.GetSignalQualityRemote(null, Lang.bind(this, function(proxy, result) {
|
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
|
||||||
try {
|
if (err) {
|
||||||
[this.signal_quality] = proxy.GetSignalQualityFinish(result);
|
|
||||||
} catch(e) {
|
|
||||||
// it will return an error if the device is not connected
|
// it will return an error if the device is not connected
|
||||||
this.signal_quality = 0;
|
this.signal_quality = 0;
|
||||||
|
} else {
|
||||||
|
let [quality] = result;
|
||||||
|
this.signal_quality = quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('notify::signal-quality');
|
this.emit('notify::signal-quality');
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
_refreshServingSystem: function() {
|
_refreshServingSystem: function() {
|
||||||
this._proxy.GetServingSystemRemote(null, Lang.bind(this, function(proxy, result) {
|
this._proxy.GetServingSystemRemote(Lang.bind(this, function(result, err) {
|
||||||
try {
|
if (err) {
|
||||||
let [bandClass, band, name] = proxy.GetServingSystemFinish(result);
|
|
||||||
if (name.length > 0)
|
|
||||||
this.operator_name = this._findProviderForSid(name);
|
|
||||||
else
|
|
||||||
this.operator_name = null;
|
|
||||||
} catch(e) {
|
|
||||||
// it will return an error if the device is not connected
|
// it will return an error if the device is not connected
|
||||||
this.operator_name = null;
|
this.operator_name = null;
|
||||||
|
} else {
|
||||||
|
let [bandClass, band, id] = result;
|
||||||
|
if (name.length > 0)
|
||||||
|
this.operator_name = this._findProviderForSid(id);
|
||||||
|
else
|
||||||
|
this.operator_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('notify::operator-name');
|
this.emit('notify::operator-name');
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -253,5 +221,5 @@ const ModemCdma = new Lang.Class({
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(ModemCdma.prototype);
|
Signals.addSignalMethods(ModemCdma.prototype);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
// parse:
|
// parse:
|
||||||
// @params: caller-provided parameter object, or %null
|
// @params: caller-provided parameter object, or %null
|
||||||
|
53
js/misc/screenSaver.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const DBus = imports.dbus;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
|
||||||
|
const ScreenSaverIface = {
|
||||||
|
name: 'org.gnome.ScreenSaver',
|
||||||
|
methods: [{ name: 'GetActive',
|
||||||
|
inSignature: '',
|
||||||
|
outSignature: 'b' },
|
||||||
|
{ name: 'Lock',
|
||||||
|
inSignature: '' },
|
||||||
|
{ name: 'SetActive',
|
||||||
|
inSignature: 'b' }],
|
||||||
|
signals: [{ name: 'ActiveChanged',
|
||||||
|
inSignature: 'b' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
function ScreenSaverProxy() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenSaverProxy.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
DBus.session.proxifyObject(this,
|
||||||
|
'org.gnome.ScreenSaver',
|
||||||
|
'/org/gnome/ScreenSaver');
|
||||||
|
|
||||||
|
DBus.session.watch_name('org.gnome.ScreenSaver',
|
||||||
|
false, // do not launch a name-owner if none exists
|
||||||
|
Lang.bind(this, this._onSSAppeared),
|
||||||
|
Lang.bind(this, this._onSSVanished));
|
||||||
|
|
||||||
|
this.screenSaverActive = false;
|
||||||
|
this.connect('ActiveChanged',
|
||||||
|
Lang.bind(this, this._onActiveChanged));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onSSAppeared: function(owner) {
|
||||||
|
this.GetActiveRemote(Lang.bind(this, function(isActive) {
|
||||||
|
this.screenSaverActive = isActive;
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
_onSSVanished: function(oldOwner) {
|
||||||
|
this.screenSaverActive = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onActiveChanged: function(object, isActive) {
|
||||||
|
this.screenSaverActive = isActive;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DBus.proxifyPrototype(ScreenSaverProxy.prototype, ScreenSaverIface);
|
114
js/misc/util.js
@ -1,35 +1,14 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Gdk = imports.gi.Gdk;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
|
||||||
const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)';
|
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
|
||||||
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
|
|
||||||
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
|
|
||||||
|
|
||||||
const _urlRegexp = new RegExp(
|
|
||||||
'(^|' + _leadingJunk + ')' +
|
|
||||||
'(' +
|
|
||||||
'(?:' +
|
|
||||||
'[a-z][\\w-]+://' + // scheme://
|
|
||||||
'|' +
|
|
||||||
'www\\d{0,3}[.]' + // www.
|
|
||||||
'|' +
|
|
||||||
'[a-z0-9.\\-]+[.][a-z]{2,4}/' + // foo.xx/
|
|
||||||
')' +
|
|
||||||
'(?:' + // one or more:
|
|
||||||
'[^\\s()<>]+' + // run of non-space non-()
|
|
||||||
'|' + // or
|
|
||||||
_balancedParens + // balanced parens
|
|
||||||
')+' +
|
|
||||||
'(?:' + // end with:
|
|
||||||
_balancedParens + // balanced parens
|
|
||||||
'|' + // or
|
|
||||||
_notTrailingJunk + // last non-junk char
|
|
||||||
')' +
|
|
||||||
')', 'gi');
|
|
||||||
|
|
||||||
// findUrls:
|
// findUrls:
|
||||||
// @str: string to find URLs in
|
// @str: string to find URLs in
|
||||||
@ -42,7 +21,7 @@ const _urlRegexp = new RegExp(
|
|||||||
function findUrls(str) {
|
function findUrls(str) {
|
||||||
let res = [], match;
|
let res = [], match;
|
||||||
while ((match = _urlRegexp.exec(str)))
|
while ((match = _urlRegexp.exec(str)))
|
||||||
res.push({ url: match[2], pos: match.index + match[1].length });
|
res.push({ url: match[0], pos: match.index });
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,33 +59,24 @@ function spawnCommandLine(command_line) {
|
|||||||
// this will throw an error.
|
// this will throw an error.
|
||||||
function trySpawn(argv)
|
function trySpawn(argv)
|
||||||
{
|
{
|
||||||
var success, pid;
|
|
||||||
try {
|
try {
|
||||||
[success, pid] = GLib.spawn_async(null, argv, null,
|
GLib.spawn_async(null, argv, null,
|
||||||
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
|
GLib.SpawnFlags.SEARCH_PATH,
|
||||||
null);
|
null, null);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
/* Rewrite the error in case of ENOENT */
|
if (err.code == GLib.SpawnError.G_SPAWN_ERROR_NOENT) {
|
||||||
if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) {
|
err.message = _("Command not found");
|
||||||
throw new GLib.SpawnError({ code: GLib.SpawnError.NOENT,
|
} else {
|
||||||
message: _("Command not found") });
|
|
||||||
} else if (err instanceof GLib.Error) {
|
|
||||||
// The exception from gjs contains an error string like:
|
// The exception from gjs contains an error string like:
|
||||||
// Error invoking GLib.spawn_command_line_async: Failed to
|
// Error invoking GLib.spawn_command_line_async: Failed to
|
||||||
// execute child process "foo" (No such file or directory)
|
// execute child process "foo" (No such file or directory)
|
||||||
// We are only interested in the part in the parentheses. (And
|
// We are only interested in the part in the parentheses. (And
|
||||||
// we can't pattern match the text, since it gets localized.)
|
// we can't pattern match the text, since it gets localized.)
|
||||||
let message = err.message.replace(/.*\((.+)\)/, '$1');
|
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
||||||
throw new (err.constructor)({ code: err.code,
|
|
||||||
message: message });
|
|
||||||
} else {
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
// Dummy child watch; we don't want to double-fork internally
|
|
||||||
// because then we lose the parent-child relationship, which
|
|
||||||
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
|
|
||||||
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {}, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// trySpawnCommandLine:
|
// trySpawnCommandLine:
|
||||||
@ -150,7 +120,7 @@ function killall(processName) {
|
|||||||
// whatever...
|
// whatever...
|
||||||
|
|
||||||
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
|
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
|
||||||
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null);
|
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
|
||||||
// It might be useful to return success/failure, but we'd need
|
// It might be useful to return success/failure, but we'd need
|
||||||
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
|
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
|
||||||
// the current callers care, we don't bother.
|
// the current callers care, we don't bother.
|
||||||
@ -238,53 +208,3 @@ function fixupPCIDescription(desc) {
|
|||||||
|
|
||||||
return out.join(' ');
|
return out.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// lowerBound:
|
|
||||||
// @array: an array or array-like object, already sorted
|
|
||||||
// according to @cmp
|
|
||||||
// @val: the value to add
|
|
||||||
// @cmp: a comparator (or undefined to compare as numbers)
|
|
||||||
//
|
|
||||||
// Returns the position of the first element that is not
|
|
||||||
// lower than @val, according to @cmp.
|
|
||||||
// That is, returns the first position at which it
|
|
||||||
// is possible to insert @val without violating the
|
|
||||||
// order.
|
|
||||||
// This is quite like an ordinary binary search, except
|
|
||||||
// that it doesn't stop at first element comparing equal.
|
|
||||||
|
|
||||||
function lowerBound(array, val, cmp) {
|
|
||||||
let min, max, mid, v;
|
|
||||||
cmp = cmp || function(a, b) { return a - b; };
|
|
||||||
|
|
||||||
if (array.length == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
min = 0; max = array.length;
|
|
||||||
while (min < (max - 1)) {
|
|
||||||
mid = Math.floor((min + max) / 2);
|
|
||||||
v = cmp(array[mid], val);
|
|
||||||
|
|
||||||
if (v < 0)
|
|
||||||
min = mid + 1;
|
|
||||||
else
|
|
||||||
max = mid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (min == max || cmp(array[min], val) < 0) ? max : min;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertSorted:
|
|
||||||
// @array: an array sorted according to @cmp
|
|
||||||
// @val: a value to insert
|
|
||||||
// @cmp: the sorting function
|
|
||||||
//
|
|
||||||
// Inserts @val into @array, preserving the
|
|
||||||
// sorting invariants.
|
|
||||||
// Returns the position at which it was inserted
|
|
||||||
function insertSorted(array, val, cmp) {
|
|
||||||
let pos = lowerBound(array, val, cmp);
|
|
||||||
array.splice(pos, 0, val);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const System = imports.system;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Scripting = imports.ui.scripting;
|
const Scripting = imports.ui.scripting;
|
||||||
@ -101,7 +99,7 @@ function run() {
|
|||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
yield Scripting.waitLeisure();
|
yield Scripting.waitLeisure();
|
||||||
|
|
||||||
System.gc();
|
global.gc();
|
||||||
yield Scripting.sleep(1000);
|
yield Scripting.sleep(1000);
|
||||||
Scripting.collectStatistics();
|
Scripting.collectStatistics();
|
||||||
Scripting.scriptEvent('afterShowHide');
|
Scripting.scriptEvent('afterShowHide');
|
||||||
@ -115,10 +113,10 @@ function run() {
|
|||||||
|
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
Scripting.scriptEvent('applicationsShowStart');
|
Scripting.scriptEvent('applicationsShowStart');
|
||||||
Main.overview._dash.showAppsButton.checked = true;
|
Main.overview.viewSelector.switchTab('applications');
|
||||||
yield Scripting.waitLeisure();
|
yield Scripting.waitLeisure();
|
||||||
Scripting.scriptEvent('applicationsShowDone');
|
Scripting.scriptEvent('applicationsShowDone');
|
||||||
Main.overview._dash.showAppsButton.checked = false;
|
Main.overview.viewSelector.switchTab('windows');
|
||||||
yield Scripting.waitLeisure();
|
yield Scripting.waitLeisure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
334
js/ui/altTab.js
@ -1,22 +1,20 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Atk = imports.gi.Atk;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const POPUP_APPICON_SIZE = 96;
|
const POPUP_APPICON_SIZE = 96;
|
||||||
const POPUP_SCROLL_TIME = 0.10; // seconds
|
const POPUP_SCROLL_TIME = 0.10; // seconds
|
||||||
const POPUP_DELAY_TIMEOUT = 150; // milliseconds
|
const POPUP_FADE_IN_TIME = 0.4; // seconds
|
||||||
const POPUP_FADE_OUT_TIME = 0.1; // seconds
|
const POPUP_FADE_OUT_TIME = 0.1; // seconds
|
||||||
|
|
||||||
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
|
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
|
||||||
@ -33,21 +31,11 @@ function mod(a, b) {
|
|||||||
return (a + b) % b;
|
return (a + b) % b;
|
||||||
}
|
}
|
||||||
|
|
||||||
function primaryModifier(mask) {
|
function AltTabPopup() {
|
||||||
if (mask == 0)
|
this._init();
|
||||||
return 0;
|
|
||||||
|
|
||||||
let primary = 1;
|
|
||||||
while (mask > 1) {
|
|
||||||
mask >>= 1;
|
|
||||||
primary <<= 1;
|
|
||||||
}
|
|
||||||
return primary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AltTabPopup = new Lang.Class({
|
AltTabPopup.prototype = {
|
||||||
Name: 'AltTabPopup',
|
|
||||||
|
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
|
this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
|
||||||
reactive: true,
|
reactive: true,
|
||||||
@ -60,13 +48,11 @@ const AltTabPopup = new Lang.Class({
|
|||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
|
||||||
this._haveModal = false;
|
this._haveModal = false;
|
||||||
this._modifierMask = 0;
|
|
||||||
|
|
||||||
this._currentApp = 0;
|
this._currentApp = 0;
|
||||||
this._currentWindow = -1;
|
this._currentWindow = -1;
|
||||||
this._thumbnailTimeoutId = 0;
|
this._thumbnailTimeoutId = 0;
|
||||||
this._motionTimeoutId = 0;
|
this._motionTimeoutId = 0;
|
||||||
this._initialDelayTimeoutId = 0;
|
|
||||||
|
|
||||||
this.thumbnailsVisible = false;
|
this.thumbnailsVisible = false;
|
||||||
|
|
||||||
@ -127,57 +113,23 @@ const AltTabPopup = new Lang.Class({
|
|||||||
if (childBox.x2 > primary.x + primary.width - rightPadding)
|
if (childBox.x2 > primary.x + primary.width - rightPadding)
|
||||||
childBox.x2 = primary.x + primary.width - rightPadding;
|
childBox.x2 = primary.x + primary.width - rightPadding;
|
||||||
childBox.y1 = this._appSwitcher.actor.allocation.y2 + spacing;
|
childBox.y1 = this._appSwitcher.actor.allocation.y2 + spacing;
|
||||||
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
|
this._thumbnails.addClones(primary.height - bottomPadding - childBox.y1);
|
||||||
let [childMinHeight, childNaturalHeight] = this._thumbnails.actor.get_preferred_height(-1);
|
let [childMinHeight, childNaturalHeight] = this._thumbnails.actor.get_preferred_height(-1);
|
||||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||||
this._thumbnails.actor.allocate(childBox, flags);
|
this._thumbnails.actor.allocate(childBox, flags);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getAppLists: function() {
|
show : function(backward, binding) {
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
let appSys = Shell.AppSystem.get_default();
|
let apps = tracker.get_running_apps ('');
|
||||||
let allApps = appSys.get_running ();
|
|
||||||
|
|
||||||
let screen = global.screen;
|
if (!apps.length)
|
||||||
let display = screen.get_display();
|
|
||||||
let windows = display.get_tab_list(Meta.TabList.NORMAL_ALL, screen,
|
|
||||||
screen.get_active_workspace());
|
|
||||||
|
|
||||||
// windows is only the windows on the current workspace. For
|
|
||||||
// each one, if it corresponds to an app we know, move that
|
|
||||||
// app from allApps to apps.
|
|
||||||
let apps = [];
|
|
||||||
for (let i = 0; i < windows.length && allApps.length != 0; i++) {
|
|
||||||
let app = tracker.get_window_app(windows[i]);
|
|
||||||
let index = allApps.indexOf(app);
|
|
||||||
if (index != -1) {
|
|
||||||
apps.push(app);
|
|
||||||
allApps.splice(index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now @apps is a list of apps on the current workspace, in
|
|
||||||
// standard Alt+Tab order (MRU except for minimized windows),
|
|
||||||
// and allApps is a list of apps that only appear on other
|
|
||||||
// workspaces, sorted by user_time, which is good enough.
|
|
||||||
return [apps, allApps];
|
|
||||||
},
|
|
||||||
|
|
||||||
show : function(backward, binding, mask) {
|
|
||||||
let [localApps, otherApps] = this._getAppLists();
|
|
||||||
|
|
||||||
if (localApps.length == 0 && otherApps.length == 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!Main.pushModal(this.actor)) {
|
if (!Main.pushModal(this.actor))
|
||||||
// Probably someone else has a pointer grab, try again with keyboard only
|
return false;
|
||||||
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._haveModal = true;
|
this._haveModal = true;
|
||||||
this._modifierMask = primaryModifier(mask);
|
|
||||||
|
|
||||||
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
||||||
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
||||||
@ -185,7 +137,7 @@ const AltTabPopup = new Lang.Class({
|
|||||||
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
|
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
|
||||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
||||||
|
|
||||||
this._appSwitcher = new AppSwitcher(localApps, otherApps, this);
|
this._appSwitcher = new AppSwitcher(apps, this);
|
||||||
this.actor.add_actor(this._appSwitcher.actor);
|
this.actor.add_actor(this._appSwitcher.actor);
|
||||||
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
|
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
|
||||||
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
|
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
|
||||||
@ -199,7 +151,7 @@ const AltTabPopup = new Lang.Class({
|
|||||||
this.actor.get_allocation_box();
|
this.actor.get_allocation_box();
|
||||||
|
|
||||||
// Make the initial selection
|
// Make the initial selection
|
||||||
if (binding == 'switch-group') {
|
if (binding == 'switch_group') {
|
||||||
if (backward) {
|
if (backward) {
|
||||||
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
||||||
} else {
|
} else {
|
||||||
@ -208,9 +160,9 @@ const AltTabPopup = new Lang.Class({
|
|||||||
else
|
else
|
||||||
this._select(0, 0);
|
this._select(0, 0);
|
||||||
}
|
}
|
||||||
} else if (binding == 'switch-group-backward') {
|
} else if (binding == 'switch_group_backward') {
|
||||||
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
this._select(0, this._appIcons[0].cachedWindows.length - 1);
|
||||||
} else if (binding == 'switch-windows-backward') {
|
} else if (binding == 'switch_windows_backward') {
|
||||||
this._select(this._appIcons.length - 1);
|
this._select(this._appIcons.length - 1);
|
||||||
} else if (this._appIcons.length == 1) {
|
} else if (this._appIcons.length == 1) {
|
||||||
this._select(0);
|
this._select(0);
|
||||||
@ -226,18 +178,21 @@ const AltTabPopup = new Lang.Class({
|
|||||||
// details.) So we check now. (Have to do this after updating
|
// details.) So we check now. (Have to do this after updating
|
||||||
// selection.)
|
// selection.)
|
||||||
let [x, y, mods] = global.get_pointer();
|
let [x, y, mods] = global.get_pointer();
|
||||||
if (!(mods & this._modifierMask)) {
|
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
|
||||||
this._finish();
|
this._finish();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We delay showing the popup so that fast Alt+Tab users aren't
|
// Using easeInOutExpo over 400ms gives us 150ms of "nearly
|
||||||
// disturbed by the popup briefly flashing.
|
// invisible" (less than 10% opacity), followed by a 100ms
|
||||||
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
|
// tween in (to 90% opacity, with the last 10% coming over the
|
||||||
Lang.bind(this, function () {
|
// next 150ms). So if the user releases Alt quickly after we
|
||||||
this.actor.opacity = 255;
|
// start tweening, they'll never see the switcher.
|
||||||
this._initialDelayTimeoutId = 0;
|
Tweener.addTween(this.actor,
|
||||||
}));
|
{ opacity: 255,
|
||||||
|
time: POPUP_FADE_IN_TIME,
|
||||||
|
transition: 'easeInOutExpo'
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
@ -266,9 +221,9 @@ const AltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
_keyPressEvent : function(actor, event) {
|
_keyPressEvent : function(actor, event) {
|
||||||
let keysym = event.get_key_symbol();
|
let keysym = event.get_key_symbol();
|
||||||
let event_state = event.get_state();
|
let event_state = Shell.get_event_state(event);
|
||||||
let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
|
let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
|
||||||
let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
|
let action = global.screen.get_display().get_keybinding_action(event.get_key_code(), event_state);
|
||||||
|
|
||||||
this._disableHover();
|
this._disableHover();
|
||||||
|
|
||||||
@ -303,7 +258,7 @@ const AltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
_keyReleaseEvent : function(actor, event) {
|
_keyReleaseEvent : function(actor, event) {
|
||||||
let [x, y, mods] = global.get_pointer();
|
let [x, y, mods] = global.get_pointer();
|
||||||
let state = mods & this._modifierMask;
|
let state = mods & Clutter.ModifierType.MOD1_MASK;
|
||||||
|
|
||||||
if (state == 0)
|
if (state == 0)
|
||||||
this._finish();
|
this._finish();
|
||||||
@ -440,8 +395,6 @@ const AltTabPopup = new Lang.Class({
|
|||||||
Mainloop.source_remove(this._motionTimeoutId);
|
Mainloop.source_remove(this._motionTimeoutId);
|
||||||
if (this._thumbnailTimeoutId != 0)
|
if (this._thumbnailTimeoutId != 0)
|
||||||
Mainloop.source_remove(this._thumbnailTimeoutId);
|
Mainloop.source_remove(this._thumbnailTimeoutId);
|
||||||
if (this._initialDelayTimeoutId != 0)
|
|
||||||
Mainloop.source_remove(this._initialDelayTimeoutId);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -519,7 +472,6 @@ const AltTabPopup = new Lang.Class({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
this._thumbnails = null;
|
this._thumbnails = null;
|
||||||
this._appSwitcher._items[this._currentApp].remove_accessible_state (Atk.StateType.EXPANDED);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_createThumbnails : function() {
|
_createThumbnails : function() {
|
||||||
@ -529,10 +481,6 @@ const AltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
this.actor.add_actor(this._thumbnails.actor);
|
this.actor.add_actor(this._thumbnails.actor);
|
||||||
|
|
||||||
// Need to force an allocation so we can figure out whether we
|
|
||||||
// need to scroll when selecting
|
|
||||||
this._thumbnails.actor.get_allocation_box();
|
|
||||||
|
|
||||||
this._thumbnails.actor.opacity = 0;
|
this._thumbnails.actor.opacity = 0;
|
||||||
Tweener.addTween(this._thumbnails.actor,
|
Tweener.addTween(this._thumbnails.actor,
|
||||||
{ opacity: 255,
|
{ opacity: 255,
|
||||||
@ -540,14 +488,14 @@ const AltTabPopup = new Lang.Class({
|
|||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad',
|
||||||
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
|
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
|
||||||
});
|
});
|
||||||
|
|
||||||
this._appSwitcher._items[this._currentApp].add_accessible_state (Atk.StateType.EXPANDED);
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const SwitcherList = new Lang.Class({
|
function SwitcherList(squareItems) {
|
||||||
Name: 'SwitcherList',
|
this._init(squareItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitcherList.prototype = {
|
||||||
_init : function(squareItems) {
|
_init : function(squareItems) {
|
||||||
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
|
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
|
||||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
@ -566,14 +514,14 @@ const SwitcherList = new Lang.Class({
|
|||||||
this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
this._list.connect('allocate', Lang.bind(this, this._allocate));
|
this._list.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
|
|
||||||
this._scrollView = new St.ScrollView({ style_class: 'hfade',
|
this._clipBin = new St.Bin({style_class: 'cbin'});
|
||||||
enable_mouse_scrolling: false });
|
this._clipBin.child = this._list;
|
||||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
|
this.actor.add_actor(this._clipBin);
|
||||||
|
|
||||||
let scrollBox = new St.BoxLayout();
|
this._leftGradient = new St.BoxLayout({style_class: 'thumbnail-scroll-gradient-left', vertical: true});
|
||||||
scrollBox.add_actor(this._list);
|
this._rightGradient = new St.BoxLayout({style_class: 'thumbnail-scroll-gradient-right', vertical: true});
|
||||||
this._scrollView.add_actor(scrollBox);
|
this.actor.add_actor(this._leftGradient);
|
||||||
this.actor.add_actor(this._scrollView);
|
this.actor.add_actor(this._rightGradient);
|
||||||
|
|
||||||
// Those arrows indicate whether scrolling in one direction is possible
|
// Those arrows indicate whether scrolling in one direction is possible
|
||||||
this._leftArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
|
this._leftArrow = new St.DrawingArea({ style_class: 'switcher-arrow',
|
||||||
@ -604,9 +552,21 @@ const SwitcherList = new Lang.Class({
|
|||||||
let childBox = new Clutter.ActorBox();
|
let childBox = new Clutter.ActorBox();
|
||||||
let scrollable = this._minSize > box.x2 - box.x1;
|
let scrollable = this._minSize > box.x2 - box.x1;
|
||||||
|
|
||||||
box.y1 -= this.actor.get_theme_node().get_padding(St.Side.TOP);
|
this._clipBin.allocate(box, flags);
|
||||||
box.y2 += this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
|
|
||||||
this._scrollView.allocate(box, flags);
|
childBox.x1 = 0;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.x2 = this._leftGradient.width;
|
||||||
|
childBox.y2 = this.actor.height;
|
||||||
|
this._leftGradient.allocate(childBox, flags);
|
||||||
|
this._leftGradient.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
|
||||||
|
|
||||||
|
childBox.x1 = (this.actor.allocation.x2 - this.actor.allocation.x1) - this._rightGradient.width;
|
||||||
|
childBox.y1 = 0;
|
||||||
|
childBox.x2 = childBox.x1 + this._rightGradient.width;
|
||||||
|
childBox.y2 = this.actor.height;
|
||||||
|
this._rightGradient.allocate(childBox, flags);
|
||||||
|
this._rightGradient.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
|
||||||
|
|
||||||
let arrowWidth = Math.floor(leftPadding / 3);
|
let arrowWidth = Math.floor(leftPadding / 3);
|
||||||
let arrowHeight = arrowWidth * 2;
|
let arrowHeight = arrowWidth * 2;
|
||||||
@ -615,7 +575,7 @@ const SwitcherList = new Lang.Class({
|
|||||||
childBox.x2 = childBox.x1 + arrowWidth;
|
childBox.x2 = childBox.x1 + arrowWidth;
|
||||||
childBox.y2 = childBox.y1 + arrowHeight;
|
childBox.y2 = childBox.y1 + arrowHeight;
|
||||||
this._leftArrow.allocate(childBox, flags);
|
this._leftArrow.allocate(childBox, flags);
|
||||||
this._leftArrow.opacity = (this._scrollableLeft && scrollable) ? 255 : 0;
|
this._leftArrow.opacity = this._leftGradient.opacity;
|
||||||
|
|
||||||
arrowWidth = Math.floor(rightPadding / 3);
|
arrowWidth = Math.floor(rightPadding / 3);
|
||||||
arrowHeight = arrowWidth * 2;
|
arrowHeight = arrowWidth * 2;
|
||||||
@ -624,7 +584,7 @@ const SwitcherList = new Lang.Class({
|
|||||||
childBox.x2 = childBox.x1 + arrowWidth;
|
childBox.x2 = childBox.x1 + arrowWidth;
|
||||||
childBox.y2 = childBox.y1 + arrowHeight;
|
childBox.y2 = childBox.y1 + arrowHeight;
|
||||||
this._rightArrow.allocate(childBox, flags);
|
this._rightArrow.allocate(childBox, flags);
|
||||||
this._rightArrow.opacity = (this._scrollableRight && scrollable) ? 255 : 0;
|
this._rightArrow.opacity = this._rightGradient.opacity;
|
||||||
},
|
},
|
||||||
|
|
||||||
addItem : function(item, label) {
|
addItem : function(item, label) {
|
||||||
@ -641,8 +601,6 @@ const SwitcherList = new Lang.Class({
|
|||||||
bbox.label_actor = label;
|
bbox.label_actor = label;
|
||||||
|
|
||||||
this._items.push(bbox);
|
this._items.push(bbox);
|
||||||
|
|
||||||
return bbox;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onItemClicked: function (index) {
|
_onItemClicked: function (index) {
|
||||||
@ -674,66 +632,48 @@ const SwitcherList = new Lang.Class({
|
|||||||
this._items[this._highlighted].add_style_pseudo_class('selected');
|
this._items[this._highlighted].add_style_pseudo_class('selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
let adjustment = this._scrollView.hscroll.adjustment;
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
|
let itemSize = this._items[index].allocation.x2 - this._items[index].allocation.x1;
|
||||||
let [absItemX, absItemY] = this._items[index].get_transformed_position();
|
let [posX, posY] = this._items[index].get_transformed_position();
|
||||||
let [result, posX, posY] = this.actor.transform_stage_point(absItemX, 0);
|
posX += this.actor.x;
|
||||||
let [containerWidth, containerHeight] = this.actor.get_transformed_size();
|
if (posX + itemSize > monitor.width + monitor.x)
|
||||||
if (posX + this._items[index].get_width() > containerWidth)
|
|
||||||
this._scrollToRight();
|
this._scrollToRight();
|
||||||
else if (this._items[index].allocation.x1 - value < 0)
|
else if (posX < 0)
|
||||||
this._scrollToLeft();
|
this._scrollToLeft();
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_scrollToLeft : function() {
|
_scrollToLeft : function() {
|
||||||
let adjustment = this._scrollView.hscroll.adjustment;
|
let x = this._items[this._highlighted].allocation.x1;
|
||||||
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
|
|
||||||
|
|
||||||
let item = this._items[this._highlighted];
|
|
||||||
|
|
||||||
if (item.allocation.x1 < value)
|
|
||||||
value = Math.min(0, item.allocation.x1);
|
|
||||||
else if (item.allocation.x2 > value + pageSize)
|
|
||||||
value = Math.max(upper, item.allocation.x2 - pageSize);
|
|
||||||
|
|
||||||
this._scrollableRight = true;
|
this._scrollableRight = true;
|
||||||
Tweener.addTween(adjustment,
|
Tweener.addTween(this._list, { anchor_x: x,
|
||||||
{ value: value,
|
time: POPUP_SCROLL_TIME,
|
||||||
time: POPUP_SCROLL_TIME,
|
transition: 'easeOutQuad',
|
||||||
transition: 'easeOutQuad',
|
onComplete: Lang.bind(this, function () {
|
||||||
onComplete: Lang.bind(this, function () {
|
if (this._highlighted == 0) {
|
||||||
if (this._highlighted == 0) {
|
this._scrollableLeft = false;
|
||||||
this._scrollableLeft = false;
|
this.actor.queue_relayout();
|
||||||
this.actor.queue_relayout();
|
}
|
||||||
}
|
})
|
||||||
})
|
});
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_scrollToRight : function() {
|
_scrollToRight : function() {
|
||||||
let adjustment = this._scrollView.hscroll.adjustment;
|
|
||||||
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
|
|
||||||
|
|
||||||
let item = this._items[this._highlighted];
|
|
||||||
|
|
||||||
if (item.allocation.x1 < value)
|
|
||||||
value = Math.max(0, item.allocation.x1);
|
|
||||||
else if (item.allocation.x2 > value + pageSize)
|
|
||||||
value = Math.min(upper, item.allocation.x2 - pageSize);
|
|
||||||
|
|
||||||
this._scrollableLeft = true;
|
this._scrollableLeft = true;
|
||||||
Tweener.addTween(adjustment,
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
{ value: value,
|
let padding = this.actor.get_theme_node().get_horizontal_padding();
|
||||||
time: POPUP_SCROLL_TIME,
|
let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
|
||||||
transition: 'easeOutQuad',
|
let x = this._items[this._highlighted].allocation.x2 - monitor.width + padding + parentPadding;
|
||||||
onComplete: Lang.bind(this, function () {
|
Tweener.addTween(this._list, { anchor_x: x,
|
||||||
if (this._highlighted == this._items.length - 1) {
|
time: POPUP_SCROLL_TIME,
|
||||||
this._scrollableRight = false;
|
transition: 'easeOutQuad',
|
||||||
this.actor.queue_relayout();
|
onComplete: Lang.bind(this, function () {
|
||||||
}
|
if (this._highlighted == this._items.length - 1) {
|
||||||
})
|
this._scrollableRight = false;
|
||||||
});
|
this.actor.queue_relayout();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_itemActivated: function(n) {
|
_itemActivated: function(n) {
|
||||||
@ -819,6 +759,14 @@ const SwitcherList = new Lang.Class({
|
|||||||
|
|
||||||
let primary = Main.layoutManager.primaryMonitor;
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
let parentRightPadding = this.actor.get_parent().get_theme_node().get_padding(St.Side.RIGHT);
|
let parentRightPadding = this.actor.get_parent().get_theme_node().get_padding(St.Side.RIGHT);
|
||||||
|
if (this.actor.allocation.x2 == primary.x + primary.width - parentRightPadding) {
|
||||||
|
if (this._squareItems)
|
||||||
|
childWidth = childHeight;
|
||||||
|
else {
|
||||||
|
let [childMin, childNat] = children[0].get_preferred_width(childHeight);
|
||||||
|
childWidth = childMin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < children.length; i++) {
|
for (let i = 0; i < children.length; i++) {
|
||||||
if (this._items.indexOf(children[i]) != -1) {
|
if (this._items.indexOf(children[i]) != -1) {
|
||||||
@ -844,14 +792,24 @@ const SwitcherList = new Lang.Class({
|
|||||||
// we don't allocate it.
|
// we don't allocate it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
|
||||||
|
let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
|
||||||
|
let topPadding = this.actor.get_theme_node().get_padding(St.Side.TOP);
|
||||||
|
let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
|
||||||
|
|
||||||
|
// Clip the area for scrolling
|
||||||
|
this._clipBin.set_clip(0, -topPadding, (this.actor.allocation.x2 - this.actor.allocation.x1) - leftPadding - rightPadding, this.actor.height + bottomPadding);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(SwitcherList.prototype);
|
Signals.addSignalMethods(SwitcherList.prototype);
|
||||||
|
|
||||||
const AppIcon = new Lang.Class({
|
function AppIcon(app) {
|
||||||
Name: 'AppIcon',
|
this._init(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIcon.prototype = {
|
||||||
_init: function(app) {
|
_init: function(app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
|
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
|
||||||
@ -869,32 +827,36 @@ const AppIcon = new Lang.Class({
|
|||||||
this._iconBin.set_size(size, size);
|
this._iconBin.set_size(size, size);
|
||||||
this._iconBin.child = this.icon;
|
this._iconBin.child = this.icon;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const AppSwitcher = new Lang.Class({
|
function AppSwitcher(apps, altTabPopup) {
|
||||||
Name: 'AppSwitcher',
|
this._init(apps, altTabPopup);
|
||||||
Extends: SwitcherList,
|
}
|
||||||
|
|
||||||
_init : function(localApps, otherApps, altTabPopup) {
|
AppSwitcher.prototype = {
|
||||||
this.parent(true);
|
__proto__ : SwitcherList.prototype,
|
||||||
|
|
||||||
// Construct the AppIcons, add to the popup
|
_init : function(apps, altTabPopup) {
|
||||||
|
SwitcherList.prototype._init.call(this, true);
|
||||||
|
|
||||||
|
// Construct the AppIcons, sort by time, add to the popup
|
||||||
let activeWorkspace = global.screen.get_active_workspace();
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
let workspaceIcons = [];
|
let workspaceIcons = [];
|
||||||
let otherIcons = [];
|
let otherIcons = [];
|
||||||
for (let i = 0; i < localApps.length; i++) {
|
for (let i = 0; i < apps.length; i++) {
|
||||||
let appIcon = new AppIcon(localApps[i]);
|
let appIcon = new AppIcon(apps[i]);
|
||||||
// Cache the window list now; we don't handle dynamic changes here,
|
// Cache the window list now; we don't handle dynamic changes here,
|
||||||
// and we don't want to be continually retrieving it
|
// and we don't want to be continually retrieving it
|
||||||
appIcon.cachedWindows = appIcon.app.get_windows();
|
appIcon.cachedWindows = appIcon.app.get_windows();
|
||||||
workspaceIcons.push(appIcon);
|
if (this._hasWindowsOnWorkspace(appIcon, activeWorkspace))
|
||||||
}
|
workspaceIcons.push(appIcon);
|
||||||
for (let i = 0; i < otherApps.length; i++) {
|
else
|
||||||
let appIcon = new AppIcon(otherApps[i]);
|
otherIcons.push(appIcon);
|
||||||
appIcon.cachedWindows = appIcon.app.get_windows();
|
|
||||||
otherIcons.push(appIcon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
|
||||||
|
otherIcons.sort(Lang.bind(this, this._sortAppIcon));
|
||||||
|
|
||||||
this.icons = [];
|
this.icons = [];
|
||||||
this._arrows = [];
|
this._arrows = [];
|
||||||
for (let i = 0; i < workspaceIcons.length; i++)
|
for (let i = 0; i < workspaceIcons.length; i++)
|
||||||
@ -955,7 +917,7 @@ const AppSwitcher = new Lang.Class({
|
|||||||
|
|
||||||
_allocate: function (actor, box, flags) {
|
_allocate: function (actor, box, flags) {
|
||||||
// Allocate the main list items
|
// Allocate the main list items
|
||||||
this.parent(actor, box, flags);
|
SwitcherList.prototype._allocate.call(this, actor, box, flags);
|
||||||
|
|
||||||
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
|
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
|
||||||
let arrowWidth = arrowHeight * 2;
|
let arrowWidth = arrowHeight * 2;
|
||||||
@ -1010,7 +972,7 @@ const AppSwitcher = new Lang.Class({
|
|||||||
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
|
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.parent(n, justOutline);
|
SwitcherList.prototype.highlight.call(this, n, justOutline);
|
||||||
this._curApp = n;
|
this._curApp = n;
|
||||||
|
|
||||||
if (this._curApp != -1) {
|
if (this._curApp != -1) {
|
||||||
@ -1023,7 +985,7 @@ const AppSwitcher = new Lang.Class({
|
|||||||
|
|
||||||
_addIcon : function(appIcon) {
|
_addIcon : function(appIcon) {
|
||||||
this.icons.push(appIcon);
|
this.icons.push(appIcon);
|
||||||
let item = this.addItem(appIcon.actor, appIcon.label);
|
this.addItem(appIcon.actor, appIcon.label);
|
||||||
|
|
||||||
let n = this._arrows.length;
|
let n = this._arrows.length;
|
||||||
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
|
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
|
||||||
@ -1033,17 +995,31 @@ const AppSwitcher = new Lang.Class({
|
|||||||
|
|
||||||
if (appIcon.cachedWindows.length == 1)
|
if (appIcon.cachedWindows.length == 1)
|
||||||
arrow.hide();
|
arrow.hide();
|
||||||
else
|
},
|
||||||
item.add_accessible_state (Atk.StateType.EXPANDABLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ThumbnailList = new Lang.Class({
|
_hasWindowsOnWorkspace: function(appIcon, workspace) {
|
||||||
Name: 'ThumbnailList',
|
let windows = appIcon.cachedWindows;
|
||||||
Extends: SwitcherList,
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
if (windows[i].get_workspace() == workspace)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_sortAppIcon : function(appIcon1, appIcon2) {
|
||||||
|
return appIcon1.app.compare(appIcon2.app);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function ThumbnailList(windows) {
|
||||||
|
this._init(windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThumbnailList.prototype = {
|
||||||
|
__proto__ : SwitcherList.prototype,
|
||||||
|
|
||||||
_init : function(windows) {
|
_init : function(windows) {
|
||||||
this.parent(false);
|
SwitcherList.prototype._init.call(this);
|
||||||
|
|
||||||
let activeWorkspace = global.screen.get_active_workspace();
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
|
||||||
@ -1121,7 +1097,7 @@ const ThumbnailList = new Lang.Class({
|
|||||||
// Make sure we only do this once
|
// Make sure we only do this once
|
||||||
this._thumbnailBins = new Array();
|
this._thumbnailBins = new Array();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
function _drawArrow(area, side) {
|
function _drawArrow(area, side) {
|
||||||
let themeNode = area.get_theme_node();
|
let themeNode = area.get_theme_node();
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const GMenu = imports.gi.GMenu;
|
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Atk = imports.gi.Atk;
|
|
||||||
|
|
||||||
const AppFavorites = imports.ui.appFavorites;
|
const AppFavorites = imports.ui.appFavorites;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
@ -22,22 +20,23 @@ const Search = imports.ui.search;
|
|||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
const Params = imports.misc.params;
|
const Params = imports.misc.params;
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
const MAX_APPLICATION_WORK_MILLIS = 75;
|
const MAX_APPLICATION_WORK_MILLIS = 75;
|
||||||
const MENU_POPUP_TIMEOUT = 600;
|
const MENU_POPUP_TIMEOUT = 600;
|
||||||
const SCROLL_TIME = 0.1;
|
const SCROLL_TIME = 0.1;
|
||||||
|
|
||||||
const AlphabeticalView = new Lang.Class({
|
function AlphabeticalView() {
|
||||||
Name: 'AlphabeticalView',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AlphabeticalView.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
|
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
this._pendingAppLaterId = 0;
|
this._pendingAppLaterId = 0;
|
||||||
this._appIcons = {}; // desktop file id
|
this._apps = [];
|
||||||
this._allApps = [];
|
this._filterApp = null;
|
||||||
|
|
||||||
let box = new St.BoxLayout({ vertical: true });
|
let box = new St.BoxLayout({ vertical: true });
|
||||||
box.add(this._grid.actor, { y_align: St.Align.START, expand: true });
|
box.add(this._grid.actor, { y_align: St.Align.START, expand: true });
|
||||||
@ -62,25 +61,22 @@ const AlphabeticalView = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAll: function() {
|
_removeAll: function() {
|
||||||
this._grid.removeAll();
|
this._grid.removeAll();
|
||||||
this._appIcons = {};
|
this._apps = [];
|
||||||
this._allApps = [];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addApp: function(app) {
|
_addApp: function(appInfo) {
|
||||||
var id = app.get_id();
|
let appIcon = new AppWellIcon(this._appSystem.get_app(appInfo.get_id()));
|
||||||
if (this._appIcons[id] !== undefined)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let appIcon = new AppWellIcon(app);
|
this._grid.addItem(appIcon.actor);
|
||||||
let pos = Util.insertSorted(this._allApps, app, function(a, b) {
|
|
||||||
return a.compare_by_name(b);
|
|
||||||
});
|
|
||||||
this._grid.addItem(appIcon.actor, pos);
|
|
||||||
appIcon.actor.connect('key-focus-in', Lang.bind(this, this._ensureIconVisible));
|
appIcon.actor.connect('key-focus-in', Lang.bind(this, this._ensureIconVisible));
|
||||||
|
|
||||||
this._appIcons[id] = appIcon;
|
appIcon._appInfo = appInfo;
|
||||||
|
if (this._filterApp && !this._filterApp(appInfo))
|
||||||
|
appIcon.actor.hide();
|
||||||
|
|
||||||
|
this._apps.push(appIcon);
|
||||||
},
|
},
|
||||||
|
|
||||||
_ensureIconVisible: function(icon) {
|
_ensureIconVisible: function(icon) {
|
||||||
@ -109,31 +105,60 @@ const AlphabeticalView = new Lang.Class({
|
|||||||
transition: 'easeOutQuad' });
|
transition: 'easeOutQuad' });
|
||||||
},
|
},
|
||||||
|
|
||||||
setVisibleApps: function(apps) {
|
setFilter: function(filter) {
|
||||||
if (apps == null) { // null implies "all"
|
this._filterApp = filter;
|
||||||
for (var id in this._appIcons) {
|
for (let i = 0; i < this._apps.length; i++)
|
||||||
var icon = this._appIcons[id];
|
this._apps[i].actor.visible = filter(this._apps[i]._appInfo);
|
||||||
icon.actor.visible = true;
|
},
|
||||||
}
|
|
||||||
} else {
|
// Create actors for the applications in an idle to avoid blocking
|
||||||
// Set everything to not-visible, then set to visible what we should see
|
// for too long; see bug 647778
|
||||||
for (var id in this._appIcons) {
|
_addPendingApps: function() {
|
||||||
var icon = this._appIcons[id];
|
let i;
|
||||||
icon.actor.visible = false;
|
let startTimeMillis = new Date().getTime();
|
||||||
}
|
for (i = 0; i < this._pendingAppIds.length; i++) {
|
||||||
for (var i = 0; i < apps.length; i++) {
|
let id = this._pendingAppIds[i];
|
||||||
var app = apps[i];
|
this._addApp(this._pendingApps[id]);
|
||||||
var id = app.get_id();
|
|
||||||
var icon = this._appIcons[id];
|
let currentTimeMillis = new Date().getTime();
|
||||||
icon.actor.visible = true;
|
if (currentTimeMillis - startTimeMillis > MAX_APPLICATION_WORK_MILLIS)
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
this._pendingAppIds.splice(0, i + 1);
|
||||||
|
if (this._pendingAppIds.length > 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this._pendingAppLaterId = 0;
|
||||||
|
this._pendingAppIds = null;
|
||||||
|
this._pendingApps = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh: function(apps) {
|
||||||
|
let ids = [];
|
||||||
|
for (let i in apps)
|
||||||
|
ids.push(i);
|
||||||
|
ids.sort(function(a, b) {
|
||||||
|
return apps[a].get_name().localeCompare(apps[b].get_name());
|
||||||
|
});
|
||||||
|
|
||||||
|
this._removeAll();
|
||||||
|
|
||||||
|
this._pendingAppIds = ids;
|
||||||
|
this._pendingApps = apps;
|
||||||
|
if (this._pendingAppLaterId)
|
||||||
|
Meta.later_remove(this._pendingAppLaterId);
|
||||||
|
this._pendingAppLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
||||||
|
Lang.bind(this, this._addPendingApps));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const ViewByCategories = new Lang.Class({
|
function ViewByCategories() {
|
||||||
Name: 'ViewByCategories',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewByCategories.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
this.actor = new St.BoxLayout({ style_class: 'all-app' });
|
this.actor = new St.BoxLayout({ style_class: 'all-app' });
|
||||||
@ -146,25 +171,23 @@ const ViewByCategories = new Lang.Class({
|
|||||||
// -2 is a flag to indicate that nothing is selected
|
// -2 is a flag to indicate that nothing is selected
|
||||||
// (used only before the actor is mapped the first time)
|
// (used only before the actor is mapped the first time)
|
||||||
this._currentCategory = -2;
|
this._currentCategory = -2;
|
||||||
this._categories = [];
|
this._filters = new St.BoxLayout({ vertical: true, reactive: true });
|
||||||
|
this._filtersBox = new St.ScrollView({ x_fill: false,
|
||||||
this._categoryBox = new St.BoxLayout({ vertical: true,
|
y_fill: false,
|
||||||
reactive: true,
|
style_class: 'vfade' });
|
||||||
accessible_role: Atk.Role.LIST });
|
this._filtersBox.add_actor(this._filters);
|
||||||
this._categoryScroll = new St.ScrollView({ x_fill: false,
|
|
||||||
y_fill: false,
|
|
||||||
style_class: 'vfade' });
|
|
||||||
this._categoryScroll.add_actor(this._categoryBox);
|
|
||||||
this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
|
this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
|
||||||
this.actor.add(this._categoryScroll, { expand: false, y_fill: false, y_align: St.Align.START });
|
this.actor.add(this._filtersBox, { expand: false, y_fill: false, y_align: St.Align.START });
|
||||||
|
|
||||||
// Always select the "All" filter when switching to the app view
|
// Always select the "All" filter when switching to the app view
|
||||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
this.actor.connect('notify::mapped', Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
if (this.actor.mapped && this._allCategoryButton)
|
if (this.actor.mapped && this._allFilter)
|
||||||
this._selectCategory(-1);
|
this._selectCategory(-1);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this._sections = [];
|
||||||
|
|
||||||
// We need a dummy actor to catch the keyboard focus if the
|
// We need a dummy actor to catch the keyboard focus if the
|
||||||
// user Ctrl-Alt-Tabs here before the deferred work creates
|
// user Ctrl-Alt-Tabs here before the deferred work creates
|
||||||
// our real contents
|
// our real contents
|
||||||
@ -178,96 +201,64 @@ const ViewByCategories = new Lang.Class({
|
|||||||
|
|
||||||
this._currentCategory = num;
|
this._currentCategory = num;
|
||||||
|
|
||||||
if (num != -1) {
|
if (num != -1)
|
||||||
var category = this._categories[num];
|
this._allFilter.remove_style_pseudo_class('selected');
|
||||||
this._allCategoryButton.remove_style_pseudo_class('selected');
|
else
|
||||||
this._view.setVisibleApps(category.apps);
|
this._allFilter.add_style_pseudo_class('selected');
|
||||||
} else {
|
|
||||||
this._allCategoryButton.add_style_pseudo_class('selected');
|
|
||||||
this._view.setVisibleApps(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < this._categories.length; i++) {
|
this._view.setFilter(Lang.bind(this, function(app) {
|
||||||
|
if (num == -1)
|
||||||
|
return true;
|
||||||
|
return this._sections[num].name == app.get_section();
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (let i = 0; i < this._sections.length; i++) {
|
||||||
if (i == num)
|
if (i == num)
|
||||||
this._categories[i].button.add_style_pseudo_class('selected');
|
this._sections[i].filterActor.add_style_pseudo_class('selected');
|
||||||
else
|
else
|
||||||
this._categories[i].button.remove_style_pseudo_class('selected');
|
this._sections[i].filterActor.remove_style_pseudo_class('selected');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
|
_addFilter: function(name, num) {
|
||||||
_loadCategory: function(dir, appList) {
|
|
||||||
var iter = dir.iter();
|
|
||||||
var nextType;
|
|
||||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
|
||||||
if (nextType == GMenu.TreeItemType.ENTRY) {
|
|
||||||
var entry = iter.get_entry();
|
|
||||||
var app = this._appSystem.lookup_app_by_tree_entry(entry);
|
|
||||||
if (!entry.get_app_info().get_nodisplay()) {
|
|
||||||
this._view.addApp(app);
|
|
||||||
appList.push(app);
|
|
||||||
}
|
|
||||||
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
|
||||||
var itemDir = iter.get_directory();
|
|
||||||
if (!itemDir.get_is_nodisplay())
|
|
||||||
this._loadCategory(itemDir, appList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_addCategory: function(name, index, dir) {
|
|
||||||
let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
|
let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
|
||||||
style_class: 'app-filter',
|
style_class: 'app-filter',
|
||||||
x_align: St.Align.START,
|
x_align: St.Align.START,
|
||||||
can_focus: true ,
|
can_focus: true });
|
||||||
accessible_role: Atk.Role.LIST_ITEM });
|
this._filters.add(button, { expand: true, x_fill: true, y_fill: false });
|
||||||
button.connect('clicked', Lang.bind(this, function() {
|
button.connect('clicked', Lang.bind(this, function() {
|
||||||
this._selectCategory(index);
|
this._selectCategory(num);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
var apps;
|
if (num != -1)
|
||||||
if (dir == null) {
|
this._sections[num] = { filterActor: button,
|
||||||
this._allCategoryButton = button;
|
name: name };
|
||||||
} else {
|
else
|
||||||
apps = [];
|
this._allFilter = button;
|
||||||
this._loadCategory(dir, apps);
|
|
||||||
this._categories.push({ apps: apps,
|
|
||||||
name: name,
|
|
||||||
button: button });
|
|
||||||
}
|
|
||||||
|
|
||||||
this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_removeAll: function() {
|
_removeAll: function() {
|
||||||
this._view.removeAll();
|
this._sections = [];
|
||||||
this._categories = [];
|
this._filters.destroy_children();
|
||||||
this._categoryBox.destroy_all_children();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function(apps) {
|
||||||
this._removeAll();
|
this._removeAll();
|
||||||
|
|
||||||
|
let sections = this._appSystem.get_sections();
|
||||||
|
this._apps = apps;
|
||||||
|
|
||||||
/* Translators: Filter to display all applications */
|
/* Translators: Filter to display all applications */
|
||||||
this._addCategory(_("All"), -1, null);
|
this._addFilter(_("All"), -1);
|
||||||
|
|
||||||
var tree = this._appSystem.get_tree();
|
if (!sections)
|
||||||
var root = tree.get_root_directory();
|
return;
|
||||||
|
|
||||||
var iter = root.iter();
|
for (let i = 0; i < sections.length; i++)
|
||||||
var nextType;
|
this._addFilter(sections[i], i);
|
||||||
var i = 0;
|
|
||||||
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
|
||||||
if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
|
||||||
var dir = iter.get_directory();
|
|
||||||
if (dir.get_is_nodisplay())
|
|
||||||
continue;
|
|
||||||
this._addCategory(dir.get_name(), i, dir);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._selectCategory(-1);
|
this._selectCategory(-1);
|
||||||
|
this._view.refresh(apps);
|
||||||
|
|
||||||
if (this._focusDummy) {
|
if (this._focusDummy) {
|
||||||
let focused = this._focusDummy.has_key_focus();
|
let focused = this._focusDummy.has_key_focus();
|
||||||
@ -277,14 +268,16 @@ const ViewByCategories = new Lang.Class({
|
|||||||
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
/* This class represents a display containing a collection of application items.
|
/* This class represents a display containing a collection of application items.
|
||||||
* The applications are sorted based on their name.
|
* The applications are sorted based on their name.
|
||||||
*/
|
*/
|
||||||
const AllAppDisplay = new Lang.Class({
|
function AllAppDisplay() {
|
||||||
Name: 'AllAppDisplay',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AllAppDisplay.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
|
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
|
||||||
@ -298,142 +291,137 @@ const AllAppDisplay = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_redisplay: function() {
|
_redisplay: function() {
|
||||||
this._appView.refresh();
|
let apps = this._appSystem.get_flattened_apps().filter(function(app) {
|
||||||
|
return !app.get_is_nodisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._appView.refresh(apps);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const AppSearchProvider = new Lang.Class({
|
function BaseAppSearchProvider() {
|
||||||
Name: 'AppSearchProvider',
|
this._init();
|
||||||
Extends: Search.SearchProvider,
|
}
|
||||||
|
|
||||||
_init: function() {
|
BaseAppSearchProvider.prototype = {
|
||||||
this.parent(_("APPLICATIONS"));
|
__proto__: Search.SearchProvider.prototype,
|
||||||
|
|
||||||
|
_init: function(name) {
|
||||||
|
Search.SearchProvider.prototype._init.call(this, name);
|
||||||
this._appSys = Shell.AppSystem.get_default();
|
this._appSys = Shell.AppSystem.get_default();
|
||||||
},
|
},
|
||||||
|
|
||||||
getResultMetas: function(apps, callback) {
|
getResultMeta: function(resultId) {
|
||||||
let metas = [];
|
let app = this._appSys.get_app(resultId);
|
||||||
for (let i = 0; i < apps.length; i++) {
|
if (!app)
|
||||||
let app = apps[i];
|
return null;
|
||||||
metas.push({ 'id': app,
|
return { 'id': resultId,
|
||||||
'name': app.get_name(),
|
'name': app.get_name(),
|
||||||
'createIcon': function(size) {
|
'createIcon': function(size) {
|
||||||
return app.create_icon_texture(size);
|
return app.create_icon_texture(size);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
|
||||||
callback(metas);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
activateResult: function(id, params) {
|
||||||
this.searchSystem.pushResults(this, this._appSys.initial_search(terms));
|
params = Params.parse(params, { workspace: null,
|
||||||
},
|
timestamp: null });
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
|
||||||
this.searchSystem.pushResults(this, this._appSys.subsearch(previousResults, terms));
|
|
||||||
},
|
|
||||||
|
|
||||||
activateResult: function(app, params) {
|
|
||||||
params = Params.parse(params, { workspace: -1,
|
|
||||||
timestamp: 0 });
|
|
||||||
|
|
||||||
|
let workspace = params.workspace ? params.workspace.index() : -1;
|
||||||
let event = Clutter.get_current_event();
|
let event = Clutter.get_current_event();
|
||||||
let modifiers = event ? event.get_state() : 0;
|
let modifiers = event ? Shell.get_event_state(event) : 0;
|
||||||
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
|
||||||
|
|
||||||
|
let app = this._appSys.get_app(id);
|
||||||
if (openNewWindow)
|
if (openNewWindow)
|
||||||
app.open_new_window(params.workspace);
|
app.open_new_window(workspace);
|
||||||
else
|
else
|
||||||
app.activate_full(params.workspace, params.timestamp);
|
app.activate(workspace);
|
||||||
},
|
},
|
||||||
|
|
||||||
dragActivateResult: function(id, params) {
|
dragActivateResult: function(id, params) {
|
||||||
params = Params.parse(params, { workspace: -1,
|
params = Params.parse(params, { workspace: null,
|
||||||
timestamp: 0 });
|
timestamp: null });
|
||||||
|
|
||||||
let app = this._appSys.lookup_app(id);
|
let app = this._appSys.get_app(id);
|
||||||
app.open_new_window(workspace);
|
app.open_new_window(params.workspace ? params.workspace.index() : -1);
|
||||||
},
|
|
||||||
|
|
||||||
createResultActor: function (resultMeta, terms) {
|
|
||||||
let app = resultMeta['id'];
|
|
||||||
let icon = new AppWellIcon(app);
|
|
||||||
return icon.actor;
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const SettingsSearchProvider = new Lang.Class({
|
function AppSearchProvider() {
|
||||||
Name: 'SettingsSearchProvider',
|
this._init();
|
||||||
Extends: Search.SearchProvider,
|
}
|
||||||
|
|
||||||
|
AppSearchProvider.prototype = {
|
||||||
|
__proto__: BaseAppSearchProvider.prototype,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent(_("SETTINGS"));
|
BaseAppSearchProvider.prototype._init.call(this, _("APPLICATIONS"));
|
||||||
|
|
||||||
this._appSys = Shell.AppSystem.get_default();
|
|
||||||
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
|
|
||||||
},
|
|
||||||
|
|
||||||
getResultMetas: function(prefs, callback) {
|
|
||||||
let metas = [];
|
|
||||||
for (let i = 0; i < prefs.length; i++) {
|
|
||||||
let pref = prefs[i];
|
|
||||||
metas.push({ 'id': pref,
|
|
||||||
'name': pref.get_name(),
|
|
||||||
'createIcon': function(size) {
|
|
||||||
return pref.create_icon_texture(size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
callback(metas);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
getInitialResultSet: function(terms) {
|
||||||
this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
|
return this._appSys.initial_search(false, terms);
|
||||||
},
|
},
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
getSubsearchResultSet: function(previousResults, terms) {
|
||||||
this.searchSystem.pushResults(this, this._appSys.search_settings(terms));
|
return this._appSys.subsearch(false, previousResults, terms);
|
||||||
},
|
|
||||||
|
|
||||||
activateResult: function(pref, params) {
|
|
||||||
params = Params.parse(params, { workspace: -1,
|
|
||||||
timestamp: 0 });
|
|
||||||
|
|
||||||
pref.activate_full(params.workspace, params.timestamp);
|
|
||||||
},
|
|
||||||
|
|
||||||
dragActivateResult: function(pref, params) {
|
|
||||||
this.activateResult(pref, params);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
createResultActor: function (resultMeta, terms) {
|
createResultActor: function (resultMeta, terms) {
|
||||||
let app = resultMeta['id'];
|
let app = this._appSys.get_app(resultMeta['id']);
|
||||||
let icon = new AppWellIcon(app);
|
let icon = new AppWellIcon(app);
|
||||||
return icon.actor;
|
return icon.actor;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const AppIcon = new Lang.Class({
|
function PrefsSearchProvider() {
|
||||||
Name: 'AppIcon',
|
this._init();
|
||||||
Extends: IconGrid.BaseIcon,
|
}
|
||||||
|
|
||||||
|
PrefsSearchProvider.prototype = {
|
||||||
|
__proto__: BaseAppSearchProvider.prototype,
|
||||||
|
|
||||||
|
_init: function() {
|
||||||
|
BaseAppSearchProvider.prototype._init.call(this, _("SETTINGS"));
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialResultSet: function(terms) {
|
||||||
|
return this._appSys.initial_search(true, terms);
|
||||||
|
},
|
||||||
|
|
||||||
|
getSubsearchResultSet: function(previousResults, terms) {
|
||||||
|
return this._appSys.subsearch(true, previousResults, terms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function AppIcon(app, params) {
|
||||||
|
this._init(app, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIcon.prototype = {
|
||||||
|
__proto__: IconGrid.BaseIcon.prototype,
|
||||||
|
|
||||||
_init : function(app, params) {
|
_init : function(app, params) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
|
||||||
let label = this.app.get_name();
|
let label = this.app.get_name();
|
||||||
|
|
||||||
this.parent(label, params);
|
IconGrid.BaseIcon.prototype._init.call(this,
|
||||||
|
label,
|
||||||
|
params);
|
||||||
},
|
},
|
||||||
|
|
||||||
createIcon: function(iconSize) {
|
createIcon: function(iconSize) {
|
||||||
return this.app.create_icon_texture(iconSize);
|
return this.app.create_icon_texture(iconSize);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const AppWellIcon = new Lang.Class({
|
function AppWellIcon(app, iconParams) {
|
||||||
Name: 'AppWellIcon',
|
this._init(app, iconParams);
|
||||||
|
}
|
||||||
|
|
||||||
_init : function(app, iconParams, onActivateOverride) {
|
AppWellIcon.prototype = {
|
||||||
|
_init : function(app, iconParams) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.actor = new St.Button({ style_class: 'app-well-app',
|
this.actor = new St.Button({ style_class: 'app-well-app',
|
||||||
reactive: true,
|
reactive: true,
|
||||||
@ -448,8 +436,6 @@ const AppWellIcon = new Lang.Class({
|
|||||||
|
|
||||||
this.actor.label_actor = this.icon.label;
|
this.actor.label_actor = this.icon.label;
|
||||||
|
|
||||||
// A function callback to override the default "app.activate()"; used by preferences
|
|
||||||
this._onActivateOverride = onActivateOverride;
|
|
||||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||||
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
|
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
|
||||||
@ -479,7 +465,6 @@ const AppWellIcon = new Lang.Class({
|
|||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
this._onStateChanged));
|
this._onStateChanged));
|
||||||
this._onStateChanged();
|
this._onStateChanged();
|
||||||
this.isMenuUp = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
@ -552,7 +537,7 @@ const AppWellIcon = new Lang.Class({
|
|||||||
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
|
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
|
||||||
this.activateWindow(window);
|
this.activateWindow(window);
|
||||||
}));
|
}));
|
||||||
this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
|
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
|
||||||
if (!isPoppedUp)
|
if (!isPoppedUp)
|
||||||
this._onMenuPoppedDown();
|
this._onMenuPoppedDown();
|
||||||
}));
|
}));
|
||||||
@ -561,8 +546,8 @@ const AppWellIcon = new Lang.Class({
|
|||||||
this._menuManager.addMenu(this._menu);
|
this._menuManager.addMenu(this._menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isMenuUp = true;
|
|
||||||
this.actor.set_hover(true);
|
this.actor.set_hover(true);
|
||||||
|
this.actor.show_tooltip();
|
||||||
this._menu.popup();
|
this._menu.popup();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -578,35 +563,30 @@ const AppWellIcon = new Lang.Class({
|
|||||||
|
|
||||||
_onMenuPoppedDown: function() {
|
_onMenuPoppedDown: function() {
|
||||||
this.actor.sync_hover();
|
this.actor.sync_hover();
|
||||||
this.isMenuUp = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onActivate: function (event) {
|
_onActivate: function (event) {
|
||||||
this.emit('launching');
|
this.emit('launching');
|
||||||
let modifiers = event.get_state();
|
let modifiers = Shell.get_event_state(event);
|
||||||
|
|
||||||
if (this._onActivateOverride) {
|
if (modifiers & Clutter.ModifierType.CONTROL_MASK
|
||||||
this._onActivateOverride(event);
|
&& this.app.state == Shell.AppState.RUNNING) {
|
||||||
|
this.app.open_new_window(-1);
|
||||||
} else {
|
} else {
|
||||||
if (modifiers & Clutter.ModifierType.CONTROL_MASK
|
this.app.activate(-1);
|
||||||
&& this.app.state == Shell.AppState.RUNNING) {
|
|
||||||
this.app.open_new_window(-1);
|
|
||||||
} else {
|
|
||||||
this.app.activate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Main.overview.hide();
|
Main.overview.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
shellWorkspaceLaunch : function(params) {
|
shellWorkspaceLaunch : function(params) {
|
||||||
params = Params.parse(params, { workspace: -1,
|
params = Params.parse(params, { workspace: null,
|
||||||
timestamp: 0 });
|
timestamp: null });
|
||||||
|
|
||||||
this.app.open_new_window(params.workspace);
|
this.app.open_new_window(params.workspace ? params.workspace.index() : -1);
|
||||||
},
|
},
|
||||||
|
|
||||||
getDragActor: function() {
|
getDragActor: function() {
|
||||||
return this.app.create_icon_texture(Main.overview.dashIconSize);
|
return this.app.create_icon_texture(Main.overview.dash.iconSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Returns the original actor that should align with the actor
|
// Returns the original actor that should align with the actor
|
||||||
@ -614,19 +594,22 @@ const AppWellIcon = new Lang.Class({
|
|||||||
getDragActorSource: function() {
|
getDragActorSource: function() {
|
||||||
return this.icon.icon;
|
return this.icon.icon;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(AppWellIcon.prototype);
|
Signals.addSignalMethods(AppWellIcon.prototype);
|
||||||
|
|
||||||
const AppIconMenu = new Lang.Class({
|
function AppIconMenu(source) {
|
||||||
Name: 'AppIconMenu',
|
this._init(source);
|
||||||
Extends: PopupMenu.PopupMenu,
|
}
|
||||||
|
|
||||||
|
AppIconMenu.prototype = {
|
||||||
|
__proto__: PopupMenu.PopupMenu.prototype,
|
||||||
|
|
||||||
_init: function(source) {
|
_init: function(source) {
|
||||||
let side = St.Side.LEFT;
|
let side = St.Side.LEFT;
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||||
side = St.Side.RIGHT;
|
side = St.Side.RIGHT;
|
||||||
|
|
||||||
this.parent(source.actor, 0.5, side);
|
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side, 0);
|
||||||
|
|
||||||
// We want to keep the item hovered while the menu is up
|
// We want to keep the item hovered while the menu is up
|
||||||
this.blockSourceEvents = true;
|
this.blockSourceEvents = true;
|
||||||
@ -634,6 +617,7 @@ const AppIconMenu = new Lang.Class({
|
|||||||
this._source = source;
|
this._source = source;
|
||||||
|
|
||||||
this.connect('activate', Lang.bind(this, this._onActivate));
|
this.connect('activate', Lang.bind(this, this._onActivate));
|
||||||
|
this.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
|
||||||
|
|
||||||
this.actor.add_style_class_name('app-well-menu');
|
this.actor.add_style_class_name('app-well-menu');
|
||||||
|
|
||||||
@ -666,18 +650,17 @@ const AppIconMenu = new Lang.Class({
|
|||||||
item._window = windows[i];
|
item._window = windows[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._source.app.is_window_backed()) {
|
if (windows.length > 0)
|
||||||
if (windows.length > 0)
|
|
||||||
this._appendSeparator();
|
|
||||||
|
|
||||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
|
||||||
|
|
||||||
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
|
|
||||||
this._appendSeparator();
|
this._appendSeparator();
|
||||||
|
|
||||||
this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
|
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
||||||
: _("Add to Favorites"));
|
|
||||||
}
|
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
|
||||||
|
this._appendSeparator();
|
||||||
|
|
||||||
|
this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ? _("Remove from Favorites")
|
||||||
|
: _("Add to Favorites"));
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_appendSeparator: function () {
|
_appendSeparator: function () {
|
||||||
@ -697,6 +680,14 @@ const AppIconMenu = new Lang.Class({
|
|||||||
this.open();
|
this.open();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onOpenStateChanged: function (menu, open) {
|
||||||
|
if (open) {
|
||||||
|
this.emit('popup', true);
|
||||||
|
} else {
|
||||||
|
this.emit('popup', false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_onActivate: function (actor, child) {
|
_onActivate: function (actor, child) {
|
||||||
if (child._window) {
|
if (child._window) {
|
||||||
let metaWindow = child._window;
|
let metaWindow = child._window;
|
||||||
@ -714,5 +705,5 @@ const AppIconMenu = new Lang.Class({
|
|||||||
}
|
}
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(AppIconMenu.prototype);
|
Signals.addSignalMethods(AppIconMenu.prototype);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
@ -6,9 +6,11 @@ const Signals = imports.signals;
|
|||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
const AppFavorites = new Lang.Class({
|
function AppFavorites() {
|
||||||
Name: 'AppFavorites',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AppFavorites.prototype = {
|
||||||
FAVORITE_APPS_KEY: 'favorite-apps',
|
FAVORITE_APPS_KEY: 'favorite-apps',
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
@ -26,7 +28,7 @@ const AppFavorites = new Lang.Class({
|
|||||||
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
|
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
|
||||||
let appSys = Shell.AppSystem.get_default();
|
let appSys = Shell.AppSystem.get_default();
|
||||||
let apps = ids.map(function (id) {
|
let apps = ids.map(function (id) {
|
||||||
return appSys.lookup_app(id);
|
return appSys.get_app(id);
|
||||||
}).filter(function (app) {
|
}).filter(function (app) {
|
||||||
return app != null;
|
return app != null;
|
||||||
});
|
});
|
||||||
@ -63,7 +65,7 @@ const AppFavorites = new Lang.Class({
|
|||||||
if (appId in this._favorites)
|
if (appId in this._favorites)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
let app = Shell.AppSystem.get_default().lookup_app(appId);
|
let app = Shell.AppSystem.get_default().get_app(appId);
|
||||||
|
|
||||||
if (!app)
|
if (!app)
|
||||||
return false;
|
return false;
|
||||||
@ -82,9 +84,9 @@ const AppFavorites = new Lang.Class({
|
|||||||
if (!this._addFavorite(appId, pos))
|
if (!this._addFavorite(appId, pos))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let app = Shell.AppSystem.get_default().lookup_app(appId);
|
let app = Shell.AppSystem.get_default().get_app(appId);
|
||||||
|
|
||||||
Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
|
Main.overview.shellInfo.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
|
||||||
this._removeFavorite(appId);
|
this._removeFavorite(appId);
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -115,12 +117,12 @@ const AppFavorites = new Lang.Class({
|
|||||||
if (!this._removeFavorite(appId))
|
if (!this._removeFavorite(appId))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
|
Main.overview.shellInfo.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
|
||||||
Lang.bind(this, function () {
|
Lang.bind(this, function () {
|
||||||
this._addFavorite(appId, pos);
|
this._addFavorite(appId, pos);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(AppFavorites.prototype);
|
Signals.addSignalMethods(AppFavorites.prototype);
|
||||||
|
|
||||||
var appFavoritesInstance = null;
|
var appFavoritesInstance = null;
|
||||||
|
278
js/ui/automountManager.js
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const DBus = imports.dbus;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
const Params = imports.misc.params;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const ShellMountOperation = imports.ui.shellMountOperation;
|
||||||
|
const ScreenSaver = imports.misc.screenSaver;
|
||||||
|
|
||||||
|
// GSettings keys
|
||||||
|
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
|
||||||
|
const SETTING_ENABLE_AUTOMOUNT = 'automount';
|
||||||
|
|
||||||
|
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
|
||||||
|
|
||||||
|
const ConsoleKitSessionIface = {
|
||||||
|
name: 'org.freedesktop.ConsoleKit.Session',
|
||||||
|
methods: [{ name: 'IsActive',
|
||||||
|
inSignature: '',
|
||||||
|
outSignature: 'b' }],
|
||||||
|
signals: [{ name: 'ActiveChanged',
|
||||||
|
inSignature: 'b' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
const ConsoleKitSessionProxy = DBus.makeProxyClass(ConsoleKitSessionIface);
|
||||||
|
|
||||||
|
const ConsoleKitManagerIface = {
|
||||||
|
name: 'org.freedesktop.ConsoleKit.Manager',
|
||||||
|
methods: [{ name: 'GetCurrentSession',
|
||||||
|
inSignature: '',
|
||||||
|
outSignature: 'o' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
function ConsoleKitManager() {
|
||||||
|
this._init();
|
||||||
|
};
|
||||||
|
|
||||||
|
ConsoleKitManager.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this.sessionActive = true;
|
||||||
|
|
||||||
|
DBus.system.proxifyObject(this,
|
||||||
|
'org.freedesktop.ConsoleKit',
|
||||||
|
'/org/freedesktop/ConsoleKit/Manager');
|
||||||
|
|
||||||
|
DBus.system.watch_name('org.freedesktop.ConsoleKit',
|
||||||
|
false, // do not launch a name-owner if none exists
|
||||||
|
Lang.bind(this, this._onManagerAppeared),
|
||||||
|
Lang.bind(this, this._onManagerVanished));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onManagerAppeared: function(owner) {
|
||||||
|
this.GetCurrentSessionRemote(Lang.bind(this, this._onCurrentSession));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onManagerVanished: function(oldOwner) {
|
||||||
|
this.sessionActive = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onCurrentSession: function(session) {
|
||||||
|
this._ckSession = new ConsoleKitSessionProxy(DBus.system, 'org.freedesktop.ConsoleKit', session);
|
||||||
|
|
||||||
|
this._ckSession.connect
|
||||||
|
('ActiveChanged', Lang.bind(this, function(object, isActive) {
|
||||||
|
this.sessionActive = isActive;
|
||||||
|
}));
|
||||||
|
this._ckSession.IsActiveRemote(Lang.bind(this, function(isActive) {
|
||||||
|
this.sessionActive = isActive;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);
|
||||||
|
|
||||||
|
function AutomountManager() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutomountManager.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
||||||
|
this._volumeQueue = [];
|
||||||
|
|
||||||
|
this.ckListener = new ConsoleKitManager();
|
||||||
|
|
||||||
|
this._ssProxy = new ScreenSaver.ScreenSaverProxy();
|
||||||
|
this._ssProxy.connect('ActiveChanged',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._screenSaverActiveChanged));
|
||||||
|
|
||||||
|
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||||
|
|
||||||
|
this._volumeMonitor.connect('volume-added',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onVolumeAdded));
|
||||||
|
this._volumeMonitor.connect('volume-removed',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onVolumeRemoved));
|
||||||
|
this._volumeMonitor.connect('drive-connected',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onDriveConnected));
|
||||||
|
this._volumeMonitor.connect('drive-disconnected',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onDriveDisconnected));
|
||||||
|
this._volumeMonitor.connect('drive-eject-button',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onDriveEjectButton));
|
||||||
|
|
||||||
|
Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
|
||||||
|
},
|
||||||
|
|
||||||
|
_screenSaverActiveChanged: function(object, isActive) {
|
||||||
|
if (!isActive) {
|
||||||
|
this._volumeQueue.forEach(Lang.bind(this, function(volume) {
|
||||||
|
this._checkAndMountVolume(volume);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear the queue anyway
|
||||||
|
this._volumeQueue = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
_startupMountAll: function() {
|
||||||
|
let volumes = this._volumeMonitor.get_volumes();
|
||||||
|
volumes.forEach(Lang.bind(this, function(volume) {
|
||||||
|
this._checkAndMountVolume(volume, { checkSession: false,
|
||||||
|
useMountOp: false });
|
||||||
|
}));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDriveConnected: function() {
|
||||||
|
// if we're not in the current ConsoleKit session,
|
||||||
|
// or screensaver is active, don't play sounds
|
||||||
|
if (!this.ckListener.sessionActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._ssProxy.screenSaverActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
global.play_theme_sound(0, 'device-added-media');
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDriveDisconnected: function() {
|
||||||
|
// if we're not in the current ConsoleKit session,
|
||||||
|
// or screensaver is active, don't play sounds
|
||||||
|
if (!this.ckListener.sessionActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._ssProxy.screenSaverActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
global.play_theme_sound(0, 'device-removed-media');
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDriveEjectButton: function(monitor, drive) {
|
||||||
|
// TODO: this code path is not tested, as the GVfs volume monitor
|
||||||
|
// doesn't emit this signal just yet.
|
||||||
|
if (!this.ckListener.sessionActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// we force stop/eject in this case, so we don't have to pass a
|
||||||
|
// mount operation object
|
||||||
|
if (drive.can_stop()) {
|
||||||
|
drive.stop
|
||||||
|
(Gio.MountUnmountFlags.FORCE, null, null,
|
||||||
|
Lang.bind(this, function(drive, res) {
|
||||||
|
try {
|
||||||
|
drive.stop_finish(res);
|
||||||
|
} catch (e) {
|
||||||
|
log("Unable to stop the drive after drive-eject-button " + e.toString());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else if (drive.can_eject()) {
|
||||||
|
drive.eject_with_operation
|
||||||
|
(Gio.MountUnmountFlags.FORCE, null, null,
|
||||||
|
Lang.bind(this, function(drive, res) {
|
||||||
|
try {
|
||||||
|
drive.eject_with_operation_finish(res);
|
||||||
|
} catch (e) {
|
||||||
|
log("Unable to eject the drive after drive-eject-button " + e.toString());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onVolumeAdded: function(monitor, volume) {
|
||||||
|
this._checkAndMountVolume(volume);
|
||||||
|
},
|
||||||
|
|
||||||
|
_checkAndMountVolume: function(volume, params) {
|
||||||
|
params = Params.parse(params, { checkSession: true,
|
||||||
|
useMountOp: true });
|
||||||
|
|
||||||
|
if (params.checkSession) {
|
||||||
|
// if we're not in the current ConsoleKit session,
|
||||||
|
// don't attempt automount
|
||||||
|
if (!this.ckListener.sessionActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this._ssProxy.screenSaverActive) {
|
||||||
|
if (this._volumeQueue.indexOf(volume) == -1)
|
||||||
|
this._volumeQueue.push(volume);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._settings.get_boolean(SETTING_ENABLE_AUTOMOUNT) ||
|
||||||
|
!volume.should_automount() ||
|
||||||
|
!volume.can_mount()) {
|
||||||
|
// allow the autorun to run anyway; this can happen if the
|
||||||
|
// mount gets added programmatically later, even if
|
||||||
|
// should_automount() or can_mount() are false, like for
|
||||||
|
// blank optical media.
|
||||||
|
this._allowAutorun(volume);
|
||||||
|
this._allowAutorunExpire(volume);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.useMountOp) {
|
||||||
|
let operation = new ShellMountOperation.ShellMountOperation(volume);
|
||||||
|
this._mountVolume(volume, operation.mountOp);
|
||||||
|
} else {
|
||||||
|
this._mountVolume(volume, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_mountVolume: function(volume, operation) {
|
||||||
|
this._allowAutorun(volume);
|
||||||
|
volume.mount(0, operation, null,
|
||||||
|
Lang.bind(this, this._onVolumeMounted));
|
||||||
|
},
|
||||||
|
|
||||||
|
_onVolumeMounted: function(volume, res) {
|
||||||
|
this._allowAutorunExpire(volume);
|
||||||
|
|
||||||
|
try {
|
||||||
|
volume.mount_finish(res);
|
||||||
|
} catch (e) {
|
||||||
|
let string = e.toString();
|
||||||
|
|
||||||
|
// FIXME: needs proper error code handling instead of this
|
||||||
|
// See https://bugzilla.gnome.org/show_bug.cgi?id=591480
|
||||||
|
if (string.indexOf('No key available with this passphrase') != -1)
|
||||||
|
this._reaskPassword(volume);
|
||||||
|
else
|
||||||
|
log('Unable to mount volume ' + volume.get_name() + ': ' + string);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onVolumeRemoved: function(monitor, volume) {
|
||||||
|
this._volumeQueue =
|
||||||
|
this._volumeQueue.filter(function(element) {
|
||||||
|
return (element != volume);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_reaskPassword: function(volume) {
|
||||||
|
let operation = new ShellMountOperation.ShellMountOperation(volume, { reaskPassword: true });
|
||||||
|
this._mountVolume(volume, operation.mountOp);
|
||||||
|
},
|
||||||
|
|
||||||
|
_allowAutorun: function(volume) {
|
||||||
|
volume.allowAutorun = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_allowAutorunExpire: function(volume) {
|
||||||
|
Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
|
||||||
|
volume.allowAutorun = false;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
const DBus = imports.dbus;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const LoginManager = imports.misc.loginManager;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const ShellMountOperation = imports.ui.shellMountOperation;
|
const ShellMountOperation = imports.ui.shellMountOperation;
|
||||||
@ -24,15 +23,15 @@ const AutorunSetting = {
|
|||||||
ASK: 3
|
ASK: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const HOTPLUG_ICON_SIZE = 16;
|
||||||
|
|
||||||
// misc utils
|
// misc utils
|
||||||
function shouldAutorunMount(mount, forTransient) {
|
function ignoreAutorunForMount(mount) {
|
||||||
let root = mount.get_root();
|
let root = mount.get_root();
|
||||||
let volume = mount.get_volume();
|
let volume = mount.get_volume();
|
||||||
|
|
||||||
if (!volume || (!volume.allowAutorun && forTransient))
|
if ((root.is_native() && !isMountRootHidden(root)) ||
|
||||||
return false;
|
(volume && volume.allowAutorun && volume.should_automount()))
|
||||||
|
|
||||||
if (!root.is_native() || isMountRootHidden(root))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -45,17 +44,6 @@ function isMountRootHidden(root) {
|
|||||||
return (path.indexOf('/.') != -1);
|
return (path.indexOf('/.') != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMountNonLocal(mount) {
|
|
||||||
// If the mount doesn't have an associated volume, that means it's
|
|
||||||
// an uninteresting filesystem. Most devices that we care about will
|
|
||||||
// have a mount, like media players and USB sticks.
|
|
||||||
let volume = mount.get_volume();
|
|
||||||
if (volume == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return (volume.get_identifier("class") == "network");
|
|
||||||
}
|
|
||||||
|
|
||||||
function startAppForMount(app, mount) {
|
function startAppForMount(app, mount) {
|
||||||
let files = [];
|
let files = [];
|
||||||
let root = mount.get_root();
|
let root = mount.get_root();
|
||||||
@ -76,44 +64,40 @@ function startAppForMount(app, mount) {
|
|||||||
|
|
||||||
/******************************************/
|
/******************************************/
|
||||||
|
|
||||||
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
|
const HotplugSnifferIface = {
|
||||||
<method name="SniffURI">
|
name: 'org.gnome.Shell.HotplugSniffer',
|
||||||
<arg type="s" direction="in" />
|
methods: [{ name: 'SniffURI',
|
||||||
<arg type="as" direction="out" />
|
inSignature: 's',
|
||||||
</method>
|
outSignature: 'as' }]
|
||||||
</interface>;
|
};
|
||||||
|
|
||||||
const HotplugSniffer = new Gio.DBusProxyClass({
|
const HotplugSniffer = function() {
|
||||||
Name: 'HotplugSnifferProxy',
|
this._init();
|
||||||
Interface: HotplugSnifferIface,
|
};
|
||||||
|
|
||||||
|
HotplugSniffer.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
DBus.session.proxifyObject(this,
|
||||||
g_name: 'org.gnome.Shell.HotplugSniffer',
|
'org.gnome.Shell.HotplugSniffer',
|
||||||
g_object_path: '/org/gnome/Shell/HotplugSniffer' });
|
'/org/gnome/Shell/HotplugSniffer');
|
||||||
}
|
},
|
||||||
});
|
};
|
||||||
|
DBus.proxifyPrototype(HotplugSniffer.prototype, HotplugSnifferIface);
|
||||||
|
|
||||||
const ContentTypeDiscoverer = new Lang.Class({
|
function ContentTypeDiscoverer(callback) {
|
||||||
Name: 'ContentTypeDiscoverer',
|
this._init(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentTypeDiscoverer.prototype = {
|
||||||
_init: function(callback) {
|
_init: function(callback) {
|
||||||
this._callback = callback;
|
this._callback = callback;
|
||||||
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
guessContentTypes: function(mount) {
|
guessContentTypes: function(mount) {
|
||||||
let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN);
|
// guess mount's content types using GIO
|
||||||
let shouldScan = autorunEnabled && !isMountNonLocal(mount);
|
mount.guess_content_type(false, null,
|
||||||
|
Lang.bind(this,
|
||||||
if (shouldScan) {
|
this._onContentTypeGuessed));
|
||||||
// guess mount's content types using GIO
|
|
||||||
mount.guess_content_type(false, null,
|
|
||||||
Lang.bind(this,
|
|
||||||
this._onContentTypeGuessed));
|
|
||||||
} else {
|
|
||||||
this._emitCallback(mount, []);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onContentTypeGuessed: function(mount, res) {
|
_onContentTypeGuessed: function(mount, res) {
|
||||||
@ -132,14 +116,11 @@ const ContentTypeDiscoverer = new Lang.Class({
|
|||||||
let root = mount.get_root();
|
let root = mount.get_root();
|
||||||
|
|
||||||
let hotplugSniffer = new HotplugSniffer();
|
let hotplugSniffer = new HotplugSniffer();
|
||||||
hotplugSniffer.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
hotplugSniffer.SniffURIRemote
|
||||||
proxy.init_finish(result);
|
(root.get_uri(), DBus.CALL_FLAG_START,
|
||||||
|
Lang.bind(this, function(contentTypes) {
|
||||||
proxy.SniffURIRemote(root.get_uri(), null, Lang.bind(this, function(proxy, result) {
|
this._emitCallback(mount, contentTypes);
|
||||||
let [contentTypes] = proxy.SniffURIFinish(result);
|
}));
|
||||||
this._emitCallback(mount, contentTypes);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -165,77 +146,63 @@ const ContentTypeDiscoverer = new Lang.Class({
|
|||||||
|
|
||||||
this._callback(mount, apps, contentTypes);
|
this._callback(mount, apps, contentTypes);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunManager = new Lang.Class({
|
function AutorunManager() {
|
||||||
Name: 'AutorunManager',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutorunManager.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
|
||||||
this._loginManager = manager;
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||||
|
|
||||||
this._transDispatcher = new AutorunTransientDispatcher(this);
|
this._volumeMonitor.connect('mount-added',
|
||||||
},
|
Lang.bind(this,
|
||||||
|
this._onMountAdded));
|
||||||
|
this._volumeMonitor.connect('mount-removed',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._onMountRemoved));
|
||||||
|
|
||||||
_ensureResidentSource: function() {
|
this._transDispatcher = new AutorunTransientDispatcher();
|
||||||
if (this._residentSource)
|
this._createResidentSource();
|
||||||
return;
|
|
||||||
|
|
||||||
this._residentSource = new AutorunResidentSource(this);
|
|
||||||
let destroyId = this._residentSource.connect('destroy', Lang.bind(this, function() {
|
|
||||||
this._residentSource.disconnect(destroyId);
|
|
||||||
this._residentSource = null;
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
this._scanMounts();
|
|
||||||
|
|
||||||
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
|
|
||||||
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
if (this._residentSource)
|
|
||||||
this._residentSource.destroy();
|
|
||||||
this._volumeMonitor.disconnect(this._mountAddedId);
|
|
||||||
this._volumeMonitor.disconnect(this._mountRemovedId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_processMount: function(mount, hotplug) {
|
|
||||||
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
|
|
||||||
this._ensureResidentSource();
|
|
||||||
this._residentSource.addMount(mount, apps);
|
|
||||||
|
|
||||||
if (hotplug)
|
|
||||||
this._transDispatcher.addMount(mount, apps, contentTypes);
|
|
||||||
}));
|
|
||||||
discoverer.guessContentTypes(mount);
|
|
||||||
},
|
|
||||||
|
|
||||||
_scanMounts: function() {
|
|
||||||
let mounts = this._volumeMonitor.get_mounts();
|
let mounts = this._volumeMonitor.get_mounts();
|
||||||
mounts.forEach(Lang.bind(this, function(mount) {
|
|
||||||
this._processMount(mount, false);
|
mounts.forEach(Lang.bind(this, function (mount) {
|
||||||
|
let discoverer = new ContentTypeDiscoverer(Lang.bind (this,
|
||||||
|
function (mount, apps) {
|
||||||
|
this._residentSource.addMount(mount, apps);
|
||||||
|
}));
|
||||||
|
|
||||||
|
discoverer.guessContentTypes(mount);
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_createResidentSource: function() {
|
||||||
|
this._residentSource = new AutorunResidentSource();
|
||||||
|
this._residentSource.connect('destroy',
|
||||||
|
Lang.bind(this,
|
||||||
|
this._createResidentSource));
|
||||||
|
},
|
||||||
|
|
||||||
_onMountAdded: function(monitor, mount) {
|
_onMountAdded: function(monitor, mount) {
|
||||||
// don't do anything if our session is not the currently
|
// don't do anything if our session is not the currently
|
||||||
// active one
|
// active one
|
||||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
if (!Main.automountManager.ckListener.sessionActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._processMount(mount, true);
|
let discoverer = new ContentTypeDiscoverer(Lang.bind (this,
|
||||||
|
function (mount, apps, contentTypes) {
|
||||||
|
this._transDispatcher.addMount(mount, apps, contentTypes);
|
||||||
|
this._residentSource.addMount(mount, apps);
|
||||||
|
}));
|
||||||
|
|
||||||
|
discoverer.guessContentTypes(mount);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMountRemoved: function(monitor, mount) {
|
_onMountRemoved: function(monitor, mount) {
|
||||||
this._transDispatcher.removeMount(mount);
|
this._transDispatcher.removeMount(mount);
|
||||||
if (this._residentSource)
|
this._residentSource.removeMount(mount);
|
||||||
this._residentSource.removeMount(mount);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
ejectMount: function(mount) {
|
ejectMount: function(mount) {
|
||||||
@ -271,9 +238,11 @@ const AutorunManager = new Lang.Class({
|
|||||||
try {
|
try {
|
||||||
mount.unmount_with_operation_finish(res);
|
mount.unmount_with_operation_finish(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
// FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
|
||||||
log('Unable to eject the mount ' + mount.get_name()
|
// but we can't access the error code from JS.
|
||||||
+ ': ' + e.toString());
|
// See https://bugzilla.gnome.org/show_bug.cgi?id=591480
|
||||||
|
log('Unable to eject the mount ' + mount.get_name()
|
||||||
|
+ ': ' + e.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -281,9 +250,11 @@ const AutorunManager = new Lang.Class({
|
|||||||
try {
|
try {
|
||||||
source.eject_with_operation_finish(res);
|
source.eject_with_operation_finish(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
// FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
|
||||||
log('Unable to eject the drive ' + source.get_name()
|
// but we can't access the error code from JS.
|
||||||
+ ': ' + e.toString());
|
// See https://bugzilla.gnome.org/show_bug.cgi?id=591480
|
||||||
|
log('Unable to eject the drive ' + source.get_name()
|
||||||
|
+ ': ' + e.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -291,33 +262,33 @@ const AutorunManager = new Lang.Class({
|
|||||||
try {
|
try {
|
||||||
drive.stop_finish(res);
|
drive.stop_finish(res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
// FIXME: we need to ignore G_IO_ERROR_FAILED_HANDLED errors here
|
||||||
log('Unable to stop the drive ' + drive.get_name()
|
// but we can't access the error code from JS.
|
||||||
+ ': ' + e.toString());
|
// See https://bugzilla.gnome.org/show_bug.cgi?id=591480
|
||||||
|
log('Unable to stop the drive ' + drive.get_name()
|
||||||
|
+ ': ' + e.toString());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunResidentSource = new Lang.Class({
|
function AutorunResidentSource() {
|
||||||
Name: 'AutorunResidentSource',
|
this._init();
|
||||||
Extends: MessageTray.Source,
|
}
|
||||||
|
|
||||||
_init: function(manager) {
|
AutorunResidentSource.prototype = {
|
||||||
this.parent(_("Removable Devices"), 'media-removable');
|
__proto__: MessageTray.Source.prototype,
|
||||||
this.showInLockScreen = false;
|
|
||||||
|
_init: function() {
|
||||||
|
MessageTray.Source.prototype._init.call(this, _('Removable Devices'));
|
||||||
|
|
||||||
this._mounts = [];
|
this._mounts = [];
|
||||||
|
|
||||||
this._manager = manager;
|
this._notification = new AutorunResidentNotification(this);
|
||||||
this._notification = new AutorunResidentNotification(this._manager, this);
|
this._setSummaryIcon(this.createNotificationIcon(HOTPLUG_ICON_SIZE));
|
||||||
},
|
|
||||||
|
|
||||||
buildRightClickMenu: function() {
|
|
||||||
return null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addMount: function(mount, apps) {
|
addMount: function(mount, apps) {
|
||||||
if (!shouldAutorunMount(mount, false))
|
if (ignoreAutorunForMount(mount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let filtered = this._mounts.filter(function (element) {
|
let filtered = this._mounts.filter(function (element) {
|
||||||
@ -356,22 +327,31 @@ const AutorunResidentSource = new Lang.Class({
|
|||||||
Main.messageTray.add(this);
|
Main.messageTray.add(this);
|
||||||
this.pushNotification(this._notification);
|
this.pushNotification(this._notification);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createNotificationIcon: function(iconSize) {
|
||||||
|
return new St.Icon ({ icon_name: 'drive-harddisk',
|
||||||
|
icon_size: iconSize ? iconSize : this.ICON_SIZE });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunResidentNotification = new Lang.Class({
|
function AutorunResidentNotification(source) {
|
||||||
Name: 'AutorunResidentNotification',
|
this._init(source);
|
||||||
Extends: MessageTray.Notification,
|
}
|
||||||
|
|
||||||
_init: function(manager, source) {
|
AutorunResidentNotification.prototype = {
|
||||||
this.parent(source, source.title, null, { customContent: true });
|
__proto__: MessageTray.Notification.prototype,
|
||||||
|
|
||||||
|
_init: function(source) {
|
||||||
|
MessageTray.Notification.prototype._init.call(this, source,
|
||||||
|
source.title, null,
|
||||||
|
{ customContent: true });
|
||||||
|
|
||||||
// set the notification as resident
|
// set the notification as resident
|
||||||
this.setResident(true);
|
this.setResident(true);
|
||||||
|
|
||||||
this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
|
this._layout = new St.BoxLayout ({ style_class: 'hotplug-resident-box',
|
||||||
vertical: true });
|
vertical: true });
|
||||||
this._manager = manager;
|
|
||||||
|
|
||||||
this.addActor(this._layout,
|
this.addActor(this._layout,
|
||||||
{ x_expand: true,
|
{ x_expand: true,
|
||||||
@ -380,7 +360,7 @@ const AutorunResidentNotification = new Lang.Class({
|
|||||||
|
|
||||||
updateForMounts: function(mounts) {
|
updateForMounts: function(mounts) {
|
||||||
// remove all the layout content
|
// remove all the layout content
|
||||||
this._layout.destroy_all_children();
|
this._layout.destroy_children();
|
||||||
|
|
||||||
for (let idx = 0; idx < mounts.length; idx++) {
|
for (let idx = 0; idx < mounts.length; idx++) {
|
||||||
let element = mounts[idx];
|
let element = mounts[idx];
|
||||||
@ -419,7 +399,7 @@ const AutorunResidentNotification = new Lang.Class({
|
|||||||
expand: true });
|
expand: true });
|
||||||
|
|
||||||
let ejectIcon =
|
let ejectIcon =
|
||||||
new St.Icon({ icon_name: 'media-eject-symbolic',
|
new St.Icon({ icon_name: 'media-eject',
|
||||||
style_class: 'hotplug-resident-eject-icon' });
|
style_class: 'hotplug-resident-eject-icon' });
|
||||||
|
|
||||||
let ejectButton =
|
let ejectButton =
|
||||||
@ -434,18 +414,19 @@ const AutorunResidentNotification = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
ejectButton.connect('clicked', Lang.bind(this, function() {
|
ejectButton.connect('clicked', Lang.bind(this, function() {
|
||||||
this._manager.ejectMount(mount);
|
Main.autorunManager.ejectMount(mount);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunTransientDispatcher = new Lang.Class({
|
function AutorunTransientDispatcher() {
|
||||||
Name: 'AutorunTransientDispatcher',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
_init: function(manager) {
|
AutorunTransientDispatcher.prototype = {
|
||||||
this._manager = manager;
|
_init: function() {
|
||||||
this._sources = [];
|
this._sources = [];
|
||||||
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
||||||
},
|
},
|
||||||
@ -488,7 +469,7 @@ const AutorunTransientDispatcher = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// add a new source
|
// add a new source
|
||||||
this._sources.push(new AutorunTransientSource(this._manager, mount, apps));
|
this._sources.push(new AutorunTransientSource(mount, apps));
|
||||||
},
|
},
|
||||||
|
|
||||||
addMount: function(mount, apps, contentTypes) {
|
addMount: function(mount, apps, contentTypes) {
|
||||||
@ -497,7 +478,7 @@ const AutorunTransientDispatcher = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// if the mount doesn't want to be autorun, return
|
// if the mount doesn't want to be autorun, return
|
||||||
if (!shouldAutorunMount(mount, true))
|
if (ignoreAutorunForMount(mount))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let setting = this._getAutorunSettingForType(contentTypes[0]);
|
let setting = this._getAutorunSettingForType(contentTypes[0]);
|
||||||
@ -511,7 +492,7 @@ const AutorunTransientDispatcher = new Lang.Class({
|
|||||||
let app = null;
|
let app = null;
|
||||||
|
|
||||||
if (setting == AutorunSetting.RUN) {
|
if (setting == AutorunSetting.RUN) {
|
||||||
app = Gio.app_info_get_default_for_type(contentTypes[0], false);
|
app = Gio.app_info_get_default_for_type(type, false);
|
||||||
} else if (setting == AutorunSetting.FILES) {
|
} else if (setting == AutorunSetting.FILES) {
|
||||||
app = Gio.app_info_get_default_for_type('inode/directory', false);
|
app = Gio.app_info_get_default_for_type('inode/directory', false);
|
||||||
}
|
}
|
||||||
@ -535,39 +516,47 @@ const AutorunTransientDispatcher = new Lang.Class({
|
|||||||
// destroy the notification source
|
// destroy the notification source
|
||||||
source.destroy();
|
source.destroy();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunTransientSource = new Lang.Class({
|
function AutorunTransientSource(mount, apps) {
|
||||||
Name: 'AutorunTransientSource',
|
this._init(mount, apps);
|
||||||
Extends: MessageTray.Source,
|
}
|
||||||
|
|
||||||
|
AutorunTransientSource.prototype = {
|
||||||
|
__proto__: MessageTray.Source.prototype,
|
||||||
|
|
||||||
|
_init: function(mount, apps) {
|
||||||
|
MessageTray.Source.prototype._init.call(this, mount.get_name());
|
||||||
|
|
||||||
_init: function(manager, mount, apps) {
|
|
||||||
this._manager = manager;
|
|
||||||
this.mount = mount;
|
this.mount = mount;
|
||||||
this.apps = apps;
|
this.apps = apps;
|
||||||
|
|
||||||
this.parent(mount.get_name());
|
this._notification = new AutorunTransientNotification(this);
|
||||||
|
this._setSummaryIcon(this.createNotificationIcon(this.ICON_SIZE));
|
||||||
this._notification = new AutorunTransientNotification(this._manager, this);
|
|
||||||
|
|
||||||
// add ourselves as a source, and popup the notification
|
// add ourselves as a source, and popup the notification
|
||||||
Main.messageTray.add(this);
|
Main.messageTray.add(this);
|
||||||
this.notify(this._notification);
|
this.notify(this._notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
getIcon: function() {
|
createNotificationIcon: function(iconSize) {
|
||||||
return this.mount.get_icon();
|
return new St.Icon({ gicon: this.mount.get_icon(),
|
||||||
|
icon_size: iconSize ? iconSize : this.ICON_SIZE });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const AutorunTransientNotification = new Lang.Class({
|
function AutorunTransientNotification(source) {
|
||||||
Name: 'AutorunTransientNotification',
|
this._init(source);
|
||||||
Extends: MessageTray.Notification,
|
}
|
||||||
|
|
||||||
_init: function(manager, source) {
|
AutorunTransientNotification.prototype = {
|
||||||
this.parent(source, source.title, null, { customContent: true });
|
__proto__: MessageTray.Notification.prototype,
|
||||||
|
|
||||||
|
_init: function(source) {
|
||||||
|
MessageTray.Notification.prototype._init.call(this, source,
|
||||||
|
source.title, null,
|
||||||
|
{ customContent: true });
|
||||||
|
|
||||||
this._manager = manager;
|
|
||||||
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
|
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
|
||||||
vertical: true });
|
vertical: true });
|
||||||
this.addActor(this._box);
|
this.addActor(this._box);
|
||||||
@ -599,7 +588,7 @@ const AutorunTransientNotification = new Lang.Class({
|
|||||||
|
|
||||||
let label = new St.Bin({ y_align: St.Align.MIDDLE,
|
let label = new St.Bin({ y_align: St.Align.MIDDLE,
|
||||||
child: new St.Label
|
child: new St.Label
|
||||||
({ text: _("Open with %s").format(app.get_name()) })
|
({ text: _("Open with %s").format(app.get_display_name()) })
|
||||||
});
|
});
|
||||||
box.add(label);
|
box.add(label);
|
||||||
|
|
||||||
@ -619,7 +608,7 @@ const AutorunTransientNotification = new Lang.Class({
|
|||||||
|
|
||||||
_buttonForEject: function() {
|
_buttonForEject: function() {
|
||||||
let box = new St.BoxLayout();
|
let box = new St.BoxLayout();
|
||||||
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
|
let icon = new St.Icon({ icon_name: 'media-eject',
|
||||||
style_class: 'hotplug-notification-item-icon' });
|
style_class: 'hotplug-notification-item-icon' });
|
||||||
box.add(icon);
|
box.add(icon);
|
||||||
|
|
||||||
@ -636,11 +625,10 @@ const AutorunTransientNotification = new Lang.Class({
|
|||||||
style_class: 'hotplug-notification-item' });
|
style_class: 'hotplug-notification-item' });
|
||||||
|
|
||||||
button.connect('clicked', Lang.bind(this, function() {
|
button.connect('clicked', Lang.bind(this, function() {
|
||||||
this._manager.ejectMount(this._mount);
|
Main.autorunManager.ejectMount(this._mount);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const Component = AutorunManager;
|
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
@ -9,13 +9,6 @@ const Shell = imports.gi.Shell;
|
|||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const PopupAnimation = {
|
|
||||||
NONE: 0,
|
|
||||||
SLIDE: 1 << 0,
|
|
||||||
FADE: 1 << 1,
|
|
||||||
FULL: ~0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const POPUP_ANIMATION_TIME = 0.15;
|
const POPUP_ANIMATION_TIME = 0.15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,18 +18,16 @@ const POPUP_ANIMATION_TIME = 0.15;
|
|||||||
*
|
*
|
||||||
* An actor which displays a triangle "arrow" pointing to a given
|
* An actor which displays a triangle "arrow" pointing to a given
|
||||||
* side. The .bin property is a container in which content can be
|
* side. The .bin property is a container in which content can be
|
||||||
* placed. The arrow position may be controlled via
|
* placed. The arrow position may be controlled via setArrowOrigin().
|
||||||
* setArrowOrigin(). The arrow side might be temporarily flipped
|
|
||||||
* depending on the box size and source position to keep the box
|
|
||||||
* totally inside the monitor if possible.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const BoxPointer = new Lang.Class({
|
function BoxPointer(side, binProperties) {
|
||||||
Name: 'BoxPointer',
|
this._init(side, binProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxPointer.prototype = {
|
||||||
_init: function(arrowSide, binProperties) {
|
_init: function(arrowSide, binProperties) {
|
||||||
this._arrowSide = arrowSide;
|
this._arrowSide = arrowSide;
|
||||||
this._userArrowSide = arrowSide;
|
|
||||||
this._arrowOrigin = 0;
|
this._arrowOrigin = 0;
|
||||||
this.actor = new St.Bin({ x_fill: true,
|
this.actor = new St.Bin({ x_fill: true,
|
||||||
y_fill: true });
|
y_fill: true });
|
||||||
@ -55,37 +46,16 @@ const BoxPointer = new Lang.Class({
|
|||||||
this._yOffset = 0;
|
this._yOffset = 0;
|
||||||
this._xPosition = 0;
|
this._xPosition = 0;
|
||||||
this._yPosition = 0;
|
this._yPosition = 0;
|
||||||
this._sourceAlignment = 0.5;
|
|
||||||
this._capturedEventId = 0;
|
|
||||||
this._muteInput();
|
|
||||||
},
|
|
||||||
|
|
||||||
_muteInput: function() {
|
|
||||||
if (this._capturedEventId == 0)
|
|
||||||
this._capturedEventId = this.actor.connect('captured-event',
|
|
||||||
function() { return true; });
|
|
||||||
},
|
|
||||||
|
|
||||||
_unmuteInput: function() {
|
|
||||||
if (this._capturedEventId != 0) {
|
|
||||||
this.actor.disconnect(this._capturedEventId);
|
|
||||||
this._capturedEventId = 0;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function(animate, onComplete) {
|
show: function(animate, onComplete) {
|
||||||
let themeNode = this.actor.get_theme_node();
|
let themeNode = this.actor.get_theme_node();
|
||||||
let rise = themeNode.get_length('-arrow-rise');
|
let rise = themeNode.get_length('-arrow-rise');
|
||||||
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
|
|
||||||
|
|
||||||
if (animate & PopupAnimation.FADE)
|
|
||||||
this.opacity = 0;
|
|
||||||
else
|
|
||||||
this.opacity = 255;
|
|
||||||
|
|
||||||
|
this.opacity = 0;
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
|
|
||||||
if (animate & PopupAnimation.SLIDE) {
|
if (animate) {
|
||||||
switch (this._arrowSide) {
|
switch (this._arrowSide) {
|
||||||
case St.Side.TOP:
|
case St.Side.TOP:
|
||||||
this.yOffset = -rise;
|
this.yOffset = -rise;
|
||||||
@ -105,13 +75,9 @@ const BoxPointer = new Lang.Class({
|
|||||||
Tweener.addTween(this, { opacity: 255,
|
Tweener.addTween(this, { opacity: 255,
|
||||||
xOffset: 0,
|
xOffset: 0,
|
||||||
yOffset: 0,
|
yOffset: 0,
|
||||||
transition: 'linear',
|
transition: "linear",
|
||||||
onComplete: Lang.bind(this, function() {
|
onComplete: onComplete,
|
||||||
this._unmuteInput();
|
time: POPUP_ANIMATION_TIME });
|
||||||
if (onComplete)
|
|
||||||
onComplete();
|
|
||||||
}),
|
|
||||||
time: animationTime });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function(animate, onComplete) {
|
hide: function(animate, onComplete) {
|
||||||
@ -119,10 +85,8 @@ const BoxPointer = new Lang.Class({
|
|||||||
let yOffset = 0;
|
let yOffset = 0;
|
||||||
let themeNode = this.actor.get_theme_node();
|
let themeNode = this.actor.get_theme_node();
|
||||||
let rise = themeNode.get_length('-arrow-rise');
|
let rise = themeNode.get_length('-arrow-rise');
|
||||||
let fade = (animate & PopupAnimation.FADE);
|
|
||||||
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
|
|
||||||
|
|
||||||
if (animate & PopupAnimation.SLIDE) {
|
if (animate) {
|
||||||
switch (this._arrowSide) {
|
switch (this._arrowSide) {
|
||||||
case St.Side.TOP:
|
case St.Side.TOP:
|
||||||
yOffset = rise;
|
yOffset = rise;
|
||||||
@ -139,17 +103,13 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._muteInput();
|
Tweener.addTween(this, { opacity: 0,
|
||||||
|
|
||||||
Tweener.removeTweens(this);
|
|
||||||
Tweener.addTween(this, { opacity: fade ? 0 : 255,
|
|
||||||
xOffset: xOffset,
|
xOffset: xOffset,
|
||||||
yOffset: yOffset,
|
yOffset: yOffset,
|
||||||
transition: 'linear',
|
transition: "linear",
|
||||||
time: animationTime,
|
time: POPUP_ANIMATION_TIME,
|
||||||
onComplete: Lang.bind(this, function () {
|
onComplete: Lang.bind(this, function () {
|
||||||
this.actor.hide();
|
this.actor.hide();
|
||||||
this.opacity = 0;
|
|
||||||
this.xOffset = 0;
|
this.xOffset = 0;
|
||||||
this.yOffset = 0;
|
this.yOffset = 0;
|
||||||
if (onComplete)
|
if (onComplete)
|
||||||
@ -219,27 +179,8 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
this.bin.allocate(childBox, flags);
|
this.bin.allocate(childBox, flags);
|
||||||
|
|
||||||
if (this._sourceActor && this._sourceActor.mapped) {
|
if (this._sourceActor && this._sourceActor.mapped)
|
||||||
this._reposition(this._sourceActor, this._arrowAlignment);
|
this._reposition(this._sourceActor, this._gap, this._alignment);
|
||||||
|
|
||||||
if (this._shouldFlip()) {
|
|
||||||
switch (this._arrowSide) {
|
|
||||||
case St.Side.TOP:
|
|
||||||
this._arrowSide = St.Side.BOTTOM;
|
|
||||||
break;
|
|
||||||
case St.Side.BOTTOM:
|
|
||||||
this._arrowSide = St.Side.TOP;
|
|
||||||
break;
|
|
||||||
case St.Side.LEFT:
|
|
||||||
this._arrowSide = St.Side.RIGHT;
|
|
||||||
break;
|
|
||||||
case St.Side.RIGHT:
|
|
||||||
this._arrowSide = St.Side.LEFT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this._reposition(this._sourceActor, this._arrowAlignment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_drawBorder: function(area) {
|
_drawBorder: function(area) {
|
||||||
@ -253,6 +194,7 @@ const BoxPointer = new Lang.Class({
|
|||||||
let halfBorder = borderWidth / 2;
|
let halfBorder = borderWidth / 2;
|
||||||
let halfBase = Math.floor(base/2);
|
let halfBase = Math.floor(base/2);
|
||||||
|
|
||||||
|
let borderColor = themeNode.get_color('-arrow-border-color');
|
||||||
let backgroundColor = themeNode.get_color('-arrow-background-color');
|
let backgroundColor = themeNode.get_color('-arrow-background-color');
|
||||||
|
|
||||||
let [width, height] = area.get_surface_size();
|
let [width, height] = area.get_surface_size();
|
||||||
@ -263,6 +205,7 @@ const BoxPointer = new Lang.Class({
|
|||||||
boxWidth -= rise;
|
boxWidth -= rise;
|
||||||
}
|
}
|
||||||
let cr = area.get_context();
|
let cr = area.get_context();
|
||||||
|
Clutter.cairo_set_source_color(cr, borderColor);
|
||||||
|
|
||||||
// Translate so that box goes from 0,0 to boxWidth,boxHeight,
|
// Translate so that box goes from 0,0 to boxWidth,boxHeight,
|
||||||
// with the arrow poking out of that
|
// with the arrow poking out of that
|
||||||
@ -275,51 +218,14 @@ const BoxPointer = new Lang.Class({
|
|||||||
let [x1, y1] = [halfBorder, halfBorder];
|
let [x1, y1] = [halfBorder, halfBorder];
|
||||||
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
|
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
|
||||||
|
|
||||||
let skipTopLeft = false;
|
|
||||||
let skipTopRight = false;
|
|
||||||
let skipBottomLeft = false;
|
|
||||||
let skipBottomRight = false;
|
|
||||||
|
|
||||||
switch (this._arrowSide) {
|
|
||||||
case St.Side.TOP:
|
|
||||||
if (this._arrowOrigin == x1)
|
|
||||||
skipTopLeft = true;
|
|
||||||
else if (this._arrowOrigin == x2)
|
|
||||||
skipTopRight = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case St.Side.RIGHT:
|
|
||||||
if (this._arrowOrigin == y1)
|
|
||||||
skipTopRight = true;
|
|
||||||
else if (this._arrowOrigin == y2)
|
|
||||||
skipBottomRight = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case St.Side.BOTTOM:
|
|
||||||
if (this._arrowOrigin == x1)
|
|
||||||
skipBottomLeft = true;
|
|
||||||
else if (this._arrowOrigin == x2)
|
|
||||||
skipBottomRight = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case St.Side.LEFT:
|
|
||||||
if (this._arrowOrigin == y1)
|
|
||||||
skipTopLeft = true;
|
|
||||||
else if (this._arrowOrigin == y2)
|
|
||||||
skipBottomLeft = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cr.moveTo(x1 + borderRadius, y1);
|
cr.moveTo(x1 + borderRadius, y1);
|
||||||
if (this._arrowSide == St.Side.TOP) {
|
if (this._arrowSide == St.Side.TOP) {
|
||||||
if (skipTopLeft) {
|
if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
|
||||||
cr.moveTo(x1, y2 - borderRadius);
|
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||||
cr.lineTo(x1, y1 - rise);
|
cr.lineTo(Math.max(x1 + borderRadius, this._arrowOrigin) + halfBase, y1);
|
||||||
cr.lineTo(x1 + halfBase, y1);
|
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
|
||||||
} else if (skipTopRight) {
|
cr.lineTo(Math.min(x2 - borderRadius, this._arrowOrigin) - halfBase, y1);
|
||||||
cr.lineTo(x2 - halfBase, y1);
|
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||||
cr.lineTo(x2, y1 - rise);
|
|
||||||
cr.lineTo(x2, y1 + borderRadius);
|
|
||||||
} else {
|
} else {
|
||||||
cr.lineTo(this._arrowOrigin - halfBase, y1);
|
cr.lineTo(this._arrowOrigin - halfBase, y1);
|
||||||
cr.lineTo(this._arrowOrigin, y1 - rise);
|
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||||
@ -327,20 +233,19 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipTopRight) {
|
cr.lineTo(x2 - borderRadius, y1);
|
||||||
cr.lineTo(x2 - borderRadius, y1);
|
|
||||||
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
|
// top-right corner
|
||||||
3*Math.PI/2, Math.PI*2);
|
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
|
||||||
}
|
3*Math.PI/2, Math.PI*2);
|
||||||
|
|
||||||
if (this._arrowSide == St.Side.RIGHT) {
|
if (this._arrowSide == St.Side.RIGHT) {
|
||||||
if (skipTopRight) {
|
if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
|
||||||
cr.lineTo(x2 + rise, y1);
|
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||||
cr.lineTo(x2 + rise, y1 + halfBase);
|
cr.lineTo(x2, Math.max(y1 + borderRadius, this._arrowOrigin) + halfBase);
|
||||||
} else if (skipBottomRight) {
|
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
|
||||||
cr.lineTo(x2, y2 - halfBase);
|
cr.lineTo(x2, Math.min(y2 - borderRadius, this._arrowOrigin) - halfBase);
|
||||||
cr.lineTo(x2 + rise, y2);
|
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||||
cr.lineTo(x2 - borderRadius, y2);
|
|
||||||
} else {
|
} else {
|
||||||
cr.lineTo(x2, this._arrowOrigin - halfBase);
|
cr.lineTo(x2, this._arrowOrigin - halfBase);
|
||||||
cr.lineTo(x2 + rise, this._arrowOrigin);
|
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||||
@ -348,20 +253,19 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipBottomRight) {
|
cr.lineTo(x2, y2 - borderRadius);
|
||||||
cr.lineTo(x2, y2 - borderRadius);
|
|
||||||
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
|
// bottom-right corner
|
||||||
0, Math.PI/2);
|
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
|
||||||
}
|
0, Math.PI/2);
|
||||||
|
|
||||||
if (this._arrowSide == St.Side.BOTTOM) {
|
if (this._arrowSide == St.Side.BOTTOM) {
|
||||||
if (skipBottomLeft) {
|
if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
|
||||||
cr.lineTo(x1 + halfBase, y2);
|
cr.lineTo(Math.max(x1 + borderRadius, this._arrowOrigin) + halfBase, y2);
|
||||||
cr.lineTo(x1, y2 + rise);
|
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||||
cr.lineTo(x1, y2 - borderRadius);
|
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
|
||||||
} else if (skipBottomRight) {
|
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||||
cr.lineTo(x2, y2 + rise);
|
cr.lineTo(Math.min(x2 - borderRadius, this._arrowOrigin) - halfBase, y2);
|
||||||
cr.lineTo(x2 - halfBase, y2);
|
|
||||||
} else {
|
} else {
|
||||||
cr.lineTo(this._arrowOrigin + halfBase, y2);
|
cr.lineTo(this._arrowOrigin + halfBase, y2);
|
||||||
cr.lineTo(this._arrowOrigin, y2 + rise);
|
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||||
@ -369,20 +273,19 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipBottomLeft) {
|
cr.lineTo(x1 + borderRadius, y2);
|
||||||
cr.lineTo(x1 + borderRadius, y2);
|
|
||||||
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
|
// bottom-left corner
|
||||||
Math.PI/2, Math.PI);
|
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
|
||||||
}
|
Math.PI/2, Math.PI);
|
||||||
|
|
||||||
if (this._arrowSide == St.Side.LEFT) {
|
if (this._arrowSide == St.Side.LEFT) {
|
||||||
if (skipTopLeft) {
|
if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
|
||||||
cr.lineTo(x1, y1 + halfBase);
|
cr.lineTo(x1, Math.max(y1 + borderRadius, this._arrowOrigin) + halfBase);
|
||||||
cr.lineTo(x1 - rise, y1);
|
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||||
cr.lineTo(x1 + borderRadius, y1);
|
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
|
||||||
} else if (skipBottomLeft) {
|
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||||
cr.lineTo(x1 - rise, y2)
|
cr.lineTo(x1, Math.min(y2 - borderRadius, this._arrowOrigin) - halfBase);
|
||||||
cr.lineTo(x1 - rise, y2 - halfBase);
|
|
||||||
} else {
|
} else {
|
||||||
cr.lineTo(x1, this._arrowOrigin + halfBase);
|
cr.lineTo(x1, this._arrowOrigin + halfBase);
|
||||||
cr.lineTo(x1 - rise, this._arrowOrigin);
|
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||||
@ -390,66 +293,50 @@ const BoxPointer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skipTopLeft) {
|
cr.lineTo(x1, y1 + borderRadius);
|
||||||
cr.lineTo(x1, y1 + borderRadius);
|
|
||||||
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
|
// top-left corner
|
||||||
Math.PI, 3*Math.PI/2);
|
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
|
||||||
}
|
Math.PI, 3*Math.PI/2);
|
||||||
|
|
||||||
Clutter.cairo_set_source_color(cr, backgroundColor);
|
Clutter.cairo_set_source_color(cr, backgroundColor);
|
||||||
cr.fillPreserve();
|
cr.fillPreserve();
|
||||||
|
Clutter.cairo_set_source_color(cr, borderColor);
|
||||||
if (borderWidth > 0) {
|
cr.setLineWidth(borderWidth);
|
||||||
let borderColor = themeNode.get_color('-arrow-border-color');
|
cr.stroke();
|
||||||
Clutter.cairo_set_source_color(cr, borderColor);
|
|
||||||
cr.setLineWidth(borderWidth);
|
|
||||||
cr.stroke();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setPosition: function(sourceActor, alignment) {
|
setPosition: function(sourceActor, gap, alignment) {
|
||||||
this._arrowSide = this._userArrowSide;
|
|
||||||
|
|
||||||
// We need to show it now to force an allocation,
|
// We need to show it now to force an allocation,
|
||||||
// so that we can query the correct size.
|
// so that we can query the correct size.
|
||||||
this.actor.show();
|
this.actor.show();
|
||||||
|
|
||||||
this._sourceActor = sourceActor;
|
this._sourceActor = sourceActor;
|
||||||
this._arrowAlignment = alignment;
|
this._gap = gap;
|
||||||
|
this._alignment = alignment;
|
||||||
|
|
||||||
this._reposition(sourceActor, alignment);
|
this._reposition(sourceActor, gap, alignment);
|
||||||
},
|
},
|
||||||
|
|
||||||
setSourceAlignment: function(alignment) {
|
_reposition: function(sourceActor, gap, alignment) {
|
||||||
this._sourceAlignment = alignment;
|
|
||||||
|
|
||||||
if (!this._sourceActor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.setPosition(this._sourceActor, this._arrowAlignment);
|
|
||||||
},
|
|
||||||
|
|
||||||
_reposition: function(sourceActor, alignment) {
|
|
||||||
// Position correctly relative to the sourceActor
|
// Position correctly relative to the sourceActor
|
||||||
let sourceNode = sourceActor.get_theme_node();
|
let sourceNode = sourceActor.get_theme_node();
|
||||||
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
|
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
|
||||||
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||||
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
|
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2;
|
||||||
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
|
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
|
||||||
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
|
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
|
||||||
|
|
||||||
// We also want to keep it onscreen, and separated from the
|
// We also want to keep it onscreen, and separated from the
|
||||||
// edge by the same distance as the main part of the box is
|
// edge by the same distance as the main part of the box is
|
||||||
// separated from its sourceActor
|
// separated from its sourceActor
|
||||||
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
let themeNode = this.actor.get_theme_node();
|
let themeNode = this.actor.get_theme_node();
|
||||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||||
let arrowBase = themeNode.get_length('-arrow-base');
|
let arrowBase = themeNode.get_length('-arrow-base');
|
||||||
let borderRadius = themeNode.get_length('-arrow-border-radius');
|
let borderRadius = themeNode.get_length('-arrow-border-radius');
|
||||||
let margin = (4 * borderRadius + borderWidth + arrowBase);
|
let margin = (4 * borderRadius + borderWidth + arrowBase);
|
||||||
|
let halfMargin = margin / 2;
|
||||||
let gap = themeNode.get_length('-boxpointer-gap');
|
|
||||||
let padding = themeNode.get_length('-arrow-rise');
|
|
||||||
|
|
||||||
let resX, resY;
|
let resX, resY;
|
||||||
|
|
||||||
@ -468,66 +355,29 @@ const BoxPointer = new Lang.Class({
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now align and position the pointing axis, making sure it fits on
|
// Now align and position the pointing axis, making sure
|
||||||
// screen. If the arrowOrigin is so close to the edge that the arrow
|
// it fits on screen
|
||||||
// will not be isosceles, we try to compensate as follows:
|
|
||||||
// - We skip the rounded corner and settle for a right angled arrow
|
|
||||||
// as shown below. See _drawBorder for further details.
|
|
||||||
// |\_____
|
|
||||||
// |
|
|
||||||
// |
|
|
||||||
// - If the arrow was going to be acute angled, we move the position
|
|
||||||
// of the box to maintain the arrow's accuracy.
|
|
||||||
|
|
||||||
let arrowOrigin;
|
|
||||||
let halfBase = Math.floor(arrowBase/2);
|
|
||||||
let halfBorder = borderWidth / 2;
|
|
||||||
let halfMargin = margin / 2;
|
|
||||||
let [x1, y1] = [halfBorder, halfBorder];
|
|
||||||
let [x2, y2] = [natWidth - halfBorder, natHeight - halfBorder];
|
|
||||||
|
|
||||||
switch (this._arrowSide) {
|
switch (this._arrowSide) {
|
||||||
case St.Side.TOP:
|
case St.Side.TOP:
|
||||||
case St.Side.BOTTOM:
|
case St.Side.BOTTOM:
|
||||||
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
|
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
|
||||||
|
|
||||||
resX = Math.max(resX, monitor.x + padding);
|
resX = Math.max(resX, primary.x + 10);
|
||||||
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
|
resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
|
||||||
|
this.setArrowOrigin(sourceCenterX - resX);
|
||||||
arrowOrigin = sourceCenterX - resX;
|
|
||||||
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
|
|
||||||
if (arrowOrigin > x1)
|
|
||||||
resX += (arrowOrigin - x1);
|
|
||||||
arrowOrigin = x1;
|
|
||||||
} else if (arrowOrigin >= (x2 - (borderRadius + halfBase))) {
|
|
||||||
if (arrowOrigin < x2)
|
|
||||||
resX -= (x2 - arrowOrigin);
|
|
||||||
arrowOrigin = x2;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case St.Side.LEFT:
|
case St.Side.LEFT:
|
||||||
case St.Side.RIGHT:
|
case St.Side.RIGHT:
|
||||||
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
|
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
|
||||||
|
|
||||||
resY = Math.max(resY, monitor.y + padding);
|
resY = Math.max(resY, primary.y + 10);
|
||||||
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
|
resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
|
||||||
|
|
||||||
arrowOrigin = sourceCenterY - resY;
|
this.setArrowOrigin(sourceCenterY - resY);
|
||||||
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
|
|
||||||
if (arrowOrigin > y1)
|
|
||||||
resY += (arrowOrigin - y1);
|
|
||||||
arrowOrigin = y1;
|
|
||||||
} else if (arrowOrigin >= (y2 - (borderRadius + halfBase))) {
|
|
||||||
if (arrowOrigin < y2)
|
|
||||||
resX -= (y2 - arrowOrigin);
|
|
||||||
arrowOrigin = y2;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setArrowOrigin(arrowOrigin);
|
|
||||||
|
|
||||||
let parent = this.actor.get_parent();
|
let parent = this.actor.get_parent();
|
||||||
let success, x, y;
|
let success, x, y;
|
||||||
while (!success) {
|
while (!success) {
|
||||||
@ -561,39 +411,6 @@ const BoxPointer = new Lang.Class({
|
|||||||
-(this._yPosition + this._yOffset));
|
-(this._yPosition + this._yOffset));
|
||||||
},
|
},
|
||||||
|
|
||||||
_shouldFlip: function() {
|
|
||||||
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
|
|
||||||
let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
|
|
||||||
let boxWidth = boxAllocation.x2 - boxAllocation.x1;
|
|
||||||
let boxHeight = boxAllocation.y2 - boxAllocation.y1;
|
|
||||||
let monitor = Main.layoutManager.findMonitorForActor(this.actor);
|
|
||||||
|
|
||||||
switch (this._arrowSide) {
|
|
||||||
case St.Side.TOP:
|
|
||||||
if (boxAllocation.y2 > monitor.y + monitor.height &&
|
|
||||||
boxHeight < sourceAllocation.y1 - monitor.y)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case St.Side.BOTTOM:
|
|
||||||
if (boxAllocation.y1 < monitor.y &&
|
|
||||||
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case St.Side.LEFT:
|
|
||||||
if (boxAllocation.x2 > monitor.x + monitor.width &&
|
|
||||||
boxWidth < sourceAllocation.x1 - monitor.x)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case St.Side.RIGHT:
|
|
||||||
if (boxAllocation.x1 < monitor.x &&
|
|
||||||
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
set xOffset(offset) {
|
set xOffset(offset) {
|
||||||
this._xOffset = offset;
|
this._xOffset = offset;
|
||||||
this._shiftActor();
|
this._shiftActor();
|
||||||
@ -619,4 +436,4 @@ const BoxPointer = new Lang.Class({
|
|||||||
get opacity() {
|
get opacity() {
|
||||||
return this.actor.opacity;
|
return this.actor.opacity;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const DBus = imports.dbus;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
@ -156,24 +156,28 @@ function _getEventDayAbbreviation(dayNumber) {
|
|||||||
|
|
||||||
// Abstraction for an appointment/event in a calendar
|
// Abstraction for an appointment/event in a calendar
|
||||||
|
|
||||||
const CalendarEvent = new Lang.Class({
|
function CalendarEvent(date, end, summary, allDay) {
|
||||||
Name: 'CalendarEvent',
|
this._init(date, end, summary, allDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
CalendarEvent.prototype = {
|
||||||
_init: function(date, end, summary, allDay) {
|
_init: function(date, end, summary, allDay) {
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.summary = summary;
|
this.summary = summary;
|
||||||
this.allDay = allDay;
|
this.allDay = allDay;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
// Interface for appointments/events - e.g. the contents of a calendar
|
// Interface for appointments/events - e.g. the contents of a calendar
|
||||||
//
|
//
|
||||||
|
|
||||||
// First, an implementation with no events
|
// First, an implementation with no events
|
||||||
const EmptyEventSource = new Lang.Class({
|
function EmptyEventSource() {
|
||||||
Name: 'EmptyEventSource',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmptyEventSource.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -188,30 +192,34 @@ const EmptyEventSource = new Lang.Class({
|
|||||||
hasEvents: function(day) {
|
hasEvents: function(day) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(EmptyEventSource.prototype);
|
Signals.addSignalMethods(EmptyEventSource.prototype);
|
||||||
|
|
||||||
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
|
const CalendarServerIface = {
|
||||||
<method name="GetEvents">
|
name: 'org.gnome.Shell.CalendarServer',
|
||||||
<arg type="x" direction="in" />
|
methods: [{ name: 'GetEvents',
|
||||||
<arg type="x" direction="in" />
|
inSignature: 'xxb',
|
||||||
<arg type="b" direction="in" />
|
outSignature: 'a(sssbxxa{sv})' }],
|
||||||
<arg type="a(sssbxxa{sv})" direction="out" />
|
signals: [{ name: 'Changed',
|
||||||
</method>
|
inSignature: '' }]
|
||||||
<signal name="Changed" />
|
};
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const CalendarServer = new Gio.DBusProxyClass({
|
const CalendarServer = function () {
|
||||||
Name: 'CalendarServer',
|
this._init();
|
||||||
Interface: CalendarServerIface,
|
};
|
||||||
|
|
||||||
_init: function() {
|
CalendarServer.prototype = {
|
||||||
this.parent({ g_bus_type: Gio.BusType.SESSION,
|
_init: function() {
|
||||||
g_name: 'org.gnome.Shell.CalendarServer',
|
DBus.session.proxifyObject(this, 'org.gnome.Shell.CalendarServer', '/org/gnome/Shell/CalendarServer');
|
||||||
g_object_path: '/org/gnome/Shell/CalendarServer',
|
}
|
||||||
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES });
|
};
|
||||||
}
|
|
||||||
});
|
DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
|
||||||
|
|
||||||
|
// an implementation that reads data from a session bus service
|
||||||
|
function DBusEventSource(owner) {
|
||||||
|
this._init(owner);
|
||||||
|
}
|
||||||
|
|
||||||
function _datesEqual(a, b) {
|
function _datesEqual(a, b) {
|
||||||
if (a < b)
|
if (a < b)
|
||||||
@ -231,26 +239,18 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// an implementation that reads data from a session bus service
|
|
||||||
const DBusEventSource = new Lang.Class({
|
|
||||||
Name: 'DBusEventSource',
|
|
||||||
|
|
||||||
_init: function() {
|
DBusEventSource.prototype = {
|
||||||
|
_init: function(owner) {
|
||||||
this._resetCache();
|
this._resetCache();
|
||||||
|
|
||||||
this._dbusProxy = new CalendarServer();
|
this._dbusProxy = new CalendarServer(owner);
|
||||||
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
|
this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
|
||||||
|
|
||||||
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
DBus.session.watch_name('org.gnome.Shell.CalendarServer',
|
||||||
try {
|
false, // do not launch a name-owner if none exists
|
||||||
proxy.init_finish(result);
|
Lang.bind(this, this._onNameAppeared),
|
||||||
} catch(e) {
|
Lang.bind(this, this._onNameVanished));
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._resetCache();
|
|
||||||
this.emit('changed');
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_resetCache: function() {
|
_resetCache: function() {
|
||||||
@ -259,32 +259,36 @@ const DBusEventSource = new Lang.Class({
|
|||||||
this._lastRequestEnd = null;
|
this._lastRequestEnd = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onNameAppeared: function(owner) {
|
||||||
|
this._resetCache();
|
||||||
|
this._loadEvents(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onNameVanished: function(oldOwner) {
|
||||||
|
this._resetCache();
|
||||||
|
this.emit('changed');
|
||||||
|
},
|
||||||
|
|
||||||
_onChanged: function() {
|
_onChanged: function() {
|
||||||
this._loadEvents(false);
|
this._loadEvents(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onEventsReceived: function(proxy, result) {
|
_onEventsReceived: function(appointments) {
|
||||||
let appointments;
|
|
||||||
try {
|
|
||||||
[appointments] = proxy.call_finish(result).deep_unpack();
|
|
||||||
} catch(e if e instanceof GLib.Error) {
|
|
||||||
// ignore errors coming from DBus
|
|
||||||
appointments = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
let newEvents = [];
|
let newEvents = [];
|
||||||
for (let n = 0; n < appointments.length; n++) {
|
if (appointments != null) {
|
||||||
let a = appointments[n];
|
for (let n = 0; n < appointments.length; n++) {
|
||||||
let date = new Date(a[4] * 1000);
|
let a = appointments[n];
|
||||||
let end = new Date(a[5] * 1000);
|
let date = new Date(a[4] * 1000);
|
||||||
let summary = a[1];
|
let end = new Date(a[5] * 1000);
|
||||||
let allDay = a[3];
|
let summary = a[1];
|
||||||
let event = new CalendarEvent(date, end, summary, allDay);
|
let allDay = a[3];
|
||||||
newEvents.push(event);
|
let event = new CalendarEvent(date, end, summary, allDay);
|
||||||
|
newEvents.push(event);
|
||||||
|
}
|
||||||
|
newEvents.sort(function(event1, event2) {
|
||||||
|
return event1.date.getTime() - event2.date.getTime();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
newEvents.sort(function(event1, event2) {
|
|
||||||
return event1.date.getTime() - event2.date.getTime();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._events = newEvents;
|
this._events = newEvents;
|
||||||
this.emit('changed');
|
this.emit('changed');
|
||||||
@ -292,19 +296,14 @@ const DBusEventSource = new Lang.Class({
|
|||||||
|
|
||||||
_loadEvents: function(forceReload) {
|
_loadEvents: function(forceReload) {
|
||||||
if (this._curRequestBegin && this._curRequestEnd){
|
if (this._curRequestBegin && this._curRequestEnd){
|
||||||
/* Can't use GetEventsRemote because we need to pass the
|
let callFlags = 0;
|
||||||
flags here */
|
|
||||||
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
|
|
||||||
if (forceReload)
|
if (forceReload)
|
||||||
callFlags = Gio.DBusCallFlags.NONE;
|
callFlags |= DBus.CALL_FLAG_START;
|
||||||
this._dbusProxy.call("GetEvents",
|
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
|
||||||
GLib.Variant.new("(xxb)", [this._curRequestBegin.getTime() / 1000,
|
this._curRequestEnd.getTime() / 1000,
|
||||||
this._curRequestEnd.getTime() / 1000,
|
forceReload,
|
||||||
forceReload]),
|
Lang.bind(this, this._onEventsReceived),
|
||||||
callFlags,
|
callFlags);
|
||||||
-1,
|
|
||||||
null,
|
|
||||||
Lang.bind(this, this._onEventsReceived));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -340,14 +339,29 @@ const DBusEventSource = new Lang.Class({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(DBusEventSource.prototype);
|
Signals.addSignalMethods(DBusEventSource.prototype);
|
||||||
|
|
||||||
const Calendar = new Lang.Class({
|
// Calendar:
|
||||||
Name: 'Calendar',
|
// @eventSource: is an object implementing the EventSource API, e.g. the
|
||||||
|
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
|
||||||
|
function Calendar(eventSource) {
|
||||||
|
this._init(eventSource);
|
||||||
|
}
|
||||||
|
|
||||||
_init: function() {
|
Calendar.prototype = {
|
||||||
this._weekStart = Shell.util_get_week_start();
|
_init: function(eventSource) {
|
||||||
|
this._eventSource = eventSource;
|
||||||
|
|
||||||
|
this._eventSource.connect('changed', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this._update(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// FIXME: This is actually the fallback method for GTK+ for the week start;
|
||||||
|
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
|
||||||
|
// should add a C function so we can do the full handling.
|
||||||
|
this._weekStart = NaN;
|
||||||
this._weekdate = NaN;
|
this._weekdate = NaN;
|
||||||
this._digitWidth = NaN;
|
this._digitWidth = NaN;
|
||||||
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
|
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
|
||||||
@ -355,6 +369,16 @@ const Calendar = new Lang.Class({
|
|||||||
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
|
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
|
||||||
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
|
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
|
||||||
|
|
||||||
|
let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
|
||||||
|
if (weekStartString.indexOf('calendar:week_start:') == 0) {
|
||||||
|
this._weekStart = parseInt(weekStartString.substring(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(this._weekStart) || this._weekStart < 0 || this._weekStart > 6) {
|
||||||
|
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
|
||||||
|
this._weekStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the ordering for month/year in the calendar heading
|
// Find the ordering for month/year in the calendar heading
|
||||||
this._headerFormatWithoutYear = '%B';
|
this._headerFormatWithoutYear = '%B';
|
||||||
switch (Gettext_gtk30.gettext('calendar:MY')) {
|
switch (Gettext_gtk30.gettext('calendar:MY')) {
|
||||||
@ -383,23 +407,6 @@ const Calendar = new Lang.Class({
|
|||||||
this._buildHeader ();
|
this._buildHeader ();
|
||||||
},
|
},
|
||||||
|
|
||||||
// @eventSource: is an object implementing the EventSource API, e.g. the
|
|
||||||
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
|
|
||||||
setEventSource: function(eventSource) {
|
|
||||||
if (this._eventSource) {
|
|
||||||
this._eventSource.disconnect(this._eventSourceChangedId);
|
|
||||||
this._eventSource = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._eventSource = eventSource;
|
|
||||||
|
|
||||||
if (this._eventSource) {
|
|
||||||
this._eventSourceChangedId = this._eventSource.connect('changed', Lang.bind(this, function() {
|
|
||||||
this._update(false);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sets the calendar to show a specific date
|
// Sets the calendar to show a specific date
|
||||||
setDate: function(date, forceReload) {
|
setDate: function(date, forceReload) {
|
||||||
if (!_sameDay(date, this._selectedDate)) {
|
if (!_sameDay(date, this._selectedDate)) {
|
||||||
@ -414,7 +421,7 @@ const Calendar = new Lang.Class({
|
|||||||
|
|
||||||
_buildHeader: function() {
|
_buildHeader: function() {
|
||||||
let offsetCols = this._useWeekdate ? 1 : 0;
|
let offsetCols = this._useWeekdate ? 1 : 0;
|
||||||
this.actor.destroy_all_children();
|
this.actor.destroy_children();
|
||||||
|
|
||||||
// Top line of the calendar '<| September 2009 |>'
|
// Top line of the calendar '<| September 2009 |>'
|
||||||
this._topBox = new St.BoxLayout();
|
this._topBox = new St.BoxLayout();
|
||||||
@ -456,7 +463,7 @@ const Calendar = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All the children after this are days, and get removed when we update the calendar
|
// All the children after this are days, and get removed when we update the calendar
|
||||||
this._firstDayIndex = this.actor.get_n_children();
|
this._firstDayIndex = this.actor.get_children().length;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onStyleChange: function(actor, event) {
|
_onStyleChange: function(actor, event) {
|
||||||
@ -559,10 +566,6 @@ const Calendar = new Lang.Class({
|
|||||||
let row = 2;
|
let row = 2;
|
||||||
while (true) {
|
while (true) {
|
||||||
let button = new St.Button({ label: iter.getDate().toString() });
|
let button = new St.Button({ label: iter.getDate().toString() });
|
||||||
let rtl = button.get_text_direction() == Clutter.TextDirection.RTL;
|
|
||||||
|
|
||||||
if (!this._eventSource)
|
|
||||||
button.reactive = false;
|
|
||||||
|
|
||||||
let iterStr = iter.toUTCString();
|
let iterStr = iter.toUTCString();
|
||||||
button.connect('clicked', Lang.bind(this, function() {
|
button.connect('clicked', Lang.bind(this, function() {
|
||||||
@ -570,7 +573,7 @@ const Calendar = new Lang.Class({
|
|||||||
this.setDate(newlySelectedDate, false);
|
this.setDate(newlySelectedDate, false);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let hasEvents = this._eventSource && this._eventSource.hasEvents(iter);
|
let hasEvents = this._eventSource.hasEvents(iter);
|
||||||
let styleClass = 'calendar-day-base calendar-day';
|
let styleClass = 'calendar-day-base calendar-day';
|
||||||
if (_isWorkDay(iter))
|
if (_isWorkDay(iter))
|
||||||
styleClass += ' calendar-work-day'
|
styleClass += ' calendar-work-day'
|
||||||
@ -580,10 +583,7 @@ const Calendar = new Lang.Class({
|
|||||||
// Hack used in lieu of border-collapse - see gnome-shell.css
|
// Hack used in lieu of border-collapse - see gnome-shell.css
|
||||||
if (row == 2)
|
if (row == 2)
|
||||||
styleClass = 'calendar-day-top ' + styleClass;
|
styleClass = 'calendar-day-top ' + styleClass;
|
||||||
|
if (iter.getDay() == this._weekStart)
|
||||||
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
|
|
||||||
: iter.getDay() == this._weekStart;
|
|
||||||
if (leftMost)
|
|
||||||
styleClass = 'calendar-day-left ' + styleClass;
|
styleClass = 'calendar-day-left ' + styleClass;
|
||||||
|
|
||||||
if (_sameDay(now, iter))
|
if (_sameDay(now, iter))
|
||||||
@ -620,35 +620,37 @@ const Calendar = new Lang.Class({
|
|||||||
}
|
}
|
||||||
// Signal to the event source that we are interested in events
|
// Signal to the event source that we are interested in events
|
||||||
// only from this date range
|
// only from this date range
|
||||||
if (this._eventSource)
|
this._eventSource.requestRange(beginDate, iter, forceReload);
|
||||||
this._eventSource.requestRange(beginDate, iter, forceReload);
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(Calendar.prototype);
|
Signals.addSignalMethods(Calendar.prototype);
|
||||||
|
|
||||||
const EventsList = new Lang.Class({
|
function EventsList(eventSource) {
|
||||||
Name: 'EventsList',
|
this._init(eventSource);
|
||||||
|
}
|
||||||
|
|
||||||
_init: function() {
|
EventsList.prototype = {
|
||||||
|
_init: function(eventSource) {
|
||||||
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
|
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
|
||||||
this._date = new Date();
|
this._date = new Date();
|
||||||
|
this._eventSource = eventSource;
|
||||||
|
this._eventSource.connect('changed', Lang.bind(this, this._update));
|
||||||
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
||||||
this._desktopSettings.connect('changed', Lang.bind(this, this._update));
|
this._desktopSettings.connect('changed', Lang.bind(this, this._update));
|
||||||
this._weekStart = Shell.util_get_week_start();
|
let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
|
||||||
},
|
if (weekStartString.indexOf('calendar:week_start:') == 0) {
|
||||||
|
this._weekStart = parseInt(weekStartString.substring(20));
|
||||||
setEventSource: function(eventSource) {
|
|
||||||
if (this._eventSource) {
|
|
||||||
this._eventSource.disconnect(this._eventSourceChangedId);
|
|
||||||
this._eventSource = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._eventSource = eventSource;
|
if (isNaN(this._weekStart) ||
|
||||||
|
this._weekStart < 0 ||
|
||||||
if (this._eventSource) {
|
this._weekStart > 6) {
|
||||||
this._eventSourceChangedId = this._eventSource.connect('changed', Lang.bind(this, this._update));
|
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
|
||||||
|
this._weekStart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._update();
|
||||||
},
|
},
|
||||||
|
|
||||||
_addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) {
|
_addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) {
|
||||||
@ -665,9 +667,6 @@ const EventsList = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
|
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
|
||||||
if (!this._eventSource)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let events = this._eventSource.getEvents(begin, end);
|
let events = this._eventSource.getEvents(begin, end);
|
||||||
|
|
||||||
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
|
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
|
||||||
@ -706,7 +705,7 @@ const EventsList = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_showOtherDay: function(day) {
|
_showOtherDay: function(day) {
|
||||||
this.actor.destroy_all_children();
|
this.actor.destroy_children();
|
||||||
|
|
||||||
let dayBegin = _getBeginningOfDay(day);
|
let dayBegin = _getBeginningOfDay(day);
|
||||||
let dayEnd = _getEndOfDay(day);
|
let dayEnd = _getEndOfDay(day);
|
||||||
@ -723,7 +722,7 @@ const EventsList = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_showToday: function() {
|
_showToday: function() {
|
||||||
this.actor.destroy_all_children();
|
this.actor.destroy_children();
|
||||||
|
|
||||||
let now = new Date();
|
let now = new Date();
|
||||||
let dayBegin = _getBeginningOfDay(now);
|
let dayBegin = _getBeginningOfDay(now);
|
||||||
@ -734,15 +733,13 @@ const EventsList = new Lang.Class({
|
|||||||
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
|
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
|
||||||
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
|
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
|
||||||
|
|
||||||
let dayInWeek = (dayEnd.getDay() - this._weekStart + 7) % 7;
|
if (dayEnd.getDay() <= 4 + this._weekStart) {
|
||||||
|
|
||||||
if (dayInWeek < 5) {
|
|
||||||
/* If now is within the first 5 days we show "This week" and
|
/* If now is within the first 5 days we show "This week" and
|
||||||
* include events up until and including Saturday/Sunday
|
* include events up until and including Saturday/Sunday
|
||||||
* (depending on whether a week starts on Sunday/Monday).
|
* (depending on whether a week starts on Sunday/Monday).
|
||||||
*/
|
*/
|
||||||
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
||||||
let thisWeekEnd = new Date(dayEnd.getTime() + (6 - dayInWeek) * 86400 * 1000);
|
let thisWeekEnd = new Date(dayEnd.getTime() + (6 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
|
||||||
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
|
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
|
||||||
} else {
|
} else {
|
||||||
/* otherwise it's one of the two last days of the week ... show
|
/* otherwise it's one of the two last days of the week ... show
|
||||||
@ -750,7 +747,7 @@ const EventsList = new Lang.Class({
|
|||||||
* Saturday/Sunday
|
* Saturday/Sunday
|
||||||
*/
|
*/
|
||||||
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
||||||
let nextWeekEnd = new Date(dayEnd.getTime() + (13 - dayInWeek) * 86400 * 1000);
|
let nextWeekEnd = new Date(dayEnd.getTime() + (13 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
|
||||||
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
|
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -771,4 +768,4 @@ const EventsList = new Lang.Class({
|
|||||||
this._showOtherDay(this._date);
|
this._showOtherDay(this._date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const CheckBoxContainer = new Lang.Class({
|
|
||||||
Name: 'CheckBoxContainer',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.actor = new Shell.GenericContainer();
|
|
||||||
this.actor.connect('get-preferred-width',
|
|
||||||
Lang.bind(this, this._getPreferredWidth));
|
|
||||||
this.actor.connect('get-preferred-height',
|
|
||||||
Lang.bind(this, this._getPreferredHeight));
|
|
||||||
this.actor.connect('allocate',
|
|
||||||
Lang.bind(this, this._allocate));
|
|
||||||
this.actor.connect('style-changed', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
let node = this.actor.get_theme_node();
|
|
||||||
this._spacing = node.get_length('spacing');
|
|
||||||
}));
|
|
||||||
this.actor.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
|
|
||||||
|
|
||||||
this._box = new St.Bin();
|
|
||||||
this.actor.add_actor(this._box);
|
|
||||||
|
|
||||||
this.label = new St.Label();
|
|
||||||
this.label.clutter_text.set_line_wrap(true);
|
|
||||||
this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
|
|
||||||
this.actor.add_actor(this.label);
|
|
||||||
|
|
||||||
this._spacing = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
|
||||||
let [minWidth, natWidth] = this._box.get_preferred_width(forHeight);
|
|
||||||
|
|
||||||
alloc.min_size = minWidth + this._spacing;
|
|
||||||
alloc.natural_size = natWidth + this._spacing;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
|
||||||
/* FIXME: StBoxlayout currently does not handle
|
|
||||||
height-for-width children correctly, so hard-code
|
|
||||||
two lines for the label until that problem is fixed.
|
|
||||||
|
|
||||||
https://bugzilla.gnome.org/show_bug.cgi?id=672543 */
|
|
||||||
/*
|
|
||||||
let [minBoxHeight, natBoxHeight] =
|
|
||||||
this._box.get_preferred_height(forWidth);
|
|
||||||
let [minLabelHeight, natLabelHeight] =
|
|
||||||
this.label.get_preferred_height(forWidth);
|
|
||||||
|
|
||||||
alloc.min_size = Math.max(minBoxHeight, minLabelHeight);
|
|
||||||
alloc.natural_size = Math.max(natBoxHeight, natLabelHeight);
|
|
||||||
*/
|
|
||||||
let [minBoxHeight, natBoxHeight] =
|
|
||||||
this._box.get_preferred_height(-1);
|
|
||||||
let [minLabelHeight, natLabelHeight] =
|
|
||||||
this.label.get_preferred_height(-1);
|
|
||||||
|
|
||||||
alloc.min_size = Math.max(minBoxHeight, 2 * minLabelHeight);
|
|
||||||
alloc.natural_size = Math.max(natBoxHeight, 2 * natLabelHeight);
|
|
||||||
},
|
|
||||||
|
|
||||||
_allocate: function(actor, box, flags) {
|
|
||||||
let availWidth = box.x2 - box.x1;
|
|
||||||
let availHeight = box.y2 - box.y1;
|
|
||||||
|
|
||||||
let childBox = new Clutter.ActorBox();
|
|
||||||
let [minBoxWidth, natBoxWidth] =
|
|
||||||
this._box.get_preferred_width(-1);
|
|
||||||
let [minBoxHeight, natBoxHeight] =
|
|
||||||
this._box.get_preferred_height(-1);
|
|
||||||
childBox.x1 = box.x1;
|
|
||||||
childBox.x2 = box.x1 + natBoxWidth;
|
|
||||||
childBox.y1 = box.y1;
|
|
||||||
childBox.y2 = box.y1 + natBoxHeight;
|
|
||||||
this._box.allocate(childBox, flags);
|
|
||||||
|
|
||||||
childBox.x1 = box.x1 + natBoxWidth + this._spacing;
|
|
||||||
childBox.x2 = availWidth - childBox.x1;
|
|
||||||
childBox.y1 = box.y1;
|
|
||||||
childBox.y2 = box.y2;
|
|
||||||
this.label.allocate(childBox, flags);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const CheckBox = new Lang.Class({
|
|
||||||
Name: 'CheckBox',
|
|
||||||
|
|
||||||
_init: function(label) {
|
|
||||||
this.actor = new St.Button({ style_class: 'check-box',
|
|
||||||
button_mask: St.ButtonMask.ONE,
|
|
||||||
toggle_mode: true,
|
|
||||||
can_focus: true,
|
|
||||||
x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
this._container = new CheckBoxContainer();
|
|
||||||
this.actor.set_child(this._container.actor);
|
|
||||||
|
|
||||||
if (label)
|
|
||||||
this.setLabel(label);
|
|
||||||
},
|
|
||||||
|
|
||||||
setLabel: function(label) {
|
|
||||||
this._container.label.set_text(label);
|
|
||||||
},
|
|
||||||
|
|
||||||
getLabelActor: function() {
|
|
||||||
return this._container.label;
|
|
||||||
}
|
|
||||||
});
|
|
445
js/ui/chrome.js
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const Meta = imports.gi.Meta;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Params = imports.misc.params;
|
||||||
|
const ScreenSaver = imports.misc.screenSaver;
|
||||||
|
|
||||||
|
// This manages the shell "chrome"; the UI that's visible in the
|
||||||
|
// normal mode (ie, outside the Overview), that surrounds the main
|
||||||
|
// workspace content.
|
||||||
|
|
||||||
|
const defaultParams = {
|
||||||
|
visibleInFullscreen: false,
|
||||||
|
affectsStruts: true,
|
||||||
|
affectsInputRegion: true
|
||||||
|
};
|
||||||
|
|
||||||
|
function Chrome() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Chrome.prototype = {
|
||||||
|
_init: function() {
|
||||||
|
// The group itself has zero size so it doesn't interfere with DND
|
||||||
|
this.actor = new Shell.GenericContainer({ width: 0, height: 0 });
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
this.actor.connect('allocate', Lang.bind(this, this._allocated));
|
||||||
|
|
||||||
|
this._monitors = [];
|
||||||
|
this._inOverview = false;
|
||||||
|
|
||||||
|
this._trackedActors = [];
|
||||||
|
|
||||||
|
Main.connect('initialized', Lang.bind(this, this._finishInit));
|
||||||
|
},
|
||||||
|
|
||||||
|
_finishInit: function() {
|
||||||
|
Main.layoutManager.connect('monitors-changed',
|
||||||
|
Lang.bind(this, this._relayout));
|
||||||
|
global.screen.connect('restacked',
|
||||||
|
Lang.bind(this, this._windowsRestacked));
|
||||||
|
|
||||||
|
// Need to update struts on new workspaces when they are added
|
||||||
|
global.screen.connect('notify::n-workspaces',
|
||||||
|
Lang.bind(this, this._queueUpdateRegions));
|
||||||
|
|
||||||
|
Main.overview.connect('showing',
|
||||||
|
Lang.bind(this, this._overviewShowing));
|
||||||
|
Main.overview.connect('hidden',
|
||||||
|
Lang.bind(this, this._overviewHidden));
|
||||||
|
|
||||||
|
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
|
||||||
|
this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
|
||||||
|
this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
|
||||||
|
function(result, err) {
|
||||||
|
if (!err)
|
||||||
|
this._onScreenSaverActiveChanged(this._screenSaverProxy, result);
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._relayout();
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocated: function(actor, box, flags) {
|
||||||
|
let children = this.actor.get_children();
|
||||||
|
for (let i = 0; i < children.length; i++)
|
||||||
|
children[i].allocate_preferred_size(flags);
|
||||||
|
},
|
||||||
|
|
||||||
|
// addActor:
|
||||||
|
// @actor: an actor to add to the chrome layer
|
||||||
|
// @params: (optional) additional params
|
||||||
|
//
|
||||||
|
// Adds @actor to the chrome layer and extends the input region
|
||||||
|
// and window manager struts to include it. (Window manager struts
|
||||||
|
// will only be affected if @actor is touching a screen edge.)
|
||||||
|
// Changes in @actor's size and position will automatically result
|
||||||
|
// in appropriate changes to the input region and struts. Changes
|
||||||
|
// in its visibility will affect the input region, but NOT the
|
||||||
|
// struts.
|
||||||
|
//
|
||||||
|
// If %visibleInFullscreen is %true, the actor will be visible
|
||||||
|
// even when a fullscreen window should be covering it.
|
||||||
|
//
|
||||||
|
// If %affectsStruts or %affectsInputRegion is %false, the actor
|
||||||
|
// will not have the indicated effect.
|
||||||
|
addActor: function(actor, params) {
|
||||||
|
this.actor.add_actor(actor);
|
||||||
|
this._trackActor(actor, params);
|
||||||
|
},
|
||||||
|
|
||||||
|
// trackActor:
|
||||||
|
// @actor: a descendant of the chrome to begin tracking
|
||||||
|
// @params: parameters describing how to track @actor
|
||||||
|
//
|
||||||
|
// Tells the chrome to track @actor, which must be a descendant
|
||||||
|
// of an actor added via addActor(). This can be used to extend the
|
||||||
|
// struts or input region to cover specific children.
|
||||||
|
//
|
||||||
|
// @params can have any of the same values as in addActor(), though
|
||||||
|
// some possibilities don't make sense (eg, trying to have a
|
||||||
|
// %visibleInFullscreen child of a non-%visibleInFullscreen parent).
|
||||||
|
// By default, @actor has the same params as its chrome ancestor.
|
||||||
|
trackActor: function(actor, params) {
|
||||||
|
let ancestor = actor.get_parent();
|
||||||
|
let index = this._findActor(ancestor);
|
||||||
|
while (ancestor && index == -1) {
|
||||||
|
ancestor = ancestor.get_parent();
|
||||||
|
index = this._findActor(ancestor);
|
||||||
|
}
|
||||||
|
if (!ancestor)
|
||||||
|
throw new Error('actor is not a descendent of the chrome layer');
|
||||||
|
|
||||||
|
let ancestorData = this._trackedActors[index];
|
||||||
|
if (!params)
|
||||||
|
params = {};
|
||||||
|
// We can't use Params.parse here because we want to drop
|
||||||
|
// the extra values like ancestorData.actor
|
||||||
|
for (let prop in defaultParams) {
|
||||||
|
if (!params[prop])
|
||||||
|
params[prop] = ancestorData[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._trackActor(actor, params);
|
||||||
|
},
|
||||||
|
|
||||||
|
// untrackActor:
|
||||||
|
// @actor: an actor previously tracked via trackActor()
|
||||||
|
//
|
||||||
|
// Undoes the effect of trackActor()
|
||||||
|
untrackActor: function(actor) {
|
||||||
|
this._untrackActor(actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
// removeActor:
|
||||||
|
// @actor: a child of the chrome layer
|
||||||
|
//
|
||||||
|
// Removes @actor from the chrome layer
|
||||||
|
removeActor: function(actor) {
|
||||||
|
this.actor.remove_actor(actor);
|
||||||
|
this._untrackActor(actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_findActor: function(actor) {
|
||||||
|
for (let i = 0; i < this._trackedActors.length; i++) {
|
||||||
|
let actorData = this._trackedActors[i];
|
||||||
|
if (actorData.actor == actor)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
_trackActor: function(actor, params) {
|
||||||
|
if (this._findActor(actor) != -1)
|
||||||
|
throw new Error('trying to re-track existing chrome actor');
|
||||||
|
|
||||||
|
let actorData = Params.parse(params, defaultParams);
|
||||||
|
actorData.actor = actor;
|
||||||
|
actorData.visibleId = actor.connect('notify::visible',
|
||||||
|
Lang.bind(this, this._queueUpdateRegions));
|
||||||
|
actorData.allocationId = actor.connect('notify::allocation',
|
||||||
|
Lang.bind(this, this._queueUpdateRegions));
|
||||||
|
actorData.parentSetId = actor.connect('parent-set',
|
||||||
|
Lang.bind(this, this._actorReparented));
|
||||||
|
// Note that destroying actor will unset its parent, so we don't
|
||||||
|
// need to connect to 'destroy' too.
|
||||||
|
|
||||||
|
this._trackedActors.push(actorData);
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_untrackActor: function(actor) {
|
||||||
|
let i = this._findActor(actor);
|
||||||
|
|
||||||
|
if (i == -1)
|
||||||
|
return;
|
||||||
|
let actorData = this._trackedActors[i];
|
||||||
|
|
||||||
|
this._trackedActors.splice(i, 1);
|
||||||
|
actor.disconnect(actorData.visibleId);
|
||||||
|
actor.disconnect(actorData.allocationId);
|
||||||
|
actor.disconnect(actorData.parentSetId);
|
||||||
|
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_actorReparented: function(actor, oldParent) {
|
||||||
|
if (!this.actor.contains(actor))
|
||||||
|
this._untrackActor(actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateVisibility: function() {
|
||||||
|
for (let i = 0; i < this._trackedActors.length; i++) {
|
||||||
|
let actorData = this._trackedActors[i];
|
||||||
|
if (!this._inOverview && !actorData.visibleInFullscreen &&
|
||||||
|
this._findMonitorForActor(actorData.actor).inFullscreen)
|
||||||
|
this.actor.set_skip_paint(actorData.actor, true);
|
||||||
|
else
|
||||||
|
this.actor.set_skip_paint(actorData.actor, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_overviewShowing: function() {
|
||||||
|
this._inOverview = true;
|
||||||
|
this._updateVisibility();
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_overviewHidden: function() {
|
||||||
|
this._inOverview = false;
|
||||||
|
this._updateVisibility();
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_relayout: function() {
|
||||||
|
this._monitors = Main.layoutManager.monitors;
|
||||||
|
this._primaryMonitor = Main.layoutManager.primaryMonitor;
|
||||||
|
|
||||||
|
this._updateFullscreen();
|
||||||
|
this._updateVisibility();
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onScreenSaverActiveChanged: function(proxy, screenSaverActive) {
|
||||||
|
this.actor.visible = !screenSaverActive;
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMonitorForRect: function(x, y, w, h) {
|
||||||
|
// First look at what monitor the center of the rectangle is at
|
||||||
|
let cx = x + w/2;
|
||||||
|
let cy = y + h/2;
|
||||||
|
for (let i = 0; i < this._monitors.length; i++) {
|
||||||
|
let monitor = this._monitors[i];
|
||||||
|
if (cx >= monitor.x && cx < monitor.x + monitor.width &&
|
||||||
|
cy >= monitor.y && cy < monitor.y + monitor.height)
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
// If the center is not on a monitor, return the first overlapping monitor
|
||||||
|
for (let i = 0; i < this._monitors.length; i++) {
|
||||||
|
let monitor = this._monitors[i];
|
||||||
|
if (x + w > monitor.x && x < monitor.x + monitor.width &&
|
||||||
|
y + h > monitor.y && y < monitor.y + monitor.height)
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
// otherwise on no monitor
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_findMonitorForWindow: function(window) {
|
||||||
|
return this._findMonitorForRect(window.x, window.y, window.width, window.height);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This call guarantees that we return some monitor to simplify usage of it
|
||||||
|
// In practice all tracked actors should be visible on some monitor anyway
|
||||||
|
_findMonitorForActor: function(actor) {
|
||||||
|
let [x, y] = actor.get_transformed_position();
|
||||||
|
let [w, h] = actor.get_transformed_size();
|
||||||
|
let monitor = this._findMonitorForRect(x, y, w, h);
|
||||||
|
if (monitor)
|
||||||
|
return monitor;
|
||||||
|
return this._primaryMonitor; // Not on any monitor, pretend its on the primary
|
||||||
|
},
|
||||||
|
|
||||||
|
_queueUpdateRegions: function() {
|
||||||
|
if (!this._updateRegionIdle)
|
||||||
|
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
|
||||||
|
Meta.PRIORITY_BEFORE_REDRAW);
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateFullscreen: function() {
|
||||||
|
let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
|
||||||
|
|
||||||
|
// Reset all monitors to not fullscreen
|
||||||
|
for (let i = 0; i < this._monitors.length; i++)
|
||||||
|
this._monitors[i].inFullscreen = false;
|
||||||
|
|
||||||
|
// The chrome layer should be visible unless there is a window
|
||||||
|
// with layer FULLSCREEN, or a window with layer
|
||||||
|
// OVERRIDE_REDIRECT that covers the whole screen.
|
||||||
|
// ('override_redirect' is not actually a layer above all
|
||||||
|
// other windows, but this seems to be how mutter treats it
|
||||||
|
// currently...) If we wanted to be extra clever, we could
|
||||||
|
// figure out when an OVERRIDE_REDIRECT window was trying to
|
||||||
|
// partially overlap us, and then adjust the input region and
|
||||||
|
// our clip region accordingly...
|
||||||
|
|
||||||
|
// @windows is sorted bottom to top.
|
||||||
|
|
||||||
|
for (let i = windows.length - 1; i > -1; i--) {
|
||||||
|
let window = windows[i];
|
||||||
|
let layer = window.get_meta_window().get_layer();
|
||||||
|
|
||||||
|
if (layer == Meta.StackLayer.FULLSCREEN) {
|
||||||
|
let monitor = this._findMonitorForWindow(window);
|
||||||
|
if (monitor)
|
||||||
|
monitor.inFullscreen = true;
|
||||||
|
}
|
||||||
|
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
|
||||||
|
let monitor = this._findMonitorForWindow(window);
|
||||||
|
if (monitor &&
|
||||||
|
window.x <= monitor.x &&
|
||||||
|
window.x + window.width >= monitor.x + monitor.width &&
|
||||||
|
window.y <= monitor.y &&
|
||||||
|
window.y + window.height >= monitor.y + monitor.height)
|
||||||
|
monitor.inFullscreen = true;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_windowsRestacked: function() {
|
||||||
|
let wasInFullscreen = [];
|
||||||
|
for (let i = 0; i < this._monitors.length; i++)
|
||||||
|
wasInFullscreen[i] = this._monitors[i].inFullscreen;
|
||||||
|
|
||||||
|
this._updateFullscreen();
|
||||||
|
|
||||||
|
let changed = false;
|
||||||
|
for (let i = 0; i < wasInFullscreen.length; i++) {
|
||||||
|
if (wasInFullscreen[i] != this._monitors[i].inFullscreen) {
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
this._updateVisibility();
|
||||||
|
this._queueUpdateRegions();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateRegions: function() {
|
||||||
|
let rects = [], struts = [], i;
|
||||||
|
|
||||||
|
delete this._updateRegionIdle;
|
||||||
|
|
||||||
|
for (i = 0; i < this._trackedActors.length; i++) {
|
||||||
|
let actorData = this._trackedActors[i];
|
||||||
|
if (!actorData.affectsInputRegion && !actorData.affectsStruts)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let [x, y] = actorData.actor.get_transformed_position();
|
||||||
|
let [w, h] = actorData.actor.get_transformed_size();
|
||||||
|
x = Math.round(x);
|
||||||
|
y = Math.round(y);
|
||||||
|
w = Math.round(w);
|
||||||
|
h = Math.round(h);
|
||||||
|
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
|
||||||
|
|
||||||
|
if (actorData.affectsInputRegion &&
|
||||||
|
actorData.actor.get_paint_visibility() &&
|
||||||
|
!this.actor.get_skip_paint(actorData.actor))
|
||||||
|
rects.push(rect);
|
||||||
|
|
||||||
|
if (!actorData.affectsStruts)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Limit struts to the size of the screen
|
||||||
|
let x1 = Math.max(x, 0);
|
||||||
|
let x2 = Math.min(x + w, global.screen_width);
|
||||||
|
let y1 = Math.max(y, 0);
|
||||||
|
let y2 = Math.min(y + h, global.screen_height);
|
||||||
|
|
||||||
|
// NetWM struts are not really powerful enought to handle
|
||||||
|
// a multi-monitor scenario, they only describe what happens
|
||||||
|
// around the outer sides of the full display region. However
|
||||||
|
// it can describe a partial region along each side, so
|
||||||
|
// we can support having the struts only affect the
|
||||||
|
// primary monitor. This should be enough as we only have
|
||||||
|
// chrome affecting the struts on the primary monitor so
|
||||||
|
// far.
|
||||||
|
//
|
||||||
|
// Metacity wants to know what side of the screen the
|
||||||
|
// strut is considered to be attached to. If the actor is
|
||||||
|
// only touching one edge, or is touching the entire
|
||||||
|
// border of the primary monitor, then it's obvious which
|
||||||
|
// side to call it. If it's in a corner, we pick a side
|
||||||
|
// arbitrarily. If it doesn't touch any edges, or it spans
|
||||||
|
// the width/height across the middle of the screen, then
|
||||||
|
// we don't create a strut for it at all.
|
||||||
|
let side;
|
||||||
|
let primary = this._primaryMonitor;
|
||||||
|
if (x1 <= primary.x && x2 >= primary.x + primary.width) {
|
||||||
|
if (y1 <= primary.y)
|
||||||
|
side = Meta.Side.TOP;
|
||||||
|
else if (y2 >= primary.y + primary.height)
|
||||||
|
side = Meta.Side.BOTTOM;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
} else if (y1 <= primary.y && y2 >= primary.y + primary.height) {
|
||||||
|
if (x1 <= 0)
|
||||||
|
side = Meta.Side.LEFT;
|
||||||
|
else if (x2 >= global.screen_width)
|
||||||
|
side = Meta.Side.RIGHT;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
} else if (x1 <= 0)
|
||||||
|
side = Meta.Side.LEFT;
|
||||||
|
else if (y1 <= 0)
|
||||||
|
side = Meta.Side.TOP;
|
||||||
|
else if (x2 >= global.screen_width)
|
||||||
|
side = Meta.Side.RIGHT;
|
||||||
|
else if (y2 >= global.screen_height)
|
||||||
|
side = Meta.Side.BOTTOM;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ensure that the strut rects goes all the way to the screen edge,
|
||||||
|
// as this really what mutter expects.
|
||||||
|
switch (side) {
|
||||||
|
case Meta.Side.TOP:
|
||||||
|
y1 = 0;
|
||||||
|
break;
|
||||||
|
case Meta.Side.BOTTOM:
|
||||||
|
y2 = global.screen_height;
|
||||||
|
break;
|
||||||
|
case Meta.Side.LEFT:
|
||||||
|
x1 = 0;
|
||||||
|
break;
|
||||||
|
case Meta.Side.RIGHT:
|
||||||
|
x2 = global.screen_width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1});
|
||||||
|
let strut = new Meta.Strut({ rect: strutRect, side: side });
|
||||||
|
struts.push(strut);
|
||||||
|
}
|
||||||
|
|
||||||
|
global.set_stage_input_region(rects);
|
||||||
|
|
||||||
|
let screen = global.screen;
|
||||||
|
for (let w = 0; w < screen.n_workspaces; w++) {
|
||||||
|
let workspace = screen.get_workspace_by_index(w);
|
||||||
|
workspace.set_builtin_struts(struts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(Chrome.prototype);
|
@ -1,65 +0,0 @@
|
|||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const ComponentManager = new Lang.Class({
|
|
||||||
Name: 'ComponentManager',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._allComponents = {};
|
|
||||||
this._enabledComponents = [];
|
|
||||||
|
|
||||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
|
||||||
this._sessionUpdated();
|
|
||||||
},
|
|
||||||
|
|
||||||
_sessionUpdated: function() {
|
|
||||||
let newEnabledComponents = Main.sessionMode.components;
|
|
||||||
|
|
||||||
newEnabledComponents.filter(Lang.bind(this, function(name) {
|
|
||||||
return this._enabledComponents.indexOf(name) == -1;
|
|
||||||
})).forEach(Lang.bind(this, function(name) {
|
|
||||||
this._enableComponent(name);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._enabledComponents.filter(Lang.bind(this, function(name) {
|
|
||||||
return newEnabledComponents.indexOf(name) == -1;
|
|
||||||
})).forEach(Lang.bind(this, function(name) {
|
|
||||||
this._disableComponent(name);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._enabledComponents = newEnabledComponents;
|
|
||||||
},
|
|
||||||
|
|
||||||
_importComponent: function(name) {
|
|
||||||
let module = imports.ui.components[name];
|
|
||||||
return module.Component;
|
|
||||||
},
|
|
||||||
|
|
||||||
_ensureComponent: function(name) {
|
|
||||||
let component = this._allComponents[name];
|
|
||||||
if (component)
|
|
||||||
return component;
|
|
||||||
|
|
||||||
if (Main.sessionMode.isLocked)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
let constructor = this._importComponent(name);
|
|
||||||
component = new constructor();
|
|
||||||
this._allComponents[name] = component;
|
|
||||||
return component;
|
|
||||||
},
|
|
||||||
|
|
||||||
_enableComponent: function(name) {
|
|
||||||
let component = this._ensureComponent(name);
|
|
||||||
if (component)
|
|
||||||
component.enable();
|
|
||||||
},
|
|
||||||
|
|
||||||
_disableComponent: function(name) {
|
|
||||||
let component = this._allComponents[name];
|
|
||||||
if (component == null)
|
|
||||||
return;
|
|
||||||
component.disable();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,243 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
const GnomeSession = imports.misc.gnomeSession;
|
|
||||||
const LoginManager = imports.misc.loginManager;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const ShellMountOperation = imports.ui.shellMountOperation;
|
|
||||||
|
|
||||||
const GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
|
|
||||||
|
|
||||||
// GSettings keys
|
|
||||||
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
|
|
||||||
const SETTING_ENABLE_AUTOMOUNT = 'automount';
|
|
||||||
|
|
||||||
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
|
|
||||||
|
|
||||||
const AutomountManager = new Lang.Class({
|
|
||||||
Name: 'AutomountManager',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
|
||||||
this._volumeQueue = [];
|
|
||||||
this._session = new GnomeSession.SessionManager();
|
|
||||||
this._session.connectSignal('InhibitorAdded',
|
|
||||||
Lang.bind(this, this._InhibitorsChanged));
|
|
||||||
this._session.connectSignal('InhibitorRemoved',
|
|
||||||
Lang.bind(this, this._InhibitorsChanged));
|
|
||||||
this._inhibited = false;
|
|
||||||
|
|
||||||
LoginManager.getLoginManager(Lang.bind(this, function(manager) {
|
|
||||||
this._loginManager = manager;
|
|
||||||
}));
|
|
||||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
this._volumeAddedId = this._volumeMonitor.connect('volume-added', Lang.bind(this, this._onVolumeAdded));
|
|
||||||
this._volumeRemovedId = this._volumeMonitor.connect('volume-removed', Lang.bind(this, this._onVolumeRemoved));
|
|
||||||
this._driveConnectedId = this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._onDriveConnected));
|
|
||||||
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._onDriveDisconnected));
|
|
||||||
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton));
|
|
||||||
|
|
||||||
this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
this._volumeMonitor.disconnect(this._volumeAddedId);
|
|
||||||
this._volumeMonitor.disconnect(this._volumeRemovedId);
|
|
||||||
this._volumeMonitor.disconnect(this._driveConnectedId);
|
|
||||||
this._volumeMonitor.disconnect(this._driveDisconnectedId);
|
|
||||||
this._volumeMonitor.disconnect(this._driveEjectButtonId);
|
|
||||||
|
|
||||||
if (this._mountAllId > 0) {
|
|
||||||
Mainloop.source_remove(this._mountAllId);
|
|
||||||
this._mountAllId = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_InhibitorsChanged: function(object, senderName, [inhibtor]) {
|
|
||||||
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
|
|
||||||
Lang.bind(this,
|
|
||||||
function(result, error) {
|
|
||||||
if (!error) {
|
|
||||||
this._inhibited = result[0];
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_startupMountAll: function() {
|
|
||||||
let volumes = this._volumeMonitor.get_volumes();
|
|
||||||
volumes.forEach(Lang.bind(this, function(volume) {
|
|
||||||
this._checkAndMountVolume(volume, { checkSession: false,
|
|
||||||
useMountOp: false,
|
|
||||||
allowAutorun: false });
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._mountAllId = 0;
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onDriveConnected: function() {
|
|
||||||
// if we're not in the current ConsoleKit session,
|
|
||||||
// or screensaver is active, don't play sounds
|
|
||||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
global.play_theme_sound(0, 'device-added-media');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onDriveDisconnected: function() {
|
|
||||||
// if we're not in the current ConsoleKit session,
|
|
||||||
// or screensaver is active, don't play sounds
|
|
||||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
global.play_theme_sound(0, 'device-removed-media');
|
|
||||||
},
|
|
||||||
|
|
||||||
_onDriveEjectButton: function(monitor, drive) {
|
|
||||||
// TODO: this code path is not tested, as the GVfs volume monitor
|
|
||||||
// doesn't emit this signal just yet.
|
|
||||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// we force stop/eject in this case, so we don't have to pass a
|
|
||||||
// mount operation object
|
|
||||||
if (drive.can_stop()) {
|
|
||||||
drive.stop
|
|
||||||
(Gio.MountUnmountFlags.FORCE, null, null,
|
|
||||||
Lang.bind(this, function(drive, res) {
|
|
||||||
try {
|
|
||||||
drive.stop_finish(res);
|
|
||||||
} catch (e) {
|
|
||||||
log("Unable to stop the drive after drive-eject-button " + e.toString());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
} else if (drive.can_eject()) {
|
|
||||||
drive.eject_with_operation
|
|
||||||
(Gio.MountUnmountFlags.FORCE, null, null,
|
|
||||||
Lang.bind(this, function(drive, res) {
|
|
||||||
try {
|
|
||||||
drive.eject_with_operation_finish(res);
|
|
||||||
} catch (e) {
|
|
||||||
log("Unable to eject the drive after drive-eject-button " + e.toString());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onVolumeAdded: function(monitor, volume) {
|
|
||||||
this._checkAndMountVolume(volume);
|
|
||||||
},
|
|
||||||
|
|
||||||
_checkAndMountVolume: function(volume, params) {
|
|
||||||
params = Params.parse(params, { checkSession: true,
|
|
||||||
useMountOp: true,
|
|
||||||
allowAutorun: true });
|
|
||||||
|
|
||||||
if (params.checkSession) {
|
|
||||||
// if we're not in the current ConsoleKit session,
|
|
||||||
// don't attempt automount
|
|
||||||
if (!this._loginManager || !this._loginManager.sessionActive)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._inhibited)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Volume is already mounted, don't bother.
|
|
||||||
if (volume.get_mount())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!this._settings.get_boolean(SETTING_ENABLE_AUTOMOUNT) ||
|
|
||||||
!volume.should_automount() ||
|
|
||||||
!volume.can_mount()) {
|
|
||||||
// allow the autorun to run anyway; this can happen if the
|
|
||||||
// mount gets added programmatically later, even if
|
|
||||||
// should_automount() or can_mount() are false, like for
|
|
||||||
// blank optical media.
|
|
||||||
this._allowAutorun(volume);
|
|
||||||
this._allowAutorunExpire(volume);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.useMountOp) {
|
|
||||||
let operation = new ShellMountOperation.ShellMountOperation(volume);
|
|
||||||
this._mountVolume(volume, operation, params.allowAutorun);
|
|
||||||
} else {
|
|
||||||
this._mountVolume(volume, null, params.allowAutorun);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_mountVolume: function(volume, operation, allowAutorun) {
|
|
||||||
if (allowAutorun)
|
|
||||||
this._allowAutorun(volume);
|
|
||||||
|
|
||||||
let mountOp = operation ? operation.mountOp : null;
|
|
||||||
volume._operation = operation;
|
|
||||||
|
|
||||||
volume.mount(0, mountOp, null,
|
|
||||||
Lang.bind(this, this._onVolumeMounted));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onVolumeMounted: function(volume, res) {
|
|
||||||
this._allowAutorunExpire(volume);
|
|
||||||
|
|
||||||
try {
|
|
||||||
volume.mount_finish(res);
|
|
||||||
this._closeOperation(volume);
|
|
||||||
} catch (e) {
|
|
||||||
// FIXME: we will always get G_IO_ERROR_FAILED from the gvfs udisks
|
|
||||||
// backend in this case, see
|
|
||||||
// https://bugs.freedesktop.org/show_bug.cgi?id=51271
|
|
||||||
if (e.message.indexOf('No key available with this passphrase') != -1) {
|
|
||||||
this._reaskPassword(volume);
|
|
||||||
} else {
|
|
||||||
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
|
|
||||||
log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString());
|
|
||||||
|
|
||||||
this._closeOperation(volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onVolumeRemoved: function(monitor, volume) {
|
|
||||||
this._volumeQueue =
|
|
||||||
this._volumeQueue.filter(function(element) {
|
|
||||||
return (element != volume);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_reaskPassword: function(volume) {
|
|
||||||
let existingDialog = volume._operation ? volume._operation.borrowDialog() : null;
|
|
||||||
let operation =
|
|
||||||
new ShellMountOperation.ShellMountOperation(volume,
|
|
||||||
{ existingDialog: existingDialog });
|
|
||||||
this._mountVolume(volume, operation);
|
|
||||||
},
|
|
||||||
|
|
||||||
_closeOperation: function(volume) {
|
|
||||||
if (volume._operation)
|
|
||||||
volume._operation.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
_allowAutorun: function(volume) {
|
|
||||||
volume.allowAutorun = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_allowAutorunExpire: function(volume) {
|
|
||||||
Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
|
|
||||||
volume.allowAutorun = false;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const Component = AutomountManager;
|
|
@ -1,227 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Gcr = imports.gi.Gcr;
|
|
||||||
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
const ShellEntry = imports.ui.shellEntry;
|
|
||||||
const CheckBox = imports.ui.checkBox;
|
|
||||||
|
|
||||||
let prompter = null;
|
|
||||||
|
|
||||||
const KeyringDialog = new Lang.Class({
|
|
||||||
Name: 'KeyringDialog',
|
|
||||||
Extends: ModalDialog.ModalDialog,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ styleClass: 'prompt-dialog' });
|
|
||||||
|
|
||||||
this.prompt = new Shell.KeyringPrompt();
|
|
||||||
this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
|
|
||||||
this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
|
|
||||||
this.prompt.connect('hide-prompt', Lang.bind(this, this._onHidePrompt));
|
|
||||||
|
|
||||||
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
|
|
||||||
vertical: false });
|
|
||||||
this.contentLayout.add(mainContentBox);
|
|
||||||
|
|
||||||
let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
|
|
||||||
mainContentBox.add(icon,
|
|
||||||
{ x_fill: true,
|
|
||||||
y_fill: false,
|
|
||||||
x_align: St.Align.END,
|
|
||||||
y_align: St.Align.START });
|
|
||||||
|
|
||||||
this._messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
|
|
||||||
vertical: true });
|
|
||||||
mainContentBox.add(this._messageBox,
|
|
||||||
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
|
|
||||||
|
|
||||||
let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
|
|
||||||
this.prompt.bind_property('message', subject, 'text', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
|
|
||||||
this._messageBox.add(subject,
|
|
||||||
{ y_fill: false,
|
|
||||||
y_align: St.Align.START });
|
|
||||||
|
|
||||||
let description = new St.Label({ style_class: 'prompt-dialog-description' });
|
|
||||||
description.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
||||||
description.clutter_text.line_wrap = true;
|
|
||||||
this.prompt.bind_property('description', description, 'text', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
this._messageBox.add(description,
|
|
||||||
{ y_fill: true,
|
|
||||||
y_align: St.Align.START });
|
|
||||||
|
|
||||||
this._controlTable = null;
|
|
||||||
|
|
||||||
let buttons = [{ label: '',
|
|
||||||
action: Lang.bind(this, this._onCancelButton),
|
|
||||||
key: Clutter.Escape
|
|
||||||
},
|
|
||||||
{ label: '',
|
|
||||||
action: Lang.bind(this, this._onContinueButton),
|
|
||||||
default: true
|
|
||||||
}]
|
|
||||||
|
|
||||||
this.setButtons(buttons);
|
|
||||||
this._cancelButton = buttons[0].button;
|
|
||||||
this._continueButton = buttons[1].button;
|
|
||||||
|
|
||||||
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildControlTable: function() {
|
|
||||||
let table = new St.Table({ style_class: 'keyring-dialog-control-table' });
|
|
||||||
let row = 0;
|
|
||||||
|
|
||||||
if (this.prompt.password_visible) {
|
|
||||||
let label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
|
|
||||||
label.set_text(_("Password:"));
|
|
||||||
table.add(label, { row: row, col: 0,
|
|
||||||
x_expand: false, x_fill: true,
|
|
||||||
x_align: St.Align.START,
|
|
||||||
y_fill: false, y_align: St.Align.MIDDLE });
|
|
||||||
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
|
||||||
text: '',
|
|
||||||
can_focus: true});
|
|
||||||
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
|
||||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
|
||||||
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
|
|
||||||
table.add(this._passwordEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
|
|
||||||
row++;
|
|
||||||
} else {
|
|
||||||
this._passwordEntry = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.prompt.confirm_visible) {
|
|
||||||
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
|
|
||||||
label.set_text(_("Type again:"));
|
|
||||||
table.add(label, { row: row, col: 0,
|
|
||||||
x_expand: false, x_fill: true,
|
|
||||||
x_align: St.Align.START,
|
|
||||||
y_fill: false, y_align: St.Align.MIDDLE });
|
|
||||||
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
|
||||||
text: '',
|
|
||||||
can_focus: true});
|
|
||||||
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
|
||||||
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
|
|
||||||
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
|
|
||||||
table.add(this._confirmEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
|
|
||||||
row++;
|
|
||||||
} else {
|
|
||||||
this._confirmEntry = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.prompt.set_password_actor(this._passwordEntry ? this._passwordEntry.clutter_text : null);
|
|
||||||
this.prompt.set_confirm_actor(this._confirmEntry ? this._confirmEntry.clutter_text : null);
|
|
||||||
|
|
||||||
if (this.prompt.choice_visible) {
|
|
||||||
let choice = new CheckBox.CheckBox();
|
|
||||||
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
|
|
||||||
table.add(choice.actor, { row: row, col: 1, x_expand: false, x_fill: true, x_align: St.Align.START });
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
|
|
||||||
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
|
||||||
warning.clutter_text.line_wrap = true;
|
|
||||||
table.add(warning, { row: row, col: 1, x_expand: false, x_fill: false, x_align: St.Align.START });
|
|
||||||
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
|
|
||||||
if (this._controlTable) {
|
|
||||||
this._controlTable.destroy_all_children();
|
|
||||||
this._controlTable.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._controlTable = table;
|
|
||||||
this._messageBox.add(table, { x_fill: true, y_fill: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
_ensureOpen: function() {
|
|
||||||
// NOTE: ModalDialog.open() is safe to call if the dialog is
|
|
||||||
// already open - it just returns true without side-effects
|
|
||||||
if (this.open())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// The above fail if e.g. unable to get input grab
|
|
||||||
//
|
|
||||||
// In an ideal world this wouldn't happen (because the
|
|
||||||
// Shell is in complete control of the session) but that's
|
|
||||||
// just not how things work right now.
|
|
||||||
|
|
||||||
log('keyringPrompt: Failed to show modal dialog.' +
|
|
||||||
' Dismissing prompt request');
|
|
||||||
this.prompt.cancel()
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onShowPassword: function(prompt) {
|
|
||||||
this._buildControlTable();
|
|
||||||
this._ensureOpen();
|
|
||||||
this._passwordEntry.grab_key_focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onShowConfirm: function(prompt) {
|
|
||||||
this._buildControlTable();
|
|
||||||
this._ensureOpen();
|
|
||||||
this._continueButton.grab_key_focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onHidePrompt: function(prompt) {
|
|
||||||
this.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onPasswordActivate: function() {
|
|
||||||
if (this.prompt.confirm_visible)
|
|
||||||
this._confirmEntry.grab_key_focus();
|
|
||||||
else
|
|
||||||
this._onContinueButton();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onConfirmActivate: function() {
|
|
||||||
this._onContinueButton();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onContinueButton: function() {
|
|
||||||
this.prompt.complete();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCancelButton: function() {
|
|
||||||
this.prompt.cancel();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const KeyringPrompter = new Lang.Class({
|
|
||||||
Name: 'KeyringPrompter',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._prompter = new Gcr.SystemPrompter();
|
|
||||||
this._prompter.connect('new-prompt', function(prompter) {
|
|
||||||
let dialog = new KeyringDialog();
|
|
||||||
return dialog.prompt;
|
|
||||||
});
|
|
||||||
this._dbusId = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
this._prompter.register(Gio.DBus.session);
|
|
||||||
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
|
|
||||||
Gio.BusNameOwnerFlags.REPLACE, null, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
this._prompter.unregister(false);
|
|
||||||
Gio.DBus.session.unown_name(this._dbusId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Component = KeyringPrompter;
|
|
@ -1,707 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const GObject = imports.gi.GObject;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const NetworkManager = imports.gi.NetworkManager;
|
|
||||||
const NMClient = imports.gi.NMClient;
|
|
||||||
const Pango = imports.gi.Pango;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Config = imports.misc.config;
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
|
||||||
const ShellEntry = imports.ui.shellEntry;
|
|
||||||
|
|
||||||
const VPN_UI_GROUP = 'VPN Plugin UI';
|
|
||||||
|
|
||||||
const NetworkSecretDialog = new Lang.Class({
|
|
||||||
Name: 'NetworkSecretDialog',
|
|
||||||
Extends: ModalDialog.ModalDialog,
|
|
||||||
|
|
||||||
_init: function(agent, requestId, connection, settingName, hints, contentOverride) {
|
|
||||||
this.parent({ styleClass: 'prompt-dialog' });
|
|
||||||
|
|
||||||
this._agent = agent;
|
|
||||||
this._requestId = requestId;
|
|
||||||
this._connection = connection;
|
|
||||||
this._settingName = settingName;
|
|
||||||
this._hints = hints;
|
|
||||||
|
|
||||||
if (contentOverride)
|
|
||||||
this._content = contentOverride;
|
|
||||||
else
|
|
||||||
this._content = this._getContent();
|
|
||||||
|
|
||||||
let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
|
|
||||||
vertical: false });
|
|
||||||
this.contentLayout.add(mainContentBox,
|
|
||||||
{ x_fill: true,
|
|
||||||
y_fill: true });
|
|
||||||
|
|
||||||
let icon = new St.Icon({ icon_name: 'dialog-password-symbolic' });
|
|
||||||
mainContentBox.add(icon,
|
|
||||||
{ x_fill: true,
|
|
||||||
y_fill: false,
|
|
||||||
x_align: St.Align.END,
|
|
||||||
y_align: St.Align.START });
|
|
||||||
|
|
||||||
let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
|
|
||||||
vertical: true });
|
|
||||||
mainContentBox.add(messageBox,
|
|
||||||
{ y_align: St.Align.START });
|
|
||||||
|
|
||||||
let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
|
|
||||||
text: this._content.title });
|
|
||||||
messageBox.add(subjectLabel,
|
|
||||||
{ y_fill: false,
|
|
||||||
y_align: St.Align.START });
|
|
||||||
|
|
||||||
if (this._content.message != null) {
|
|
||||||
let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
|
|
||||||
text: this._content.message,
|
|
||||||
// HACK: for reasons unknown to me, the label
|
|
||||||
// is not asked the correct height for width,
|
|
||||||
// and thus is underallocated
|
|
||||||
// place a fixed height to avoid overflowing
|
|
||||||
style: 'height: 3em'
|
|
||||||
});
|
|
||||||
descriptionLabel.clutter_text.line_wrap = true;
|
|
||||||
|
|
||||||
messageBox.add(descriptionLabel,
|
|
||||||
{ y_fill: true,
|
|
||||||
y_align: St.Align.START,
|
|
||||||
expand: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
|
|
||||||
let initialFocusSet = false;
|
|
||||||
let pos = 0;
|
|
||||||
for (let i = 0; i < this._content.secrets.length; i++) {
|
|
||||||
let secret = this._content.secrets[i];
|
|
||||||
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
|
|
||||||
text: secret.label });
|
|
||||||
|
|
||||||
let reactive = secret.key != null;
|
|
||||||
|
|
||||||
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
|
|
||||||
text: secret.value, can_focus: reactive,
|
|
||||||
reactive: reactive });
|
|
||||||
ShellEntry.addContextMenu(secret.entry,
|
|
||||||
{ isPassword: secret.password });
|
|
||||||
|
|
||||||
if (secret.validate)
|
|
||||||
secret.valid = secret.validate(secret);
|
|
||||||
else // no special validation, just ensure it's not empty
|
|
||||||
secret.valid = secret.value.length > 0;
|
|
||||||
|
|
||||||
if (reactive) {
|
|
||||||
if (!initialFocusSet) {
|
|
||||||
this.setInitialKeyFocus(secret.entry);
|
|
||||||
initialFocusSet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
secret.entry.clutter_text.connect('activate', Lang.bind(this, this._onOk));
|
|
||||||
secret.entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
|
|
||||||
secret.value = secret.entry.get_text();
|
|
||||||
if (secret.validate)
|
|
||||||
secret.valid = secret.validate(secret);
|
|
||||||
else
|
|
||||||
secret.valid = secret.value.length > 0;
|
|
||||||
this._updateOkButton();
|
|
||||||
}));
|
|
||||||
} else
|
|
||||||
secret.valid = true;
|
|
||||||
|
|
||||||
secretTable.add(label, { row: pos, col: 0,
|
|
||||||
x_expand: false, x_fill: true,
|
|
||||||
x_align: St.Align.START,
|
|
||||||
y_fill: false, y_align: St.Align.MIDDLE });
|
|
||||||
secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
if (secret.password)
|
|
||||||
secret.entry.clutter_text.set_password_char('\u25cf');
|
|
||||||
}
|
|
||||||
|
|
||||||
messageBox.add(secretTable);
|
|
||||||
|
|
||||||
this._okButton = { label: _("Connect"),
|
|
||||||
action: Lang.bind(this, this._onOk),
|
|
||||||
default: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setButtons([{ label: _("Cancel"),
|
|
||||||
action: Lang.bind(this, this.cancel),
|
|
||||||
key: Clutter.KEY_Escape,
|
|
||||||
},
|
|
||||||
this._okButton]);
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateOkButton: function() {
|
|
||||||
let valid = true;
|
|
||||||
for (let i = 0; i < this._content.secrets.length; i++) {
|
|
||||||
let secret = this._content.secrets[i];
|
|
||||||
valid = valid && secret.valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._okButton.button.reactive = valid;
|
|
||||||
this._okButton.button.can_focus = valid;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onOk: function() {
|
|
||||||
let valid = true;
|
|
||||||
for (let i = 0; i < this._content.secrets.length; i++) {
|
|
||||||
let secret = this._content.secrets[i];
|
|
||||||
valid = valid && secret.valid;
|
|
||||||
if (secret.key != null)
|
|
||||||
this._agent.set_password(this._requestId, secret.key, secret.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
|
|
||||||
this.close(global.get_current_time());
|
|
||||||
}
|
|
||||||
// do nothing if not valid
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function() {
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
|
||||||
this.close(global.get_current_time());
|
|
||||||
},
|
|
||||||
|
|
||||||
_validateWpaPsk: function(secret) {
|
|
||||||
let value = secret.value;
|
|
||||||
if (value.length == 64) {
|
|
||||||
// must be composed of hexadecimal digits only
|
|
||||||
for (let i = 0; i < 64; i++) {
|
|
||||||
if (!((value[i] >= 'a' && value[i] <= 'f')
|
|
||||||
|| (value[i] >= 'A' && value[i] <= 'F')
|
|
||||||
|| (value[i] >= '0' && value[i] <= '9')))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (value.length >= 8 && value.length <= 63);
|
|
||||||
},
|
|
||||||
|
|
||||||
_validateStaticWep: function(secret) {
|
|
||||||
let value = secret.value;
|
|
||||||
if (secret.wep_key_type == NetworkManager.WepKeyType.KEY) {
|
|
||||||
if (value.length == 10 || value.length == 26) {
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
|
||||||
if (!((value[i] >= 'a' && value[i] <= 'f')
|
|
||||||
|| (value[i] >= 'A' && value[i] <= 'F')
|
|
||||||
|| (value[i] >= '0' && value[i] <= '9')))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (value.length == 5 || value.length == 13) {
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
|
||||||
if (!((value[i] >= 'a' && value[i] <= 'z')
|
|
||||||
|| (value[i] >= 'A' && value[i] <= 'Z')))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
} else if (secret.wep_key_type == NetworkManager.WepKeyType.PASSPHRASE) {
|
|
||||||
if (value.length < 0 || value.length > 64)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getWirelessSecrets: function(secrets, wirelessSetting) {
|
|
||||||
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
|
|
||||||
switch (wirelessSecuritySetting.key_mgmt) {
|
|
||||||
// First the easy ones
|
|
||||||
case 'wpa-none':
|
|
||||||
case 'wpa-psk':
|
|
||||||
secrets.push({ label: _("Password: "), key: 'psk',
|
|
||||||
value: wirelessSecuritySetting.psk || '',
|
|
||||||
validate: this._validateWpaPsk, password: true });
|
|
||||||
break;
|
|
||||||
case 'none': // static WEP
|
|
||||||
secrets.push({ label: _("Key: "), key: 'wep-key' + wirelessSecuritySetting.wep_tx_keyidx,
|
|
||||||
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
|
|
||||||
wep_key_type: wirelessSecuritySetting.wep_key_type,
|
|
||||||
validate: this._validateStaticWep, password: true });
|
|
||||||
break;
|
|
||||||
case 'ieee8021x':
|
|
||||||
if (wirelessSecuritySetting.auth_alg == 'leap') // Cisco LEAP
|
|
||||||
secrets.push({ label: _("Password: "), key: 'leap-password',
|
|
||||||
value: wirelessSecuritySetting.leap_password || '', password: true });
|
|
||||||
else // Dynamic (IEEE 802.1x) WEP
|
|
||||||
this._get8021xSecrets(secrets);
|
|
||||||
break;
|
|
||||||
case 'wpa-eap':
|
|
||||||
this._get8021xSecrets(secrets);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_get8021xSecrets: function(secrets) {
|
|
||||||
let ieee8021xSetting = this._connection.get_setting_802_1x();
|
|
||||||
let phase2method;
|
|
||||||
|
|
||||||
switch (ieee8021xSetting.get_eap_method(0)) {
|
|
||||||
case 'md5':
|
|
||||||
case 'leap':
|
|
||||||
case 'ttls':
|
|
||||||
case 'peap':
|
|
||||||
// TTLS and PEAP are actually much more complicated, but this complication
|
|
||||||
// is not visible here since we only care about phase2 authentication
|
|
||||||
// (and don't even care of which one)
|
|
||||||
secrets.push({ label: _("Username: "), key: null,
|
|
||||||
value: ieee8021xSetting.identity || '', password: false });
|
|
||||||
secrets.push({ label: _("Password: "), key: 'password',
|
|
||||||
value: ieee8021xSetting.password || '', password: true });
|
|
||||||
break;
|
|
||||||
case 'tls':
|
|
||||||
secrets.push({ label: _("Identity: "), key: null,
|
|
||||||
value: ieee8021xSetting.identity || '', password: false });
|
|
||||||
secrets.push({ label: _("Private key password: "), key: 'private-key-password',
|
|
||||||
value: ieee8021xSetting.private_key_password || '', password: true });
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_getPPPoESecrets: function(secrets) {
|
|
||||||
let pppoeSetting = this._connection.get_setting_pppoe();
|
|
||||||
secrets.push({ label: _("Username: "), key: 'username',
|
|
||||||
value: pppoeSetting.username || '', password: false });
|
|
||||||
secrets.push({ label: _("Service: "), key: 'service',
|
|
||||||
value: pppoeSetting.service || '', password: false });
|
|
||||||
secrets.push({ label: _("Password: "), key: 'password',
|
|
||||||
value: pppoeSetting.password || '', password: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
_getMobileSecrets: function(secrets, connectionType) {
|
|
||||||
let setting;
|
|
||||||
if (connectionType == 'bluetooth')
|
|
||||||
setting = this._connection.get_setting_cdma() || this._connection.get_setting_gsm();
|
|
||||||
else
|
|
||||||
setting = this._connection.get_setting_by_name(connectionType);
|
|
||||||
secrets.push({ label: _("Password: "), key: 'password',
|
|
||||||
value: setting.value || '', password: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
_getContent: function() {
|
|
||||||
let connectionSetting = this._connection.get_setting_connection();
|
|
||||||
let connectionType = connectionSetting.get_connection_type();
|
|
||||||
let wirelessSetting;
|
|
||||||
let ssid;
|
|
||||||
|
|
||||||
let content = { };
|
|
||||||
content.secrets = [ ];
|
|
||||||
|
|
||||||
switch (connectionType) {
|
|
||||||
case '802-11-wireless':
|
|
||||||
wirelessSetting = this._connection.get_setting_wireless();
|
|
||||||
ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
|
|
||||||
content.title = _("Authentication required by wireless network");
|
|
||||||
content.message = _("Passwords or encryption keys are required to access the wireless network '%s'.").format(ssid);
|
|
||||||
this._getWirelessSecrets(content.secrets, wirelessSetting);
|
|
||||||
break;
|
|
||||||
case '802-3-ethernet':
|
|
||||||
content.title = _("Wired 802.1X authentication");
|
|
||||||
content.message = null;
|
|
||||||
content.secrets.push({ label: _("Network name: "), key: null,
|
|
||||||
value: connectionSetting.get_id(), password: false });
|
|
||||||
this._get8021xSecrets(content.secrets);
|
|
||||||
break;
|
|
||||||
case 'pppoe':
|
|
||||||
content.title = _("DSL authentication");
|
|
||||||
content.message = null;
|
|
||||||
this._getPPPoESecrets(content.secrets);
|
|
||||||
break;
|
|
||||||
case 'gsm':
|
|
||||||
if (this._hints.indexOf('pin') != -1) {
|
|
||||||
let gsmSetting = this._connection.get_setting_gsm();
|
|
||||||
content.title = _("PIN code required");
|
|
||||||
content.message = _("PIN code is needed for the mobile broadband device");
|
|
||||||
content.secrets.push({ label: _("PIN: "), key: 'pin',
|
|
||||||
value: gsmSetting.pin || '', password: true });
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
case 'cdma':
|
|
||||||
case 'bluetooth':
|
|
||||||
content.title = _("Mobile broadband network password");
|
|
||||||
content.message = _("A password is required to connect to '%s'.").format(connectionSetting.get_id());
|
|
||||||
this._getMobileSecrets(content.secrets, connectionType);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log('Invalid connection type: ' + connectionType);
|
|
||||||
};
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const VPNRequestHandler = new Lang.Class({
|
|
||||||
Name: 'VPNRequestHandler',
|
|
||||||
|
|
||||||
_init: function(agent, requestId, authHelper, serviceType, connection, hints, flags) {
|
|
||||||
this._agent = agent;
|
|
||||||
this._requestId = requestId;
|
|
||||||
this._connection = connection;
|
|
||||||
this._pluginOutBuffer = [];
|
|
||||||
this._title = null;
|
|
||||||
this._description = null;
|
|
||||||
this._content = [ ];
|
|
||||||
this._shellDialog = null;
|
|
||||||
|
|
||||||
let connectionSetting = connection.get_setting_connection();
|
|
||||||
|
|
||||||
let argv = [ authHelper.fileName,
|
|
||||||
'-u', connectionSetting.uuid,
|
|
||||||
'-n', connectionSetting.id,
|
|
||||||
'-s', serviceType
|
|
||||||
];
|
|
||||||
if (authHelper.externalUIMode)
|
|
||||||
argv.push('--external-ui-mode');
|
|
||||||
if (flags & NMClient.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
|
|
||||||
argv.push('-i');
|
|
||||||
if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW)
|
|
||||||
argv.push('-r');
|
|
||||||
|
|
||||||
this._newStylePlugin = authHelper.externalUIMode;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let [success, pid, stdin, stdout, stderr] =
|
|
||||||
GLib.spawn_async_with_pipes(null, /* pwd */
|
|
||||||
argv,
|
|
||||||
null, /* envp */
|
|
||||||
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
|
|
||||||
null /* child_setup */);
|
|
||||||
|
|
||||||
this._childPid = pid;
|
|
||||||
this._stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true });
|
|
||||||
this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
|
|
||||||
// We need this one too, even if don't actually care of what the process
|
|
||||||
// has to say on stderr, because otherwise the fd opened by g_spawn_async_with_pipes
|
|
||||||
// is kept open indefinitely
|
|
||||||
let stderrStream = new Gio.UnixInputStream({ fd: stderr, close_fd: true });
|
|
||||||
stderrStream.close(null);
|
|
||||||
this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout });
|
|
||||||
|
|
||||||
if (this._newStylePlugin)
|
|
||||||
this._readStdoutNewStyle();
|
|
||||||
else
|
|
||||||
this._readStdoutOldStyle();
|
|
||||||
|
|
||||||
this._childWatch = GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid,
|
|
||||||
Lang.bind(this, this._vpnChildFinished));
|
|
||||||
|
|
||||||
this._writeConnection();
|
|
||||||
} catch(e) {
|
|
||||||
logError(e, 'error while spawning VPN auth helper');
|
|
||||||
|
|
||||||
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function(respond) {
|
|
||||||
if (respond)
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
|
||||||
|
|
||||||
if (this._newStylePlugin && this._shellDialog) {
|
|
||||||
this._shellDialog.close(global.get_current_time());
|
|
||||||
this._shellDialog.destroy();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
this._stdin.write('QUIT\n\n', null);
|
|
||||||
} catch(e) { /* ignore broken pipe errors */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
this.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
if (this._destroyed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
GLib.source_remove(this._childWatch);
|
|
||||||
|
|
||||||
this._stdin.close(null);
|
|
||||||
// Stdout is closed when we finish reading from it
|
|
||||||
|
|
||||||
this._destroyed = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_vpnChildFinished: function(pid, status, requestObj) {
|
|
||||||
if (this._newStylePlugin) {
|
|
||||||
// For new style plugin, all work is done in the async reading functions
|
|
||||||
// Just reap the process here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let [exited, exitStatus] = Shell.util_wifexited(status);
|
|
||||||
|
|
||||||
if (exited) {
|
|
||||||
if (exitStatus != 0)
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
|
|
||||||
else
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
|
|
||||||
} else
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
|
||||||
|
|
||||||
this.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
_vpnChildProcessLineOldStyle: function(line) {
|
|
||||||
if (this._previousLine != undefined) {
|
|
||||||
// Two consecutive newlines mean that the child should be closed
|
|
||||||
// (the actual newlines are eaten by Gio.DataInputStream)
|
|
||||||
// Send a termination message
|
|
||||||
if (line == '' && this._previousLine == '') {
|
|
||||||
try {
|
|
||||||
this._stdin.write('QUIT\n\n', null);
|
|
||||||
} catch(e) { /* ignore broken pipe errors */ }
|
|
||||||
} else {
|
|
||||||
this._agent.set_password(this._requestId, this._previousLine, line);
|
|
||||||
this._previousLine = undefined;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this._previousLine = line;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_readStdoutOldStyle: function() {
|
|
||||||
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
|
|
||||||
let [line, len] = this._dataStdout.read_line_finish_utf8(result);
|
|
||||||
|
|
||||||
if (line == null) {
|
|
||||||
// end of file
|
|
||||||
this._stdout.close(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._vpnChildProcessLineOldStyle(line);
|
|
||||||
|
|
||||||
// try to read more!
|
|
||||||
this._readStdoutOldStyle();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_readStdoutNewStyle: function() {
|
|
||||||
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
|
|
||||||
let cnt = this._dataStdout.fill_finish(result);
|
|
||||||
|
|
||||||
if (cnt == 0) {
|
|
||||||
// end of file
|
|
||||||
this._showNewStyleDialog();
|
|
||||||
|
|
||||||
this._stdout.close(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to read more
|
|
||||||
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
|
|
||||||
this._readStdoutNewStyle();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_showNewStyleDialog: function() {
|
|
||||||
let keyfile = new GLib.KeyFile();
|
|
||||||
let contentOverride;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let data = this._dataStdout.peek_buffer();
|
|
||||||
keyfile.load_from_data(data.toString(), data.length,
|
|
||||||
GLib.KeyFileFlags.NONE);
|
|
||||||
|
|
||||||
if (keyfile.get_integer(VPN_UI_GROUP, 'Version') != 2)
|
|
||||||
throw new Error('Invalid plugin keyfile version, is %d');
|
|
||||||
|
|
||||||
contentOverride = { title: keyfile.get_string(VPN_UI_GROUP, 'Title'),
|
|
||||||
message: keyfile.get_string(VPN_UI_GROUP, 'Description'),
|
|
||||||
secrets: [] };
|
|
||||||
|
|
||||||
let [groups, len] = keyfile.get_groups();
|
|
||||||
for (let i = 0; i < groups.length; i++) {
|
|
||||||
if (groups[i] == VPN_UI_GROUP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let value = keyfile.get_string(groups[i], 'Value');
|
|
||||||
let shouldAsk = keyfile.get_boolean(groups[i], 'ShouldAsk');
|
|
||||||
|
|
||||||
if (shouldAsk) {
|
|
||||||
contentOverride.secrets.push({ label: keyfile.get_string(groups[i], 'Label'),
|
|
||||||
key: groups[i],
|
|
||||||
value: value,
|
|
||||||
password: keyfile.get_boolean(groups[i], 'IsSecret')
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (!value.length) // Ignore empty secrets
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this._agent.set_password(this._requestId, groups[i], value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
logError(e, 'error while reading VPN plugin output keyfile');
|
|
||||||
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentOverride.secrets.length) {
|
|
||||||
// Only show the dialog if we actually have something to ask
|
|
||||||
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride);
|
|
||||||
this._shellDialog.open(global.get_current_time());
|
|
||||||
} else {
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_writeConnection: function() {
|
|
||||||
let vpnSetting = this._connection.get_setting_vpn();
|
|
||||||
|
|
||||||
try {
|
|
||||||
vpnSetting.foreach_data_item(Lang.bind(this, function(key, value) {
|
|
||||||
this._stdin.write('DATA_KEY=' + key + '\n', null);
|
|
||||||
this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
|
|
||||||
}));
|
|
||||||
vpnSetting.foreach_secret(Lang.bind(this, function(key, value) {
|
|
||||||
this._stdin.write('SECRET_KEY=' + key + '\n', null);
|
|
||||||
this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
|
|
||||||
}));
|
|
||||||
this._stdin.write('DONE\n\n', null);
|
|
||||||
} catch(e) {
|
|
||||||
logError(e, 'internal error while writing connection to helper');
|
|
||||||
|
|
||||||
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const NetworkAgent = new Lang.Class({
|
|
||||||
Name: 'NetworkAgent',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._native = new Shell.NetworkAgent({ auto_register: false,
|
|
||||||
identifier: 'org.gnome.Shell.NetworkAgent' });
|
|
||||||
|
|
||||||
this._dialogs = { };
|
|
||||||
this._vpnRequests = { };
|
|
||||||
|
|
||||||
this._native.connect('new-request', Lang.bind(this, this._newRequest));
|
|
||||||
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
this._native.register();
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
let requestId;
|
|
||||||
|
|
||||||
for (requestId in this._dialogs)
|
|
||||||
this._dialogs[requestId].cancel();
|
|
||||||
this._dialogs = { };
|
|
||||||
|
|
||||||
for (requestId in this._vpnRequests)
|
|
||||||
this._vpnRequests[requestId].cancel(true);
|
|
||||||
this._vpnRequests = { };
|
|
||||||
|
|
||||||
this._native.unregister();
|
|
||||||
},
|
|
||||||
|
|
||||||
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
|
|
||||||
if (settingName == 'vpn') {
|
|
||||||
this._vpnRequest(requestId, connection, hints, flags);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dialog = new NetworkSecretDialog(agent, requestId, connection, settingName, hints);
|
|
||||||
dialog.connect('destroy', Lang.bind(this, function() {
|
|
||||||
delete this._dialogs[requestId];
|
|
||||||
}));
|
|
||||||
this._dialogs[requestId] = dialog;
|
|
||||||
dialog.open(global.get_current_time());
|
|
||||||
},
|
|
||||||
|
|
||||||
_cancelRequest: function(agent, requestId) {
|
|
||||||
if (this._dialogs[requestId]) {
|
|
||||||
this._dialogs[requestId].close(global.get_current_time());
|
|
||||||
this._dialogs[requestId].destroy();
|
|
||||||
delete this._dialogs[requestId];
|
|
||||||
} else if (this._vpnRequests[requestId]) {
|
|
||||||
this._vpnRequests[requestId].cancel(false);
|
|
||||||
delete this._vpnRequests[requestId];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_vpnRequest: function(requestId, connection, hints, flags) {
|
|
||||||
let vpnSetting = connection.get_setting_vpn();
|
|
||||||
let serviceType = vpnSetting.service_type;
|
|
||||||
|
|
||||||
this._buildVPNServiceCache();
|
|
||||||
|
|
||||||
let binary = this._vpnBinaries[serviceType];
|
|
||||||
if (!binary) {
|
|
||||||
log('Invalid VPN service type (cannot find authentication binary)');
|
|
||||||
|
|
||||||
/* cancel the auth process */
|
|
||||||
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._vpnRequests[requestId] = new VPNRequestHandler(this._native, requestId, binary, serviceType, connection, hints, flags);
|
|
||||||
},
|
|
||||||
|
|
||||||
_buildVPNServiceCache: function() {
|
|
||||||
if (this._vpnCacheBuilt)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._vpnCacheBuilt = true;
|
|
||||||
this._vpnBinaries = { };
|
|
||||||
|
|
||||||
let dir = Gio.file_new_for_path(GLib.build_filenamev([Config.SYSCONFDIR, 'NetworkManager/VPN']));
|
|
||||||
try {
|
|
||||||
let fileEnum = dir.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NONE, null);
|
|
||||||
let info;
|
|
||||||
|
|
||||||
while ((info = fileEnum.next_file(null))) {
|
|
||||||
let name = info.get_name();
|
|
||||||
if (name.substr(-5) != '.name')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let keyfile = new GLib.KeyFile();
|
|
||||||
keyfile.load_from_file(dir.get_child(name).get_path(), GLib.KeyFileFlags.NONE);
|
|
||||||
let service = keyfile.get_string('VPN Connection', 'service');
|
|
||||||
let binary = keyfile.get_string('GNOME', 'auth-dialog');
|
|
||||||
let externalUIMode = false;
|
|
||||||
try {
|
|
||||||
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
|
|
||||||
} catch(e) { } // ignore errors if key does not exist
|
|
||||||
let path = binary;
|
|
||||||
if (!GLib.path_is_absolute(path)) {
|
|
||||||
path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE))
|
|
||||||
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode };
|
|
||||||
else
|
|
||||||
throw new Error('VPN plugin at %s is not executable'.format(path));
|
|
||||||
} catch(e) {
|
|
||||||
log('Error \'%s\' while processing VPN keyfile \'%s\''.
|
|
||||||
format(e.message, dir.get_child(name).get_path()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
logError(e, 'error while enumerating VPN auth helpers');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const Component = NetworkAgent;
|
|
@ -1,58 +0,0 @@
|
|||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
const Recorder = new Lang.Class({
|
|
||||||
Name: 'Recorder',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
|
|
||||||
this._desktopLockdownSettings = new Gio.Settings({ schema: 'org.gnome.desktop.lockdown' });
|
|
||||||
this._bindingSettings = new Gio.Settings({ schema: 'org.gnome.shell.keybindings' });
|
|
||||||
this._recorder = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
enable: function() {
|
|
||||||
global.display.add_keybinding('toggle-recording',
|
|
||||||
this._bindingSettings,
|
|
||||||
Meta.KeyBindingFlags.NONE, Lang.bind(this, this._toggleRecorder));
|
|
||||||
},
|
|
||||||
|
|
||||||
disable: function() {
|
|
||||||
global.display.remove_keybinding('toggle-recording');
|
|
||||||
},
|
|
||||||
|
|
||||||
_ensureRecorder: function() {
|
|
||||||
if (this._recorder == null)
|
|
||||||
this._recorder = new Shell.Recorder({ stage: global.stage });
|
|
||||||
return this._recorder;
|
|
||||||
},
|
|
||||||
|
|
||||||
_toggleRecorder: function() {
|
|
||||||
let recorder = this._ensureRecorder();
|
|
||||||
if (recorder.is_recording()) {
|
|
||||||
recorder.close();
|
|
||||||
Meta.enable_unredirect_for_screen(global.screen);
|
|
||||||
} else if (!this._desktopLockdownSettings.get_boolean('disable-save-to-disk')) {
|
|
||||||
// read the parameters from GSettings always in case they have changed
|
|
||||||
recorder.set_framerate(this._recorderSettings.get_int('framerate'));
|
|
||||||
/* Translators: this is a filename used for screencast recording */
|
|
||||||
// xgettext:no-c-format
|
|
||||||
recorder.set_file_template(_("Screencast from %d %t") + '.' + this._recorderSettings.get_string('file-extension'));
|
|
||||||
let pipeline = this._recorderSettings.get_string('pipeline');
|
|
||||||
|
|
||||||
if (!pipeline.match(/^\s*$/))
|
|
||||||
recorder.set_pipeline(pipeline);
|
|
||||||
else
|
|
||||||
recorder.set_pipeline(null);
|
|
||||||
|
|
||||||
Meta.disable_unredirect_for_screen(global.screen);
|
|
||||||
recorder.record();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Component = Recorder;
|
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gdk = imports.gi.Gdk;
|
const Gdk = imports.gi.Gdk;
|
||||||
@ -22,11 +22,14 @@ const SortGroup = {
|
|||||||
BOTTOM: 2
|
BOTTOM: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
const CtrlAltTabManager = new Lang.Class({
|
function CtrlAltTabManager() {
|
||||||
Name: 'CtrlAltTabManager',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
CtrlAltTabManager.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this._items = [];
|
this._items = [];
|
||||||
|
this._focusManager = St.FocusManager.get_for_stage(global.stage);
|
||||||
},
|
},
|
||||||
|
|
||||||
addGroup: function(root, name, icon, params) {
|
addGroup: function(root, name, icon, params) {
|
||||||
@ -40,11 +43,11 @@ const CtrlAltTabManager = new Lang.Class({
|
|||||||
|
|
||||||
this._items.push(item);
|
this._items.push(item);
|
||||||
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
|
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
|
||||||
global.focus_manager.add_group(root);
|
this._focusManager.add_group(root);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeGroup: function(root) {
|
removeGroup: function(root) {
|
||||||
global.focus_manager.remove_group(root);
|
this._focusManager.remove_group(root);
|
||||||
for (let i = 0; i < this._items.length; i++) {
|
for (let i = 0; i < this._items.length; i++) {
|
||||||
if (this._items[i].root == root) {
|
if (this._items[i].root == root) {
|
||||||
this._items.splice(i, 1);
|
this._items.splice(i, 1);
|
||||||
@ -54,17 +57,16 @@ const CtrlAltTabManager = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
focusGroup: function(item) {
|
focusGroup: function(item) {
|
||||||
if (item.window) {
|
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
|
||||||
Main.activateWindow(item.window);
|
global.stage_input_mode == Shell.StageInputMode.NORMAL)
|
||||||
} else if (item.focusCallback) {
|
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
||||||
item.focusCallback();
|
|
||||||
} else {
|
|
||||||
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
|
|
||||||
global.stage_input_mode == Shell.StageInputMode.NORMAL)
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
|
||||||
|
|
||||||
|
if (item.window)
|
||||||
|
Main.activateWindow(item.window);
|
||||||
|
else if (item.focusCallback)
|
||||||
|
item.focusCallback();
|
||||||
|
else
|
||||||
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sort the items into a consistent order; panel first, tray last,
|
// Sort the items into a consistent order; panel first, tray last,
|
||||||
@ -92,7 +94,7 @@ const CtrlAltTabManager = new Lang.Class({
|
|||||||
return a.x - b.x;
|
return a.x - b.x;
|
||||||
},
|
},
|
||||||
|
|
||||||
popup: function(backwards, mask) {
|
popup: function(backwards) {
|
||||||
// Start with the set of focus groups that are currently mapped
|
// Start with the set of focus groups that are currently mapped
|
||||||
let items = this._items.filter(function (item) { return item.proxy.mapped; });
|
let items = this._items.filter(function (item) { return item.proxy.mapped; });
|
||||||
|
|
||||||
@ -121,26 +123,19 @@ const CtrlAltTabManager = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
items.sort(Lang.bind(this, this._sortItems));
|
items.sort(Lang.bind(this, this._sortItems));
|
||||||
|
new CtrlAltTabPopup().show(items, backwards);
|
||||||
if (!this._popup) {
|
|
||||||
this._popup = new CtrlAltTabPopup();
|
|
||||||
this._popup.show(items, backwards, mask);
|
|
||||||
|
|
||||||
this._popup.actor.connect('destroy',
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
this._popup = null;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
function mod(a, b) {
|
function mod(a, b) {
|
||||||
return (a + b) % b;
|
return (a + b) % b;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CtrlAltTabPopup = new Lang.Class({
|
function CtrlAltTabPopup() {
|
||||||
Name: 'CtrlAltTabPopup',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
CtrlAltTabPopup.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
|
this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
|
||||||
reactive: true });
|
reactive: true });
|
||||||
@ -152,7 +147,6 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
|
||||||
this._haveModal = false;
|
this._haveModal = false;
|
||||||
this._modifierMask = 0;
|
|
||||||
this._selection = 0;
|
this._selection = 0;
|
||||||
|
|
||||||
Main.uiGroup.add_actor(this.actor);
|
Main.uiGroup.add_actor(this.actor);
|
||||||
@ -183,17 +177,16 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
|
let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
|
||||||
let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
|
let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
|
||||||
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
|
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
|
||||||
childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
|
childBox.x2 = Math.min(primary.width - hPadding, childBox.x1 + childNaturalWidth);
|
||||||
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
|
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
|
||||||
childBox.y2 = childBox.y1 + childNaturalHeight;
|
childBox.y2 = childBox.y1 + childNaturalHeight;
|
||||||
this._switcher.actor.allocate(childBox, flags);
|
this._switcher.actor.allocate(childBox, flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
show : function(items, startBackwards, mask) {
|
show : function(items, startBackwards) {
|
||||||
if (!Main.pushModal(this.actor))
|
if (!Main.pushModal(this.actor))
|
||||||
return false;
|
return false;
|
||||||
this._haveModal = true;
|
this._haveModal = true;
|
||||||
this._modifierMask = AltTab.primaryModifier(mask);
|
|
||||||
|
|
||||||
this._keyPressEventId = this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
this._keyPressEventId = this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
||||||
this._keyReleaseEventId = this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
this._keyReleaseEventId = this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
||||||
@ -207,7 +200,7 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
this._select(this._selection);
|
this._select(this._selection);
|
||||||
|
|
||||||
let [x, y, mods] = global.get_pointer();
|
let [x, y, mods] = global.get_pointer();
|
||||||
if (!(mods & this._modifierMask)) {
|
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
|
||||||
this._finish();
|
this._finish();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -233,7 +226,7 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
_keyPressEvent : function(actor, event) {
|
_keyPressEvent : function(actor, event) {
|
||||||
let keysym = event.get_key_symbol();
|
let keysym = event.get_key_symbol();
|
||||||
let shift = (event.get_state() & Clutter.ModifierType.SHIFT_MASK);
|
let shift = (Shell.get_event_state(event) & Clutter.ModifierType.SHIFT_MASK);
|
||||||
if (shift && keysym == Clutter.KEY_Tab)
|
if (shift && keysym == Clutter.KEY_Tab)
|
||||||
keysym = Clutter.ISO_Left_Tab;
|
keysym = Clutter.ISO_Left_Tab;
|
||||||
|
|
||||||
@ -253,7 +246,7 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
|
|
||||||
_keyReleaseEvent : function(actor, event) {
|
_keyReleaseEvent : function(actor, event) {
|
||||||
let [x, y, mods] = global.get_pointer();
|
let [x, y, mods] = global.get_pointer();
|
||||||
let state = mods & this._modifierMask;
|
let state = mods & Clutter.ModifierType.MOD1_MASK;
|
||||||
|
|
||||||
if (state == 0)
|
if (state == 0)
|
||||||
this._finish();
|
this._finish();
|
||||||
@ -299,14 +292,17 @@ const CtrlAltTabPopup = new Lang.Class({
|
|||||||
this._selection = num;
|
this._selection = num;
|
||||||
this._switcher.highlight(num);
|
this._switcher.highlight(num);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const CtrlAltTabSwitcher = new Lang.Class({
|
function CtrlAltTabSwitcher(items) {
|
||||||
Name: 'CtrlAltTabSwitcher',
|
this._init(items);
|
||||||
Extends: AltTab.SwitcherList,
|
}
|
||||||
|
|
||||||
|
CtrlAltTabSwitcher.prototype = {
|
||||||
|
__proto__ : AltTab.SwitcherList.prototype,
|
||||||
|
|
||||||
_init : function(items) {
|
_init : function(items) {
|
||||||
this.parent(true);
|
AltTab.SwitcherList.prototype._init.call(this, true);
|
||||||
|
|
||||||
for (let i = 0; i < items.length; i++)
|
for (let i = 0; i < items.length; i++)
|
||||||
this._addIcon(items[i]);
|
this._addIcon(items[i]);
|
||||||
@ -319,6 +315,7 @@ const CtrlAltTabSwitcher = new Lang.Class({
|
|||||||
let icon = item.iconActor;
|
let icon = item.iconActor;
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
icon = new St.Icon({ icon_name: item.iconName,
|
icon = new St.Icon({ icon_name: item.iconName,
|
||||||
|
icon_type: St.IconType.SYMBOLIC,
|
||||||
icon_size: POPUP_APPICON_SIZE });
|
icon_size: POPUP_APPICON_SIZE });
|
||||||
}
|
}
|
||||||
box.add(icon, { x_fill: false, y_fill: false } );
|
box.add(icon, { x_fill: false, y_fill: false } );
|
||||||
@ -328,4 +325,4 @@ const CtrlAltTabSwitcher = new Lang.Class({
|
|||||||
|
|
||||||
this.addItem(box, text);
|
this.addItem(box, text);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
510
js/ui/dash.js
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
@ -6,7 +6,6 @@ const Lang = imports.lang;
|
|||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const AppFavorites = imports.ui.appFavorites;
|
const AppFavorites = imports.ui.appFavorites;
|
||||||
@ -17,27 +16,14 @@ const Tweener = imports.ui.tweener;
|
|||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
const DASH_ANIMATION_TIME = 0.2;
|
const DASH_ANIMATION_TIME = 0.2;
|
||||||
const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
|
|
||||||
const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
|
|
||||||
const DASH_ITEM_HOVER_TIMEOUT = 300;
|
|
||||||
|
|
||||||
function getAppFromSource(source) {
|
|
||||||
if (source instanceof AppDisplay.AppWellIcon) {
|
|
||||||
let appSystem = Shell.AppSystem.get_default();
|
|
||||||
return appSystem.lookup_app(source.getId());
|
|
||||||
} else if (source.metaWindow) {
|
|
||||||
let tracker = Shell.WindowTracker.get_default();
|
|
||||||
return tracker.get_window_app(source.metaWindow);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A container like StBin, but taking the child's scale into account
|
// A container like StBin, but taking the child's scale into account
|
||||||
// when requesting a size
|
// when requesting a size
|
||||||
const DashItemContainer = new Lang.Class({
|
function DashItemContainer() {
|
||||||
Name: 'DashItemContainer',
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
DashItemContainer.prototype = {
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
|
this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
|
||||||
this.actor.connect('get-preferred-width',
|
this.actor.connect('get-preferred-width',
|
||||||
@ -48,16 +34,9 @@ const DashItemContainer = new Lang.Class({
|
|||||||
Lang.bind(this, this._allocate));
|
Lang.bind(this, this._allocate));
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
|
||||||
this._labelText = "";
|
|
||||||
this.label = new St.Label({ style_class: 'dash-label'});
|
|
||||||
this.label.hide();
|
|
||||||
Main.layoutManager.addChrome(this.label);
|
|
||||||
this.actor.label_actor = this.label;
|
|
||||||
|
|
||||||
this.child = null;
|
this.child = null;
|
||||||
this._childScale = 1;
|
this._childScale = 1;
|
||||||
this._childOpacity = 255;
|
this._childOpacity = 255;
|
||||||
this.animatingOut = false;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_allocate: function(actor, box, flags) {
|
_allocate: function(actor, box, flags) {
|
||||||
@ -106,60 +85,11 @@ const DashItemContainer = new Lang.Class({
|
|||||||
alloc.natural_size = natWidth * this.child.scale_y;
|
alloc.natural_size = natWidth * this.child.scale_y;
|
||||||
},
|
},
|
||||||
|
|
||||||
showLabel: function() {
|
|
||||||
if (!this._labelText)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.label.set_text(this._labelText);
|
|
||||||
this.label.opacity = 0;
|
|
||||||
this.label.show();
|
|
||||||
|
|
||||||
let [stageX, stageY] = this.actor.get_transformed_position();
|
|
||||||
|
|
||||||
let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
|
|
||||||
|
|
||||||
let labelHeight = this.label.get_height();
|
|
||||||
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
|
|
||||||
|
|
||||||
let y = stageY + yOffset;
|
|
||||||
|
|
||||||
let node = this.label.get_theme_node();
|
|
||||||
let xOffset = node.get_length('-x-offset');
|
|
||||||
|
|
||||||
let x;
|
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
x = stageX - this.label.get_width() - xOffset;
|
|
||||||
else
|
|
||||||
x = stageX + this.actor.get_width() + xOffset;
|
|
||||||
|
|
||||||
this.label.set_position(x, y);
|
|
||||||
Tweener.addTween(this.label,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: DASH_ITEM_LABEL_SHOW_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setLabelText: function(text) {
|
|
||||||
this._labelText = text;
|
|
||||||
},
|
|
||||||
|
|
||||||
hideLabel: function () {
|
|
||||||
Tweener.addTween(this.label,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: DASH_ITEM_LABEL_HIDE_TIME,
|
|
||||||
transition: 'easeOutQuad',
|
|
||||||
onComplete: Lang.bind(this, function() {
|
|
||||||
this.label.hide();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setChild: function(actor) {
|
setChild: function(actor) {
|
||||||
if (this.child == actor)
|
if (this.child == actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.actor.destroy_all_children();
|
this.actor.destroy_children();
|
||||||
|
|
||||||
this.child = actor;
|
this.child = actor;
|
||||||
this.actor.add_actor(this.child);
|
this.actor.add_actor(this.child);
|
||||||
@ -179,23 +109,12 @@ const DashItemContainer = new Lang.Class({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
|
||||||
if (this.label)
|
|
||||||
this.label.destroy();
|
|
||||||
|
|
||||||
this.actor.destroy();
|
|
||||||
},
|
|
||||||
|
|
||||||
animateOutAndDestroy: function() {
|
animateOutAndDestroy: function() {
|
||||||
if (this.label)
|
|
||||||
this.label.destroy();
|
|
||||||
|
|
||||||
if (this.child == null) {
|
if (this.child == null) {
|
||||||
this.actor.destroy();
|
this.actor.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.animatingOut = true;
|
|
||||||
this.childScale = 1.0;
|
this.childScale = 1.0;
|
||||||
Tweener.addTween(this,
|
Tweener.addTween(this,
|
||||||
{ childScale: 0.0,
|
{ childScale: 0.0,
|
||||||
@ -236,79 +155,63 @@ const DashItemContainer = new Lang.Class({
|
|||||||
get childOpacity() {
|
get childOpacity() {
|
||||||
return this._childOpacity;
|
return this._childOpacity;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const ShowAppsIcon = new Lang.Class({
|
function RemoveFavoriteIcon() {
|
||||||
Name: 'ShowAppsIcon',
|
this._init();
|
||||||
Extends: DashItemContainer,
|
}
|
||||||
|
|
||||||
|
RemoveFavoriteIcon.prototype = {
|
||||||
|
__proto__: DashItemContainer.prototype,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent();
|
DashItemContainer.prototype._init.call(this);
|
||||||
|
|
||||||
this.toggleButton = new St.Button({ style_class: 'show-apps',
|
this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
|
||||||
track_hover: true,
|
|
||||||
can_focus: true,
|
|
||||||
toggle_mode: true });
|
|
||||||
this._iconActor = null;
|
this._iconActor = null;
|
||||||
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
|
this.icon = new IconGrid.BaseIcon(_("Remove"),
|
||||||
{ setSizeManually: true,
|
{ setSizeManually: true,
|
||||||
showLabel: false,
|
showLabel: false,
|
||||||
createIcon: Lang.bind(this, this._createIcon) });
|
createIcon: Lang.bind(this, this._createIcon) });
|
||||||
this.toggleButton.add_actor(this.icon.actor);
|
this._iconBin.set_child(this.icon.actor);
|
||||||
this.toggleButton._delegate = this;
|
this._iconBin._delegate = this;
|
||||||
|
|
||||||
this.setChild(this.toggleButton);
|
this.setChild(this._iconBin);
|
||||||
this.setDragApp(null);
|
this.hiding = false;
|
||||||
this.toggleButton.label_actor = this.label;
|
},
|
||||||
|
|
||||||
|
animateOutAndDestroy: function() {
|
||||||
|
DashItemContainer.prototype.animateOutAndDestroy.call(this);
|
||||||
|
this.hiding = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
_createIcon: function(size) {
|
_createIcon: function(size) {
|
||||||
this._iconActor = new St.Icon({ icon_name: 'view-grid-symbolic',
|
this._iconActor = new St.Icon({ icon_name: 'user-trash',
|
||||||
icon_size: size,
|
style_class: 'remove-favorite-icon',
|
||||||
style_class: 'show-apps-icon',
|
icon_size: size });
|
||||||
track_hover: true });
|
|
||||||
return this._iconActor;
|
return this._iconActor;
|
||||||
},
|
},
|
||||||
|
|
||||||
_canRemoveApp: function(app) {
|
setHover: function(hovered) {
|
||||||
if (app == null)
|
this._iconBin.set_hover(hovered);
|
||||||
return false;
|
|
||||||
|
|
||||||
let id = app.get_id();
|
|
||||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
|
|
||||||
return isFavorite;
|
|
||||||
},
|
|
||||||
|
|
||||||
setDragApp: function(app) {
|
|
||||||
let canRemove = this._canRemoveApp(app);
|
|
||||||
|
|
||||||
this.toggleButton.set_hover(canRemove);
|
|
||||||
if (this._iconActor)
|
if (this._iconActor)
|
||||||
this._iconActor.set_hover(canRemove);
|
this._iconActor.set_hover(hovered);
|
||||||
|
|
||||||
if (canRemove)
|
|
||||||
this.setLabelText(_("Remove from Favorites"));
|
|
||||||
else
|
|
||||||
this.setLabelText(_("Show Applications"));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Rely on the dragged item being a favorite
|
||||||
handleDragOver: function(source, actor, x, y, time) {
|
handleDragOver: function(source, actor, x, y, time) {
|
||||||
let app = getAppFromSource(source);
|
|
||||||
if (app == null)
|
|
||||||
return DND.DragMotionResult.NO_DROP;
|
|
||||||
|
|
||||||
let id = app.get_id();
|
|
||||||
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
|
|
||||||
if (!isFavorite)
|
|
||||||
return DND.DragMotionResult.NO_DROP;
|
|
||||||
|
|
||||||
return DND.DragMotionResult.MOVE_DROP;
|
return DND.DragMotionResult.MOVE_DROP;
|
||||||
},
|
},
|
||||||
|
|
||||||
acceptDrop: function(source, actor, x, y, time) {
|
acceptDrop: function(source, actor, x, y, time) {
|
||||||
let app = getAppFromSource(source);
|
let app = null;
|
||||||
if (app == null)
|
if (source instanceof AppDisplay.AppWellIcon) {
|
||||||
return false;
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
app = appSystem.get_app(source.getId());
|
||||||
|
} else if (source.metaWindow) {
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
app = tracker.get_window_app(source.metaWindow);
|
||||||
|
}
|
||||||
|
|
||||||
let id = app.get_id();
|
let id = app.get_id();
|
||||||
|
|
||||||
@ -320,54 +223,28 @@ const ShowAppsIcon = new Lang.Class({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const DragPlaceholderItem = new Lang.Class({
|
|
||||||
Name: 'DragPlaceholderItem',
|
function DragPlaceholderItem() {
|
||||||
Extends: DashItemContainer,
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
DragPlaceholderItem.prototype = {
|
||||||
|
__proto__: DashItemContainer.prototype,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent();
|
DashItemContainer.prototype._init.call(this);
|
||||||
this.setChild(new St.Bin({ style_class: 'placeholder' }));
|
this.setChild(new St.Bin({ style_class: 'dash-placeholder' }));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
const DashActor = new Lang.Class({
|
|
||||||
Name: 'DashActor',
|
|
||||||
Extends: St.Widget,
|
|
||||||
|
|
||||||
_init: function() {
|
function Dash() {
|
||||||
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
|
this._init();
|
||||||
this.parent({ name: 'dash',
|
}
|
||||||
layout_manager: layout,
|
|
||||||
clip_to_allocation: true });
|
|
||||||
},
|
|
||||||
|
|
||||||
vfunc_allocate: function(box, flags) {
|
|
||||||
let contentBox = this.get_theme_node().get_content_box(box);
|
|
||||||
let availWidth = contentBox.x2 - contentBox.x1;
|
|
||||||
|
|
||||||
this.set_allocation(box, flags);
|
|
||||||
|
|
||||||
let [appIcons, showAppsButton] = this.get_children();
|
|
||||||
let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
|
|
||||||
|
|
||||||
let childBox = new Clutter.ActorBox();
|
|
||||||
childBox.x1 = contentBox.x1;
|
|
||||||
childBox.y1 = contentBox.y1;
|
|
||||||
childBox.x2 = contentBox.x2;
|
|
||||||
childBox.y2 = contentBox.y2 - showAppsNatHeight;
|
|
||||||
appIcons.allocate(childBox, flags);
|
|
||||||
|
|
||||||
childBox.y1 = contentBox.y2 - showAppsNatHeight;
|
|
||||||
childBox.y2 = contentBox.y2;
|
|
||||||
showAppsButton.allocate(childBox, flags);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const Dash = new Lang.Class({
|
|
||||||
Name: 'Dash',
|
|
||||||
|
|
||||||
|
Dash.prototype = {
|
||||||
_init : function() {
|
_init : function() {
|
||||||
this._maxHeight = -1;
|
this._maxHeight = -1;
|
||||||
this.iconSize = 64;
|
this.iconSize = 64;
|
||||||
@ -376,25 +253,14 @@ const Dash = new Lang.Class({
|
|||||||
this._dragPlaceholder = null;
|
this._dragPlaceholder = null;
|
||||||
this._dragPlaceholderPos = -1;
|
this._dragPlaceholderPos = -1;
|
||||||
this._animatingPlaceholdersCount = 0;
|
this._animatingPlaceholdersCount = 0;
|
||||||
this._showLabelTimeoutId = 0;
|
this._favRemoveTarget = null;
|
||||||
this._resetHoverTimeoutId = 0;
|
|
||||||
this._labelShowing = false;
|
|
||||||
|
|
||||||
this._container = new DashActor();
|
this._box = new St.BoxLayout({ name: 'dash',
|
||||||
this._box = new St.BoxLayout({ vertical: true,
|
vertical: true,
|
||||||
clip_to_allocation: true });
|
clip_to_allocation: true });
|
||||||
this._box._delegate = this;
|
this._box._delegate = this;
|
||||||
this._container.add_actor(this._box);
|
|
||||||
|
|
||||||
this._showAppsIcon = new ShowAppsIcon();
|
this.actor = new St.Bin({ y_align: St.Align.START, child: this._box });
|
||||||
this._showAppsIcon.icon.setIconSize(this.iconSize);
|
|
||||||
this._hookUpLabel(this._showAppsIcon);
|
|
||||||
|
|
||||||
this.showAppsButton = this._showAppsIcon.toggleButton;
|
|
||||||
|
|
||||||
this._container.add_actor(this._showAppsIcon.actor);
|
|
||||||
|
|
||||||
this.actor = new St.Bin({ child: this._container });
|
|
||||||
this.actor.connect('notify::height', Lang.bind(this,
|
this.actor.connect('notify::height', Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
if (this._maxHeight != this.actor.height)
|
if (this._maxHeight != this.actor.height)
|
||||||
@ -404,11 +270,12 @@ const Dash = new Lang.Class({
|
|||||||
|
|
||||||
this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
|
this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
|
||||||
|
|
||||||
|
this._tracker = Shell.WindowTracker.get_default();
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
|
this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
|
||||||
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
|
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
|
||||||
this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
|
this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
|
||||||
|
|
||||||
Main.overview.connect('item-drag-begin',
|
Main.overview.connect('item-drag-begin',
|
||||||
Lang.bind(this, this._onDragBegin));
|
Lang.bind(this, this._onDragBegin));
|
||||||
@ -446,25 +313,56 @@ const Dash = new Lang.Class({
|
|||||||
|
|
||||||
_endDrag: function() {
|
_endDrag: function() {
|
||||||
this._clearDragPlaceholder();
|
this._clearDragPlaceholder();
|
||||||
this._showAppsIcon.setDragApp(null);
|
if (this._favRemoveTarget) {
|
||||||
|
this._favRemoveTarget.actor.hide();
|
||||||
|
this._adjustIconSize();
|
||||||
|
this._favRemoveTarget.actor.show();
|
||||||
|
|
||||||
|
this._favRemoveTarget.animateOutAndDestroy();
|
||||||
|
this._favRemoveTarget.actor.connect('destroy', Lang.bind(this,
|
||||||
|
function() {
|
||||||
|
this._favRemoveTarget = null;
|
||||||
|
}));
|
||||||
|
}
|
||||||
DND.removeDragMonitor(this._dragMonitor);
|
DND.removeDragMonitor(this._dragMonitor);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDragMotion: function(dragEvent) {
|
_onDragMotion: function(dragEvent) {
|
||||||
let app = getAppFromSource(dragEvent.source);
|
let app = null;
|
||||||
if (app == null)
|
if (dragEvent.source instanceof AppDisplay.AppWellIcon)
|
||||||
|
app = this._appSystem.get_app(dragEvent.source.getId());
|
||||||
|
else if (dragEvent.source.metaWindow)
|
||||||
|
app = this._tracker.get_window_app(dragEvent.source.metaWindow);
|
||||||
|
else
|
||||||
return DND.DragMotionResult.CONTINUE;
|
return DND.DragMotionResult.CONTINUE;
|
||||||
|
|
||||||
let showAppsHovered =
|
let id = app.get_id();
|
||||||
this._showAppsIcon.actor.contains(dragEvent.targetActor);
|
|
||||||
|
|
||||||
if (!this._box.contains(dragEvent.targetActor) || showAppsHovered)
|
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||||
|
|
||||||
|
let srcIsFavorite = (id in favorites);
|
||||||
|
|
||||||
|
if (srcIsFavorite &&
|
||||||
|
dragEvent.source.actor &&
|
||||||
|
this.actor.contains (dragEvent.source.actor) &&
|
||||||
|
this._favRemoveTarget == null) {
|
||||||
|
this._favRemoveTarget = new RemoveFavoriteIcon();
|
||||||
|
this._favRemoveTarget.icon.setIconSize(this.iconSize);
|
||||||
|
this._box.add(this._favRemoveTarget.actor);
|
||||||
|
this._adjustIconSize();
|
||||||
|
this._favRemoveTarget.animateIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
let favRemoveHovered = false;
|
||||||
|
if (this._favRemoveTarget)
|
||||||
|
favRemoveHovered =
|
||||||
|
this._favRemoveTarget.actor.contains(dragEvent.targetActor);
|
||||||
|
|
||||||
|
if (!this._box.contains(dragEvent.targetActor) || favRemoveHovered)
|
||||||
this._clearDragPlaceholder();
|
this._clearDragPlaceholder();
|
||||||
|
|
||||||
if (showAppsHovered)
|
if (this._favRemoveTarget)
|
||||||
this._showAppsIcon.setDragApp(app);
|
this._favRemoveTarget.setHover(favRemoveHovered);
|
||||||
else
|
|
||||||
this._showAppsIcon.setDragApp(null);
|
|
||||||
|
|
||||||
return DND.DragMotionResult.CONTINUE;
|
return DND.DragMotionResult.CONTINUE;
|
||||||
},
|
},
|
||||||
@ -480,17 +378,6 @@ const Dash = new Lang.Class({
|
|||||||
Main.queueDeferredWork(this._workId);
|
Main.queueDeferredWork(this._workId);
|
||||||
},
|
},
|
||||||
|
|
||||||
_hookUpLabel: function(item) {
|
|
||||||
item.child.connect('notify::hover', Lang.bind(this, function() {
|
|
||||||
this._onHover(item);
|
|
||||||
}));
|
|
||||||
|
|
||||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
|
||||||
this._labelShowing = false;
|
|
||||||
item.hideLabel();
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_createAppItem: function(app) {
|
_createAppItem: function(app) {
|
||||||
let display = new AppDisplay.AppWellIcon(app,
|
let display = new AppDisplay.AppWellIcon(app,
|
||||||
{ setSizeManually: true,
|
{ setSizeManually: true,
|
||||||
@ -503,103 +390,45 @@ const Dash = new Lang.Class({
|
|||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
display.actor.opacity = 255;
|
display.actor.opacity = 255;
|
||||||
}));
|
}));
|
||||||
|
display.actor.set_tooltip_text(app.get_name());
|
||||||
|
|
||||||
let item = new DashItemContainer();
|
let item = new DashItemContainer();
|
||||||
item.setChild(display.actor);
|
item.setChild(display.actor);
|
||||||
|
|
||||||
item.setLabelText(app.get_name());
|
|
||||||
// Override default AppWellIcon label_actor
|
|
||||||
display.actor.label_actor = item.label;
|
|
||||||
display.icon.setIconSize(this.iconSize);
|
display.icon.setIconSize(this.iconSize);
|
||||||
this._hookUpLabel(item);
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onHover: function (item) {
|
|
||||||
if (item.child.get_hover() && !item.child._delegate.isMenuUp) {
|
|
||||||
if (this._showLabelTimeoutId == 0) {
|
|
||||||
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
|
|
||||||
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
this._labelShowing = true;
|
|
||||||
item.showLabel();
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
if (this._resetHoverTimeoutId > 0) {
|
|
||||||
Mainloop.source_remove(this._resetHoverTimeoutId);
|
|
||||||
this._resetHoverTimeoutId = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this._showLabelTimeoutId > 0)
|
|
||||||
Mainloop.source_remove(this._showLabelTimeoutId);
|
|
||||||
this._showLabelTimeoutId = 0;
|
|
||||||
item.hideLabel();
|
|
||||||
if (this._labelShowing) {
|
|
||||||
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
|
|
||||||
Lang.bind(this, function() {
|
|
||||||
this._labelShowing = false;
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_adjustIconSize: function() {
|
_adjustIconSize: function() {
|
||||||
// For the icon size, we only consider children which are "proper"
|
let children = this._box.get_children();
|
||||||
// icons (i.e. ignoring drag placeholders) and which are not
|
if (children.length == 0) {
|
||||||
// animating out (which means they will be destroyed at the end of
|
this._box.add_style_pseudo_class('empty');
|
||||||
// the animation)
|
return;
|
||||||
let iconChildren = this._box.get_children().filter(function(actor) {
|
}
|
||||||
return actor._delegate.child &&
|
|
||||||
actor._delegate.child._delegate &&
|
|
||||||
actor._delegate.child._delegate.icon &&
|
|
||||||
!actor._delegate.animatingOut;
|
|
||||||
});
|
|
||||||
|
|
||||||
iconChildren.push(this._showAppsIcon.actor);
|
this._box.remove_style_pseudo_class('empty');
|
||||||
|
|
||||||
if (this._maxHeight == -1)
|
if (this._maxHeight == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let themeNode = this._container.get_theme_node();
|
let iconChildren = children.filter(function(actor) {
|
||||||
let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
|
return actor.visible &&
|
||||||
x2: 42 /* whatever */,
|
actor._delegate.child &&
|
||||||
y2: this._maxHeight });
|
actor._delegate.child._delegate &&
|
||||||
let maxContent = themeNode.get_content_box(maxAllocation);
|
actor._delegate.child._delegate.icon;
|
||||||
let availHeight = maxContent.y2 - maxContent.y1;
|
});
|
||||||
let spacing = themeNode.get_length('spacing');
|
|
||||||
|
|
||||||
|
// Compute the amount of extra space (or missing space) we have
|
||||||
let firstIcon = iconChildren[0]._delegate.child._delegate.icon;
|
// per icon with the current icon size
|
||||||
|
let [minHeight, natHeight] = this.actor.get_preferred_height(-1);
|
||||||
let minHeight, natHeight;
|
let diff = (this._maxHeight - natHeight) / iconChildren.length;
|
||||||
|
|
||||||
// Enforce the current icon size during the size request if
|
|
||||||
// the icon is animating
|
|
||||||
if (firstIcon._animating) {
|
|
||||||
let [currentWidth, currentHeight] = firstIcon.icon.get_size();
|
|
||||||
|
|
||||||
firstIcon.icon.set_size(this.iconSize, this.iconSize);
|
|
||||||
[minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
|
|
||||||
|
|
||||||
firstIcon.icon.set_size(currentWidth, currentHeight);
|
|
||||||
} else {
|
|
||||||
[minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subtract icon padding and box spacing from the available height
|
|
||||||
availHeight -= iconChildren.length * (natHeight - this.iconSize) +
|
|
||||||
(iconChildren.length - 1) * spacing;
|
|
||||||
|
|
||||||
let availSize = availHeight / iconChildren.length;
|
|
||||||
|
|
||||||
let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
|
let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
|
||||||
|
|
||||||
let newIconSize = 16;
|
let newIconSize = 16;
|
||||||
for (let i = 0; i < iconSizes.length; i++) {
|
for (let i = 0; i < iconSizes.length; i++) {
|
||||||
if (iconSizes[i] < availSize)
|
if (iconSizes[i] < this.iconSize + diff)
|
||||||
newIconSize = iconSizes[i];
|
newIconSize = iconSizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +437,6 @@ const Dash = new Lang.Class({
|
|||||||
|
|
||||||
let oldIconSize = this.iconSize;
|
let oldIconSize = this.iconSize;
|
||||||
this.iconSize = newIconSize;
|
this.iconSize = newIconSize;
|
||||||
this.emit('icon-size-changed');
|
|
||||||
|
|
||||||
let scale = oldIconSize / newIconSize;
|
let scale = oldIconSize / newIconSize;
|
||||||
for (let i = 0; i < iconChildren.length; i++) {
|
for (let i = 0; i < iconChildren.length; i++) {
|
||||||
@ -630,15 +458,11 @@ const Dash = new Lang.Class({
|
|||||||
icon.icon.set_size(icon.icon.width * scale,
|
icon.icon.set_size(icon.icon.width * scale,
|
||||||
icon.icon.height * scale);
|
icon.icon.height * scale);
|
||||||
|
|
||||||
icon._animating = true;
|
|
||||||
Tweener.addTween(icon.icon,
|
Tweener.addTween(icon.icon,
|
||||||
{ width: targetWidth,
|
{ width: targetWidth,
|
||||||
height: targetHeight,
|
height: targetHeight,
|
||||||
time: DASH_ANIMATION_TIME,
|
time: DASH_ANIMATION_TIME,
|
||||||
transition: 'easeOutQuad',
|
transition: 'easeOutQuad'
|
||||||
onComplete: function() {
|
|
||||||
icon._animating = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -646,7 +470,10 @@ const Dash = new Lang.Class({
|
|||||||
_redisplay: function () {
|
_redisplay: function () {
|
||||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||||
|
|
||||||
let running = this._appSystem.get_running();
|
/* hardcode here pending some design about how exactly desktop contexts behave */
|
||||||
|
let contextId = '';
|
||||||
|
|
||||||
|
let running = this._tracker.get_running_apps(contextId);
|
||||||
|
|
||||||
let children = this._box.get_children().filter(function(actor) {
|
let children = this._box.get_children().filter(function(actor) {
|
||||||
return actor._delegate.child &&
|
return actor._delegate.child &&
|
||||||
@ -738,21 +565,23 @@ const Dash = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < addedItems.length; i++)
|
for (let i = 0; i < addedItems.length; i++)
|
||||||
this._box.insert_child_at_index(addedItems[i].item.actor,
|
this._box.insert_actor(addedItems[i].item.actor,
|
||||||
addedItems[i].pos);
|
addedItems[i].pos);
|
||||||
|
|
||||||
for (let i = 0; i < removedActors.length; i++) {
|
// Hide removed actors to not take them into account
|
||||||
let item = removedActors[i]._delegate;
|
// when adjusting the icon size ...
|
||||||
|
for (let i = 0; i < removedActors.length; i++)
|
||||||
|
removedActors[i].hide();
|
||||||
|
|
||||||
// Don't animate item removal when the overview is hidden
|
// ... and do the same for the remove target if necessary
|
||||||
if (Main.overview.visible)
|
if (this._favRemoveTarget && this._favRemoveTarget.hiding)
|
||||||
item.animateOutAndDestroy();
|
this._favRemoveTarget.actor.hide();
|
||||||
else
|
|
||||||
item.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._adjustIconSize();
|
this._adjustIconSize();
|
||||||
|
|
||||||
|
if (this._favRemoveTarget && this._favRemoveTarget.hiding)
|
||||||
|
this._favRemoveTarget.actor.show();
|
||||||
|
|
||||||
// Skip animations on first run when adding the initial set
|
// Skip animations on first run when adding the initial set
|
||||||
// of items, to avoid all items zooming in at once
|
// of items, to avoid all items zooming in at once
|
||||||
if (!this._shownInitially) {
|
if (!this._shownInitially) {
|
||||||
@ -760,6 +589,17 @@ const Dash = new Lang.Class({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < removedActors.length; i++) {
|
||||||
|
removedActors[i].show();
|
||||||
|
let item = removedActors[i]._delegate;
|
||||||
|
|
||||||
|
// Don't animate item removal when the overview is hidden
|
||||||
|
if (Main.overview.visible)
|
||||||
|
item.animateOutAndDestroy();
|
||||||
|
else
|
||||||
|
item.actor.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
// Don't animate item addition when the overview is hidden
|
// Don't animate item addition when the overview is hidden
|
||||||
if (!Main.overview.visible)
|
if (!Main.overview.visible)
|
||||||
return;
|
return;
|
||||||
@ -777,10 +617,14 @@ const Dash = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleDragOver : function(source, actor, x, y, time) {
|
handleDragOver : function(source, actor, x, y, time) {
|
||||||
let app = getAppFromSource(source);
|
let app = null;
|
||||||
|
if (source instanceof AppDisplay.AppWellIcon)
|
||||||
|
app = this._appSystem.get_app(source.getId());
|
||||||
|
else if (source.metaWindow)
|
||||||
|
app = this._tracker.get_window_app(source.metaWindow);
|
||||||
|
|
||||||
// Don't allow favoriting of transient apps
|
// Don't allow favoriting of transient apps
|
||||||
if (app == null || app.is_window_backed())
|
if (app == null || app.is_transient())
|
||||||
return DND.DragMotionResult.NO_DROP;
|
return DND.DragMotionResult.NO_DROP;
|
||||||
|
|
||||||
let favorites = AppFavorites.getAppFavorites().getFavorites();
|
let favorites = AppFavorites.getAppFavorites().getFavorites();
|
||||||
@ -800,10 +644,20 @@ const Dash = new Lang.Class({
|
|||||||
numChildren--;
|
numChildren--;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos = Math.floor(y * numChildren / boxHeight);
|
let pos = Math.round(y * numChildren / boxHeight);
|
||||||
|
|
||||||
if (pos != this._dragPlaceholderPos && pos <= numFavorites && this._animatingPlaceholdersCount == 0) {
|
if (pos != this._dragPlaceholderPos && pos <= numFavorites) {
|
||||||
this._dragPlaceholderPos = pos;
|
if (this._animatingPlaceholdersCount > 0) {
|
||||||
|
let appChildren = children.filter(function(actor) {
|
||||||
|
return actor._delegate &&
|
||||||
|
actor._delegate.child &&
|
||||||
|
actor._delegate.child._delegate &&
|
||||||
|
actor._delegate.child._delegate.app;
|
||||||
|
});
|
||||||
|
this._dragPlaceholderPos = children.indexOf(appChildren[pos]);
|
||||||
|
} else {
|
||||||
|
this._dragPlaceholderPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't allow positioning before or after self
|
// Don't allow positioning before or after self
|
||||||
if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
|
if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
|
||||||
@ -832,22 +686,12 @@ const Dash = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._dragPlaceholder = new DragPlaceholderItem();
|
this._dragPlaceholder = new DragPlaceholderItem();
|
||||||
this._dragPlaceholder.child.set_width (this.iconSize);
|
this._box.insert_actor(this._dragPlaceholder.actor,
|
||||||
this._dragPlaceholder.child.set_height (this.iconSize / 2);
|
this._dragPlaceholderPos);
|
||||||
this._box.insert_child_at_index(this._dragPlaceholder.actor,
|
|
||||||
this._dragPlaceholderPos);
|
|
||||||
if (fadeIn)
|
if (fadeIn)
|
||||||
this._dragPlaceholder.animateIn();
|
this._dragPlaceholder.animateIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the drag placeholder if we are not in the
|
|
||||||
// "favorites zone"
|
|
||||||
if (pos > numFavorites && this._dragPlaceholder) {
|
|
||||||
this._clearDragPlaceholder();
|
|
||||||
}
|
|
||||||
if (!this._dragPlaceholder)
|
|
||||||
return DND.DragMotionResult.NO_DROP;
|
|
||||||
|
|
||||||
let srcIsFavorite = (favPos != -1);
|
let srcIsFavorite = (favPos != -1);
|
||||||
|
|
||||||
if (srcIsFavorite)
|
if (srcIsFavorite)
|
||||||
@ -858,10 +702,15 @@ const Dash = new Lang.Class({
|
|||||||
|
|
||||||
// Draggable target interface
|
// Draggable target interface
|
||||||
acceptDrop : function(source, actor, x, y, time) {
|
acceptDrop : function(source, actor, x, y, time) {
|
||||||
let app = getAppFromSource(source);
|
let app = null;
|
||||||
|
if (source instanceof AppDisplay.AppWellIcon) {
|
||||||
|
app = this._appSystem.get_app(source.getId());
|
||||||
|
} else if (source.metaWindow) {
|
||||||
|
app = this._tracker.get_window_app(source.metaWindow);
|
||||||
|
}
|
||||||
|
|
||||||
// Don't allow favoriting of transient apps
|
// Don't allow favoriting of transient apps
|
||||||
if (app == null || app.is_window_backed()) {
|
if (app == null || app.is_transient()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,11 +734,6 @@ const Dash = new Lang.Class({
|
|||||||
favPos++;
|
favPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No drag placeholder means we don't wan't to favorite the app
|
|
||||||
// and we are dragging it to its original position
|
|
||||||
if (!this._dragPlaceholder)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
|
||||||
function () {
|
function () {
|
||||||
let appFavorites = AppFavorites.getAppFavorites();
|
let appFavorites = AppFavorites.getAppFavorites();
|
||||||
@ -902,6 +746,6 @@ const Dash = new Lang.Class({
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(Dash.prototype);
|
Signals.addSignalMethods(Dash.prototype);
|
||||||
|
@ -1,23 +1,27 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const GnomeDesktop = imports.gi.GnomeDesktop;
|
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Mainloop = imports.mainloop;
|
const Mainloop = imports.mainloop;
|
||||||
const Cairo = imports.cairo;
|
const Cairo = imports.cairo;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Atk = imports.gi.Atk;
|
|
||||||
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
const Util = imports.misc.util;
|
const Util = imports.misc.util;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
const PanelMenu = imports.ui.panelMenu;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
const Calendar = imports.ui.calendar;
|
const Calendar = imports.ui.calendar;
|
||||||
|
|
||||||
|
// in org.gnome.desktop.interface
|
||||||
|
const CLOCK_FORMAT_KEY = 'clock-format';
|
||||||
|
|
||||||
|
// in org.gnome.shell.clock
|
||||||
|
const CLOCK_SHOW_DATE_KEY = 'show-date';
|
||||||
|
const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
|
||||||
|
|
||||||
function _onVertSepRepaint (area)
|
function _onVertSepRepaint (area)
|
||||||
{
|
{
|
||||||
let cr = area.get_context();
|
let cr = area.get_context();
|
||||||
@ -34,29 +38,29 @@ function _onVertSepRepaint (area)
|
|||||||
cr.stroke();
|
cr.stroke();
|
||||||
};
|
};
|
||||||
|
|
||||||
const DateMenuButton = new Lang.Class({
|
function DateMenuButton() {
|
||||||
Name: 'DateMenuButton',
|
this._init();
|
||||||
Extends: PanelMenu.Button,
|
}
|
||||||
|
|
||||||
|
DateMenuButton.prototype = {
|
||||||
|
__proto__: PanelMenu.Button.prototype,
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
let item;
|
let item;
|
||||||
let hbox;
|
let hbox;
|
||||||
let vbox;
|
let vbox;
|
||||||
|
|
||||||
|
this._eventSource = new Calendar.DBusEventSource();
|
||||||
|
|
||||||
let menuAlignment = 0.25;
|
let menuAlignment = 0.25;
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||||
menuAlignment = 1.0 - menuAlignment;
|
menuAlignment = 1.0 - menuAlignment;
|
||||||
this.parent(menuAlignment);
|
PanelMenu.Button.prototype._init.call(this, menuAlignment);
|
||||||
|
|
||||||
// At this moment calendar menu is not keyboard navigable at
|
this._clock = new St.Label();
|
||||||
// all (so not accessible), so it doesn't make sense to set as
|
this.actor.set_child(this._clock);
|
||||||
// role ATK_ROLE_MENU like other elements of the panel.
|
|
||||||
this.actor.accessible_role = Atk.Role.LABEL;
|
|
||||||
|
|
||||||
this._clockDisplay = new St.Label();
|
hbox = new St.BoxLayout({name: 'calendarArea'});
|
||||||
this.actor.add_actor(this._clockDisplay);
|
|
||||||
|
|
||||||
hbox = new St.BoxLayout({name: 'calendarArea' });
|
|
||||||
this.menu.addActor(hbox);
|
this.menu.addActor(hbox);
|
||||||
|
|
||||||
// Fill up the first column
|
// Fill up the first column
|
||||||
@ -66,57 +70,46 @@ const DateMenuButton = new Lang.Class({
|
|||||||
|
|
||||||
// Date
|
// Date
|
||||||
this._date = new St.Label();
|
this._date = new St.Label();
|
||||||
this.actor.label_actor = this._clockDisplay;
|
|
||||||
this._date.style_class = 'datemenu-date-label';
|
this._date.style_class = 'datemenu-date-label';
|
||||||
vbox.add(this._date);
|
vbox.add(this._date);
|
||||||
|
|
||||||
this._eventList = new Calendar.EventsList();
|
this._eventList = new Calendar.EventsList(this._eventSource);
|
||||||
this._calendar = new Calendar.Calendar();
|
|
||||||
|
|
||||||
|
// Calendar
|
||||||
|
this._calendar = new Calendar.Calendar(this._eventSource);
|
||||||
this._calendar.connect('selected-date-changed',
|
this._calendar.connect('selected-date-changed',
|
||||||
Lang.bind(this, function(calendar, date) {
|
Lang.bind(this, function(calendar, date) {
|
||||||
// we know this._eventList is defined here, because selected-data-changed
|
|
||||||
// only gets emitted when the user clicks a date in the calendar,
|
|
||||||
// and the calender makes those dates unclickable when instantiated with
|
|
||||||
// a null event source
|
|
||||||
this._eventList.setDate(date);
|
this._eventList.setDate(date);
|
||||||
}));
|
}));
|
||||||
vbox.add(this._calendar.actor);
|
vbox.add(this._calendar.actor);
|
||||||
|
|
||||||
item = this.menu.addSettingsAction(_("Date and Time Settings"), 'gnome-datetime-panel.desktop');
|
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||||
if (item) {
|
item.setColumnWidths(1);
|
||||||
let separator = new PopupMenu.PopupSeparatorMenuItem();
|
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||||
separator.setColumnWidths(1);
|
item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
|
||||||
vbox.add(separator.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
||||||
|
item.actor.can_focus = false;
|
||||||
|
vbox.add(item.actor);
|
||||||
|
|
||||||
item.actor.show_on_set_parent = false;
|
// Add vertical separator
|
||||||
item.actor.can_focus = false;
|
|
||||||
item.actor.reparent(vbox);
|
|
||||||
this._dateAndTimeSeparator = separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._separator = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
|
item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
|
||||||
pseudo_class: 'highlighted' });
|
pseudo_class: 'highlighted' });
|
||||||
this._separator.connect('repaint', Lang.bind(this, _onVertSepRepaint));
|
item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
|
||||||
hbox.add(this._separator);
|
hbox.add(item);
|
||||||
|
|
||||||
// Fill up the second column
|
// Fill up the second column
|
||||||
vbox = new St.BoxLayout({ name: 'calendarEventsArea',
|
|
||||||
vertical: true });
|
vbox = new St.BoxLayout({vertical: true});
|
||||||
hbox.add(vbox, { expand: true });
|
hbox.add(vbox, { expand: true });
|
||||||
|
|
||||||
// Event list
|
// Event list
|
||||||
vbox.add(this._eventList.actor, { expand: true });
|
vbox.add(this._eventList.actor, { expand: true });
|
||||||
|
|
||||||
this._openCalendarItem = new PopupMenu.PopupMenuItem(_("Open Calendar"));
|
item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
|
||||||
this._openCalendarItem.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
|
item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
|
||||||
this._openCalendarItem.actor.can_focus = false;
|
item.actor.can_focus = false;
|
||||||
vbox.add(this._openCalendarItem.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||||
|
|
||||||
this._calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' });
|
|
||||||
this._calendarSettings.connect('changed::exec',
|
|
||||||
Lang.bind(this, this._calendarSettingsChanged));
|
|
||||||
this._calendarSettingsChanged();
|
|
||||||
|
|
||||||
// Whenever the menu is opened, select today
|
// Whenever the menu is opened, select today
|
||||||
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
|
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
|
||||||
@ -143,86 +136,76 @@ const DateMenuButton = new Lang.Class({
|
|||||||
|
|
||||||
// Done with hbox for calendar and event list
|
// Done with hbox for calendar and event list
|
||||||
|
|
||||||
this._clock = new GnomeDesktop.WallClock();
|
// Track changes to clock settings
|
||||||
this._clock.connect('notify::clock', Lang.bind(this, this._updateClockAndDate));
|
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
||||||
|
this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
|
||||||
|
this._desktopSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
|
||||||
|
this._clockSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
|
||||||
|
|
||||||
|
// Start the clock
|
||||||
this._updateClockAndDate();
|
this._updateClockAndDate();
|
||||||
|
|
||||||
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
|
|
||||||
this._sessionUpdated();
|
|
||||||
},
|
|
||||||
|
|
||||||
_calendarSettingsChanged: function() {
|
|
||||||
let exec = this._calendarSettings.get_string('exec');
|
|
||||||
let fullExec = GLib.find_program_in_path(exec);
|
|
||||||
this._openCalendarItem.actor.visible = fullExec != null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_setEventsVisibility: function(visible) {
|
|
||||||
this._openCalendarItem.actor.visible = visible;
|
|
||||||
this._separator.visible = visible;
|
|
||||||
if (visible) {
|
|
||||||
let alignment = 0.25;
|
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
alignment = 1.0 - alignment;
|
|
||||||
this.menu._arrowAlignment = alignment;
|
|
||||||
this._eventList.actor.get_parent().show();
|
|
||||||
} else {
|
|
||||||
this.menu._arrowAlignment = 0.5;
|
|
||||||
this._eventList.actor.get_parent().hide();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_setEventSource: function(eventSource) {
|
|
||||||
this._calendar.setEventSource(eventSource);
|
|
||||||
this._eventList.setEventSource(eventSource);
|
|
||||||
},
|
|
||||||
|
|
||||||
_sessionUpdated: function() {
|
|
||||||
let eventSource;
|
|
||||||
let showEvents = Main.sessionMode.showCalendarEvents;
|
|
||||||
if (showEvents) {
|
|
||||||
eventSource = new Calendar.DBusEventSource();
|
|
||||||
} else {
|
|
||||||
eventSource = null;
|
|
||||||
}
|
|
||||||
this._setEventSource(eventSource);
|
|
||||||
this._setEventsVisibility(showEvents);
|
|
||||||
|
|
||||||
// This needs to be handled manually, as the code to
|
|
||||||
// autohide separators doesn't work across the vbox
|
|
||||||
this._dateAndTimeSeparator.actor.visible = Main.sessionMode.allowSettings;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateClockAndDate: function() {
|
_updateClockAndDate: function() {
|
||||||
this._clockDisplay.set_text(this._clock.clock);
|
let format = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
|
||||||
|
let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
|
||||||
|
let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
|
||||||
|
|
||||||
|
let clockFormat;
|
||||||
|
let dateFormat;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case '24h':
|
||||||
|
if (showDate)
|
||||||
|
/* Translators: This is the time format with date used
|
||||||
|
in 24-hour mode. */
|
||||||
|
clockFormat = showSeconds ? _("%a %b %e, %R:%S")
|
||||||
|
: _("%a %b %e, %R");
|
||||||
|
else
|
||||||
|
/* Translators: This is the time format without date used
|
||||||
|
in 24-hour mode. */
|
||||||
|
clockFormat = showSeconds ? _("%a %R:%S")
|
||||||
|
: _("%a %R");
|
||||||
|
break;
|
||||||
|
case '12h':
|
||||||
|
default:
|
||||||
|
if (showDate)
|
||||||
|
/* Translators: This is a time format with date used
|
||||||
|
for AM/PM. */
|
||||||
|
clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
|
||||||
|
: _("%a %b %e, %l:%M %p");
|
||||||
|
else
|
||||||
|
/* Translators: This is a time format without date used
|
||||||
|
for AM/PM. */
|
||||||
|
clockFormat = showSeconds ? _("%a %l:%M:%S %p")
|
||||||
|
: _("%a %l:%M %p");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayDate = new Date();
|
||||||
|
|
||||||
|
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
|
||||||
|
|
||||||
/* Translators: This is the date format to use when the calendar popup is
|
/* Translators: This is the date format to use when the calendar popup is
|
||||||
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||||
*/
|
*/
|
||||||
let dateFormat = _("%A %B %e, %Y");
|
dateFormat = _("%A %B %e, %Y");
|
||||||
let displayDate = new Date();
|
|
||||||
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
|
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
|
||||||
|
|
||||||
|
Mainloop.timeout_add_seconds(1, Lang.bind(this, this._updateClockAndDate));
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onPreferencesActivate: function() {
|
||||||
|
this.menu.close();
|
||||||
|
Main.overview.hide();
|
||||||
|
let app = Shell.AppSystem.get_default().get_app('gnome-datetime-panel.desktop');
|
||||||
|
app.activate(-1);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onOpenCalendarActivate: function() {
|
_onOpenCalendarActivate: function() {
|
||||||
this.menu.close();
|
this.menu.close();
|
||||||
let tool = this._calendarSettings.get_string('exec');
|
// TODO: pass the selected day
|
||||||
if (tool.length == 0 || tool.substr(0, 9) == 'evolution') {
|
Util.spawn(['evolution', '-c', 'calendar']);
|
||||||
// TODO: pass the selected day
|
|
||||||
let app = Shell.AppSystem.get_default().lookup_app('evolution-calendar.desktop');
|
|
||||||
app.activate();
|
|
||||||
} else {
|
|
||||||
let needTerm = this._calendarSettings.get_boolean('needs-term');
|
|
||||||
if (needTerm) {
|
|
||||||
let terminalSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.terminal' });
|
|
||||||
let term = terminalSettings.get_string('exec');
|
|
||||||
let arg = terminalSettings.get_string('exec-arg');
|
|
||||||
if (arg != '')
|
|
||||||
Util.spawn([term, arg, tool]);
|
|
||||||
else
|
|
||||||
Util.spawn([term, tool]);
|
|
||||||
} else {
|
|
||||||
Util.spawnCommandLine(tool)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
51
js/ui/dnd.js
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
@ -69,9 +69,11 @@ function removeDragMonitor(monitor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _Draggable = new Lang.Class({
|
function _Draggable(actor, params) {
|
||||||
Name: 'Draggable',
|
this._init(actor, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Draggable.prototype = {
|
||||||
_init : function(actor, params) {
|
_init : function(actor, params) {
|
||||||
params = Params.parse(params, { manualMode: false,
|
params = Params.parse(params, { manualMode: false,
|
||||||
restoreOnSuccess: false,
|
restoreOnSuccess: false,
|
||||||
@ -103,8 +105,8 @@ const _Draggable = new Lang.Class({
|
|||||||
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
||||||
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
|
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
|
||||||
|
|
||||||
// During the drag, we eat enter/leave events so that actors don't prelight.
|
// During the drag, we eat enter/leave events so that actors don't prelight or show
|
||||||
// But we remember the actors that we first left/last entered so we can
|
// tooltips. But we remember the actors that we first left/last entered so we can
|
||||||
// fix up the hover state after the drag ends.
|
// fix up the hover state after the drag ends.
|
||||||
this._firstLeaveActor = null;
|
this._firstLeaveActor = null;
|
||||||
this._lastEnterActor = null;
|
this._lastEnterActor = null;
|
||||||
@ -120,7 +122,13 @@ const _Draggable = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
this._buttonDown = true;
|
this._buttonDown = true;
|
||||||
this._grabActor();
|
// special case St.Button: grabbing the pointer would mess up the
|
||||||
|
// internal state, so we start the drag manually on hover change
|
||||||
|
if (this.actor instanceof St.Button)
|
||||||
|
this.actor.connect('notify::hover',
|
||||||
|
Lang.bind(this, this._onButtonHoverChanged));
|
||||||
|
else
|
||||||
|
this._grabActor();
|
||||||
|
|
||||||
let [stageX, stageY] = event.get_coords();
|
let [stageX, stageY] = event.get_coords();
|
||||||
this._dragStartX = stageX;
|
this._dragStartX = stageX;
|
||||||
@ -129,6 +137,15 @@ const _Draggable = new Lang.Class({
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onButtonHoverChanged: function(button) {
|
||||||
|
if (button.hover || !button.pressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
button.fake_release();
|
||||||
|
this.startDrag(this._dragStartX, this._dragStartY,
|
||||||
|
global.get_current_time());
|
||||||
|
},
|
||||||
|
|
||||||
_grabActor: function() {
|
_grabActor: function() {
|
||||||
Clutter.grab_pointer(this.actor);
|
Clutter.grab_pointer(this.actor);
|
||||||
this._onEventId = this.actor.connect('event',
|
this._onEventId = this.actor.connect('event',
|
||||||
@ -217,13 +234,6 @@ const _Draggable = new Lang.Class({
|
|||||||
currentDraggable = this;
|
currentDraggable = this;
|
||||||
this._dragInProgress = true;
|
this._dragInProgress = true;
|
||||||
|
|
||||||
// Special-case St.Button: the pointer grab messes with the internal
|
|
||||||
// state, so force a reset to a reasonable state here
|
|
||||||
if (this.actor instanceof St.Button) {
|
|
||||||
this.actor.fake_release();
|
|
||||||
this.actor.hover = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('drag-begin', time);
|
this.emit('drag-begin', time);
|
||||||
if (this._onEventId)
|
if (this._onEventId)
|
||||||
this._ungrabActor();
|
this._ungrabActor();
|
||||||
@ -235,10 +245,6 @@ const _Draggable = new Lang.Class({
|
|||||||
|
|
||||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||||
this._dragActor.reparent(Main.uiGroup);
|
|
||||||
this._dragActor.raise_top();
|
|
||||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
|
||||||
|
|
||||||
// Drag actor does not always have to be the same as actor. For example drag actor
|
// Drag actor does not always have to be the same as actor. For example drag actor
|
||||||
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
// can be an image that's part of the actor. So to perform "snap back" correctly we need
|
||||||
// to know what was the drag actor source.
|
// to know what was the drag actor source.
|
||||||
@ -267,17 +273,12 @@ const _Draggable = new Lang.Class({
|
|||||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||||
} else {
|
} else {
|
||||||
this._dragActor = this.actor;
|
this._dragActor = this.actor;
|
||||||
|
|
||||||
this._dragActorSource = undefined;
|
this._dragActorSource = undefined;
|
||||||
this._dragOrigParent = this.actor.get_parent();
|
this._dragOrigParent = this.actor.get_parent();
|
||||||
this._dragOrigX = this._dragActor.x;
|
this._dragOrigX = this._dragActor.x;
|
||||||
this._dragOrigY = this._dragActor.y;
|
this._dragOrigY = this._dragActor.y;
|
||||||
this._dragOrigScale = this._dragActor.scale_x;
|
this._dragOrigScale = this._dragActor.scale_x;
|
||||||
|
|
||||||
this._dragActor.reparent(Main.uiGroup);
|
|
||||||
this._dragActor.raise_top();
|
|
||||||
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
|
||||||
|
|
||||||
let [actorStageX, actorStageY] = this.actor.get_transformed_position();
|
let [actorStageX, actorStageY] = this.actor.get_transformed_position();
|
||||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||||
@ -289,6 +290,10 @@ const _Draggable = new Lang.Class({
|
|||||||
scaledHeight / this.actor.height);
|
scaledHeight / this.actor.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._dragActor.reparent(Main.uiGroup);
|
||||||
|
this._dragActor.raise_top();
|
||||||
|
Shell.util_set_hidden_from_pick(this._dragActor, true);
|
||||||
|
|
||||||
this._dragOrigOpacity = this._dragActor.opacity;
|
this._dragOrigOpacity = this._dragActor.opacity;
|
||||||
if (this._dragActorOpacity != undefined)
|
if (this._dragActorOpacity != undefined)
|
||||||
this._dragActor.opacity = this._dragActorOpacity;
|
this._dragActor.opacity = this._dragActorOpacity;
|
||||||
@ -591,7 +596,7 @@ const _Draggable = new Lang.Class({
|
|||||||
this._dragActor = undefined;
|
this._dragActor = undefined;
|
||||||
currentDraggable = null;
|
currentDraggable = null;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
Signals.addSignalMethods(_Draggable.prototype);
|
Signals.addSignalMethods(_Draggable.prototype);
|
||||||
|
|
||||||
|
47
js/ui/docDisplay.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const DocInfo = imports.misc.docInfo;
|
||||||
|
const Params = imports.misc.params;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
|
||||||
|
|
||||||
|
function DocSearchProvider() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
DocSearchProvider.prototype = {
|
||||||
|
__proto__: Search.SearchProvider.prototype,
|
||||||
|
|
||||||
|
_init: function(name) {
|
||||||
|
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
|
||||||
|
this._docManager = DocInfo.getDocManager();
|
||||||
|
},
|
||||||
|
|
||||||
|
getResultMeta: function(resultId) {
|
||||||
|
let docInfo = this._docManager.lookupByUri(resultId);
|
||||||
|
if (!docInfo)
|
||||||
|
return null;
|
||||||
|
return { 'id': resultId,
|
||||||
|
'name': docInfo.name,
|
||||||
|
'createIcon': function(size) {
|
||||||
|
return docInfo.createIcon(size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
activateResult: function(id, params) {
|
||||||
|
params = Params.parse(params, { workspace: null,
|
||||||
|
timestamp: null });
|
||||||
|
|
||||||
|
let docInfo = this._docManager.lookupByUri(id);
|
||||||
|
docInfo.launch(params.workspace ? params.workspace.index() : -1);
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialResultSet: function(terms) {
|
||||||
|
return this._docManager.initialSearch(terms);
|
||||||
|
},
|
||||||
|
|
||||||
|
getSubsearchResultSet: function(previousResults, terms) {
|
||||||
|
return this._docManager.subsearch(previousResults, terms);
|
||||||
|
}
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||||
/*
|
*
|
||||||
* Copyright 2010 Red Hat, Inc
|
* Copyright 2010 Red Hat, Inc
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -18,23 +18,23 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const DBus = imports.dbus;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
const AccountsService = imports.gi.AccountsService;
|
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
const Gio = imports.gi.Gio;
|
const Gdm = imports.gi.Gdm;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Gtk = imports.gi.Gtk;
|
const Gtk = imports.gi.Gtk;
|
||||||
const Pango = imports.gi.Pango;
|
const Pango = imports.gi.Pango;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
const GnomeSession = imports.misc.gnomeSession;
|
const GnomeSession = imports.misc.gnomeSession
|
||||||
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
const ModalDialog = imports.ui.modalDialog;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const UserMenu = imports.ui.userMenu;
|
|
||||||
|
|
||||||
let _endSessionDialog = null;
|
let _endSessionDialog = null;
|
||||||
|
|
||||||
@ -43,69 +43,52 @@ const _DIALOG_ICON_SIZE = 32;
|
|||||||
|
|
||||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
|
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
|
||||||
|
|
||||||
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
|
const EndSessionDialogIface = {
|
||||||
<method name="Open">
|
name: 'org.gnome.SessionManager.EndSessionDialog',
|
||||||
<arg type="u" direction="in" />
|
methods: [{ name: 'Open',
|
||||||
<arg type="u" direction="in" />
|
inSignature: 'uuuao',
|
||||||
<arg type="u" direction="in" />
|
outSignature: ''
|
||||||
<arg type="ao" direction="in" />
|
}
|
||||||
</method>
|
],
|
||||||
<signal name="ConfirmedLogout" />
|
signals: [{ name: 'Canceled',
|
||||||
<signal name="ConfirmedReboot" />
|
inSignature: '',
|
||||||
<signal name="ConfirmedShutdown" />
|
}],
|
||||||
<signal name="Canceled" />
|
properties: []
|
||||||
<signal name="Closed" />
|
};
|
||||||
</interface>;
|
|
||||||
|
|
||||||
const logoutDialogContent = {
|
const logoutDialogContent = {
|
||||||
subjectWithUser: C_("title", "Log Out %s"),
|
subjectWithUser: _("Log Out %s"),
|
||||||
subject: C_("title", "Log Out"),
|
subject: _("Log Out"),
|
||||||
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
|
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
|
||||||
uninhibitedDescriptionWithUser: function(user, seconds) {
|
uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
|
||||||
return ngettext("%s will be logged out automatically in %d second.",
|
uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
|
||||||
"%s will be logged out automatically in %d seconds.",
|
|
||||||
seconds).format(user, seconds);
|
|
||||||
},
|
|
||||||
uninhibitedDescription: function(seconds) {
|
|
||||||
return ngettext("You will be logged out automatically in %d second.",
|
|
||||||
"You will be logged out automatically in %d seconds.",
|
|
||||||
seconds).format(seconds);
|
|
||||||
},
|
|
||||||
endDescription: _("Logging out of the system."),
|
endDescription: _("Logging out of the system."),
|
||||||
confirmButtons: [{ signal: 'ConfirmedLogout',
|
confirmButtons: [{ signal: 'ConfirmedLogout',
|
||||||
label: C_("button", "Log Out") }],
|
label: _("Log Out") }],
|
||||||
iconStyleClass: 'end-session-dialog-logout-icon'
|
iconStyleClass: 'end-session-dialog-logout-icon'
|
||||||
};
|
};
|
||||||
|
|
||||||
const shutdownDialogContent = {
|
const shutdownDialogContent = {
|
||||||
subject: C_("title", "Power Off"),
|
subject: _("Power Off"),
|
||||||
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
|
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
|
||||||
uninhibitedDescription: function(seconds) {
|
uninhibitedDescription: _("The system will power off automatically in %d seconds."),
|
||||||
return ngettext("The system will power off automatically in %d second.",
|
|
||||||
"The system will power off automatically in %d seconds.",
|
|
||||||
seconds).format(seconds);
|
|
||||||
},
|
|
||||||
endDescription: _("Powering off the system."),
|
endDescription: _("Powering off the system."),
|
||||||
confirmButtons: [{ signal: 'ConfirmedReboot',
|
confirmButtons: [{ signal: 'ConfirmedReboot',
|
||||||
label: C_("button", "Restart") },
|
label: _("Restart") },
|
||||||
{ signal: 'ConfirmedShutdown',
|
{ signal: 'ConfirmedShutdown',
|
||||||
label: C_("button", "Power Off") }],
|
label: _("Power Off") }],
|
||||||
iconName: 'system-shutdown-symbolic',
|
iconName: 'system-shutdown',
|
||||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||||
};
|
};
|
||||||
|
|
||||||
const restartDialogContent = {
|
const restartDialogContent = {
|
||||||
subject: C_("title", "Restart"),
|
subject: _("Restart"),
|
||||||
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
|
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
|
||||||
uninhibitedDescription: function(seconds) {
|
uninhibitedDescription: _("The system will restart automatically in %d seconds."),
|
||||||
return ngettext("The system will restart automatically in %d second.",
|
|
||||||
"The system will restart automatically in %d seconds.",
|
|
||||||
seconds).format(seconds);
|
|
||||||
},
|
|
||||||
endDescription: _("Restarting the system."),
|
endDescription: _("Restarting the system."),
|
||||||
confirmButtons: [{ signal: 'ConfirmedReboot',
|
confirmButtons: [{ signal: 'ConfirmedReboot',
|
||||||
label: C_("button", "Restart") }],
|
label: _("Restart") }],
|
||||||
iconName: 'view-refresh-symbolic',
|
iconName: 'system-shutdown',
|
||||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,17 +99,37 @@ const DialogContent = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function findAppFromInhibitor(inhibitor) {
|
function findAppFromInhibitor(inhibitor) {
|
||||||
let [desktopFile] = inhibitor.GetAppIdSync();
|
let desktopFile = inhibitor.app_id;
|
||||||
|
|
||||||
if (!GLib.str_has_suffix(desktopFile, '.desktop'))
|
if (!GLib.str_has_suffix(desktopFile, '.desktop'))
|
||||||
desktopFile += '.desktop';
|
desktopFile += '.desktop';
|
||||||
|
|
||||||
return Shell.AppSystem.get_default().lookup_heuristic_basename(desktopFile);
|
let candidateDesktopFiles = [];
|
||||||
|
|
||||||
|
candidateDesktopFiles.push(desktopFile);
|
||||||
|
candidateDesktopFiles.push('gnome-' + desktopFile);
|
||||||
|
|
||||||
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
let app = null;
|
||||||
|
for (let i = 0; i < candidateDesktopFiles.length; i++) {
|
||||||
|
try {
|
||||||
|
app = appSystem.get_app(candidateDesktopFiles[i]);
|
||||||
|
|
||||||
|
if (app)
|
||||||
|
break;
|
||||||
|
} catch(e) {
|
||||||
|
// ignore errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListItem = new Lang.Class({
|
function ListItem(app, reason) {
|
||||||
Name: 'ListItem',
|
this._init(app, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItem.prototype = {
|
||||||
_init: function(app, reason) {
|
_init: function(app, reason) {
|
||||||
this._app = app;
|
this._app = app;
|
||||||
this._reason = reason;
|
this._reason = reason;
|
||||||
@ -161,7 +164,6 @@ const ListItem = new Lang.Class({
|
|||||||
|
|
||||||
this._descriptionLabel = new St.Label({ text: this._reason,
|
this._descriptionLabel = new St.Label({ text: this._reason,
|
||||||
style_class: 'end-session-dialog-app-list-item-description' });
|
style_class: 'end-session-dialog-app-list-item-description' });
|
||||||
this.actor.label_actor = this._nameLabel;
|
|
||||||
textLayout.add(this._descriptionLabel,
|
textLayout.add(this._descriptionLabel,
|
||||||
{ expand: true,
|
{ expand: true,
|
||||||
x_fill: true });
|
x_fill: true });
|
||||||
@ -171,9 +173,9 @@ const ListItem = new Lang.Class({
|
|||||||
|
|
||||||
_onClicked: function() {
|
_onClicked: function() {
|
||||||
this.emit('activate');
|
this.emit('activate');
|
||||||
this._app.activate();
|
this._app.activate(-1);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
Signals.addSignalMethods(ListItem.prototype);
|
Signals.addSignalMethods(ListItem.prototype);
|
||||||
|
|
||||||
// The logout timer only shows updates every 10 seconds
|
// The logout timer only shows updates every 10 seconds
|
||||||
@ -211,49 +213,31 @@ function _setLabelText(label, text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EndSessionDialog() {
|
||||||
|
if (_endSessionDialog == null) {
|
||||||
|
this._init();
|
||||||
|
DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
|
||||||
|
this);
|
||||||
|
_endSessionDialog = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _endSessionDialog;
|
||||||
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
// This always returns the same singleton object
|
// This always returns the same singleton object
|
||||||
// By instantiating it initially, we register the
|
// By instantiating it initially, we register the
|
||||||
// bus object, etc.
|
// bus object, etc.
|
||||||
_endSessionDialog = new EndSessionDialog();
|
let dialog = new EndSessionDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
const EndSessionExporter = new Gio.DBusImplementerClass({
|
EndSessionDialog.prototype = {
|
||||||
Name: 'EndSessionExporter',
|
__proto__: ModalDialog.ModalDialog.prototype,
|
||||||
Interface: EndSessionDialogIface,
|
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.parent();
|
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
|
||||||
|
|
||||||
this.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
|
this._user = Gdm.UserManager.ref_default().get_user(GLib.get_user_name());
|
||||||
},
|
|
||||||
|
|
||||||
OpenAsync: function(parameters, invocation) {
|
|
||||||
this.emit('open', parameters, invocation);
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function() {
|
|
||||||
this.emit_signal('Closed');
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel: function() {
|
|
||||||
this.emit_signal('Canceled');
|
|
||||||
},
|
|
||||||
|
|
||||||
confirm: function(type) {
|
|
||||||
this.emit_signal(type);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(EndSessionExporter.prototype);
|
|
||||||
|
|
||||||
const EndSessionDialog = new Lang.Class({
|
|
||||||
Name: 'EndSessionDialog',
|
|
||||||
Extends: ModalDialog.ModalDialog,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ styleClass: 'end-session-dialog' });
|
|
||||||
|
|
||||||
this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
|
|
||||||
|
|
||||||
this._secondsLeft = 0;
|
this._secondsLeft = 0;
|
||||||
this._totalSecondsToStayOpen = 0;
|
this._totalSecondsToStayOpen = 0;
|
||||||
@ -309,22 +293,23 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
scrollView.hide();
|
scrollView.hide();
|
||||||
|
|
||||||
this._applicationList = new St.BoxLayout({ vertical: true });
|
this._applicationList = new St.BoxLayout({ vertical: true });
|
||||||
scrollView.add_actor(this._applicationList);
|
scrollView.add_actor(this._applicationList,
|
||||||
|
{ x_fill: true,
|
||||||
|
y_fill: true,
|
||||||
|
x_align: St.Align.START,
|
||||||
|
y_align: St.Align.MIDDLE });
|
||||||
|
|
||||||
this._applicationList.connect('actor-added',
|
this._applicationList.connect('actor-added',
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
if (this._applicationList.get_n_children() == 1)
|
if (this._applicationList.get_children().length == 1)
|
||||||
scrollView.show();
|
scrollView.show();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._applicationList.connect('actor-removed',
|
this._applicationList.connect('actor-removed',
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
if (this._applicationList.get_n_children() == 0)
|
if (this._applicationList.get_children().length == 0)
|
||||||
scrollView.hide();
|
scrollView.hide();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._exporter = new EndSessionExporter();
|
|
||||||
this._exporter.connect('open', Lang.bind(this, this._onOpenRequest));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
@ -332,7 +317,41 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
this._user.disconnect(this._userChangedId);
|
this._user.disconnect(this._userChangedId);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateDescription: function() {
|
_setIconFromFile: function(iconFile, styleClass) {
|
||||||
|
if (styleClass)
|
||||||
|
this._iconBin.set_style_class_name(styleClass);
|
||||||
|
this._iconBin.set_style(null);
|
||||||
|
|
||||||
|
this._iconBin.child = null;
|
||||||
|
if (iconFile) {
|
||||||
|
this._iconBin.show();
|
||||||
|
this._iconBin.set_style('background-image: url("' + iconFile + '");');
|
||||||
|
} else {
|
||||||
|
this._iconBin.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_setIconFromName: function(iconName, styleClass) {
|
||||||
|
if (styleClass)
|
||||||
|
this._iconBin.set_style_class_name(styleClass);
|
||||||
|
this._iconBin.set_style(null);
|
||||||
|
|
||||||
|
if (iconName != null) {
|
||||||
|
let textureCache = St.TextureCache.get_default();
|
||||||
|
let icon = textureCache.load_icon_name(this._iconBin.get_theme_node(),
|
||||||
|
iconName,
|
||||||
|
St.IconType.SYMBOLIC,
|
||||||
|
_DIALOG_ICON_SIZE);
|
||||||
|
|
||||||
|
this._iconBin.child = icon;
|
||||||
|
this._iconBin.show();
|
||||||
|
} else {
|
||||||
|
this._iconBin.child = null;
|
||||||
|
this._iconBin.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateContent: function() {
|
||||||
if (this.state != ModalDialog.State.OPENING &&
|
if (this.state != ModalDialog.State.OPENING &&
|
||||||
this.state != ModalDialog.State.OPENED)
|
this.state != ModalDialog.State.OPENED)
|
||||||
return;
|
return;
|
||||||
@ -342,6 +361,17 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
let subject = dialogContent.subject;
|
let subject = dialogContent.subject;
|
||||||
let description;
|
let description;
|
||||||
|
|
||||||
|
if (this._user.is_loaded && !dialogContent.iconName) {
|
||||||
|
let iconFile = this._user.get_icon_file();
|
||||||
|
if (GLib.file_test(iconFile, GLib.FileTest.EXISTS))
|
||||||
|
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
|
||||||
|
else
|
||||||
|
this._setIconFromName('avatar-default', dialogContent.iconStyleClass);
|
||||||
|
} else if (dialogContent.iconName) {
|
||||||
|
this._setIconFromName(dialogContent.iconName,
|
||||||
|
dialogContent.iconStyleClass);
|
||||||
|
}
|
||||||
|
|
||||||
if (this._inhibitors.length > 0) {
|
if (this._inhibitors.length > 0) {
|
||||||
this._stopTimer();
|
this._stopTimer();
|
||||||
description = dialogContent.inhibitedDescription;
|
description = dialogContent.inhibitedDescription;
|
||||||
@ -358,14 +388,14 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
subject = dialogContent.subjectWithUser.format(realName);
|
subject = dialogContent.subjectWithUser.format(realName);
|
||||||
|
|
||||||
if (dialogContent.uninhibitedDescriptionWithUser)
|
if (dialogContent.uninhibitedDescriptionWithUser)
|
||||||
description = dialogContent.uninhibitedDescriptionWithUser(realName, displayTime);
|
description = dialogContent.uninhibitedDescriptionWithUser.format(realName, displayTime);
|
||||||
else
|
else
|
||||||
description = dialogContent.uninhibitedDescription(displayTime);
|
description = dialogContent.uninhibitedDescription.format(displayTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!description)
|
if (!description)
|
||||||
description = dialogContent.uninhibitedDescription(displayTime);
|
description = dialogContent.uninhibitedDescription.format(displayTime);
|
||||||
} else {
|
} else {
|
||||||
description = dialogContent.endDescription;
|
description = dialogContent.endDescription;
|
||||||
}
|
}
|
||||||
@ -374,27 +404,6 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
_setLabelText(this._descriptionLabel, description);
|
_setLabelText(this._descriptionLabel, description);
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateContent: function() {
|
|
||||||
if (this.state != ModalDialog.State.OPENING &&
|
|
||||||
this.state != ModalDialog.State.OPENED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let dialogContent = DialogContent[this._type];
|
|
||||||
if (dialogContent.iconName) {
|
|
||||||
this._iconBin.child = new St.Icon({ icon_name: dialogContent.iconName,
|
|
||||||
icon_size: _DIALOG_ICON_SIZE,
|
|
||||||
style_class: dialogContent.iconStyleClass });
|
|
||||||
} else {
|
|
||||||
let avatarWidget = new UserMenu.UserAvatarWidget(this._user,
|
|
||||||
{ iconSize: _DIALOG_ICON_SIZE,
|
|
||||||
styleClass: dialogContent.iconStyleClass });
|
|
||||||
this._iconBin.child = avatarWidget.actor;
|
|
||||||
avatarWidget.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateDescription();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateButtons: function() {
|
_updateButtons: function() {
|
||||||
let dialogContent = DialogContent[this._type];
|
let dialogContent = DialogContent[this._type];
|
||||||
let buttons = [{ action: Lang.bind(this, this.cancel),
|
let buttons = [{ action: Lang.bind(this, this.cancel),
|
||||||
@ -414,20 +423,26 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
this.parent();
|
ModalDialog.ModalDialog.prototype.close.call(this);
|
||||||
this._exporter.close();
|
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||||
|
'org.gnome.SessionManager.EndSessionDialog',
|
||||||
|
'Closed', '', []);
|
||||||
},
|
},
|
||||||
|
|
||||||
cancel: function() {
|
cancel: function() {
|
||||||
this._stopTimer();
|
this._stopTimer();
|
||||||
this._exporter.cancel();
|
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||||
|
'org.gnome.SessionManager.EndSessionDialog',
|
||||||
|
'Canceled', '', []);
|
||||||
this.close(global.get_current_time());
|
this.close(global.get_current_time());
|
||||||
},
|
},
|
||||||
|
|
||||||
_confirm: function(signal) {
|
_confirm: function(signal) {
|
||||||
this._fadeOutDialog();
|
this._fadeOutDialog();
|
||||||
this._stopTimer();
|
this._stopTimer();
|
||||||
this._exporter.confirm(signal);
|
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||||
|
'org.gnome.SessionManager.EndSessionDialog',
|
||||||
|
signal, '', []);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onOpened: function() {
|
_onOpened: function() {
|
||||||
@ -441,7 +456,7 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
{ _secondsLeft: 0,
|
{ _secondsLeft: 0,
|
||||||
time: this._secondsLeft,
|
time: this._secondsLeft,
|
||||||
transition: 'linear',
|
transition: 'linear',
|
||||||
onUpdate: Lang.bind(this, this._updateDescription),
|
onUpdate: Lang.bind(this, this._updateContent),
|
||||||
onComplete: Lang.bind(this, function() {
|
onComplete: Lang.bind(this, function() {
|
||||||
let dialogContent = DialogContent[this._type];
|
let dialogContent = DialogContent[this._type];
|
||||||
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
|
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
|
||||||
@ -464,8 +479,7 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
let app = findAppFromInhibitor(inhibitor);
|
let app = findAppFromInhibitor(inhibitor);
|
||||||
|
|
||||||
if (app) {
|
if (app) {
|
||||||
let [reason] = inhibitor.GetReasonSync();
|
let item = new ListItem(app, inhibitor.reason);
|
||||||
let item = new ListItem(app, reason);
|
|
||||||
item.connect('activate',
|
item.connect('activate',
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
this.close(global.get_current_time());
|
this.close(global.get_current_time());
|
||||||
@ -480,44 +494,39 @@ const EndSessionDialog = new Lang.Class({
|
|||||||
this._updateContent();
|
this._updateContent();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onOpenRequest: function(exporter, parameters, invocation) {
|
OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
|
||||||
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
|
|
||||||
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
|
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
|
||||||
this._inhibitors = [];
|
this._inhibitors = [];
|
||||||
this._applicationList.destroy_all_children();
|
this._applicationList.destroy_children();
|
||||||
this._type = type;
|
this._type = type;
|
||||||
|
|
||||||
if (!(this._type in DialogContent)) {
|
if (!(this._type in DialogContent))
|
||||||
invocation.return_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
|
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
|
||||||
"Unknown dialog type requested");
|
"Unknown dialog type requested");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
|
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
|
||||||
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
|
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
|
||||||
inhibitor.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(proxy, result) {
|
|
||||||
proxy.init_finish(result);
|
|
||||||
|
|
||||||
this._onInhibitorLoaded(proxy);
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
inhibitor.connect('is-loaded',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
this._onInhibitorLoaded(inhibitor);
|
||||||
|
}));
|
||||||
this._inhibitors.push(inhibitor);
|
this._inhibitors.push(inhibitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._updateButtons();
|
this._updateButtons();
|
||||||
|
|
||||||
if (!this.open(timestamp)) {
|
if (!this.open(timestamp))
|
||||||
invocation.return_dbus_error('org.gnome.Shell.ModalDialog.GrabError',
|
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
|
||||||
"Cannot grab pointer and keyboard");
|
"Cannot grab pointer and keyboard");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateContent();
|
this._updateContent();
|
||||||
|
|
||||||
let signalId = this.connect('opened',
|
let signalId = this.connect('opened',
|
||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
invocation.return_value(null);
|
callback();
|
||||||
this.disconnect(signalId);
|
this.disconnect(signalId);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
imports.gi.versions.Clutter = '1.0';
|
imports.gi.versions.Clutter = '1.0';
|
||||||
imports.gi.versions.Gio = '2.0';
|
imports.gi.versions.Gio = '2.0';
|
||||||
@ -39,23 +39,20 @@ function _patchContainerClass(containerClass) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function _makeLoggingFunc(func) {
|
|
||||||
return function() {
|
|
||||||
return func([].join.call(arguments, ', '));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
// Add some bindings to the global JS namespace; (gjs keeps the web
|
// Add some bindings to the global JS namespace; (gjs keeps the web
|
||||||
// browser convention of having that namespace be called 'window'.)
|
// browser convention of having that namespace be called 'window'.)
|
||||||
window.global = Shell.Global.get();
|
window.global = Shell.Global.get();
|
||||||
|
|
||||||
window.log = _makeLoggingFunc(window.log);
|
|
||||||
|
|
||||||
window._ = Gettext.gettext;
|
window._ = Gettext.gettext;
|
||||||
window.C_ = Gettext.pgettext;
|
window.C_ = Gettext.pgettext;
|
||||||
window.ngettext = Gettext.ngettext;
|
window.ngettext = Gettext.ngettext;
|
||||||
|
|
||||||
|
// Set the default direction for St widgets (this needs to be done before any use of St)
|
||||||
|
if (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL) {
|
||||||
|
St.Widget.set_default_direction(St.TextDirection.RTL);
|
||||||
|
}
|
||||||
|
|
||||||
// Miscellaneous monkeypatching
|
// Miscellaneous monkeypatching
|
||||||
_patchContainerClass(St.BoxLayout);
|
_patchContainerClass(St.BoxLayout);
|
||||||
_patchContainerClass(St.Table);
|
_patchContainerClass(St.Table);
|
||||||
@ -67,14 +64,10 @@ function init() {
|
|||||||
let origToString = Object.prototype.toString;
|
let origToString = Object.prototype.toString;
|
||||||
Object.prototype.toString = function() {
|
Object.prototype.toString = function() {
|
||||||
let base = origToString.call(this);
|
let base = origToString.call(this);
|
||||||
try {
|
if ('actor' in this && this.actor instanceof Clutter.Actor)
|
||||||
if ('actor' in this && this.actor instanceof Clutter.Actor)
|
return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
|
||||||
return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
|
else
|
||||||
else
|
|
||||||
return base;
|
|
||||||
} catch(e) {
|
|
||||||
return base;
|
return base;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
|
||||||
@ -90,7 +83,7 @@ function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OK, now things are initialized enough that we can import shell JS
|
// OK, now things are initialized enough that we can import shell JS
|
||||||
const Format = imports.format;
|
const Format = imports.misc.format;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
Tweener.init();
|
Tweener.init();
|
||||||
|
@ -1,270 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Soup = imports.gi.Soup;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
|
|
||||||
const Config = imports.misc.config;
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
const ExtensionSystem = imports.ui.extensionSystem;
|
|
||||||
const FileUtils = imports.misc.fileUtils;
|
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
|
||||||
|
|
||||||
const _signals = ExtensionSystem._signals;
|
|
||||||
|
|
||||||
const REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
|
|
||||||
const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
|
|
||||||
const REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
|
|
||||||
const REPOSITORY_URL_UPDATE = REPOSITORY_URL_BASE + '/update-info/';
|
|
||||||
|
|
||||||
let _httpSession;
|
|
||||||
|
|
||||||
function installExtension(uuid, invocation) {
|
|
||||||
let params = { uuid: uuid,
|
|
||||||
shell_version: Config.PACKAGE_VERSION };
|
|
||||||
|
|
||||||
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
|
|
||||||
|
|
||||||
_httpSession.queue_message(message, function(session, message) {
|
|
||||||
if (message.status_code != Soup.KnownStatusCode.OK) {
|
|
||||||
ExtensionSystem.logExtensionError(uuid, 'downloading info: ' + message.status_code);
|
|
||||||
invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let info;
|
|
||||||
try {
|
|
||||||
info = JSON.parse(message.response_body.data);
|
|
||||||
} catch (e) {
|
|
||||||
ExtensionSystem.logExtensionError(uuid, 'parsing info: ' + e);
|
|
||||||
invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dialog = new InstallExtensionDialog(uuid, info, invocation);
|
|
||||||
dialog.open(global.get_current_time());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function uninstallExtension(uuid) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
if (!extension)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Don't try to uninstall system extensions
|
|
||||||
if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!ExtensionSystem.unloadExtension(extension))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
FileUtils.recursivelyDeleteDir(extension.dir, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
|
|
||||||
if (message.status_code != Soup.KnownStatusCode.OK) {
|
|
||||||
errback('DownloadExtensionError', message.status_code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!dir.query_exists(null))
|
|
||||||
dir.make_directory_with_parents(null);
|
|
||||||
} catch (e) {
|
|
||||||
errback('CreateExtensionDirectoryError', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip');
|
|
||||||
let contents = message.response_body.flatten().get_as_bytes();
|
|
||||||
stream.output_stream.write_bytes(contents, null);
|
|
||||||
stream.close(null);
|
|
||||||
let [success, pid] = GLib.spawn_async(null,
|
|
||||||
['unzip', '-uod', dir.get_path(), '--', file.get_path()],
|
|
||||||
null,
|
|
||||||
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
|
|
||||||
null);
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
errback('ExtractExtensionError');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) {
|
|
||||||
GLib.spawn_close_pid(pid);
|
|
||||||
|
|
||||||
if (status != 0)
|
|
||||||
errback('ExtractExtensionError');
|
|
||||||
else
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateExtension(uuid) {
|
|
||||||
// This gets a bit tricky. We want the update to be seamless -
|
|
||||||
// if we have any error during downloading or extracting, we
|
|
||||||
// want to not unload the current version.
|
|
||||||
|
|
||||||
let oldExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension');
|
|
||||||
let newExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension');
|
|
||||||
|
|
||||||
let params = { shell_version: Config.PACKAGE_VERSION };
|
|
||||||
|
|
||||||
let url = REPOSITORY_URL_DOWNLOAD.format(uuid);
|
|
||||||
let message = Soup.form_request_new_from_hash('GET', url, params);
|
|
||||||
|
|
||||||
_httpSession.queue_message(message, Lang.bind(this, function(session, message) {
|
|
||||||
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, function() {
|
|
||||||
let oldExtension = ExtensionUtils.extensions[uuid];
|
|
||||||
let extensionDir = oldExtension.dir;
|
|
||||||
|
|
||||||
if (!ExtensionSystem.unloadExtension(oldExtension))
|
|
||||||
return;
|
|
||||||
|
|
||||||
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
|
|
||||||
FileUtils.recursivelyMoveDir(newExtensionTmpDir, extensionDir);
|
|
||||||
|
|
||||||
let extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ExtensionSystem.loadExtension(extension);
|
|
||||||
} catch(e) {
|
|
||||||
ExtensionSystem.unloadExtension(extension);
|
|
||||||
|
|
||||||
logError(e, 'Error loading extension %s'.format(uuid));
|
|
||||||
|
|
||||||
FileUtils.recursivelyDeleteDir(extensionDir, false);
|
|
||||||
FileUtils.recursivelyMoveDir(oldExtensionTmpDir, extensionDir);
|
|
||||||
|
|
||||||
// Restore what was there before. We can't do much if we
|
|
||||||
// fail here.
|
|
||||||
ExtensionSystem.loadExtension(oldExtension);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileUtils.recursivelyDeleteDir(oldExtensionTmpDir, true);
|
|
||||||
}, function(code, message) {
|
|
||||||
log('Error while updating extension %s: %s (%s)'.format(uuid, code, message ? message : ''));
|
|
||||||
});
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkForUpdates() {
|
|
||||||
let metadatas = {};
|
|
||||||
for (let uuid in ExtensionUtils.extensions) {
|
|
||||||
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
let params = { shell_version: Config.PACKAGE_VERSION,
|
|
||||||
installed: JSON.stringify(metadatas) };
|
|
||||||
|
|
||||||
let url = REPOSITORY_URL_UPDATE;
|
|
||||||
let message = Soup.form_request_new_from_hash('GET', url, params);
|
|
||||||
_httpSession.queue_message(message, function(session, message) {
|
|
||||||
if (message.status_code != Soup.KnownStatusCode.OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let operations = JSON.parse(message.response_body.data);
|
|
||||||
for (let uuid in operations) {
|
|
||||||
let operation = operations[uuid];
|
|
||||||
if (operation == 'blacklist')
|
|
||||||
uninstallExtension(uuid);
|
|
||||||
else if (operation == 'upgrade' || operation == 'downgrade')
|
|
||||||
updateExtension(uuid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const InstallExtensionDialog = new Lang.Class({
|
|
||||||
Name: 'InstallExtensionDialog',
|
|
||||||
Extends: ModalDialog.ModalDialog,
|
|
||||||
|
|
||||||
_init: function(uuid, info, invocation) {
|
|
||||||
this.parent({ styleClass: 'extension-dialog' });
|
|
||||||
|
|
||||||
this._uuid = uuid;
|
|
||||||
this._info = info;
|
|
||||||
this._invocation = invocation;
|
|
||||||
|
|
||||||
this.setButtons([{ label: _("Cancel"),
|
|
||||||
action: Lang.bind(this, this._onCancelButtonPressed),
|
|
||||||
key: Clutter.Escape
|
|
||||||
},
|
|
||||||
{ label: _("Install"),
|
|
||||||
action: Lang.bind(this, this._onInstallButtonPressed),
|
|
||||||
default: true
|
|
||||||
}]);
|
|
||||||
|
|
||||||
let message = _("Download and install '%s' from extensions.gnome.org?").format(info.name);
|
|
||||||
|
|
||||||
let box = new St.BoxLayout();
|
|
||||||
this.contentLayout.add(box);
|
|
||||||
|
|
||||||
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
|
|
||||||
let icon = new St.Icon({ gicon: gicon });
|
|
||||||
box.add(icon);
|
|
||||||
|
|
||||||
let label = new St.Label({ text: message });
|
|
||||||
box.add(label);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCancelButtonPressed: function(button, event) {
|
|
||||||
this.close(global.get_current_time());
|
|
||||||
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
|
|
||||||
},
|
|
||||||
|
|
||||||
_onInstallButtonPressed: function(button, event) {
|
|
||||||
let params = { shell_version: Config.PACKAGE_VERSION };
|
|
||||||
|
|
||||||
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
|
|
||||||
let message = Soup.form_request_new_from_hash('GET', url, params);
|
|
||||||
|
|
||||||
let uuid = this._uuid;
|
|
||||||
let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
|
|
||||||
let invocation = this._invocation;
|
|
||||||
function errback(code, message) {
|
|
||||||
invocation.return_dbus_error('org.gnome.Shell.' + code, message ? message.toString() : '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function callback() {
|
|
||||||
// Add extension to 'enabled-extensions' for the user, always...
|
|
||||||
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
|
|
||||||
if (enabledExtensions.indexOf(uuid) == -1) {
|
|
||||||
enabledExtensions.push(uuid);
|
|
||||||
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ExtensionSystem.loadExtension(extension);
|
|
||||||
} catch(e) {
|
|
||||||
uninstallExtension(uuid);
|
|
||||||
errback('LoadExtensionError', e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
invocation.return_value(GLib.Variant.new('(s)', 'successful'));
|
|
||||||
}
|
|
||||||
|
|
||||||
_httpSession.queue_message(message, Lang.bind(this, function(session, message) {
|
|
||||||
gotExtensionZipFile(session, message, uuid, dir, callback, errback);
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.close(global.get_current_time());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });
|
|
||||||
|
|
||||||
// See: https://bugzilla.gnome.org/show_bug.cgi?id=655189 for context.
|
|
||||||
// _httpSession.add_feature(new Soup.ProxyResolverDefault());
|
|
||||||
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
|
|
||||||
}
|
|
@ -1,306 +1,219 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
const Config = imports.misc.config;
|
||||||
const Main = imports.ui.main;
|
|
||||||
|
|
||||||
const ExtensionState = {
|
const ExtensionState = {
|
||||||
ENABLED: 1,
|
ENABLED: 1,
|
||||||
DISABLED: 2,
|
DISABLED: 2,
|
||||||
ERROR: 3,
|
ERROR: 3,
|
||||||
OUT_OF_DATE: 4,
|
OUT_OF_DATE: 4
|
||||||
DOWNLOADING: 5,
|
|
||||||
INITIALIZED: 6,
|
|
||||||
|
|
||||||
// Used as an error state for operations on unknown extensions,
|
|
||||||
// should never be in a real extensionMeta object.
|
|
||||||
UNINSTALLED: 99
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ExtensionType = {
|
||||||
|
SYSTEM: 1,
|
||||||
|
PER_USER: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
// Maps uuid -> metadata object
|
||||||
|
const extensionMeta = {};
|
||||||
|
// Maps uuid -> importer object (extension directory tree)
|
||||||
|
const extensions = {};
|
||||||
// Arrays of uuids
|
// Arrays of uuids
|
||||||
|
var disabledExtensions;
|
||||||
var enabledExtensions;
|
var enabledExtensions;
|
||||||
// Contains the order that extensions were enabled in.
|
// GFile for user extensions
|
||||||
const extensionOrder = [];
|
var userExtensionsDir = null;
|
||||||
|
|
||||||
// We don't really have a class to add signals on. So, create
|
/**
|
||||||
// a simple dummy object, add the signal methods, and export those
|
* versionCheck:
|
||||||
// publically.
|
* @required: an array of versions we're compatible with
|
||||||
var _signals = {};
|
* @current: the version we have
|
||||||
Signals.addSignalMethods(_signals);
|
*
|
||||||
|
* Check if a component is compatible for an extension.
|
||||||
|
* @required is an array, and at least one version must match.
|
||||||
|
* @current must be in the format <major>.<minor>.<point>.<micro>
|
||||||
|
* <micro> is always ignored
|
||||||
|
* <point> is ignored if <minor> is even (so you can target the
|
||||||
|
* whole stable release)
|
||||||
|
* <minor> and <major> must match
|
||||||
|
* Each target version must be at least <major> and <minor>
|
||||||
|
*/
|
||||||
|
function versionCheck(required, current) {
|
||||||
|
let currentArray = current.split('.');
|
||||||
|
let major = currentArray[0];
|
||||||
|
let minor = currentArray[1];
|
||||||
|
let point = currentArray[2];
|
||||||
|
for (let i = 0; i < required.length; i++) {
|
||||||
|
let requiredArray = required[i].split('.');
|
||||||
|
if (requiredArray[0] == major &&
|
||||||
|
requiredArray[1] == minor &&
|
||||||
|
(requiredArray[2] == point ||
|
||||||
|
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const connect = Lang.bind(_signals, _signals.connect);
|
function loadExtension(dir, enabled, type) {
|
||||||
const disconnect = Lang.bind(_signals, _signals.disconnect);
|
let info;
|
||||||
|
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
|
||||||
|
|
||||||
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
|
let metadataFile = dir.get_child('metadata.json');
|
||||||
|
if (!metadataFile.query_exists(null)) {
|
||||||
var initted = false;
|
global.logError(baseErrorString + 'Missing metadata.json');
|
||||||
var enabled;
|
|
||||||
|
|
||||||
function disableExtension(uuid) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
if (!extension)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (extension.state != ExtensionState.ENABLED)
|
let metadataContents;
|
||||||
|
try {
|
||||||
|
metadataContents = Shell.get_file_contents_utf8_sync(metadataFile.get_path());
|
||||||
|
} catch (e) {
|
||||||
|
global.logError(baseErrorString + 'Failed to load metadata.json: ' + e);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
// "Rebase" the extension order by disabling and then enabling extensions
|
let meta;
|
||||||
// in order to help prevent conflicts.
|
try {
|
||||||
|
meta = JSON.parse(metadataContents);
|
||||||
// Example:
|
} catch (e) {
|
||||||
// order = [A, B, C, D, E]
|
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
|
||||||
// user disables C
|
return;
|
||||||
// this should: disable E, disable D, disable C, enable D, enable E
|
}
|
||||||
|
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
|
||||||
let orderIdx = extensionOrder.indexOf(uuid);
|
for (let i = 0; i < requiredProperties.length; i++) {
|
||||||
let order = extensionOrder.slice(orderIdx + 1);
|
let prop = requiredProperties[i];
|
||||||
let orderReversed = order.slice().reverse();
|
if (!meta[prop]) {
|
||||||
|
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
|
||||||
for (let i = 0; i < orderReversed.length; i++) {
|
return;
|
||||||
let uuid = orderReversed[i];
|
|
||||||
try {
|
|
||||||
ExtensionUtils.extensions[uuid].stateObj.disable();
|
|
||||||
} catch(e) {
|
|
||||||
logExtensionError(uuid, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension.stylesheet) {
|
if (extensions[meta.uuid] != undefined) {
|
||||||
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
global.logError(baseErrorString + "extension already loaded");
|
||||||
theme.unload_stylesheet(extension.stylesheet.get_path());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extension.stateObj.disable();
|
// Encourage people to add this
|
||||||
|
if (!meta['url']) {
|
||||||
for (let i = 0; i < order.length; i++) {
|
global.log(baseErrorString + 'Warning: Missing "url" property in metadata.json');
|
||||||
let uuid = order[i];
|
|
||||||
try {
|
|
||||||
ExtensionUtils.extensions[uuid].stateObj.enable();
|
|
||||||
} catch(e) {
|
|
||||||
logExtensionError(uuid, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionOrder.splice(orderIdx, 1);
|
let base = dir.get_basename();
|
||||||
|
if (base != meta.uuid) {
|
||||||
extension.state = ExtensionState.DISABLED;
|
global.logError(baseErrorString + 'uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + base + '"');
|
||||||
_signals.emit('extension-state-changed', extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
function enableExtension(uuid) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
if (!extension)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (extension.state == ExtensionState.INITIALIZED)
|
|
||||||
initExtension(uuid);
|
|
||||||
|
|
||||||
if (extension.state != ExtensionState.DISABLED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
extensionOrder.push(uuid);
|
|
||||||
|
|
||||||
let stylesheetFile = extension.dir.get_child('stylesheet.css');
|
|
||||||
if (stylesheetFile.query_exists(null)) {
|
|
||||||
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
|
|
||||||
theme.load_stylesheet(stylesheetFile.get_path());
|
|
||||||
extension.stylesheet = stylesheetFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension.stateObj.enable();
|
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
|
||||||
|
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
|
||||||
extension.state = ExtensionState.ENABLED;
|
global.logError(baseErrorString + 'extension is not compatible with current GNOME Shell and/or GJS version');
|
||||||
_signals.emit('extension-state-changed', extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
function logExtensionError(uuid, error) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
if (!extension)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let message = '' + error;
|
extensionMeta[meta.uuid] = meta;
|
||||||
|
extensionMeta[meta.uuid].type = type;
|
||||||
|
extensionMeta[meta.uuid].path = dir.get_path();
|
||||||
|
if (!enabled) {
|
||||||
|
extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (error.state)
|
|
||||||
extension.state = error.state;
|
|
||||||
else
|
|
||||||
extension.state = ExtensionState.ERROR;
|
|
||||||
|
|
||||||
if (!extension.errors)
|
|
||||||
extension.errors = [];
|
|
||||||
|
|
||||||
log('Extension "%s" had error: %s'.format(uuid, message));
|
|
||||||
_signals.emit('extension-state-changed', { uuid: uuid,
|
|
||||||
error: message,
|
|
||||||
state: extension.state });
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadExtension(extension) {
|
|
||||||
// Default to error, we set success as the last step
|
// Default to error, we set success as the last step
|
||||||
extension.state = ExtensionState.ERROR;
|
extensionMeta[meta.uuid].state = ExtensionState.ERROR;
|
||||||
|
|
||||||
if (ExtensionUtils.isOutOfDate(extension)) {
|
|
||||||
let error = new Error('extension is not compatible with current GNOME Shell and/or GJS version');
|
|
||||||
error.state = ExtensionState.OUT_OF_DATE;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
|
|
||||||
if (enabled) {
|
|
||||||
initExtension(extension.uuid);
|
|
||||||
if (extension.state == ExtensionState.DISABLED)
|
|
||||||
enableExtension(extension.uuid);
|
|
||||||
} else {
|
|
||||||
extension.state = ExtensionState.INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
_signals.emit('extension-state-changed', extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unloadExtension(extension) {
|
|
||||||
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
|
|
||||||
// but it will be removed on next reboot, and hopefully nothing
|
|
||||||
// broke too much.
|
|
||||||
disableExtension(extension.uuid);
|
|
||||||
|
|
||||||
extension.state = ExtensionState.UNINSTALLED;
|
|
||||||
_signals.emit('extension-state-changed', extension);
|
|
||||||
|
|
||||||
delete ExtensionUtils.extensions[extension.uuid];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reloadExtension(oldExtension) {
|
|
||||||
// Grab the things we'll need to pass to createExtensionObject
|
|
||||||
// to reload it.
|
|
||||||
let { uuid: uuid, dir: dir, type: type } = oldExtension;
|
|
||||||
|
|
||||||
// Then unload the old extension.
|
|
||||||
unloadExtension(oldExtension);
|
|
||||||
|
|
||||||
// Now, recreate the extension and load it.
|
|
||||||
let newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
|
|
||||||
loadExtension(newExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
function initExtension(uuid) {
|
|
||||||
let extension = ExtensionUtils.extensions[uuid];
|
|
||||||
let dir = extension.dir;
|
|
||||||
|
|
||||||
if (!extension)
|
|
||||||
throw new Error("Extension was not properly created. Call loadExtension first");
|
|
||||||
|
|
||||||
let extensionJs = dir.get_child('extension.js');
|
let extensionJs = dir.get_child('extension.js');
|
||||||
if (!extensionJs.query_exists(null))
|
if (!extensionJs.query_exists(null)) {
|
||||||
throw new Error('Missing extension.js');
|
global.logError(baseErrorString + 'Missing extension.js');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let stylesheetPath = null;
|
||||||
|
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||||
|
let theme = themeContext.get_theme();
|
||||||
|
let stylesheetFile = dir.get_child('stylesheet.css');
|
||||||
|
if (stylesheetFile.query_exists(null)) {
|
||||||
|
try {
|
||||||
|
theme.load_stylesheet(stylesheetFile.get_path());
|
||||||
|
} catch (e) {
|
||||||
|
global.logError(baseErrorString + 'Stylesheet parse error: ' + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let extensionModule;
|
let extensionModule;
|
||||||
let extensionState = null;
|
try {
|
||||||
|
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
|
||||||
ExtensionUtils.installImporter(extension);
|
extensionModule = extensions[meta.uuid].extension;
|
||||||
extensionModule = extension.imports.extension;
|
} catch (e) {
|
||||||
|
if (stylesheetPath != null)
|
||||||
if (extensionModule.init) {
|
theme.unload_stylesheet(stylesheetPath);
|
||||||
extensionState = extensionModule.init(extension);
|
global.logError(baseErrorString + e);
|
||||||
}
|
|
||||||
|
|
||||||
if (!extensionState)
|
|
||||||
extensionState = extensionModule;
|
|
||||||
extension.stateObj = extensionState;
|
|
||||||
|
|
||||||
extension.state = ExtensionState.DISABLED;
|
|
||||||
_signals.emit('extension-loaded', uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEnabledExtensionsChanged() {
|
|
||||||
let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Find and enable all the newly enabled extensions: UUIDs found in the
|
|
||||||
// new setting, but not in the old one.
|
|
||||||
newEnabledExtensions.filter(function(uuid) {
|
|
||||||
return enabledExtensions.indexOf(uuid) == -1;
|
|
||||||
}).forEach(function(uuid) {
|
|
||||||
try {
|
|
||||||
enableExtension(uuid);
|
|
||||||
} catch(e) {
|
|
||||||
logExtensionError(uuid, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find and disable all the newly disabled extensions: UUIDs found in the
|
|
||||||
// old setting, but not in the new one.
|
|
||||||
enabledExtensions.filter(function(item) {
|
|
||||||
return newEnabledExtensions.indexOf(item) == -1;
|
|
||||||
}).forEach(function(uuid) {
|
|
||||||
try {
|
|
||||||
disableExtension(uuid);
|
|
||||||
} catch(e) {
|
|
||||||
logExtensionError(uuid, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
enabledExtensions = newEnabledExtensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _loadExtensions() {
|
|
||||||
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
|
|
||||||
enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
|
||||||
|
|
||||||
let finder = new ExtensionUtils.ExtensionFinder();
|
|
||||||
finder.connect('extension-found', function(signals, extension) {
|
|
||||||
try {
|
|
||||||
loadExtension(extension);
|
|
||||||
} catch(e) {
|
|
||||||
logExtensionError(extension.uuid, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
finder.scanExtensions();
|
|
||||||
}
|
|
||||||
|
|
||||||
function enableAllExtensions() {
|
|
||||||
if (enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!initted) {
|
|
||||||
_loadExtensions();
|
|
||||||
initted = true;
|
|
||||||
} else {
|
|
||||||
enabledExtensions.forEach(function(uuid) {
|
|
||||||
enableExtension(uuid);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
enabled = true;
|
if (!extensionModule.main) {
|
||||||
}
|
global.logError(baseErrorString + 'missing \'main\' function');
|
||||||
|
|
||||||
function disableAllExtensions() {
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (initted) {
|
|
||||||
enabledExtensions.forEach(function(uuid) {
|
|
||||||
disableExtension(uuid);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
enabled = false;
|
extensionModule.main(meta);
|
||||||
}
|
} catch (e) {
|
||||||
|
if (stylesheetPath != null)
|
||||||
function _sessionUpdated() {
|
theme.unload_stylesheet(stylesheetPath);
|
||||||
if (Main.sessionMode.allowExtensions)
|
global.logError(baseErrorString + 'Failed to evaluate main function:' + e);
|
||||||
enableAllExtensions();
|
return;
|
||||||
else
|
}
|
||||||
disableAllExtensions();
|
extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
|
||||||
|
global.log('Loaded extension ' + meta.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
Main.sessionMode.connect('updated', _sessionUpdated);
|
let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
|
||||||
_sessionUpdated();
|
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
|
||||||
|
try {
|
||||||
|
userExtensionsDir.make_directory_with_parents(null);
|
||||||
|
} catch (e) {
|
||||||
|
global.logError('' + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
disabledExtensions = global.settings.get_strv('disabled-extensions', -1);
|
||||||
|
enabledExtensions = global.settings.get_strv('enabled-extensions', -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _loadExtensionsIn(dir, type) {
|
||||||
|
let fileEnum;
|
||||||
|
let file, info;
|
||||||
|
try {
|
||||||
|
fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
|
||||||
|
} catch (e) {
|
||||||
|
global.logError('' + e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((info = fileEnum.next_file(null)) != null) {
|
||||||
|
let fileType = info.get_file_type();
|
||||||
|
if (fileType != Gio.FileType.DIRECTORY)
|
||||||
|
continue;
|
||||||
|
let name = info.get_name();
|
||||||
|
// Enable all but disabled extensions if enabledExtensions is not set.
|
||||||
|
// If it is set, enable one those, except they are disabled as well.
|
||||||
|
let enabled = (enabledExtensions.length == 0 || enabledExtensions.indexOf(name) >= 0)
|
||||||
|
&& disabledExtensions.indexOf(name) < 0;
|
||||||
|
let child = dir.get_child(name);
|
||||||
|
loadExtension(child, enabled, type);
|
||||||
|
}
|
||||||
|
fileEnum.close(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadExtensions() {
|
||||||
|
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
|
||||||
|
let systemDataDirs = GLib.get_system_data_dirs();
|
||||||
|
for (let i = 0; i < systemDataDirs.length; i++) {
|
||||||
|
let dirPath = systemDataDirs[i] + '/gnome-shell/extensions';
|
||||||
|
let dir = Gio.file_new_for_path(dirPath);
|
||||||
|
if (dir.query_exists(null))
|
||||||
|
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Lang = imports.lang;
|
|
||||||
|
|
||||||
const Lightbox = imports.ui.lightbox;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Tweener = imports.ui.tweener;
|
|
||||||
|
|
||||||
const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
|
|
||||||
|
|
||||||
const Flashspot = new Lang.Class({
|
|
||||||
Name: 'Flashspot',
|
|
||||||
Extends: Lightbox.Lightbox,
|
|
||||||
|
|
||||||
_init: function(area) {
|
|
||||||
this.parent(Main.uiGroup, { inhibitEvents: true,
|
|
||||||
width: area.width,
|
|
||||||
height: area.height });
|
|
||||||
|
|
||||||
this.actor.style_class = 'flashspot';
|
|
||||||
this.actor.set_position(area.x, area.y);
|
|
||||||
},
|
|
||||||
|
|
||||||
fire: function() {
|
|
||||||
this.actor.opacity = 0;
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 255,
|
|
||||||
time: FLASHSPOT_ANIMATION_TIME,
|
|
||||||
transition: 'linear',
|
|
||||||
onComplete: Lang.bind(this, this._onFireShowComplete)
|
|
||||||
});
|
|
||||||
this.actor.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
_onFireShowComplete: function() {
|
|
||||||
Tweener.addTween(this.actor,
|
|
||||||
{ opacity: 0,
|
|
||||||
time: FLASHSPOT_ANIMATION_TIME,
|
|
||||||
transition: 'linear',
|
|
||||||
onComplete: Lang.bind(this, function() {
|
|
||||||
this.destroy();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,358 +0,0 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const Gtk = imports.gi.Gtk;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Meta = imports.gi.Meta;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
|
|
||||||
function _navigateActor(actor) {
|
|
||||||
if (!actor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let needsGrab = true;
|
|
||||||
if (actor instanceof St.Widget)
|
|
||||||
needsGrab = !actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
|
||||||
if (needsGrab)
|
|
||||||
actor.grab_key_focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
// GrabHelper:
|
|
||||||
// @owner: the actor that owns the GrabHelper
|
|
||||||
//
|
|
||||||
// Creates a new GrabHelper object, for dealing with keyboard and pointer grabs
|
|
||||||
// associated with a set of actors.
|
|
||||||
//
|
|
||||||
// Note that the grab can be automatically dropped at any time by the user, and
|
|
||||||
// your code just needs to deal with it; you shouldn't adjust behavior directly
|
|
||||||
// after you call ungrab(), but instead pass an 'onUngrab' callback when you
|
|
||||||
// call grab().
|
|
||||||
const GrabHelper = new Lang.Class({
|
|
||||||
Name: 'GrabHelper',
|
|
||||||
|
|
||||||
_init: function(owner) {
|
|
||||||
this._owner = owner;
|
|
||||||
|
|
||||||
this._grabStack = [];
|
|
||||||
|
|
||||||
this._actors = [];
|
|
||||||
this._capturedEventId = 0;
|
|
||||||
this._eventId = 0;
|
|
||||||
this._keyFocusNotifyId = 0;
|
|
||||||
this._focusWindowChangedId = 0;
|
|
||||||
this._ignoreRelease = false;
|
|
||||||
|
|
||||||
this._modalCount = 0;
|
|
||||||
this._grabFocusCount = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// addActor:
|
|
||||||
// @actor: an actor
|
|
||||||
//
|
|
||||||
// Adds @actor to the set of actors that are allowed to process events
|
|
||||||
// during a grab.
|
|
||||||
addActor: function(actor) {
|
|
||||||
actor.__grabHelperDestroyId = actor.connect('destroy', Lang.bind(this, function() { this.removeActor(actor); }));
|
|
||||||
this._actors.push(actor);
|
|
||||||
},
|
|
||||||
|
|
||||||
// removeActor:
|
|
||||||
// @actor: an actor
|
|
||||||
//
|
|
||||||
// Removes @actor from the set of actors that are allowed to
|
|
||||||
// process events during a grab.
|
|
||||||
removeActor: function(actor) {
|
|
||||||
let index = this._actors.indexOf(actor);
|
|
||||||
if (index != -1)
|
|
||||||
this._actors.splice(index, 1);
|
|
||||||
if (actor.__grabHelperDestroyId) {
|
|
||||||
actor.disconnect(actor.__grabHelperDestroyId);
|
|
||||||
delete actor.__grabHelperDestroyId;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_isWithinGrabbedActor: function(actor) {
|
|
||||||
while (actor) {
|
|
||||||
if (this._actors.indexOf(actor) != -1)
|
|
||||||
return true;
|
|
||||||
actor = actor.get_parent();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
get currentGrab() {
|
|
||||||
return this._grabStack[this._grabStack.length - 1] || {};
|
|
||||||
},
|
|
||||||
|
|
||||||
_findStackIndex: function(actor) {
|
|
||||||
if (!actor)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (let i = 0; i < this._grabStack.length; i++) {
|
|
||||||
if (this._grabStack[i].actor === actor)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
isActorGrabbed: function(actor) {
|
|
||||||
return this._findStackIndex(actor) >= 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// grab:
|
|
||||||
// @params: A bunch of parameters, see below
|
|
||||||
//
|
|
||||||
// Grabs the mouse and keyboard, according to the GrabHelper's
|
|
||||||
// parameters. If @newFocus is not %null, then the keyboard focus
|
|
||||||
// is moved to the first #StWidget:can-focus widget inside it.
|
|
||||||
//
|
|
||||||
// The grab will automatically be dropped if:
|
|
||||||
// - The user clicks outside the grabbed actors
|
|
||||||
// - The user types Escape
|
|
||||||
// - The keyboard focus is moved outside the grabbed actors
|
|
||||||
// - A window is focused
|
|
||||||
//
|
|
||||||
// If @params.actor is not null, then it will be focused as the
|
|
||||||
// new actor. If you attempt to grab an already focused actor, the
|
|
||||||
// request to be focused will be ignored. The actor will not be
|
|
||||||
// added to the grab stack, so do not call a paired ungrab().
|
|
||||||
//
|
|
||||||
// If @params contains { modal: true }, then grab() will push a modal
|
|
||||||
// on the owner of the GrabHelper. As long as there is at least one
|
|
||||||
// { modal: true } actor on the grab stack, the grab will be kept.
|
|
||||||
// When the last { modal: true } actor is ungrabbed, then the modal
|
|
||||||
// will be dropped. A modal grab can fail if there is already a grab
|
|
||||||
// in effect from aother application; in this case the function returns
|
|
||||||
// false and nothing happens. Non-modal grabs can never fail.
|
|
||||||
//
|
|
||||||
// If @params contains { grabFocus: true }, then if you call grab()
|
|
||||||
// while the shell is outside the overview, it will set the stage
|
|
||||||
// input mode to %Shell.StageInputMode.FOCUSED, and ungrab() will
|
|
||||||
// revert it back, and re-focus the previously-focused window (if
|
|
||||||
// another window hasn't been explicitly focused before then).
|
|
||||||
grab: function(params) {
|
|
||||||
params = Params.parse(params, { actor: null,
|
|
||||||
modal: false,
|
|
||||||
grabFocus: false,
|
|
||||||
onUngrab: null });
|
|
||||||
|
|
||||||
let focus = global.stage.key_focus;
|
|
||||||
let hadFocus = focus && this._isWithinGrabbedActor(focus);
|
|
||||||
let newFocus = params.actor;
|
|
||||||
|
|
||||||
if (this.isActorGrabbed(params.actor))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
params.savedFocus = focus;
|
|
||||||
|
|
||||||
if (params.modal && !this._takeModalGrab())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (params.grabFocus && !this._takeFocusGrab(hadFocus))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (hadFocus || params.grabFocus)
|
|
||||||
_navigateActor(newFocus);
|
|
||||||
|
|
||||||
this._grabStack.push(params);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_takeModalGrab: function() {
|
|
||||||
let firstGrab = (this._modalCount == 0);
|
|
||||||
if (firstGrab) {
|
|
||||||
if (!Main.pushModal(this._owner))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
|
|
||||||
this._eventId = global.stage.connect('event', Lang.bind(this, this._onEvent));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._modalCount++;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_releaseModalGrab: function() {
|
|
||||||
this._modalCount--;
|
|
||||||
if (this._modalCount > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._capturedEventId > 0) {
|
|
||||||
global.stage.disconnect(this._capturedEventId);
|
|
||||||
this._capturedEventId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._eventId > 0) {
|
|
||||||
global.stage.disconnect(this._eventId);
|
|
||||||
this._eventId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Main.popModal(this._owner);
|
|
||||||
global.sync_pointer();
|
|
||||||
},
|
|
||||||
|
|
||||||
_takeFocusGrab: function(hadFocus) {
|
|
||||||
let firstGrab = (this._grabFocusCount == 0);
|
|
||||||
if (firstGrab) {
|
|
||||||
let metaDisplay = global.screen.get_display();
|
|
||||||
|
|
||||||
this._grabbedFromKeynav = hadFocus;
|
|
||||||
this._preGrabInputMode = global.stage_input_mode;
|
|
||||||
this._prevFocusedWindow = metaDisplay.focus_window;
|
|
||||||
|
|
||||||
if (this._preGrabInputMode == Shell.StageInputMode.NONREACTIVE ||
|
|
||||||
this._preGrabInputMode == Shell.StageInputMode.NORMAL) {
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._keyFocusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
|
|
||||||
this._focusWindowChangedId = metaDisplay.connect('notify::focus-window', Lang.bind(this, this._focusWindowChanged));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._grabFocusCount++;
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
_releaseFocusGrab: function() {
|
|
||||||
this._grabFocusCount--;
|
|
||||||
if (this._grabFocusCount > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._keyFocusNotifyId > 0) {
|
|
||||||
global.stage.disconnect(this._keyFocusNotifyId);
|
|
||||||
this._keyFocusNotifyId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._focusWindowChanged > 0) {
|
|
||||||
let metaDisplay = global.screen.get_display();
|
|
||||||
metaDisplay.disconnect(this._focusWindowChangedId);
|
|
||||||
this._focusWindowChangedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let prePopInputMode = global.stage_input_mode;
|
|
||||||
|
|
||||||
if (this._grabbedFromKeynav) {
|
|
||||||
if (this._preGrabInputMode == Shell.StageInputMode.FOCUSED &&
|
|
||||||
prePopInputMode != Shell.StageInputMode.FULLSCREEN)
|
|
||||||
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._prevFocusedWindow) {
|
|
||||||
let metaDisplay = global.screen.get_display();
|
|
||||||
if (!metaDisplay.focus_window) {
|
|
||||||
metaDisplay.set_input_focus_window(this._prevFocusedWindow,
|
|
||||||
false, global.get_current_time());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// ignoreRelease:
|
|
||||||
//
|
|
||||||
// Make sure that the next button release event evaluated by the
|
|
||||||
// capture event handler returns false. This is designed for things
|
|
||||||
// like the ComboBoxMenu that go away on press, but need to eat
|
|
||||||
// the next release event.
|
|
||||||
ignoreRelease: function() {
|
|
||||||
this._ignoreRelease = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
// ungrab:
|
|
||||||
// @params: The parameters for the grab; see below.
|
|
||||||
//
|
|
||||||
// Pops an actor from the grab stack, potentially dropping the grab.
|
|
||||||
//
|
|
||||||
// If the actor that was popped from the grab stack was not the actor
|
|
||||||
// That was passed in, this call is ignored.
|
|
||||||
ungrab: function(params) {
|
|
||||||
params = Params.parse(params, { actor: this.currentGrab.actor });
|
|
||||||
|
|
||||||
let grabStackIndex = this._findStackIndex(params.actor);
|
|
||||||
if (grabStackIndex < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let focus = global.stage.key_focus;
|
|
||||||
let hadFocus = focus && this._isWithinGrabbedActor(focus);
|
|
||||||
|
|
||||||
let poppedGrabs = this._grabStack.slice(grabStackIndex);
|
|
||||||
// "Pop" all newly ungrabbed actors off the grab stack
|
|
||||||
// by truncating the array.
|
|
||||||
this._grabStack.length = grabStackIndex;
|
|
||||||
|
|
||||||
for (let i = poppedGrabs.length - 1; i >= 0; i--) {
|
|
||||||
let poppedGrab = poppedGrabs[i];
|
|
||||||
|
|
||||||
if (poppedGrab.onUngrab)
|
|
||||||
poppedGrab.onUngrab();
|
|
||||||
|
|
||||||
if (poppedGrab.modal)
|
|
||||||
this._releaseModalGrab();
|
|
||||||
|
|
||||||
if (poppedGrab.grabFocus)
|
|
||||||
this._releaseFocusGrab();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hadFocus) {
|
|
||||||
let poppedGrab = poppedGrabs[0];
|
|
||||||
_navigateActor(poppedGrab.savedFocus);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onCapturedEvent: function(actor, event) {
|
|
||||||
let type = event.type();
|
|
||||||
let press = type == Clutter.EventType.BUTTON_PRESS;
|
|
||||||
let release = type == Clutter.EventType.BUTTON_RELEASE;
|
|
||||||
let button = press || release;
|
|
||||||
|
|
||||||
if (release && this._ignoreRelease) {
|
|
||||||
this._ignoreRelease = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!button && this._modalCount == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this._isWithinGrabbedActor(event.get_source()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Main.keyboard.shouldTakeEvent(event))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (button) {
|
|
||||||
// If we have a press event, ignore the next event,
|
|
||||||
// which should be a release event.
|
|
||||||
if (press)
|
|
||||||
this._ignoreRelease = true;
|
|
||||||
this.ungrab({ actor: this._grabStack[0].actor });
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._modalCount > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// We catch 'event' rather than 'key-press-event' so that we get
|
|
||||||
// a chance to run before the overview's own Escape check
|
|
||||||
_onEvent: function(actor, event) {
|
|
||||||
if (event.type() == Clutter.EventType.KEY_PRESS &&
|
|
||||||
event.get_key_symbol() == Clutter.KEY_Escape) {
|
|
||||||
this.ungrab();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onKeyFocusChanged: function() {
|
|
||||||
let focus = global.stage.key_focus;
|
|
||||||
if (!focus || !this._isWithinGrabbedActor(focus))
|
|
||||||
this.ungrab();
|
|
||||||
},
|
|
||||||
|
|
||||||
_focusWindowChanged: function() {
|
|
||||||
let metaDisplay = global.screen.get_display();
|
|
||||||
if (metaDisplay.focus_window != null)
|
|
||||||
this.ungrab();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,228 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const Clutter = imports.gi.Clutter;
|
|
||||||
const IBus = imports.gi.IBus;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const BoxPointer = imports.ui.boxpointer;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
|
||||||
|
|
||||||
const MAX_CANDIDATES_PER_PAGE = 16;
|
|
||||||
|
|
||||||
const CandidateArea = new Lang.Class({
|
|
||||||
Name: 'CandidateArea',
|
|
||||||
Extends: PopupMenu.PopupBaseMenuItem,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent({ reactive: false });
|
|
||||||
|
|
||||||
// St.Table exhibits some sizing problems so let's go with a
|
|
||||||
// clutter layout manager for now.
|
|
||||||
this._table = new Clutter.Actor();
|
|
||||||
this.addActor(this._table);
|
|
||||||
|
|
||||||
this._tableLayout = new Clutter.TableLayout();
|
|
||||||
this._table.set_layout_manager(this._tableLayout);
|
|
||||||
|
|
||||||
this._indexLabels = [];
|
|
||||||
this._candidateLabels = [];
|
|
||||||
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
|
|
||||||
this._indexLabels.push(new St.Label({ style_class: 'candidate-index' }));
|
|
||||||
this._candidateLabels.push(new St.Label({ style_class: 'candidate-label' }));
|
|
||||||
}
|
|
||||||
|
|
||||||
this._orientation = -1;
|
|
||||||
this._cursorPosition = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
_setOrientation: function(orientation) {
|
|
||||||
if (this._orientation == orientation)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._orientation = orientation;
|
|
||||||
|
|
||||||
this._table.remove_all_children();
|
|
||||||
|
|
||||||
if (this._orientation == IBus.Orientation.HORIZONTAL)
|
|
||||||
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
|
|
||||||
this._tableLayout.pack(this._indexLabels[i], i*2, 0);
|
|
||||||
this._tableLayout.pack(this._candidateLabels[i], i*2 + 1, 0);
|
|
||||||
}
|
|
||||||
else // VERTICAL || SYSTEM
|
|
||||||
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
|
|
||||||
this._tableLayout.pack(this._indexLabels[i], 0, i);
|
|
||||||
this._tableLayout.pack(this._candidateLabels[i], 1, i);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setCandidates: function(indexes, candidates, orientation, cursorPosition, cursorVisible) {
|
|
||||||
this._setOrientation(orientation);
|
|
||||||
|
|
||||||
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
|
|
||||||
let visible = i < candidates.length;
|
|
||||||
this._indexLabels[i].visible = visible;
|
|
||||||
this._candidateLabels[i].visible = visible;
|
|
||||||
|
|
||||||
if (!visible)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this._indexLabels[i].text = ((indexes && indexes[i]) ? indexes[i] : '%x.'.format(i + 1));
|
|
||||||
this._candidateLabels[i].text = candidates[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
this._candidateLabels[this._cursorPosition].remove_style_pseudo_class('selected');
|
|
||||||
this._cursorPosition = cursorPosition;
|
|
||||||
if (cursorVisible)
|
|
||||||
this._candidateLabels[cursorPosition].add_style_pseudo_class('selected');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const CandidatePopup = new Lang.Class({
|
|
||||||
Name: 'CandidatePopup',
|
|
||||||
Extends: PopupMenu.PopupMenu,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._cursor = new St.Bin({ opacity: 0 });
|
|
||||||
Main.uiGroup.add_actor(this._cursor);
|
|
||||||
|
|
||||||
this.parent(this._cursor, 0, St.Side.TOP);
|
|
||||||
this.actor.hide();
|
|
||||||
Main.uiGroup.add_actor(this.actor);
|
|
||||||
|
|
||||||
this._preeditTextItem = new PopupMenu.PopupMenuItem('', { reactive: false });
|
|
||||||
this._preeditTextItem.actor.hide();
|
|
||||||
this.addMenuItem(this._preeditTextItem);
|
|
||||||
|
|
||||||
this._auxTextItem = new PopupMenu.PopupMenuItem('', { reactive: false });
|
|
||||||
this._auxTextItem.actor.hide();
|
|
||||||
this.addMenuItem(this._auxTextItem);
|
|
||||||
|
|
||||||
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
|
||||||
|
|
||||||
this._lookupTableItem = new CandidateArea();
|
|
||||||
this._lookupTableItem.actor.hide();
|
|
||||||
this.addMenuItem(this._lookupTableItem);
|
|
||||||
|
|
||||||
this._panelService = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
setPanelService: function(panelService) {
|
|
||||||
this._panelService = panelService;
|
|
||||||
if (!panelService)
|
|
||||||
return;
|
|
||||||
|
|
||||||
panelService.connect('set-cursor-location',
|
|
||||||
Lang.bind(this, function(ps, x, y, w, h) {
|
|
||||||
this._cursor.set_position(x, y);
|
|
||||||
this._cursor.set_size(w, h);
|
|
||||||
}));
|
|
||||||
panelService.connect('update-preedit-text',
|
|
||||||
Lang.bind(this, function(ps, text, cursorPosition, visible) {
|
|
||||||
if (visible)
|
|
||||||
this._preeditTextItem.actor.show();
|
|
||||||
else
|
|
||||||
this._preeditTextItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
|
|
||||||
this._preeditTextItem.actor.label_actor.text = text.get_text();
|
|
||||||
|
|
||||||
let attrs = text.get_attributes();
|
|
||||||
if (attrs)
|
|
||||||
this._setTextAttributes(this._preeditTextItem.actor.label_actor.clutter_text,
|
|
||||||
attrs);
|
|
||||||
}));
|
|
||||||
panelService.connect('show-preedit-text',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._preeditTextItem.actor.show();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('hide-preedit-text',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._preeditTextItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('update-auxiliary-text',
|
|
||||||
Lang.bind(this, function(ps, text, visible) {
|
|
||||||
if (visible)
|
|
||||||
this._auxTextItem.actor.show();
|
|
||||||
else
|
|
||||||
this._auxTextItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
|
|
||||||
this._auxTextItem.actor.label_actor.text = text.get_text();
|
|
||||||
}));
|
|
||||||
panelService.connect('show-auxiliary-text',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._auxTextItem.actor.show();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('hide-auxiliary-text',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._auxTextItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('update-lookup-table',
|
|
||||||
Lang.bind(this, function(ps, lookupTable, visible) {
|
|
||||||
if (visible)
|
|
||||||
this._lookupTableItem.actor.show();
|
|
||||||
else
|
|
||||||
this._lookupTableItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
|
|
||||||
let cursorPos = lookupTable.get_cursor_pos();
|
|
||||||
let pageSize = lookupTable.get_page_size();
|
|
||||||
let page = ((cursorPos == 0) ? 0 : Math.floor(cursorPos / pageSize));
|
|
||||||
let startIndex = page * pageSize;
|
|
||||||
let endIndex = Math.min((page + 1) * pageSize,
|
|
||||||
lookupTable.get_number_of_candidates());
|
|
||||||
let indexes = [];
|
|
||||||
let indexLabel;
|
|
||||||
for (let i = 0; indexLabel = lookupTable.get_label(i); ++i)
|
|
||||||
indexes.push(indexLabel.get_text());
|
|
||||||
|
|
||||||
let candidates = [];
|
|
||||||
for (let i = startIndex; i < endIndex; ++i)
|
|
||||||
candidates.push(lookupTable.get_candidate(i).get_text());
|
|
||||||
|
|
||||||
this._lookupTableItem.setCandidates(indexes,
|
|
||||||
candidates,
|
|
||||||
lookupTable.get_orientation(),
|
|
||||||
cursorPos % pageSize,
|
|
||||||
lookupTable.is_cursor_visible());
|
|
||||||
}));
|
|
||||||
panelService.connect('show-lookup-table',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._lookupTableItem.actor.show();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('hide-lookup-table',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this._lookupTableItem.actor.hide();
|
|
||||||
this._updateVisibility();
|
|
||||||
}));
|
|
||||||
panelService.connect('focus-out',
|
|
||||||
Lang.bind(this, function(ps) {
|
|
||||||
this.close(BoxPointer.PopupAnimation.NONE);
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateVisibility: function() {
|
|
||||||
let isVisible = (this._preeditTextItem.actor.visible ||
|
|
||||||
this._auxTextItem.actor.visible ||
|
|
||||||
this._lookupTableItem.actor.visible);
|
|
||||||
|
|
||||||
if (isVisible)
|
|
||||||
this.open(BoxPointer.PopupAnimation.NONE);
|
|
||||||
else
|
|
||||||
this.close(BoxPointer.PopupAnimation.NONE);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setTextAttributes: function(clutterText, ibusAttrList) {
|
|
||||||
let attr;
|
|
||||||
for (let i = 0; attr = ibusAttrList.get(i); ++i)
|
|
||||||
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
|
|
||||||
clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
|
|
||||||
}
|
|
||||||
});
|
|