Compare commits
82 Commits
Author | SHA1 | Date | |
---|---|---|---|
471006ba67 | |||
98bd590a5d | |||
9d88a13d3c | |||
159690b2d3 | |||
8a2bfd0e55 | |||
2ddc7cf00f | |||
04f10ceb4e | |||
ceefc5eea4 | |||
9feda69888 | |||
33f9895d71 | |||
2812c21322 | |||
7ac9fb2dd0 | |||
05c99241d6 | |||
9fb8dad80c | |||
004ad86e9d | |||
02c65fab8d | |||
dfe16f4af6 | |||
e52cb3c213 | |||
6e31e59b57 | |||
458778bcfd | |||
d8cabbee0b | |||
3029a4086b | |||
5598de6543 | |||
913aeae166 | |||
dddad9e1b5 | |||
4bfa68d209 | |||
42e3a93c20 | |||
05812ef7f9 | |||
a0df412deb | |||
678a88dbdb | |||
5e944c9a3b | |||
b28b60b47b | |||
16caa74386 | |||
470c65d046 | |||
ef6ea078dd | |||
37ee16b34d | |||
5880b3b0ed | |||
80a5f78eb2 | |||
4b727ef40d | |||
d0d79c5b3e | |||
0882da0a71 | |||
25410a730e | |||
22c445cffc | |||
42bf91fdc4 | |||
7f88e02a26 | |||
d540af847a | |||
2f78907aeb | |||
d471541495 | |||
fa5fb6b8a8 | |||
0a29cf6195 | |||
b7b4c54ab5 | |||
52abf266c0 | |||
11872cfb79 | |||
21309aa28f | |||
38d21c8edf | |||
090908439b | |||
0a17a28608 | |||
926643b025 | |||
1a834f7d8b | |||
3e54087e42 | |||
304b377dae | |||
ac4bcee050 | |||
553503dace | |||
90381ceea2 | |||
687814b6c6 | |||
6153094057 | |||
0245a0cd0e | |||
bcc3dc0711 | |||
3d499219da | |||
94b26888cf | |||
156fdf1fa3 | |||
2a3f9e8f83 | |||
849ce371ff | |||
a76ac5501c | |||
5803aa7e65 | |||
0fd6bc5172 | |||
0e3cea41e0 | |||
45c600cd25 | |||
7fb8e2d0ef | |||
2d5d54f3cd | |||
949359db5d | |||
5bd2695863 |
20
README
20
README
@ -0,0 +1,20 @@
|
||||
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
|
||||
like switching to windows and launching applications. GNOME Shell takes
|
||||
advantage of the capabilities of modern graphics hardware and introduces
|
||||
innovative user interface concepts to provide a visually attractive and
|
||||
easy to use experience.
|
||||
|
||||
For more information about GNOME Shell, including instructions on how
|
||||
to build GNOME Shell from source and how to get involved with the project,
|
||||
see:
|
||||
|
||||
http://live.gnome.org/GnomeShell
|
||||
|
||||
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
|
||||
product.
|
||||
|
||||
License
|
||||
=======
|
||||
GNOME Shell is distributed under the terms of the GNU General Public License,
|
||||
version 2 or later. See the COPYING file for details.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT(gnome-shell, 2.27.1)
|
||||
AC_INIT(gnome-shell, 2.27.3)
|
||||
|
||||
AC_CONFIG_AUX_DIR(config)
|
||||
|
||||
@ -28,6 +28,10 @@ AM_GLIB_GNU_GETTEXT
|
||||
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
|
||||
AM_GCONF_SOURCE_2
|
||||
|
||||
# Get a value to substitute into gnome-shell.in
|
||||
AM_PATH_PYTHON([2.5])
|
||||
AC_SUBST(PYTHON)
|
||||
|
||||
# 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.
|
||||
GSTREAMER_MIN_VERSION=0.10.16
|
||||
@ -51,7 +55,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
|
||||
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
|
||||
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
|
||||
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||
gobject-introspection-1.0 >= 0.6.4)
|
||||
gobject-introspection-1.0 >= 0.6.5)
|
||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||
|
@ -16,6 +16,8 @@ imagedir = $(pkgdatadir)/images
|
||||
|
||||
dist_image_DATA = \
|
||||
add-workspace.svg \
|
||||
app-well-glow.png \
|
||||
back.svg \
|
||||
close.svg \
|
||||
close-black.svg \
|
||||
info.svg \
|
||||
|
BIN
data/app-well-glow.png
Normal file
BIN
data/app-well-glow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
7
data/back.svg
Normal file
7
data/back.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<?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: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="12" height="16" viewBox="0 0 12 16" enable-background="new 0 0 29 18" xml:space="preserve" sodipodi:version="0.32" inkscape:version="0.46+devel" sodipodi:docname="back.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata id="metadata16"><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="defs14"><inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 9 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="29 : 9 : 1" inkscape:persp3d-origin="14.5 : 6 : 1" id="perspective18"/></defs><sodipodi:namedview inkscape:window-height="728" inkscape:window-width="1103" inkscape:pageshadow="2" inkscape:pageopacity="1" guidetolerance="10.0" gridtolerance="10.0" objecttolerance="10.0" borderopacity="1.0" bordercolor="#666666" pagecolor="#000000" id="base" showgrid="true" inkscape:zoom="27.260185" inkscape:cx="12.592456" inkscape:cy="8.2696842" inkscape:window-x="145" inkscape:window-y="38" inkscape:current-layer="Foreground" inkscape:snap-global="true" showguides="false"><inkscape:grid type="xygrid" id="grid2391" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true"/></sodipodi:namedview>
|
||||
|
||||
|
||||
|
||||
<path style="fill: rgb(255, 255, 255); fill-opacity: 1; stroke: none;" d="M 10,2 10,14 2,8 10,2 z" id="path43"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -1,6 +1,21 @@
|
||||
<gconfschemafile>
|
||||
<schemalist>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/development_tools</key>
|
||||
<applyto>/desktop/gnome/shell/development_tools</applyto>
|
||||
<owner>gnome-shell</owner>
|
||||
<type>bool</type>
|
||||
<default>true</default>
|
||||
<locale name="C">
|
||||
<short>Enable internal tools useful for developers and testers from Alt-F2</short>
|
||||
<long>
|
||||
Allows access to internal debugging and monitoring tools using
|
||||
the Alt-F2 dialog.
|
||||
</long>
|
||||
</locale>
|
||||
</schema>
|
||||
|
||||
<schema>
|
||||
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
|
||||
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>
|
||||
|
53
gnome-shell.doap
Normal file
53
gnome-shell.doap
Normal file
@ -0,0 +1,53 @@
|
||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
|
||||
<name xml:lang="en">GNOME Shell</name>
|
||||
<shortdesc xml:lang="en">Next generation GNOME desktop shell</shortdesc>
|
||||
<!--
|
||||
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
|
||||
-->
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>William Jon McCann</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
|
||||
<gnome:userid>mccann</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Owen Taylor</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
|
||||
<gnome:userid>otaylor</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Colin Walters</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
|
||||
<gnome:userid>cwalters</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Dan Winship</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
|
||||
<gnome:userid>danw</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Marina Zhurakhinskaya</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
|
||||
<gnome:userid>marinaz</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
</Project>
|
@ -36,8 +36,6 @@ function AltTabPopup() {
|
||||
|
||||
AltTabPopup.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
|
||||
corner_radius: POPUP_GRID_SPACING,
|
||||
padding: POPUP_GRID_SPACING,
|
||||
@ -140,8 +138,6 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
show : function(initialSelection) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
global.window_group.add_actor(this._overlay);
|
||||
this._overlay.raise_top();
|
||||
this._overlay.show();
|
||||
@ -234,8 +230,6 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
_adjust_overlay : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (this._selected && this._selected.icon_rect) {
|
||||
// We want to highlight a specific rectangle within the
|
||||
// task bar, so rearrange the pieces of the overlay to
|
||||
|
@ -26,6 +26,27 @@ const WELL_DEFAULT_COLUMNS = 4;
|
||||
const WELL_ITEM_HSPACING = 0;
|
||||
const WELL_ITEM_VSPACING = 4;
|
||||
|
||||
const WELL_MENU_POPUP_TIMEOUT_MS = 600;
|
||||
|
||||
const TRANSPARENT_COLOR = new Clutter.Color();
|
||||
TRANSPARENT_COLOR.from_pixel(0x00000000);
|
||||
|
||||
const WELL_MENU_BACKGROUND_COLOR = new Clutter.Color();
|
||||
WELL_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
|
||||
const WELL_MENU_FONT = 'Sans 14px';
|
||||
const WELL_MENU_COLOR = new Clutter.Color();
|
||||
WELL_MENU_COLOR.from_pixel(0xffffffff);
|
||||
const WELL_MENU_SELECTED_COLOR = new Clutter.Color();
|
||||
WELL_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
|
||||
const WELL_MENU_BORDER_COLOR = new Clutter.Color();
|
||||
WELL_MENU_BORDER_COLOR.from_pixel(0x787878ff);
|
||||
const WELL_MENU_SEPARATOR_COLOR = new Clutter.Color();
|
||||
WELL_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
|
||||
const WELL_MENU_BORDER_WIDTH = 1;
|
||||
const WELL_MENU_ARROW_SIZE = 12;
|
||||
const WELL_MENU_CORNER_RADIUS = 4;
|
||||
const WELL_MENU_PADDING = 4;
|
||||
|
||||
const MENU_ICON_SIZE = 24;
|
||||
const MENU_SPACING = 15;
|
||||
|
||||
@ -57,7 +78,13 @@ AppDisplayItem.prototype = {
|
||||
|
||||
// Opens an application represented by this display item.
|
||||
launch : function() {
|
||||
this._appInfo.launch();
|
||||
let windows = Shell.AppMonitor.get_default().get_windows_for_app(this._appInfo.get_id());
|
||||
if (windows.length > 0) {
|
||||
let mostRecentWindow = windows[0];
|
||||
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
|
||||
} else {
|
||||
this._appInfo.launch();
|
||||
}
|
||||
},
|
||||
|
||||
//// Protected method overrides ////
|
||||
@ -161,21 +188,25 @@ MenuItem.prototype = {
|
||||
}
|
||||
Signals.addSignalMethods(MenuItem.prototype);
|
||||
|
||||
|
||||
/* This class represents a display containing a collection of application items.
|
||||
* The applications are sorted based on their popularity by default, and based on
|
||||
* their name if some search filter is applied.
|
||||
*
|
||||
* showPrefs - a boolean indicating if this AppDisplay should contain preference
|
||||
* applets, rather than applications
|
||||
*/
|
||||
function AppDisplay() {
|
||||
this._init();
|
||||
function AppDisplay(showPrefs) {
|
||||
this._init(showPrefs);
|
||||
}
|
||||
|
||||
AppDisplay.prototype = {
|
||||
__proto__: GenericDisplay.GenericDisplay.prototype,
|
||||
|
||||
_init : function() {
|
||||
_init : function(showPrefs) {
|
||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||
|
||||
this._showPrefs = showPrefs;
|
||||
|
||||
this._menus = [];
|
||||
this._menuDisplays = [];
|
||||
|
||||
@ -327,36 +358,37 @@ AppDisplay.prototype = {
|
||||
|
||||
// Gets information about all applications by calling Gio.app_info_get_all().
|
||||
_refreshCache : function() {
|
||||
let me = this;
|
||||
if (!this._appsStale)
|
||||
return;
|
||||
this._allItems = {};
|
||||
this._appCategories = {};
|
||||
|
||||
// Loop over the toplevel menu items, load the set of desktop file ids
|
||||
// associated with each one, skipping empty menus
|
||||
let allMenus = this._appSystem.get_menus();
|
||||
this._menus = [];
|
||||
for (let i = 0; i < allMenus.length; i++) {
|
||||
let menu = allMenus[i];
|
||||
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
|
||||
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
|
||||
if (!hasVisibleApps) {
|
||||
continue;
|
||||
}
|
||||
this._menus.push(menu);
|
||||
for (let j = 0; j < menuApps.length; j++) {
|
||||
let app = menuApps[j];
|
||||
if (this._showPrefs) {
|
||||
// Get the desktop file ids for settings/preferences.
|
||||
// These are used for search results, but not in the app menus.
|
||||
let settings = this._appSystem.get_all_settings();
|
||||
for (let i = 0; i < settings.length; i++) {
|
||||
let app = settings[i];
|
||||
this._addApp(app);
|
||||
}
|
||||
}
|
||||
|
||||
// Now grab the desktop file ids for settings/preferences.
|
||||
// These show up in search, but not with the rest of apps.
|
||||
let settings = this._appSystem.get_all_settings();
|
||||
for (let i = 0; i < settings.length; i++) {
|
||||
let app = settings[i];
|
||||
this._addApp(app);
|
||||
} else {
|
||||
// Loop over the toplevel menu items, load the set of desktop file ids
|
||||
// associated with each one, skipping empty menus
|
||||
let allMenus = this._appSystem.get_menus();
|
||||
this._menus = [];
|
||||
for (let i = 0; i < allMenus.length; i++) {
|
||||
let menu = allMenus[i];
|
||||
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
|
||||
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
|
||||
if (!hasVisibleApps) {
|
||||
continue;
|
||||
}
|
||||
this._menus.push(menu);
|
||||
for (let j = 0; j < menuApps.length; j++) {
|
||||
let app = menuApps[j];
|
||||
this._addApp(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._appsStale = false;
|
||||
@ -448,35 +480,286 @@ AppDisplay.prototype = {
|
||||
|
||||
Signals.addSignalMethods(AppDisplay.prototype);
|
||||
|
||||
function WellDisplayItem(appInfo, isFavorite) {
|
||||
function WellMenu(source) {
|
||||
this._init(source);
|
||||
}
|
||||
|
||||
WellMenu.prototype = {
|
||||
_init: function(source) {
|
||||
this._source = source;
|
||||
|
||||
// Whether or not we successfully picked a window
|
||||
this.didActivateWindow = false;
|
||||
|
||||
this.actor = new Shell.GenericContainer({ reactive: true });
|
||||
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._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
border_color: WELL_MENU_BORDER_COLOR,
|
||||
border: WELL_MENU_BORDER_WIDTH,
|
||||
background_color: WELL_MENU_BACKGROUND_COLOR,
|
||||
padding: 4,
|
||||
corner_radius: WELL_MENU_CORNER_RADIUS,
|
||||
width: Main.overview._dash.actor.width * 0.75 });
|
||||
this._windowContainer.connect('unselected', Lang.bind(this, this._onWindowUnselected));
|
||||
this._windowContainer.connect('selected', Lang.bind(this, this._onWindowSelected));
|
||||
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
|
||||
this._windowContainer.connect('activate', Lang.bind(this, this._onWindowActivate));
|
||||
this.actor.add_actor(this._windowContainer);
|
||||
|
||||
// Stay popped up on release over application icon
|
||||
this._windowContainer.set_persistent_source(this._source.actor);
|
||||
|
||||
// Intercept events while the menu has the pointer grab to do window-related effects
|
||||
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
|
||||
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
|
||||
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
|
||||
|
||||
this._arrow = new Shell.DrawingArea();
|
||||
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
|
||||
Shell.draw_box_pointer(texture, WELL_MENU_BORDER_COLOR, WELL_MENU_BACKGROUND_COLOR);
|
||||
}));
|
||||
this.actor.add_actor(this._arrow);
|
||||
|
||||
// Chain our visibility and lifecycle to that of the source
|
||||
source.actor.connect('notify::mapped', Lang.bind(this, function () {
|
||||
if (!source.actor.mapped)
|
||||
this._windowContainer.popdown();
|
||||
}));
|
||||
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
|
||||
|
||||
global.stage.add_actor(this.actor);
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
|
||||
alloc.min_size = min + WELL_MENU_ARROW_SIZE;
|
||||
alloc.natural_size = natural + WELL_MENU_ARROW_SIZE;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
|
||||
alloc.min_size = min;
|
||||
alloc.natural_size = natural;
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let childBox = new Clutter.ActorBox();
|
||||
|
||||
let width = box.x2 - box.x1;
|
||||
let height = box.y2 - box.y1;
|
||||
|
||||
childBox.x1 = 0;
|
||||
childBox.x2 = WELL_MENU_ARROW_SIZE;
|
||||
childBox.y1 = Math.floor((height / 2) - (WELL_MENU_ARROW_SIZE / 2));
|
||||
childBox.y2 = childBox.y1 + WELL_MENU_ARROW_SIZE;
|
||||
this._arrow.allocate(childBox, flags);
|
||||
|
||||
/* overlap by one pixel to hide the border */
|
||||
childBox.x1 = WELL_MENU_ARROW_SIZE - 1;
|
||||
childBox.x2 = width;
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = height;
|
||||
this._windowContainer.allocate(childBox, flags);
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
this._windowContainer.remove_all();
|
||||
|
||||
this.didActivateWindow = false;
|
||||
|
||||
let windows = this._source.windows;
|
||||
|
||||
this._windowContainer.show();
|
||||
|
||||
let iconsDiffer = false;
|
||||
let texCache = Shell.TextureCache.get_default();
|
||||
let firstIcon = windows[0].mini_icon;
|
||||
for (let i = 1; i < windows.length; i++) {
|
||||
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
|
||||
iconsDiffer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let activeWorkspace = global.screen.get_active_workspace();
|
||||
|
||||
let currentWorkspaceWindows = windows.filter(function (w) {
|
||||
return w.get_workspace() == activeWorkspace;
|
||||
});
|
||||
let otherWorkspaceWindows = windows.filter(function (w) {
|
||||
return w.get_workspace() != activeWorkspace;
|
||||
});
|
||||
|
||||
this._appendWindows(currentWorkspaceWindows, iconsDiffer);
|
||||
if (currentWorkspaceWindows.length > 0 && otherWorkspaceWindows.length > 0) {
|
||||
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
|
||||
box.append(new Clutter.Rectangle({ height: 1,
|
||||
color: WELL_MENU_SEPARATOR_COLOR }),
|
||||
Big.BoxPackFlags.EXPAND);
|
||||
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
|
||||
},
|
||||
|
||||
_appendWindows: function (windows, iconsDiffer) {
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let metaWindow = windows[i];
|
||||
|
||||
/* Use padding here rather than spacing in the box above so that
|
||||
* we have a larger reactive area.
|
||||
*/
|
||||
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_top: 4,
|
||||
padding_bottom: 4,
|
||||
spacing: 4,
|
||||
reactive: true });
|
||||
box._window = metaWindow;
|
||||
let vCenter;
|
||||
if (iconsDiffer) {
|
||||
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||
let icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
|
||||
vCenter.append(icon, Big.BoxPackFlags.NONE);
|
||||
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
|
||||
let label = new Clutter.Text({ text: metaWindow.title,
|
||||
font_name: WELL_MENU_FONT,
|
||||
ellipsize: Pango.EllipsizeMode.END,
|
||||
color: WELL_MENU_COLOR });
|
||||
vCenter.append(label, Big.BoxPackFlags.NONE);
|
||||
box.append(vCenter, Big.BoxPackFlags.NONE);
|
||||
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
},
|
||||
|
||||
popup: function() {
|
||||
let [stageX, stageY] = this._source.actor.get_transformed_position();
|
||||
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
|
||||
|
||||
this._redisplay();
|
||||
|
||||
this._windowContainer.popup(0, Clutter.get_current_event_time());
|
||||
|
||||
this.emit('popup', true);
|
||||
|
||||
let x = Math.floor(stageX + stageWidth);
|
||||
let y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
|
||||
this.actor.set_position(x, y);
|
||||
this.actor.show();
|
||||
},
|
||||
|
||||
_findWindowCloneForActor: function (actor) {
|
||||
if (actor._delegate instanceof Workspaces.WindowClone)
|
||||
return actor._delegate;
|
||||
return null;
|
||||
},
|
||||
|
||||
// This function is called while the menu has a pointer grab; what we want
|
||||
// to do is see if the mouse was released over a window clone actor
|
||||
_onMenuButtonRelease: function (actor, event) {
|
||||
let clone = this._findWindowCloneForActor(event.get_source());
|
||||
if (clone) {
|
||||
this.didActivateWindow = true;
|
||||
Main.overview.activateWindow(clone.metaWindow, event.get_time());
|
||||
}
|
||||
},
|
||||
|
||||
_setHighlightWindow: function (metaWindow) {
|
||||
let children = this._windowContainer.get_children();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
let menuMetaWindow = child._window;
|
||||
if (metaWindow != null && menuMetaWindow == metaWindow) {
|
||||
child.background_color = WELL_MENU_SELECTED_COLOR;
|
||||
} else {
|
||||
child.background_color = TRANSPARENT_COLOR;
|
||||
}
|
||||
}
|
||||
this.emit('highlight-window', metaWindow);
|
||||
},
|
||||
|
||||
// Called while menu has a pointer grab
|
||||
_onMenuEnter: function (actor, event) {
|
||||
let clone = this._findWindowCloneForActor(event.get_source());
|
||||
if (clone) {
|
||||
this._setHighlightWindow(clone.metaWindow);
|
||||
}
|
||||
},
|
||||
|
||||
// Called while menu has a pointer grab
|
||||
_onMenuLeave: function (actor, event) {
|
||||
let clone = this._findWindowCloneForActor(event.get_source());
|
||||
if (clone) {
|
||||
this._setHighlightWindow(null);
|
||||
}
|
||||
},
|
||||
|
||||
_onWindowUnselected: function (actor, child) {
|
||||
this._setHighlightWindow(null);
|
||||
},
|
||||
|
||||
_onWindowSelected: function (actor, child) {
|
||||
this._setHighlightWindow(child._window);
|
||||
},
|
||||
|
||||
_onWindowActivate: function (actor, child) {
|
||||
let metaWindow = child._window;
|
||||
this.didActivateWindow = true;
|
||||
Main.overview.activateWindow(metaWindow, Clutter.get_current_event_time());
|
||||
this.emit('popup', false);
|
||||
this.actor.hide();
|
||||
},
|
||||
|
||||
_onWindowSelectionCancelled: function () {
|
||||
this.emit('highlight-window', null);
|
||||
this.emit('popup', false);
|
||||
this.actor.hide();
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(WellMenu.prototype);
|
||||
|
||||
function BaseWellItem(appInfo, isFavorite) {
|
||||
this._init(appInfo, isFavorite);
|
||||
}
|
||||
|
||||
WellDisplayItem.prototype = {
|
||||
__proto__ : AppIcon.AppIcon.prototype,
|
||||
|
||||
_init : function(appInfo, isFavorite) {
|
||||
AppIcon.AppIcon.prototype._init.call(this, appInfo);
|
||||
|
||||
BaseWellItem.prototype = {
|
||||
_init: function(appInfo, isFavorite) {
|
||||
this.appInfo = appInfo;
|
||||
this.isFavorite = isFavorite;
|
||||
this.icon = new AppIcon.AppIcon(appInfo);
|
||||
this.windows = this.icon.windows;
|
||||
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
border: WELL_MENU_BORDER_WIDTH,
|
||||
corner_radius: WELL_MENU_CORNER_RADIUS,
|
||||
reactive: true });
|
||||
this.icon.actor._delegate = this;
|
||||
this._draggable = DND.makeDraggable(this.icon.actor, true);
|
||||
|
||||
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
|
||||
this._handleActivate();
|
||||
// Do these as anonymous functions to avoid conflict with handlers in subclasses
|
||||
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
return false;
|
||||
}));
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
},
|
||||
|
||||
_handleActivate: function () {
|
||||
if (this._windows.length == 0) {
|
||||
this.appInfo.launch();
|
||||
Main.overview.hide();
|
||||
} else {
|
||||
/* Pick the first window and activate it;
|
||||
* In the future, we want to have a menu dropdown here. */
|
||||
let first = this._windows[0];
|
||||
Main.overview.activateWindow(first, Clutter.get_current_event_time());
|
||||
}
|
||||
this.actor.connect('notify::hover', Lang.bind(this, function () {
|
||||
let hover = this.actor.hover;
|
||||
if (!hover) {
|
||||
if (this.actor.pressed && this._dragStartX != null) {
|
||||
this.actor.fake_release();
|
||||
this._draggable.startDrag(this.icon.actor, this._dragStartX, this._dragStartY,
|
||||
Clutter.get_current_event_time());
|
||||
} else {
|
||||
this._dragStartX = null;
|
||||
this._dragStartY = null;
|
||||
}
|
||||
}
|
||||
}));
|
||||
this.actor.append(this.icon.actor, Big.BoxPackFlags.NONE);
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch : function() {
|
||||
@ -492,17 +775,140 @@ WellDisplayItem.prototype = {
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
return this.appInfo.create_icon_texture(this._icon.height);
|
||||
return this.icon.getDragActor(stageX, stageY);
|
||||
},
|
||||
|
||||
// Returns the original icon that is being used as a source for the cloned texture
|
||||
// that represents the item as it is being dragged.
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
return this.icon.getDragActorSource();
|
||||
}
|
||||
}
|
||||
|
||||
function RunningWellItem(appInfo, isFavorite) {
|
||||
this._init(appInfo, isFavorite);
|
||||
}
|
||||
|
||||
RunningWellItem.prototype = {
|
||||
__proto__: BaseWellItem.prototype,
|
||||
|
||||
_init: function(appInfo, isFavorite) {
|
||||
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
|
||||
|
||||
this._menuTimeoutId = 0;
|
||||
this._menu = null;
|
||||
this._dragStartX = 0;
|
||||
this._dragStartY = 0;
|
||||
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
|
||||
this.actor.connect('activate', Lang.bind(this, this._onActivate));
|
||||
},
|
||||
|
||||
setWidth: function(width) {
|
||||
this._nameBox.width = width + GLOW_PADDING * 2;
|
||||
_onActivate: function (actor, event) {
|
||||
let modifiers = event.get_state();
|
||||
|
||||
if (this._menuTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._menuTimeoutId);
|
||||
this._menuTimeoutId = 0;
|
||||
}
|
||||
|
||||
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
|
||||
this.appInfo.launch();
|
||||
} else {
|
||||
this.activateMostRecentWindow();
|
||||
}
|
||||
},
|
||||
|
||||
activateMostRecentWindow: function () {
|
||||
// The _get_windows_for_app sorts them for us
|
||||
let mostRecentWindow = this.windows[0];
|
||||
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
|
||||
},
|
||||
|
||||
_onHoverChanged: function() {
|
||||
let hover = this.actor.hover;
|
||||
if (!hover && this._menuTimeoutId > 0) {
|
||||
Mainloop.source_remove(this._menuTimeoutId);
|
||||
this._menuTimeoutId = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (this._menuTimeoutId > 0)
|
||||
Mainloop.source_remove(this._menuTimeoutId);
|
||||
this._menuTimeoutId = Mainloop.timeout_add(WELL_MENU_POPUP_TIMEOUT_MS,
|
||||
Lang.bind(this, this._popupMenu));
|
||||
return false;
|
||||
},
|
||||
|
||||
_popupMenu: function() {
|
||||
this._menuTimeoutId = 0;
|
||||
|
||||
this.actor.fake_release();
|
||||
|
||||
if (this._menu == null) {
|
||||
this._menu = new WellMenu(this);
|
||||
this._menu.connect('highlight-window', Lang.bind(this, function (menu, metaWindow) {
|
||||
Main.overview.getWorkspacesForWindow(metaWindow).setHighlightWindow(metaWindow);
|
||||
}));
|
||||
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
|
||||
let id;
|
||||
|
||||
// If we successfully picked a window, don't reset the workspace
|
||||
// state, since picking a window already did that.
|
||||
if (!isPoppedUp && menu.didActivateWindow)
|
||||
return;
|
||||
if (isPoppedUp)
|
||||
id = this.appInfo.get_id();
|
||||
else
|
||||
id = null;
|
||||
|
||||
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(id);
|
||||
}));
|
||||
}
|
||||
|
||||
this._menu.popup();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function InactiveWellItem(appInfo, isFavorite) {
|
||||
this._init(appInfo, isFavorite);
|
||||
}
|
||||
|
||||
InactiveWellItem.prototype = {
|
||||
__proto__: BaseWellItem.prototype,
|
||||
|
||||
_init : function(appInfo, isFavorite) {
|
||||
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
|
||||
|
||||
this.actor.connect('notify::pressed', Lang.bind(this, this._onPressedChanged));
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
|
||||
this.actor.connect('activate', Lang.bind(this, this._onActivate));
|
||||
},
|
||||
|
||||
_onPressedChanged: function() {
|
||||
let pressed = this.actor.pressed;
|
||||
if (pressed) {
|
||||
this.actor.border_color = WELL_MENU_BORDER_COLOR;
|
||||
} else {
|
||||
this.actor.border_color = TRANSPARENT_COLOR;
|
||||
}
|
||||
},
|
||||
|
||||
_onHoverChanged: function() {
|
||||
let hover = this.actor.hover;
|
||||
},
|
||||
|
||||
_onActivate: function() {
|
||||
if (this.windows.length == 0) {
|
||||
this.appInfo.launch();
|
||||
Main.overview.hide();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@ -755,22 +1161,25 @@ AppWell.prototype = {
|
||||
this._displays = displays;
|
||||
},
|
||||
|
||||
_addApps: function(apps) {
|
||||
_addApps: function(apps, isFavorite) {
|
||||
for (let i = 0; i < apps.length; i++) {
|
||||
let app = apps[i];
|
||||
let display = new WellDisplayItem(app, this.isFavorite);
|
||||
let windows = this._appMonitor.get_windows_for_app(app.get_id());
|
||||
let display;
|
||||
if (windows.length > 0)
|
||||
display = new RunningWellItem(app, isFavorite);
|
||||
else
|
||||
display = new InactiveWellItem(app, isFavorite);
|
||||
this._grid.actor.add_actor(display.actor);
|
||||
}
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let appSystem = Shell.AppSystem.get_default();
|
||||
|
||||
let app = null;
|
||||
if (source instanceof WellDisplayItem) {
|
||||
if (source instanceof BaseWellItem) {
|
||||
app = source.appInfo;
|
||||
} else if (source instanceof AppDisplayItem) {
|
||||
app = appSystem.lookup_cached_app(source.getId());
|
||||
|
120
js/ui/appIcon.js
120
js/ui/appIcon.js
@ -2,6 +2,7 @@
|
||||
|
||||
const Big = imports.gi.Big;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Lang = imports.lang;
|
||||
@ -11,7 +12,8 @@ const Main = imports.ui.main;
|
||||
|
||||
const GLOW_COLOR = new Clutter.Color();
|
||||
GLOW_COLOR.from_pixel(0x4f6ba4ff);
|
||||
const GLOW_PADDING = 5;
|
||||
const GLOW_PADDING_HORIZONTAL = 3;
|
||||
const GLOW_PADDING_VERTICAL = 3;
|
||||
|
||||
const APP_ICON_SIZE = 48;
|
||||
|
||||
@ -22,27 +24,31 @@ function AppIcon(appInfo) {
|
||||
AppIcon.prototype = {
|
||||
_init : function(appInfo) {
|
||||
this.appInfo = appInfo;
|
||||
this.windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||
for (let i = 0; i < this.windows.length; i++) {
|
||||
this.windows[i].connect('notify::user-time', Lang.bind(this, this._resortWindows));
|
||||
}
|
||||
this._resortWindows();
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
corner_radius: 2,
|
||||
border: 0,
|
||||
padding: 1,
|
||||
border_color: GenericDisplay.ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR,
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
this._icon = appInfo.create_icon_texture(APP_ICON_SIZE);
|
||||
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
|
||||
this.icon = appInfo.create_icon_texture(APP_ICON_SIZE);
|
||||
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
|
||||
|
||||
let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
x_align: Big.BoxAlignment.CENTER });
|
||||
let nameBox = new Shell.GenericContainer();
|
||||
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
|
||||
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
|
||||
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
|
||||
this._nameBox = nameBox;
|
||||
|
||||
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
|
||||
@ -50,34 +56,78 @@ AppIcon.prototype = {
|
||||
line_alignment: Pango.Alignment.CENTER,
|
||||
ellipsize: Pango.EllipsizeMode.END,
|
||||
text: appInfo.get_name() });
|
||||
nameBox.append(this._name, Big.BoxPackFlags.NONE);
|
||||
if (this._windows.length > 0) {
|
||||
let glow = new Shell.DrawingArea({});
|
||||
glow.connect('redraw', Lang.bind(this, function (e, tex) {
|
||||
Shell.draw_app_highlight(tex,
|
||||
this._windows.length,
|
||||
GLOW_COLOR.red / 255,
|
||||
GLOW_COLOR.green / 255,
|
||||
GLOW_COLOR.blue / 255,
|
||||
GLOW_COLOR.alpha / 255);
|
||||
}));
|
||||
this._name.connect('notify::allocation', Lang.bind(this, function () {
|
||||
let x = this._name.x;
|
||||
let y = this._name.y;
|
||||
let width = this._name.width;
|
||||
let height = this._name.height;
|
||||
// If we're smaller than the allocated box width, pad out the glow a bit
|
||||
// to make it more visible
|
||||
if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
|
||||
width += GLOW_PADDING * 2;
|
||||
x -= GLOW_PADDING;
|
||||
}
|
||||
glow.set_size(width, height);
|
||||
glow.set_position(x, y);
|
||||
}));
|
||||
nameBox.add_actor(glow);
|
||||
glow.lower(this._name);
|
||||
nameBox.add_actor(this._name);
|
||||
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
|
||||
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
|
||||
for (let i = 0; i < this._windows.length && i < 3; i++) {
|
||||
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
glowPath, -1, -1);
|
||||
glow.keep_aspect_ratio = false;
|
||||
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
|
||||
}
|
||||
this._nameBox.add_actor(this._glowBox);
|
||||
this._glowBox.lower(this._name);
|
||||
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
|
||||
},
|
||||
|
||||
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
|
||||
let [min, natural] = this._name.get_preferred_width(forHeight);
|
||||
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
|
||||
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
|
||||
},
|
||||
|
||||
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
|
||||
let [min, natural] = this._name.get_preferred_height(forWidth);
|
||||
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
|
||||
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
|
||||
},
|
||||
|
||||
_nameBoxAllocate: function (nameBox, box, flags) {
|
||||
let childBox = new Clutter.ActorBox();
|
||||
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
|
||||
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
|
||||
let availWidth = box.x2 - box.x1;
|
||||
let availHeight = box.y2 - box.y1;
|
||||
let targetWidth = availWidth;
|
||||
let xPadding = 0;
|
||||
if (naturalWidth < availWidth) {
|
||||
xPadding = Math.floor((availWidth - naturalWidth) / 2);
|
||||
}
|
||||
childBox.x1 = xPadding;
|
||||
childBox.x2 = availWidth - xPadding;
|
||||
childBox.y1 = GLOW_PADDING_VERTICAL;
|
||||
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
|
||||
this._name.allocate(childBox, flags);
|
||||
|
||||
// Now the glow
|
||||
if (this._glowBox != null) {
|
||||
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
|
||||
glowPaddingHoriz = Math.max(GLOW_PADDING_HORIZONTAL, glowPaddingHoriz);
|
||||
childBox.x1 = glowPaddingHoriz;
|
||||
childBox.x2 = availWidth - glowPaddingHoriz;
|
||||
childBox.y1 = 0;
|
||||
childBox.y2 = availHeight;
|
||||
this._glowBox.allocate(childBox, flags);
|
||||
}
|
||||
},
|
||||
|
||||
_resortWindows: function() {
|
||||
this.windows.sort(function (a, b) {
|
||||
let timeA = a.get_user_time();
|
||||
let timeB = b.get_user_time();
|
||||
if (timeA == timeB)
|
||||
return 0;
|
||||
else if (timeA > timeB)
|
||||
return -1;
|
||||
return 1;
|
||||
});
|
||||
},
|
||||
|
||||
getDragActor: function() {
|
||||
return this.appInfo.create_icon_texture(APP_ICON_SIZE);
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this.icon;
|
||||
}
|
||||
};
|
||||
|
@ -22,14 +22,12 @@ const DEFAULT_FONT = 'Sans Bold 16px';
|
||||
// Padding on the left and right side of the button.
|
||||
const SIDE_PADDING = 14;
|
||||
|
||||
function Button(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
||||
this._init(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font);
|
||||
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
|
||||
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
|
||||
}
|
||||
|
||||
Button.prototype = {
|
||||
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
||||
let me = this;
|
||||
|
||||
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
|
||||
this._buttonColor = buttonColor
|
||||
if (buttonColor == null)
|
||||
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
||||
@ -42,27 +40,20 @@ Button.prototype = {
|
||||
if (textColor == null)
|
||||
this._textColor = DEFAULT_TEXT_COLOR;
|
||||
|
||||
this._staysPressed = staysPressed
|
||||
if (staysPressed == null)
|
||||
this._staysPressed = false;
|
||||
|
||||
this._font = font;
|
||||
if (font == null)
|
||||
this._font = DEFAULT_FONT;
|
||||
|
||||
// if this._staysPressed is true, this._active will be true past the first release of a button, until a subsequent one (the button
|
||||
// is unpressed) or until release() is called explicitly
|
||||
this._active = false;
|
||||
this._isBetweenPressAndRelease = false;
|
||||
this._mouseIsOverButton = false;
|
||||
|
||||
this.button = new Big.Box({ reactive: true,
|
||||
corner_radius: 5,
|
||||
padding_left: SIDE_PADDING,
|
||||
padding_right: SIDE_PADDING,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER
|
||||
});
|
||||
this.actor = new Shell.ButtonBox({ reactive: true,
|
||||
corner_radius: 5,
|
||||
padding_left: SIDE_PADDING,
|
||||
padding_right: SIDE_PADDING,
|
||||
orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
y_align: Big.BoxAlignment.CENTER
|
||||
});
|
||||
if (typeof widgetOrText == 'string') {
|
||||
this._widget = new Clutter.Text({ font_name: this._font,
|
||||
color: this._textColor,
|
||||
@ -71,61 +62,20 @@ Button.prototype = {
|
||||
this._widget = widgetOrText;
|
||||
}
|
||||
|
||||
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this.button.connect('button-press-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = true;
|
||||
me.button.backgroundColor = me._pressedButtonColor;
|
||||
return false;
|
||||
});
|
||||
this.button.connect('button-release-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = false;
|
||||
if (!me._staysPressed || me._active) {
|
||||
me.release();
|
||||
} else {
|
||||
me._active = true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.button.connect('enter-event',
|
||||
function(o, event) {
|
||||
me._mouseIsOverButton = true;
|
||||
if (!me._active) {
|
||||
me.button.backgroundColor = me._buttonColor;
|
||||
}
|
||||
me.emit('enter-event');
|
||||
return false;
|
||||
});
|
||||
this.button.connect('leave-event',
|
||||
function(o, event) {
|
||||
me._isBetweenPressAndRelease = false;
|
||||
me._mouseIsOverButton = false;
|
||||
if (!me._active) {
|
||||
me.button.backgroundColor = null;
|
||||
}
|
||||
me.emit('leave-event');
|
||||
return false;
|
||||
});
|
||||
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
|
||||
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
|
||||
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
|
||||
},
|
||||
|
||||
pressIn : function() {
|
||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
||||
this._active = true;
|
||||
this.button.backgroundColor = this._pressedButtonColor;
|
||||
}
|
||||
},
|
||||
|
||||
release : function() {
|
||||
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
||||
this._active = false;
|
||||
if (this._mouseIsOverButton) {
|
||||
this.button.backgroundColor = this._buttonColor;
|
||||
} else {
|
||||
this.button.backgroundColor = null;
|
||||
}
|
||||
}
|
||||
_updateColors : function() {
|
||||
if (this.actor.active || this.actor.pressed)
|
||||
this.actor.backgroundColor = this._pressedButtonColor;
|
||||
else if (this.actor.hover)
|
||||
this.actor.backgroundColor = this._buttonColor;
|
||||
else
|
||||
this.actor.backgroundColor = null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -156,16 +106,15 @@ iconButton.prototype = {
|
||||
this.actor.set_opacity(0);
|
||||
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
|
||||
this._shouldHide = false;
|
||||
|
||||
// Nothing to do if the cursor has come back from a child of the parent actor
|
||||
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
||||
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||
return;
|
||||
|
||||
this._fadeIn();
|
||||
}));
|
||||
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
|
||||
// Nothing to do if the cursor has merely entered a child of the parent actor
|
||||
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
||||
if (actor.get_children().indexOf(event.get_related()) != -1)
|
||||
return;
|
||||
|
||||
// Remember that we should not be visible to hide the button if forceShow is unset
|
||||
|
@ -18,8 +18,6 @@ function Chrome() {
|
||||
|
||||
Chrome.prototype = {
|
||||
_init: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// The group itself has zero size so it doesn't interfere with DND
|
||||
this.actor = new Clutter.Group({ width: 0, height: 0 });
|
||||
global.stage.add_actor(this.actor);
|
||||
@ -238,7 +236,6 @@ Chrome.prototype = {
|
||||
},
|
||||
|
||||
_windowsRestacked: function() {
|
||||
let global = Shell.Global.get();
|
||||
let windows = global.get_windows();
|
||||
|
||||
// The chrome layer should be visible unless there is a window
|
||||
@ -280,7 +277,6 @@ Chrome.prototype = {
|
||||
},
|
||||
|
||||
_updateRegions: function() {
|
||||
let global = Shell.Global.get();
|
||||
let rects = [], struts = [], i;
|
||||
|
||||
delete this._updateRegionIdle;
|
||||
|
426
js/ui/dash.js
426
js/ui/dash.js
@ -70,6 +70,34 @@ const PANE_BORDER_WIDTH = 2;
|
||||
const PANE_BACKGROUND_COLOR = new Clutter.Color();
|
||||
PANE_BACKGROUND_COLOR.from_pixel(0x000000f4);
|
||||
|
||||
const APPS = "apps";
|
||||
const PREFS = "prefs";
|
||||
const DOCS = "docs";
|
||||
|
||||
/*
|
||||
* Returns the index in an array of a given length that is obtained
|
||||
* if the provided index is incremented by an increment and the array
|
||||
* is wrapped in if necessary.
|
||||
*
|
||||
* index: prior index, expects 0 <= index < length
|
||||
* increment: the change in index, expects abs(increment) <= length
|
||||
* length: the length of the array
|
||||
*/
|
||||
function _getIndexWrapped(index, increment, length) {
|
||||
return (index + increment + length) % length;
|
||||
}
|
||||
|
||||
function _createDisplay(displayType) {
|
||||
if (displayType == APPS)
|
||||
return new AppDisplay.AppDisplay();
|
||||
else if (displayType == PREFS)
|
||||
return new AppDisplay.AppDisplay(true);
|
||||
else if (displayType == DOCS)
|
||||
return new DocDisplay.DocDisplay();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function Pane() {
|
||||
this._init();
|
||||
}
|
||||
@ -92,7 +120,6 @@ Pane.prototype = {
|
||||
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: 6 });
|
||||
|
||||
let global = Shell.Global.get();
|
||||
let closeIconUri = "file://" + global.imagedir + "close.svg";
|
||||
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
closeIconUri,
|
||||
@ -146,12 +173,12 @@ Pane.prototype = {
|
||||
}
|
||||
Signals.addSignalMethods(Pane.prototype);
|
||||
|
||||
function ResultArea(displayClass, enableNavigation) {
|
||||
this._init(displayClass, enableNavigation);
|
||||
function ResultArea(displayType, enableNavigation) {
|
||||
this._init(displayType, enableNavigation);
|
||||
}
|
||||
|
||||
ResultArea.prototype = {
|
||||
_init : function(displayClass, enableNavigation) {
|
||||
_init : function(displayType, enableNavigation) {
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||
this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
spacing: DEFAULT_PADDING
|
||||
@ -160,7 +187,7 @@ ResultArea.prototype = {
|
||||
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
|
||||
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.display = new displayClass();
|
||||
this.display = _createDisplay(displayType);
|
||||
|
||||
this.navArea = this.display.getNavigationArea();
|
||||
if (enableNavigation && this.navArea)
|
||||
@ -217,10 +244,10 @@ ResultPane.prototype = {
|
||||
this._dash = dash;
|
||||
},
|
||||
|
||||
// Create an instance of displayClass and pack it into this pane's
|
||||
// content area. Return the displayClass instance.
|
||||
packResults: function(displayClass, enableNavigation) {
|
||||
let resultArea = new ResultArea(displayClass, enableNavigation);
|
||||
// Create a display of displayType and pack it into this pane's
|
||||
// content area. Return the display.
|
||||
packResults: function(displayType, enableNavigation) {
|
||||
let resultArea = new ResultArea(displayType, enableNavigation);
|
||||
|
||||
createPaneForDetails(this._dash, resultArea.display);
|
||||
|
||||
@ -288,7 +315,6 @@ SearchEntry.prototype = {
|
||||
padding_right: 4 });
|
||||
box.append(this._iconBox, Big.BoxPackFlags.END);
|
||||
|
||||
let global = Shell.Global.get();
|
||||
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
|
||||
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
magnifierUri, 18, 18);
|
||||
@ -393,6 +419,30 @@ MoreLink.prototype = {
|
||||
|
||||
Signals.addSignalMethods(MoreLink.prototype);
|
||||
|
||||
function BackLink() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
BackLink.prototype = {
|
||||
_init : function () {
|
||||
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_right: DEFAULT_PADDING,
|
||||
padding_left: DEFAULT_PADDING,
|
||||
reactive: true,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
border_right: SECTION_BORDER,
|
||||
border_color: SECTION_BORDER_COLOR });
|
||||
|
||||
let backIconUri = "file://" + global.imagedir + "back.svg";
|
||||
let backIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
backIconUri,
|
||||
12,
|
||||
16);
|
||||
this.actor.append(backIcon, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
function SectionHeader(title, suppressBrowse) {
|
||||
this._init(title, suppressBrowse);
|
||||
}
|
||||
@ -416,6 +466,14 @@ SectionHeader.prototype = {
|
||||
backgroundGradient.set_size(width, height);
|
||||
}));
|
||||
|
||||
this.backLink = new BackLink();
|
||||
this._innerBox.append(this.backLink.actor, Big.BoxPackFlags.NONE);
|
||||
this.backLink.actor.hide();
|
||||
|
||||
this.backLink.actor.connect('activate', Lang.bind(this, function (actor) {
|
||||
this.emit('back-link-activated');
|
||||
}));
|
||||
|
||||
let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_top: DEFAULT_PADDING,
|
||||
padding_bottom: DEFAULT_PADDING });
|
||||
@ -424,15 +482,42 @@ SectionHeader.prototype = {
|
||||
text: title });
|
||||
textBox.append(this.text, Big.BoxPackFlags.NONE);
|
||||
|
||||
this.countText = new Clutter.Text({ color: TEXT_COLOR,
|
||||
font_name: 'Sans Bold 14px' });
|
||||
textBox.append(this.countText, Big.BoxPackFlags.END);
|
||||
this.countText.hide();
|
||||
|
||||
this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
if (!suppressBrowse) {
|
||||
this.moreLink = new MoreLink();
|
||||
this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
|
||||
}
|
||||
},
|
||||
|
||||
setTitle : function(title) {
|
||||
this.text.text = title;
|
||||
},
|
||||
|
||||
setBackLinkVisible : function(visible) {
|
||||
if (visible)
|
||||
this.backLink.actor.show();
|
||||
else
|
||||
this.backLink.actor.hide();
|
||||
},
|
||||
|
||||
setCountText : function(countText) {
|
||||
if (countText == "") {
|
||||
this.countText.hide();
|
||||
} else {
|
||||
this.countText.show();
|
||||
this.countText.text = countText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Signals.addSignalMethods(SectionHeader.prototype);
|
||||
|
||||
function SearchSectionHeader(title, onClick) {
|
||||
this._init(title, onClick);
|
||||
}
|
||||
@ -457,37 +542,22 @@ SearchSectionHeader.prototype = {
|
||||
box.append(this.countText, Big.BoxPackFlags.END);
|
||||
|
||||
this.tooltip.hide();
|
||||
this._showTooltip = true;
|
||||
|
||||
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
|
||||
TEXT_COLOR, false, null);
|
||||
button.button.height = box.height;
|
||||
button.button.padding_left = DEFAULT_PADDING;
|
||||
button.button.padding_right = DEFAULT_PADDING;
|
||||
TEXT_COLOR);
|
||||
button.actor.height = box.height;
|
||||
button.actor.padding_left = DEFAULT_PADDING;
|
||||
button.actor.padding_right = DEFAULT_PADDING;
|
||||
|
||||
button.button.connect('button-release-event', onClick);
|
||||
button.connect('enter-event', Lang.bind(this, this._onButtonEntered));
|
||||
button.connect('leave-event', Lang.bind(this, this._onButtonLeft));
|
||||
this.actor = button.button;
|
||||
button.actor.connect('activate', onClick);
|
||||
button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip));
|
||||
this.actor = button.actor;
|
||||
},
|
||||
|
||||
_onButtonEntered : function() {
|
||||
if (this._showTooltip)
|
||||
_updateTooltip : function(actor) {
|
||||
if (actor.hover)
|
||||
this.tooltip.show();
|
||||
},
|
||||
|
||||
_onButtonLeft : function() {
|
||||
this.tooltip.hide();
|
||||
},
|
||||
|
||||
setShowTooltip : function(showTooltip) {
|
||||
this._showTooltip = showTooltip;
|
||||
// Because we only show tooltip on mouse-over,
|
||||
// we should not just show it here if showTooltip is
|
||||
// set to true, but in the future we could check if
|
||||
// the mouse happens to be over the header and show it
|
||||
// in that case.
|
||||
if (!this._showTooltip)
|
||||
else
|
||||
this.tooltip.hide();
|
||||
}
|
||||
}
|
||||
@ -512,8 +582,6 @@ function Dash() {
|
||||
|
||||
Dash.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
|
||||
// are not passed to the transparent background underneath them. This background is used for the workspaces area when
|
||||
// the additional dash panes are being shown and it handles clicks by closing the additional panes, so that the user
|
||||
@ -567,29 +635,62 @@ Dash.prototype = {
|
||||
this._searchTimeoutId = 0;
|
||||
let text = this._searchEntry.getText();
|
||||
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
|
||||
this._appSearchResultArea.display.setSearch(text);
|
||||
this._docSearchResultArea.display.setSearch(text);
|
||||
|
||||
this._appSearchHeader.countText.text = this._appSearchResultArea.display.getMatchedItemsCount() + "";
|
||||
this._docSearchHeader.countText.text = this._docSearchResultArea.display.getMatchedItemsCount() + "";
|
||||
|
||||
let selectionSet = false;
|
||||
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.resultArea.display.setSearch(text);
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
let itemCountText = itemCount + "";
|
||||
section.header.countText.text = itemCountText;
|
||||
|
||||
if (this._searchResultsSingleShownSection == section.type) {
|
||||
this._searchResultsSection.header.setCountText(itemCountText);
|
||||
if (itemCount == 0) {
|
||||
section.resultArea.actor.hide();
|
||||
} else {
|
||||
section.resultArea.actor.show();
|
||||
}
|
||||
} else if (this._searchResultsSingleShownSection == null) {
|
||||
// Don't show the section if it has no results
|
||||
if (itemCount == 0) {
|
||||
section.header.actor.hide();
|
||||
section.resultArea.actor.hide();
|
||||
} else {
|
||||
section.header.actor.show();
|
||||
section.resultArea.actor.show();
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the selection when a new search is applied.
|
||||
section.resultArea.display.unsetSelected();
|
||||
if (!selectionSet && section.resultArea.display.hasItems() &&
|
||||
(this._searchResultsSingleShownSection == null || this._searchResultsSingleShownSection == section.type)) {
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}));
|
||||
}));
|
||||
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
|
||||
// only one of the displays will have an item selected, so it's ok to
|
||||
// call activateSelected() on all of them
|
||||
this._appSearchResultArea.display.activateSelected();
|
||||
this._docSearchResultArea.display.activateSelected();
|
||||
// Only one of the displays will have an item selected, so it's ok to
|
||||
// call activateSelected() on all of them.
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.resultArea.display.activateSelected();
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
|
||||
let text = this._searchEntry.getText();
|
||||
let symbol = Shell.get_event_key_symbol(e);
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
// Escape will keep clearing things back to the desktop.
|
||||
// If we are showing a particular section of search, go back to all sections.
|
||||
if (this._getOnlyAppSearchShown() || this._getOnlyDocSearchShown())
|
||||
if (this._searchResultsSingleShownSection != null)
|
||||
this._showAllSearchSections();
|
||||
// If we have an active search, we remove it.
|
||||
else if (this._searchActive)
|
||||
@ -608,22 +709,40 @@ Dash.prototype = {
|
||||
// too, but there doesn't seem to be any flickering if we first select
|
||||
// something in one display, but then unset the selection, and move
|
||||
// it to the other display, so it's ok to do that.
|
||||
if (this._docSearchResultArea.display.hasSelected())
|
||||
this._docSearchResultArea.display.selectUp();
|
||||
else if (this._appSearchResultArea.display.hasItems())
|
||||
this._appSearchResultArea.display.selectUp();
|
||||
else
|
||||
this._docSearchResultArea.display.selectUp();
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectUp()) {
|
||||
if (this._searchResultsSingleShownSection != section.type) {
|
||||
// We need to move the selection to the next section above this section that has items,
|
||||
// wrapping around at the bottom, if necessary.
|
||||
let newSectionIndex = this._findAnotherSectionWithItems(i, -1);
|
||||
if (newSectionIndex >= 0) {
|
||||
this._searchSections[newSectionIndex].resultArea.display.selectLastItem();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (symbol == Clutter.Down) {
|
||||
if (!this._searchActive)
|
||||
return true;
|
||||
if (this._docSearchResultArea.display.hasSelected())
|
||||
this._docSearchResultArea.display.selectDown();
|
||||
else if (this._appSearchResultArea.display.hasItems())
|
||||
this._appSearchResultArea.display.selectDown();
|
||||
else
|
||||
this._docSearchResultArea.display.selectDown();
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectDown()) {
|
||||
if (this._searchResultsSingleShownSection != section.type) {
|
||||
// We need to move the selection to the next section below this section that has items,
|
||||
// wrapping around at the top, if necessary.
|
||||
let newSectionIndex = this._findAnotherSectionWithItems(i, 1);
|
||||
if (newSectionIndex >= 0) {
|
||||
this._searchSections[newSectionIndex].resultArea.display.selectFirstItem();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -639,7 +758,7 @@ Dash.prototype = {
|
||||
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||
if (this._moreAppsPane == null) {
|
||||
this._moreAppsPane = new ResultPane(this);
|
||||
this._moreAppsPane.packResults(AppDisplay.AppDisplay, true);
|
||||
this._moreAppsPane.packResults(APPS, true);
|
||||
this._addPane(this._moreAppsPane);
|
||||
link.setPane(this._moreAppsPane);
|
||||
}
|
||||
@ -667,7 +786,7 @@ Dash.prototype = {
|
||||
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
|
||||
if (this._moreDocsPane == null) {
|
||||
this._moreDocsPane = new ResultPane(this);
|
||||
this._moreDocsPane.packResults(DocDisplay.DocDisplay, true);
|
||||
this._moreDocsPane.packResults(DOCS, true);
|
||||
this._addPane(this._moreDocsPane);
|
||||
link.setPane(this._moreDocsPane);
|
||||
}
|
||||
@ -679,36 +798,49 @@ Dash.prototype = {
|
||||
|
||||
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
|
||||
|
||||
this._appSearchHeader = new SearchSectionHeader(_("APPLICATIONS"),
|
||||
Lang.bind(this,
|
||||
function () {
|
||||
this._toggleOnlyAppSearchShown();
|
||||
return true;
|
||||
}));
|
||||
this._searchResultsSection.content.append(this._appSearchHeader.actor, Big.BoxPackFlags.NONE);
|
||||
this._appSearchResultArea = new ResultArea(AppDisplay.AppDisplay, false);
|
||||
this._appSearchResultArea.controlBox.hide();
|
||||
this._searchResultsSection.content.append(this._appSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
createPaneForDetails(this, this._appSearchResultArea.display);
|
||||
this._searchResultsSingleShownSection = null;
|
||||
|
||||
this._docSearchHeader = new SearchSectionHeader(_("RECENT DOCUMENTS"),
|
||||
Lang.bind(this,
|
||||
function () {
|
||||
this._toggleOnlyDocSearchShown();
|
||||
return true;
|
||||
}));
|
||||
this._searchResultsSection.content.append(this._docSearchHeader.actor, Big.BoxPackFlags.NONE);
|
||||
this._docSearchResultArea = new ResultArea(DocDisplay.DocDisplay, false);
|
||||
this._docSearchResultArea.controlBox.hide();
|
||||
this._searchResultsSection.content.append(this._docSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
createPaneForDetails(this, this._docSearchResultArea.display);
|
||||
this._searchResultsSection.header.connect('back-link-activated', Lang.bind(this, function () {
|
||||
this._showAllSearchSections();
|
||||
}));
|
||||
|
||||
this._searchSections = [
|
||||
{ type: APPS,
|
||||
title: _("APPLICATIONS"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
},
|
||||
{ type: PREFS,
|
||||
title: _("PREFERENCES"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
},
|
||||
{ type: DOCS,
|
||||
title: _("RECENT DOCUMENTS"),
|
||||
header: null,
|
||||
resultArea: null
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
section.header = new SearchSectionHeader(section.title,
|
||||
Lang.bind(this,
|
||||
function () {
|
||||
this._showSingleSearchSection(section.type);
|
||||
}));
|
||||
this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE);
|
||||
section.resultArea = new ResultArea(section.type, false);
|
||||
section.resultArea.controlBox.hide();
|
||||
this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND);
|
||||
createPaneForDetails(this, section.resultArea.display);
|
||||
}
|
||||
|
||||
this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND);
|
||||
this._searchResultsSection.actor.hide();
|
||||
},
|
||||
|
||||
show: function() {
|
||||
let global = Shell.Global.get();
|
||||
global.stage.set_key_focus(this._searchEntry.entry);
|
||||
},
|
||||
|
||||
@ -753,67 +885,79 @@ Dash.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_toggleOnlyAppSearchShown: function() {
|
||||
if (this._getOnlyAppSearchShown()) {
|
||||
this._setDocSearchShown(true);
|
||||
} else {
|
||||
this._setDocSearchShown(false);
|
||||
_showSingleSearchSection: function(type) {
|
||||
// We currently don't allow going from showing one section to showing another section.
|
||||
if (this._searchResultsSingleShownSection != null) {
|
||||
throw new Error("We were already showing a single search section: '" + this._searchResultsSingleShownSection
|
||||
+ "' when _showSingleSearchSection() was called for '" + type + "'");
|
||||
}
|
||||
},
|
||||
|
||||
_toggleOnlyDocSearchShown: function() {
|
||||
if (this._getOnlyDocSearchShown()) {
|
||||
this._setAppSearchShown(true);
|
||||
} else {
|
||||
this._setAppSearchShown(false);
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.type == type) {
|
||||
// This will be the only section shown.
|
||||
section.resultArea.display.selectFirstItem();
|
||||
section.resultArea.controlBox.show();
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
let itemCountText = itemCount + "";
|
||||
section.header.actor.hide();
|
||||
this._searchResultsSection.header.setTitle(section.title);
|
||||
this._searchResultsSection.header.setBackLinkVisible(true);
|
||||
this._searchResultsSection.header.setCountText(itemCountText);
|
||||
} else {
|
||||
// We need to hide this section.
|
||||
section.header.actor.hide();
|
||||
section.resultArea.actor.hide();
|
||||
section.resultArea.display.unsetSelected();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// TODO: the following two functions currently rely on us showing the
|
||||
// section header even if there are no results in that section. We'll need
|
||||
// to change the check if we update that behavior. We'll also need to change
|
||||
// the check if we add more sections to search results.
|
||||
_getOnlyAppSearchShown: function() {
|
||||
return this._searchActive && !this._docSearchHeader.actor.visible;
|
||||
},
|
||||
|
||||
_getOnlyDocSearchShown: function() {
|
||||
return this._searchActive && !this._appSearchHeader.actor.visible;
|
||||
},
|
||||
|
||||
_setAppSearchShown: function(show) {
|
||||
if (show) {
|
||||
this._appSearchHeader.actor.show();
|
||||
this._appSearchResultArea.actor.show();
|
||||
this._docSearchResultArea.display.displayPage(0);
|
||||
this._docSearchResultArea.controlBox.hide();
|
||||
this._docSearchHeader.setShowTooltip(true);
|
||||
} else {
|
||||
this._appSearchHeader.actor.hide();
|
||||
this._appSearchResultArea.actor.hide();
|
||||
this._docSearchResultArea.controlBox.show();
|
||||
this._docSearchHeader.setShowTooltip(false);
|
||||
}
|
||||
},
|
||||
|
||||
_setDocSearchShown: function(show) {
|
||||
if (show) {
|
||||
this._docSearchHeader.actor.show();
|
||||
this._docSearchResultArea.actor.show();
|
||||
this._appSearchResultArea.display.displayPage(0);
|
||||
this._appSearchResultArea.controlBox.hide();
|
||||
this._appSearchHeader.setShowTooltip(true);
|
||||
} else {
|
||||
this._docSearchHeader.actor.hide();
|
||||
this._docSearchResultArea.actor.hide();
|
||||
this._appSearchResultArea.controlBox.show();
|
||||
this._appSearchHeader.setShowTooltip(false);
|
||||
}
|
||||
this._searchResultsSingleShownSection = type;
|
||||
},
|
||||
|
||||
_showAllSearchSections: function() {
|
||||
this._setAppSearchShown(true);
|
||||
this._setDocSearchShown(true);
|
||||
if (this._searchResultsSingleShownSection != null) {
|
||||
let selectionSet = false;
|
||||
for (var i = 0; i < this._searchSections.length; i++) {
|
||||
let section = this._searchSections[i];
|
||||
if (section.type == this._searchResultsSingleShownSection) {
|
||||
// This will no longer be the only section shown.
|
||||
section.resultArea.display.displayPage(0);
|
||||
section.resultArea.controlBox.hide();
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
if (itemCount != 0) {
|
||||
section.header.actor.show();
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
this._searchResultsSection.header.setTitle(_("SEARCH RESULTS"));
|
||||
this._searchResultsSection.header.setBackLinkVisible(false);
|
||||
this._searchResultsSection.header.setCountText("");
|
||||
} else {
|
||||
// We need to restore this section.
|
||||
let itemCount = section.resultArea.display.getMatchedItemsCount();
|
||||
if (itemCount != 0) {
|
||||
section.header.actor.show();
|
||||
section.resultArea.actor.show();
|
||||
// This ensures that some other section will have the selection if the
|
||||
// single section that was being displayed did not have any items.
|
||||
if (!selectionSet) {
|
||||
section.resultArea.display.selectFirstItem();
|
||||
selectionSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._searchResultsSingleShownSection = null;
|
||||
}
|
||||
},
|
||||
|
||||
_findAnotherSectionWithItems: function(index, increment) {
|
||||
let pos = _getIndexWrapped(index, increment, this._searchSections.length);
|
||||
while (pos != index) {
|
||||
if (this._searchSections[pos].resultArea.display.hasItems())
|
||||
return pos;
|
||||
pos = _getIndexWrapped(pos, increment, this._searchSections.length);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Dash.prototype);
|
||||
|
150
js/ui/dnd.js
150
js/ui/dnd.js
@ -8,15 +8,17 @@ const Tweener = imports.ui.tweener;
|
||||
|
||||
const SNAP_BACK_ANIMATION_TIME = 0.25;
|
||||
|
||||
function _Draggable(actor) {
|
||||
this._init(actor);
|
||||
function _Draggable(actor, manualMode) {
|
||||
this._init(actor, manualMode);
|
||||
}
|
||||
|
||||
_Draggable.prototype = {
|
||||
_init : function(actor) {
|
||||
_init : function(actor, manualMode) {
|
||||
this.actor = actor;
|
||||
this.actor.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
if (!manualMode)
|
||||
this.actor.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
this._haveSourceGrab = false;
|
||||
},
|
||||
|
||||
_onButtonPress : function (actor, event) {
|
||||
@ -25,6 +27,7 @@ _Draggable.prototype = {
|
||||
if (Tweener.getTweenCount(actor))
|
||||
return false;
|
||||
|
||||
this._haveSourceGrab = true;
|
||||
this._grabActor(actor);
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
@ -66,6 +69,80 @@ _Draggable.prototype = {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* startDrag:
|
||||
* @actor: Origin actor for drag and drop
|
||||
* @stageX: X coordinate of event
|
||||
* @stageY: Y coordinate of event
|
||||
* @time: Event timestamp
|
||||
*
|
||||
* Directly initiate a drag and drop operation from the given actor.
|
||||
* This function is useful to call if you've specified manualMode
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag: function (actor, stageX, stageY, time) {
|
||||
this.emit('drag-begin', time);
|
||||
|
||||
this._dragStartX = stageX;
|
||||
this._dragStartY = stageY;
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||
// 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
|
||||
// to know what was the drag actor source.
|
||||
if (this.actor._delegate.getDragActorSource) {
|
||||
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
||||
// If the user dragged from the source, then position
|
||||
// the dragActor over it. Otherwise, center it
|
||||
// around the pointer
|
||||
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
||||
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
||||
let x, y;
|
||||
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
||||
stageY > sourceY && stageY <= sourceY + sourceHeight) {
|
||||
x = sourceX;
|
||||
y = sourceY;
|
||||
} else {
|
||||
x = stageX - this._dragActor.width / 2;
|
||||
y = stageY - this._dragActor.height / 2;
|
||||
}
|
||||
this._dragActor.set_position(x, y);
|
||||
} else {
|
||||
this._dragActorSource = this.actor;
|
||||
}
|
||||
this._dragOrigParent = undefined;
|
||||
if (this._haveSourceGrab) {
|
||||
this._haveSourceGrab = false;
|
||||
this._ungrabActor(actor);
|
||||
}
|
||||
this._grabActor(this._dragActor);
|
||||
|
||||
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||
} else {
|
||||
this._dragActor = actor;
|
||||
this._dragActorSource = undefined;
|
||||
this._dragOrigParent = actor.get_parent();
|
||||
this._dragOrigX = this._dragActor.x;
|
||||
this._dragOrigY = this._dragActor.y;
|
||||
this._dragOrigScale = this._dragActor.scale_x;
|
||||
|
||||
let [actorStageX, actorStageY] = actor.get_transformed_position();
|
||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
// Set the actor's scale such that it will keep the same
|
||||
// transformed size when it's reparented to the stage
|
||||
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
|
||||
actor.set_scale(scaledWidth / actor.width,
|
||||
scaledHeight / actor.height);
|
||||
}
|
||||
|
||||
this._dragActor.reparent(actor.get_stage());
|
||||
this._dragActor.raise_top();
|
||||
},
|
||||
|
||||
_onMotion : function (actor, event) {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
@ -75,55 +152,7 @@ _Draggable.prototype = {
|
||||
if (!this._dragActor &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
this.emit('drag-begin', event.get_time());
|
||||
|
||||
if (this.actor._delegate && this.actor._delegate.getDragActor) {
|
||||
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
|
||||
// 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
|
||||
// to know what was the drag actor source.
|
||||
if (this.actor._delegate.getDragActorSource) {
|
||||
this._dragActorSource = this.actor._delegate.getDragActorSource();
|
||||
// If the user dragged from the source, then position
|
||||
// the dragActor over it. Otherwise, center it
|
||||
// around the pointer
|
||||
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
|
||||
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
|
||||
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
|
||||
stageY > sourceY && stageY <= sourceY + sourceHeight)
|
||||
this._dragActor.set_position(sourceX, sourceY);
|
||||
else
|
||||
this._dragActor.set_position(stageX - this._dragActor.width / 2, stageY - this._dragActor.height / 2);
|
||||
} else {
|
||||
this._dragActorSource = this.actor;
|
||||
}
|
||||
this._dragOrigParent = undefined;
|
||||
this._ungrabActor(actor);
|
||||
this._grabActor(this._dragActor);
|
||||
|
||||
this._dragOffsetX = this._dragActor.x - this._dragStartX;
|
||||
this._dragOffsetY = this._dragActor.y - this._dragStartY;
|
||||
} else {
|
||||
this._dragActor = actor;
|
||||
this._dragActorSource = undefined;
|
||||
this._dragOrigParent = actor.get_parent();
|
||||
this._dragOrigX = this._dragActor.x;
|
||||
this._dragOrigY = this._dragActor.y;
|
||||
this._dragOrigScale = this._dragActor.scale_x;
|
||||
|
||||
let [actorStageX, actorStageY] = actor.get_transformed_position();
|
||||
this._dragOffsetX = actorStageX - this._dragStartX;
|
||||
this._dragOffsetY = actorStageY - this._dragStartY;
|
||||
|
||||
// Set the actor's scale such that it will keep the same
|
||||
// transformed size when it's reparented to the stage
|
||||
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
|
||||
actor.set_scale(scaledWidth / actor.width,
|
||||
scaledHeight / actor.height);
|
||||
}
|
||||
|
||||
this._dragActor.reparent(actor.get_stage());
|
||||
this._dragActor.raise_top();
|
||||
this.startDrag(actor, stageX, stageY, event.get_time());
|
||||
}
|
||||
|
||||
// If we are dragging, update the position
|
||||
@ -149,7 +178,7 @@ _Draggable.prototype = {
|
||||
event.get_time());
|
||||
}
|
||||
target = target.get_parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -225,6 +254,13 @@ _Draggable.prototype = {
|
||||
|
||||
Signals.addSignalMethods(_Draggable.prototype);
|
||||
|
||||
function makeDraggable(actor) {
|
||||
return new _Draggable(actor);
|
||||
/**
|
||||
* makeDraggable:
|
||||
* @actor: Source actor
|
||||
* @manualMode: If given, do not automatically start drag and drop on click
|
||||
*
|
||||
* Create an object which controls drag and drop for the given actor.
|
||||
*/
|
||||
function makeDraggable(actor, manualMode) {
|
||||
return new _Draggable(actor, manualMode);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ DocDisplayItem.prototype = {
|
||||
_resetTimeDisplay: function(currentSecs) {
|
||||
let lastSecs = this._docInfo.timestamp;
|
||||
let timeDelta = currentSecs - lastSecs;
|
||||
let [text, nextUpdate] = Shell.Global.get().format_time_relative_pretty(timeDelta);
|
||||
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
|
||||
this._timeoutTime = currentSecs + nextUpdate;
|
||||
this._setDescriptionText(text);
|
||||
}
|
||||
@ -120,8 +120,6 @@ DocDisplay.prototype = {
|
||||
|
||||
_init : function() {
|
||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||
let me = this;
|
||||
|
||||
// We keep a single timeout callback for updating last visited times
|
||||
// for all the items in the display. This avoids creating individual
|
||||
// callbacks for each item in the display. So proper time updates
|
||||
@ -132,14 +130,14 @@ DocDisplay.prototype = {
|
||||
|
||||
this._docManager = DocInfo.getDocManager();
|
||||
this._docsStale = true;
|
||||
this._docManager.connect('changed', function(mgr, userData) {
|
||||
me._docsStale = true;
|
||||
this._docManager.connect('changed', Lang.bind(this, function(mgr, userData) {
|
||||
this._docsStale = true;
|
||||
// Changes in local recent files should not happen when we are in the Overview mode,
|
||||
// but redisplaying right away is cool when we use Zephyr.
|
||||
// Also, we might be displaying remote documents, like Google Docs, in the future
|
||||
// which might be edited by someone else.
|
||||
me._redisplay(false);
|
||||
});
|
||||
this._redisplay(false);
|
||||
}));
|
||||
|
||||
this.connect('destroy', Lang.bind(this, function (o) {
|
||||
if (this._updateTimeoutId > 0)
|
||||
|
@ -7,6 +7,7 @@ const Gdk = imports.gi.Gdk;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -87,7 +88,6 @@ GenericDisplayItem.prototype = {
|
||||
spacing: DEFAULT_PADDING });
|
||||
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let global = Shell.Global.get();
|
||||
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
||||
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
|
||||
infoIconUri,
|
||||
@ -426,7 +426,11 @@ GenericDisplay.prototype = {
|
||||
|
||||
// Returns true if the display has any displayed items.
|
||||
hasItems: function() {
|
||||
return this._list.displayedCount > 0;
|
||||
// TODO: figure out why this._list.displayedCount is returning a
|
||||
// positive number when this._mathedItems.length is 0
|
||||
// This can be triggered if a search string is entered for which there are no matches.
|
||||
// log("this._mathedItems.length: " + this._matchedItems.length + " this._list.displayedCount " + this._list.displayedCount);
|
||||
return this._matchedItems.length > 0;
|
||||
},
|
||||
|
||||
getMatchedItemsCount: function() {
|
||||
@ -457,6 +461,10 @@ GenericDisplay.prototype = {
|
||||
|
||||
// Displays the page specified by the pageNumber argument.
|
||||
displayPage: function(pageNumber) {
|
||||
// Cleanup from the previous selection, but don't unset this._selectedIndex
|
||||
if (this.hasSelected()) {
|
||||
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||
}
|
||||
this._list.page = pageNumber;
|
||||
},
|
||||
|
||||
@ -487,24 +495,23 @@ GenericDisplay.prototype = {
|
||||
this.selectFirstItem();
|
||||
}
|
||||
|
||||
// We currently redisplay matching items and raise the sideshow as part of two different callbacks.
|
||||
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
|
||||
Mainloop.timeout_add(5,
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
// Check if the pointer is over one of the items and display the information button if it is.
|
||||
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
||||
let global = Shell.Global.get();
|
||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||
x, y);
|
||||
if (actor != null) {
|
||||
let item = this._findDisplayedByActor(actor);
|
||||
if (item != null) {
|
||||
item.onDrawnUnderPointer();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
// Check if the pointer is over one of the items and display the information button if it is.
|
||||
// We want to do this between finishing our changes to the display and the point where
|
||||
// the display is redrawn.
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function() {
|
||||
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
|
||||
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
|
||||
x, y);
|
||||
if (actor != null) {
|
||||
let item = this._findDisplayedByActor(actor);
|
||||
if (item != null) {
|
||||
item.onDrawnUnderPointer();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
Meta.PRIORITY_BEFORE_REDRAW);
|
||||
},
|
||||
|
||||
// Creates a display item based on the information associated with itemId
|
||||
@ -698,9 +705,11 @@ GenericDisplay.prototype = {
|
||||
*/
|
||||
_updateDisplayControl: function(resetDisplayControl) {
|
||||
if (resetDisplayControl) {
|
||||
this._selectedIndex = -1;
|
||||
this.displayControl.remove_all();
|
||||
let nPages = this._list.n_pages;
|
||||
// Don't show the page indicator if there is only one page.
|
||||
if (nPages == 1)
|
||||
return;
|
||||
let pageNumber = this._list.page;
|
||||
for (let i = 0; i < nPages; i++) {
|
||||
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
|
||||
@ -730,6 +739,9 @@ GenericDisplay.prototype = {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.hasSelected()) {
|
||||
this.selectFirstItem();
|
||||
}
|
||||
},
|
||||
|
||||
// Returns a display item based on its index in the ordering of the
|
||||
@ -754,17 +766,8 @@ GenericDisplay.prototype = {
|
||||
// Selects (e.g. highlights) a display item at the provided index,
|
||||
// updates this.selectedItemDetails actor, and emits 'selected' signal.
|
||||
_selectIndex: function(index) {
|
||||
if (index >= this._list.displayedCount)
|
||||
return
|
||||
|
||||
// If the item is already selected, all we do is toggling the details pane.
|
||||
if (this._selectedIndex == index && index >= 0) {
|
||||
this.emit('details', index);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cleanup from the previous item
|
||||
if (this._selectedIndex >= 0) {
|
||||
if (this.hasSelected()) {
|
||||
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@ var commandHeader = "const Clutter = imports.gi.Clutter; " +
|
||||
"const Tweener = imports.ui.tweener; " +
|
||||
/* Utility functions...we should probably be able to use these
|
||||
* in the shell core code too. */
|
||||
"const global = Shell.Global.get(); " +
|
||||
"const stage = global.stage; " +
|
||||
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
|
||||
/* Special lookingGlass functions */
|
||||
@ -249,7 +248,6 @@ function Inspector() {
|
||||
|
||||
Inspector.prototype = {
|
||||
_init: function() {
|
||||
let global = Shell.Global.get();
|
||||
let width = 150;
|
||||
let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
|
||||
border: 1,
|
||||
@ -274,7 +272,6 @@ Inspector.prototype = {
|
||||
}));
|
||||
|
||||
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
|
||||
let global = Shell.Global.get();
|
||||
Clutter.ungrab_pointer(eventHandler);
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
@ -288,7 +285,6 @@ Inspector.prototype = {
|
||||
}));
|
||||
|
||||
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
|
||||
let global = Shell.Global.get();
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
|
||||
stageX,
|
||||
@ -312,8 +308,6 @@ function LookingGlass() {
|
||||
|
||||
LookingGlass.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._idleHistorySaveId = 0;
|
||||
let historyPath = global.configdir + "/lookingglass-history.txt";
|
||||
this._historyFile = Gio.file_new_for_path(historyPath);
|
||||
@ -392,7 +386,7 @@ LookingGlass.prototype = {
|
||||
activatable: true,
|
||||
singleLineMode: true,
|
||||
text: ''});
|
||||
/* kind of a hack */
|
||||
/* unmapping the edit box will un-focus it, undo that */
|
||||
notebook.connect('selection', Lang.bind(this, function (nb, child) {
|
||||
if (child == this._evalBox)
|
||||
global.stage.set_key_focus(this._entry);
|
||||
@ -423,7 +417,7 @@ LookingGlass.prototype = {
|
||||
return true;
|
||||
}));
|
||||
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||
let symbol = Shell.get_event_key_symbol(e);
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close();
|
||||
return true;
|
||||
@ -524,8 +518,7 @@ LookingGlass.prototype = {
|
||||
},
|
||||
|
||||
_resizeTo: function(actor) {
|
||||
let stage = Shell.Global.get().stage;
|
||||
let stageWidth = stage.width;
|
||||
let stage = global.stage;
|
||||
let myWidth = stage.width * 0.7;
|
||||
let myHeight = stage.height * 0.7;
|
||||
let [srcX, srcY] = actor.get_transformed_position();
|
||||
@ -555,10 +548,7 @@ LookingGlass.prototype = {
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
if (!Main.beginModal())
|
||||
return;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
Main.pushModal(this.actor);
|
||||
global.stage.set_key_focus(this._entry);
|
||||
|
||||
Tweener.addTween(this.actor, { time: 0.5,
|
||||
@ -575,7 +565,7 @@ LookingGlass.prototype = {
|
||||
this._open = false;
|
||||
Tweener.removeTweens(this.actor);
|
||||
|
||||
Main.endModal();
|
||||
Main.popModal(this.actor);
|
||||
|
||||
Tweener.addTween(this.actor, { time: 0.5,
|
||||
transition: "easeOutQuad",
|
||||
|
125
js/ui/main.js
125
js/ui/main.js
@ -30,10 +30,14 @@ let runDialog = null;
|
||||
let lookingGlass = null;
|
||||
let wm = null;
|
||||
let recorder = null;
|
||||
let inModal = false;
|
||||
let modalCount = 0;
|
||||
let modalActorFocusStack = [];
|
||||
|
||||
function start() {
|
||||
let global = Shell.Global.get();
|
||||
// Add a binding for "global" in the global JS namespace; (gjs
|
||||
// keeps the web browser convention of having that namespace be
|
||||
// called "window".)
|
||||
window.global = Shell.Global.get();
|
||||
|
||||
Gio.DesktopAppInfo.set_desktop_env("GNOME");
|
||||
|
||||
@ -64,10 +68,7 @@ function start() {
|
||||
|
||||
global.connect('panel-run-dialog', function(panel) {
|
||||
// Make sure not more than one run dialog is shown.
|
||||
if (runDialog == null) {
|
||||
runDialog = new RunDialog.RunDialog();
|
||||
}
|
||||
runDialog.open();
|
||||
getRunDialog().open();
|
||||
});
|
||||
|
||||
overview = new Overview.Overview();
|
||||
@ -102,7 +103,6 @@ function start() {
|
||||
}
|
||||
|
||||
function _relayout() {
|
||||
let global = Shell.Global.get();
|
||||
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
|
||||
overview.relayout();
|
||||
}
|
||||
@ -114,8 +114,6 @@ function _relayout() {
|
||||
// is called.)
|
||||
function _removeUnusedWorkspaces() {
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let windows = global.get_windows();
|
||||
let maxWorkspace = 0;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
@ -149,13 +147,13 @@ function _removeUnusedWorkspaces() {
|
||||
// should be asking Mutter to resolve the key into an action and then
|
||||
// base our handling based on the action.
|
||||
function _globalKeyPressHandler(actor, event) {
|
||||
if (!inModal)
|
||||
if (modalCount == 0)
|
||||
return false;
|
||||
|
||||
let type = event.type();
|
||||
|
||||
if (type == Clutter.EventType.KEY_PRESS) {
|
||||
let symbol = Shell.get_event_key_symbol (event);
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Print) {
|
||||
// We want to be able to take screenshots of the shell at all times
|
||||
let gconf = Shell.GConf.get_default();
|
||||
@ -169,7 +167,7 @@ function _globalKeyPressHandler(actor, event) {
|
||||
return true;
|
||||
}
|
||||
} else if (type == Clutter.EventType.KEY_RELEASE) {
|
||||
let symbol = Shell.get_event_key_symbol (event);
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
|
||||
// The super key is the default for triggering the overview, and should
|
||||
// get us out of the overview when we are already in it.
|
||||
@ -177,35 +175,96 @@ function _globalKeyPressHandler(actor, event) {
|
||||
overview.hide();
|
||||
|
||||
return true;
|
||||
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
|
||||
getRunDialog().open();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Used to go into a mode where all keyboard and mouse input goes to
|
||||
// the stage. Returns true if we successfully grabbed the keyboard and
|
||||
// went modal, false otherwise
|
||||
function beginModal() {
|
||||
let global = Shell.Global.get();
|
||||
let timestamp = global.screen.get_display().get_current_time();
|
||||
|
||||
if (!global.begin_modal(timestamp))
|
||||
return false;
|
||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||
|
||||
inModal = true;
|
||||
|
||||
return true;
|
||||
function _findModal(actor) {
|
||||
for (let i = 0; i < modalActorFocusStack.length; i++) {
|
||||
let [stackActor, stackFocus] = modalActorFocusStack[i];
|
||||
if (stackActor == actor) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function endModal() {
|
||||
let global = Shell.Global.get();
|
||||
/**
|
||||
* pushModal:
|
||||
* @actor: #ClutterActor which will be given keyboard focus
|
||||
*
|
||||
* Ensure we are in a mode where all keyboard and mouse input goes to
|
||||
* the stage. Multiple calls to this function act in a stacking fashion;
|
||||
* the effect will be undone when an equal number of popModal() invocations
|
||||
* have been made.
|
||||
*
|
||||
* Next, record the current Clutter keyboard focus on a stack. If the modal stack
|
||||
* returns to this actor, reset the focus to the actor which was focused
|
||||
* at the time pushModal() was invoked.
|
||||
*/
|
||||
function pushModal(actor) {
|
||||
let timestamp = global.screen.get_display().get_current_time();
|
||||
|
||||
modalCount += 1;
|
||||
actor.connect('destroy', function() {
|
||||
let index = _findModal(actor);
|
||||
if (index >= 0)
|
||||
modalActorFocusStack.splice(index, 1);
|
||||
});
|
||||
let curFocus = global.stage.get_key_focus();
|
||||
if (curFocus != null) {
|
||||
curFocus.connect('destroy', function() {
|
||||
let index = _findModal(actor);
|
||||
if (index >= 0)
|
||||
modalActorFocusStack[index][1] = null;
|
||||
});
|
||||
}
|
||||
modalActorFocusStack.push([actor, curFocus]);
|
||||
|
||||
if (modalCount > 1)
|
||||
return;
|
||||
|
||||
if (!global.begin_modal(timestamp)) {
|
||||
log("pushModal: invocation of begin_modal failed");
|
||||
return;
|
||||
}
|
||||
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* popModal:
|
||||
* @actor: #ClutterActor passed to original invocation of pushModal().
|
||||
*
|
||||
* Reverse the effect of pushModal(). If this invocation is undoing
|
||||
* the topmost invocation, then the focus will be restored to the
|
||||
* previous focus at the time when pushModal() was invoked.
|
||||
*/
|
||||
function popModal(actor) {
|
||||
let timestamp = global.screen.get_display().get_current_time();
|
||||
|
||||
modalCount -= 1;
|
||||
let focusIndex = _findModal(actor);
|
||||
if (focusIndex >= 0) {
|
||||
if (focusIndex == modalActorFocusStack.length - 1) {
|
||||
let [stackActor, stackFocus] = modalActorFocusStack[focusIndex];
|
||||
global.stage.set_key_focus(stackFocus);
|
||||
} else {
|
||||
// Remove from the middle, shift the focus chain up
|
||||
for (let i = focusIndex; i < modalActorFocusStack.length - 1; i++) {
|
||||
modalActorFocusStack[i + 1][1] = modalActorFocusStack[i][1];
|
||||
}
|
||||
}
|
||||
modalActorFocusStack.splice(focusIndex, 1);
|
||||
}
|
||||
if (modalCount > 0)
|
||||
return;
|
||||
|
||||
global.end_modal(timestamp);
|
||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||
inModal = false;
|
||||
}
|
||||
|
||||
function createLookingGlass() {
|
||||
@ -216,8 +275,14 @@ function createLookingGlass() {
|
||||
return lookingGlass;
|
||||
}
|
||||
|
||||
function getRunDialog() {
|
||||
if (runDialog == null) {
|
||||
runDialog = new RunDialog.RunDialog();
|
||||
}
|
||||
return runDialog;
|
||||
}
|
||||
|
||||
function createAppLaunchContext() {
|
||||
let global = Shell.Global.get();
|
||||
let screen = global.screen;
|
||||
let display = screen.get_display();
|
||||
|
||||
|
@ -73,6 +73,7 @@ const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
|
||||
let wideScreen = false;
|
||||
let displayGridColumnWidth = null;
|
||||
let displayGridRowHeight = null;
|
||||
let addRemoveButtonSize = null;
|
||||
|
||||
function Overview() {
|
||||
this._init();
|
||||
@ -80,10 +81,6 @@ function Overview() {
|
||||
|
||||
Overview.prototype = {
|
||||
_init : function() {
|
||||
let me = this;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._group = new Clutter.Group();
|
||||
this._group._delegate = this;
|
||||
|
||||
@ -95,7 +92,15 @@ Overview.prototype = {
|
||||
|
||||
this._activeDisplayPane = null;
|
||||
|
||||
// Used to catch any clicks when we have an active pane; see the comments
|
||||
// During transitions, we raise this to the top to avoid having the overview
|
||||
// area be reactive; it causes too many issues such as double clicks on
|
||||
// Dash elements, or mouseover handlers in the workspaces.
|
||||
this._coverPane = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
this._group.add_actor(this._coverPane);
|
||||
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
|
||||
|
||||
// Similar to the cover pane but used for dialogs ("panes"); see the comments
|
||||
// in addPane below.
|
||||
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
|
||||
reactive: true });
|
||||
@ -127,12 +132,12 @@ Overview.prototype = {
|
||||
this._transparentBackground.lower_bottom();
|
||||
this._paneContainer.lower_bottom();
|
||||
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
this._workspaces = null;
|
||||
},
|
||||
|
||||
_recalculateGridSizes: function () {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
|
||||
|
||||
// We divide the screen into an imaginary grid which helps us determine the layout of
|
||||
@ -147,12 +152,14 @@ Overview.prototype = {
|
||||
},
|
||||
|
||||
relayout: function () {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let screenHeight = global.screen_height;
|
||||
let screenWidth = global.screen_width;
|
||||
|
||||
let contentHeight = screenHeight - Panel.PANEL_HEIGHT;
|
||||
let contentY = Panel.PANEL_HEIGHT;
|
||||
let contentHeight = screenHeight - contentY;
|
||||
|
||||
this._coverPane.set_position(0, contentY);
|
||||
this._coverPane.set_size(screenWidth, contentHeight);
|
||||
|
||||
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
|
||||
@ -167,22 +174,21 @@ Overview.prototype = {
|
||||
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
|
||||
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
|
||||
|
||||
let dashY = Panel.PANEL_HEIGHT;
|
||||
this._dash.actor.set_position(0, dashY);
|
||||
this._dash.actor.set_size(displayGridColumnWidth, screenHeight - dashY);
|
||||
this._dash.searchArea.height = this._workspacesY - dashY;
|
||||
this._dash.actor.set_position(0, contentY);
|
||||
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
|
||||
this._dash.searchArea.height = this._workspacesY - contentY;
|
||||
this._dash.sectionArea.height = this._workspacesHeight;
|
||||
|
||||
// place the 'Add Workspace' button in the bottom row of the grid
|
||||
this._addButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||
this._addButtonX = this._workspacesX + this._workspacesWidth - this._addButtonSize;
|
||||
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
|
||||
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
|
||||
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
|
||||
|
||||
this._backOver.set_position(0, Panel.PANEL_HEIGHT);
|
||||
this._backOver.set_position(0, contentY);
|
||||
this._backOver.set_size(global.screen_width, contentHeight);
|
||||
|
||||
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
|
||||
Panel.PANEL_HEIGHT);
|
||||
contentY);
|
||||
// Dynamic width
|
||||
this._paneContainer.height = contentHeight;
|
||||
|
||||
@ -232,7 +238,7 @@ Overview.prototype = {
|
||||
// This allows the user to place the item on any workspace.
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source instanceof GenericDisplay.GenericDisplayItem
|
||||
|| source instanceof AppDisplay.WellDisplayItem) {
|
||||
|| source instanceof AppDisplay.BaseWellItem) {
|
||||
if (this._activeDisplayPane != null)
|
||||
this._activeDisplayPane.close();
|
||||
return true;
|
||||
@ -271,20 +277,16 @@ Overview.prototype = {
|
||||
show : function() {
|
||||
if (this.visible)
|
||||
return;
|
||||
if (!Main.beginModal())
|
||||
return;
|
||||
Main.pushModal(this._dash.actor);
|
||||
|
||||
this.visible = true;
|
||||
this.animationInProgress = true;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._dash.show();
|
||||
|
||||
/* TODO: make this stuff dynamic */
|
||||
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
|
||||
this._workspacesX, this._workspacesY,
|
||||
this._addButtonSize, this._addButtonX, this._addButtonY);
|
||||
this._workspacesX, this._workspacesY);
|
||||
this._group.add_actor(this._workspaces.actor);
|
||||
|
||||
// The workspaces actor is as big as the screen, so we have to raise the dash above it
|
||||
@ -292,6 +294,12 @@ Overview.prototype = {
|
||||
// be as big as the screen.
|
||||
this._dash.actor.raise(this._workspaces.actor);
|
||||
|
||||
// Create (+) button
|
||||
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
|
||||
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
|
||||
this._group.add_actor(this._addButton.actor);
|
||||
this._addButton.actor.raise(this._workspaces.actor);
|
||||
|
||||
// All the the actors in the window group are completely obscured,
|
||||
// hiding the group holding them while the Overview is displayed greatly
|
||||
// increases performance of the Overview especially when there are many
|
||||
@ -327,15 +335,14 @@ Overview.prototype = {
|
||||
time: ANIMATION_TIME
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this.emit('showing');
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
hide: function() {
|
||||
if (!this.visible || this._hideInProgress)
|
||||
return;
|
||||
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this.animationInProgress = true;
|
||||
this._hideInProgress = true;
|
||||
if (this._activeDisplayPane != null)
|
||||
@ -365,6 +372,7 @@ Overview.prototype = {
|
||||
time: ANIMATION_TIME
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this.emit('hiding');
|
||||
},
|
||||
|
||||
@ -375,6 +383,18 @@ Overview.prototype = {
|
||||
this.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* getWorkspacesForWindow:
|
||||
* @metaWindow: A #MetaWindow
|
||||
*
|
||||
* Returns the Workspaces object associated with the given window.
|
||||
* This method is not be accessible if the overview is not open
|
||||
* and will return %null.
|
||||
*/
|
||||
getWorkspacesForWindow: function(metaWindow) {
|
||||
return this._workspaces;
|
||||
},
|
||||
|
||||
/**
|
||||
* activateWindow:
|
||||
* @metaWindow: A #MetaWindow
|
||||
@ -387,7 +407,6 @@ Overview.prototype = {
|
||||
*/
|
||||
activateWindow: function (metaWindow, time) {
|
||||
this._workspaces.activateWindowFromOverview(metaWindow, time);
|
||||
this.hide();
|
||||
},
|
||||
|
||||
//// Private methods ////
|
||||
@ -397,13 +416,12 @@ Overview.prototype = {
|
||||
return;
|
||||
|
||||
this.animationInProgress = false;
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
this.emit('shown');
|
||||
},
|
||||
|
||||
_hideDone: function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
global.window_group.show();
|
||||
|
||||
this._workspaces.destroy();
|
||||
@ -416,8 +434,47 @@ Overview.prototype = {
|
||||
this.animationInProgress = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
Main.endModal();
|
||||
this._coverPane.lower_bottom();
|
||||
|
||||
Main.popModal(this._dash.actor);
|
||||
this.emit('hidden');
|
||||
},
|
||||
|
||||
_addNewWorkspace: function() {
|
||||
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
|
||||
},
|
||||
|
||||
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
|
||||
this._addNewWorkspace();
|
||||
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Overview.prototype);
|
||||
|
||||
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
||||
}
|
||||
|
||||
AddWorkspaceButton.prototype = {
|
||||
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||
this.actor = new Clutter.Group({ x: buttonX,
|
||||
y: buttonY,
|
||||
width: global.screen_width - buttonX,
|
||||
height: global.screen_height - buttonY,
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
this._acceptDropCallback = acceptDropCallback;
|
||||
|
||||
let plus = new Clutter.Texture({ x: 0,
|
||||
y: 0,
|
||||
width: buttonSize,
|
||||
height: buttonSize });
|
||||
plus.set_from_file(global.imagedir + 'add-workspace.svg');
|
||||
this.actor.add_actor(plus);
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop: function(source, actor, x, y, time) {
|
||||
return this._acceptDropCallback(source, actor, x, y, time);
|
||||
}
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ function AppPanelMenu() {
|
||||
|
||||
AppPanelMenu.prototype = {
|
||||
_init: function() {
|
||||
this._metaDisplay = Shell.Global.get().screen.get_display();
|
||||
this._metaDisplay = global.screen.get_display();
|
||||
|
||||
this._focusedApp = null;
|
||||
this._activeSequence = null;
|
||||
@ -168,8 +168,6 @@ function Panel() {
|
||||
|
||||
Panel.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
|
||||
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
|
||||
});
|
||||
@ -269,10 +267,10 @@ Panel.prototype = {
|
||||
/* left side */
|
||||
|
||||
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||
PANEL_FOREGROUND_COLOR, true, DEFAULT_FONT);
|
||||
this.button.button.height = PANEL_HEIGHT;
|
||||
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
|
||||
this.button.actor.height = PANEL_HEIGHT;
|
||||
|
||||
this._leftBox.append(this.button.button, Big.BoxPackFlags.NONE);
|
||||
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
// We use this flag to mark the case where the user has entered the
|
||||
// hot corner and has not left both the hot corner and a surrounding
|
||||
@ -374,43 +372,46 @@ Panel.prototype = {
|
||||
let statusbutton = new Button.Button(statusbox,
|
||||
PANEL_BUTTON_COLOR,
|
||||
PRESSED_BUTTON_BACKGROUND_COLOR,
|
||||
PANEL_FOREGROUND_COLOR,
|
||||
true);
|
||||
statusbutton.button.height = PANEL_HEIGHT;
|
||||
statusbutton.button.connect('button-press-event', function (b, e) {
|
||||
statusmenu.toggle(e);
|
||||
return false;
|
||||
PANEL_FOREGROUND_COLOR);
|
||||
statusbutton.actor.height = PANEL_HEIGHT;
|
||||
statusbutton.actor.connect('button-press-event', function (b, e) {
|
||||
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||
statusmenu.toggle(e);
|
||||
// The statusmenu might not pop up if it couldn't get a pointer grab
|
||||
if (statusmenu.is_active())
|
||||
statusbutton.actor.active = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// If popping up the menu failed (because there was already a grab in
|
||||
// effect from Mutter or another app), then we'll never get a ::deactivated
|
||||
// signal because the menu was never activated, so we need to unhighlight
|
||||
// separately when the user releases the mouse button.
|
||||
//
|
||||
// We depend on connection ordering; this needs to be called after Button's
|
||||
// ::button-release-event handler; that will set the active flag for this
|
||||
// stays-pressed button, then we unset the active flag by calling release().
|
||||
statusbutton.button.connect('button-release-event', function (b, e) {
|
||||
if (!statusmenu.is_active())
|
||||
statusbutton.release();
|
||||
return false;
|
||||
});
|
||||
this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
|
||||
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
|
||||
// We get a deactivated event when the popup disappears
|
||||
this._statusmenu.connect('deactivated', function (sm) {
|
||||
statusbutton.release();
|
||||
statusbutton.actor.active = false;
|
||||
});
|
||||
|
||||
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
|
||||
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
|
||||
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
|
||||
// to switch to.
|
||||
this.button.button.connect('button-press-event',
|
||||
Lang.bind(Main.overview, Main.overview.toggle));
|
||||
this.button.actor.connect('button-press-event', function(b, e) {
|
||||
if (e.get_button() == 1 && e.get_click_count() == 1) {
|
||||
Main.overview.toggle();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
|
||||
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
|
||||
// and to be released when it is exited regardless of how it was triggered.
|
||||
Main.overview.connect('showing', Lang.bind(this.button, this.button.pressIn));
|
||||
Main.overview.connect('hiding', Lang.bind(this.button, this.button.release));
|
||||
Main.overview.connect('showing', Lang.bind(this, function() {
|
||||
this.button.actor.active = true;
|
||||
}));
|
||||
Main.overview.connect('hiding', Lang.bind(this, function() {
|
||||
this.button.actor.active = false;
|
||||
}));
|
||||
|
||||
Main.chrome.addActor(this.actor);
|
||||
Main.chrome.setVisibleInOverview(this.actor, true);
|
||||
@ -471,14 +472,14 @@ Panel.prototype = {
|
||||
},
|
||||
|
||||
_onHotCornerLeft : function(actor, event) {
|
||||
if (Shell.get_event_related(event) != this._hotCornerEnvirons) {
|
||||
if (event.get_related() != this._hotCornerEnvirons) {
|
||||
this._hotCornerEntered = false;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_onHotCornerEnvironsLeft : function(actor, event) {
|
||||
if (Shell.get_event_related(event) != this._hotCorner) {
|
||||
if (event.get_related() != this._hotCorner) {
|
||||
this._hotCornerEntered = false;
|
||||
}
|
||||
return false;
|
||||
|
@ -80,6 +80,9 @@ Places.prototype = {
|
||||
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: PLACES_VSPACING });
|
||||
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
|
||||
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: PLACES_VSPACING });
|
||||
|
||||
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
spacing: PLACES_VSPACING });
|
||||
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
|
||||
@ -98,6 +101,23 @@ Places.prototype = {
|
||||
|
||||
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
|
||||
|
||||
/*
|
||||
* Show devices, code more or less ported from nautilus-places-sidebar.c
|
||||
*/
|
||||
|
||||
this._menuBox.append(this._devBox, Big.BoxPackFlags.NONE);
|
||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
||||
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
|
||||
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
|
||||
this._updateDevices();
|
||||
|
||||
let networkApp = null;
|
||||
try {
|
||||
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
|
||||
@ -151,6 +171,9 @@ Places.prototype = {
|
||||
|
||||
this._dirsBox.remove_all();
|
||||
|
||||
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
|
||||
return;
|
||||
|
||||
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
|
||||
|
||||
if (!success)
|
||||
@ -194,6 +217,62 @@ Places.prototype = {
|
||||
});
|
||||
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
},
|
||||
|
||||
_updateDevices: function() {
|
||||
this._devBox.remove_all();
|
||||
|
||||
/* first go through all connected drives */
|
||||
let drives = this._volumeMonitor.get_connected_drives();
|
||||
for (let i = 0; i < drives.length; i++) {
|
||||
let volumes = drives[i].get_volumes();
|
||||
for(let j = 0; j < volumes.length; j++) {
|
||||
let mount = volumes[j].get_mount();
|
||||
if(mount != null) {
|
||||
this._addMount(mount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add all volumes that is not associated with a drive */
|
||||
let volumes = this._volumeMonitor.get_volumes();
|
||||
for(let i = 0; i < volumes.length; i++) {
|
||||
if(volumes[i].get_drive() != null)
|
||||
continue;
|
||||
|
||||
let mount = volumes[i].get_mount();
|
||||
if(mount != null) {
|
||||
this._addMount(mount);
|
||||
}
|
||||
}
|
||||
|
||||
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
|
||||
let mounts = this._volumeMonitor.get_mounts();
|
||||
for(let i = 0; i < mounts.length; i++) {
|
||||
if(mounts[i].is_shadowed())
|
||||
continue;
|
||||
|
||||
if(mounts[i].get_volume())
|
||||
continue;
|
||||
|
||||
this._addMount(mounts[i]);
|
||||
}
|
||||
},
|
||||
|
||||
_addMount: function(mount) {
|
||||
let mountLabel = mount.get_name();
|
||||
let mountIcon = mount.get_icon();
|
||||
let root = mount.get_root();
|
||||
let mountUri = root.get_uri();
|
||||
let devItem = new PlaceDisplay(mountLabel,
|
||||
function() {
|
||||
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
|
||||
},
|
||||
function() {
|
||||
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
|
||||
});
|
||||
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
|
||||
}
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(Places.prototype);
|
||||
|
@ -5,6 +5,7 @@ const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
@ -21,8 +22,10 @@ BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
|
||||
const BOX_TEXT_COLOR = new Clutter.Color();
|
||||
BOX_TEXT_COLOR.from_pixel(0xffffffff);
|
||||
|
||||
const BOX_WIDTH = 320;
|
||||
const BOX_HEIGHT = 56;
|
||||
const DIALOG_WIDTH = 320;
|
||||
const DIALOG_PADDING = 6;
|
||||
const ICON_SIZE = 24;
|
||||
const ICON_BOX_SIZE = 36;
|
||||
|
||||
function RunDialog() {
|
||||
this._init();
|
||||
@ -30,25 +33,31 @@ function RunDialog() {
|
||||
|
||||
RunDialog.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this._isOpen = false;
|
||||
|
||||
let gconf = Shell.GConf.get_default();
|
||||
gconf.connect('changed', Lang.bind(this, function (gconf, key) {
|
||||
if (key == 'development_tools')
|
||||
this._enableInternalCommands = gconf.get_bool('development_tools');
|
||||
}));
|
||||
this._enableInternalCommands = gconf.get_boolean('development_tools');
|
||||
|
||||
this._internalCommands = { 'lg':
|
||||
Lang.bind(this, function() {
|
||||
// Run in an idle to avoid recursive key grab problems
|
||||
Mainloop.idle_add(function() { Main.createLookingGlass().open(); });
|
||||
Main.createLookingGlass().open();
|
||||
}),
|
||||
|
||||
'r': Lang.bind(this, function() {
|
||||
let global = Shell.Global.get();
|
||||
global.reexec_self();
|
||||
}),
|
||||
|
||||
// Developer brain backwards compatibility
|
||||
'restart': Lang.bind(this, function() {
|
||||
let global = Shell.Global.get();
|
||||
global.reexec_self();
|
||||
}),
|
||||
|
||||
'debugexit': Lang.bind(this, function() {
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
})
|
||||
};
|
||||
|
||||
@ -64,45 +73,77 @@ RunDialog.prototype = {
|
||||
reactive: true });
|
||||
this._group.add_actor(this._overlay);
|
||||
|
||||
let boxGroup = new Clutter.Group();
|
||||
boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
|
||||
(global.screen_height - BOX_HEIGHT) / 2);
|
||||
this._group.add_actor(boxGroup);
|
||||
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
width: global.screen_width,
|
||||
height: global.screen_height });
|
||||
|
||||
let box = new Big.Box({ background_color: BOX_BACKGROUND_COLOR,
|
||||
corner_radius: 4,
|
||||
reactive: false,
|
||||
width: BOX_WIDTH,
|
||||
height: BOX_HEIGHT
|
||||
});
|
||||
boxGroup.add_actor(box);
|
||||
this._group.add_actor(boxH);
|
||||
|
||||
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
y_align: Big.BoxAlignment.CENTER });
|
||||
|
||||
boxH.append(boxV, Big.BoxPackFlags.NONE);
|
||||
|
||||
|
||||
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
background_color: BOX_BACKGROUND_COLOR,
|
||||
corner_radius: 4,
|
||||
reactive: false,
|
||||
padding: DIALOG_PADDING,
|
||||
width: DIALOG_WIDTH });
|
||||
|
||||
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||
font_name: '18px Sans',
|
||||
text: _("Please enter a command:") });
|
||||
label.set_position(6, 6);
|
||||
boxGroup.add_actor(label);
|
||||
|
||||
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||
font_name: '20px Sans Bold',
|
||||
editable: true,
|
||||
activatable: true,
|
||||
singleLineMode: true,
|
||||
text: '',
|
||||
width: BOX_WIDTH - 12,
|
||||
height: BOX_HEIGHT - 12 });
|
||||
// TODO: Implement relative positioning using Tidy.
|
||||
this._entry.set_position(6, 30);
|
||||
boxGroup.add_actor(this._entry);
|
||||
singleLineMode: true });
|
||||
|
||||
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._errorBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
|
||||
padding_top: DIALOG_PADDING });
|
||||
|
||||
dialogBox.append(this._errorBox, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
|
||||
y_align: Big.BoxAlignment.CENTER,
|
||||
x_align: Big.BoxAlignment.CENTER,
|
||||
width: ICON_BOX_SIZE,
|
||||
height: ICON_BOX_SIZE });
|
||||
|
||||
this._errorBox.append(iconBox, Big.BoxPackFlags.NONE);
|
||||
|
||||
this._commandError = false;
|
||||
|
||||
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
|
||||
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._errorMessage = new Clutter.Text({ color: BOX_TEXT_COLOR,
|
||||
font_name: '18px Sans Bold',
|
||||
line_wrap: true });
|
||||
|
||||
this._errorBox.append(this._errorMessage, Big.BoxPackFlags.EXPAND);
|
||||
|
||||
this._errorBox.hide();
|
||||
|
||||
this._entry.connect('activate', Lang.bind(this, function (o, e) {
|
||||
this._run(o.get_text());
|
||||
this.close();
|
||||
return false;
|
||||
if (!this._commandError)
|
||||
this.close();
|
||||
}));
|
||||
|
||||
|
||||
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
|
||||
let symbol = Shell.get_event_key_symbol(e);
|
||||
let symbol = e.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close();
|
||||
return true;
|
||||
@ -112,17 +153,31 @@ RunDialog.prototype = {
|
||||
},
|
||||
|
||||
_run : function(command) {
|
||||
let f = this._internalCommands[command];
|
||||
let f;
|
||||
if (this._enableInternalCommands)
|
||||
f = this._internalCommands[command];
|
||||
else
|
||||
f = null;
|
||||
if (f) {
|
||||
f();
|
||||
} else if (command) {
|
||||
try {
|
||||
this._commandError = false;
|
||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||
let p = new Shell.Process({'args' : args});
|
||||
p.run();
|
||||
} catch (e) {
|
||||
// TODO: Give the user direct feedback.
|
||||
log('Could not run command ' + command + ': ' + e);
|
||||
this._commandError = true;
|
||||
/*
|
||||
* The exception contains an error string like:
|
||||
* Error invoking Shell.run: Failed to execute child process "foo"
|
||||
* (No such file or directory)
|
||||
* We are only interested in the actual error, so parse that out.
|
||||
*/
|
||||
let m = /.+\((.+)\)/.exec(e);
|
||||
let errorStr = "Execution of '" + command + "' failed:\n" + m[1];
|
||||
this._errorMessage.set_text(errorStr);
|
||||
this._errorBox.show();
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -131,13 +186,10 @@ RunDialog.prototype = {
|
||||
if (this._isOpen) // Already shown
|
||||
return;
|
||||
|
||||
if (!Main.beginModal())
|
||||
return;
|
||||
|
||||
this._isOpen = true;
|
||||
this._group.show();
|
||||
|
||||
let global = Shell.Global.get();
|
||||
Main.pushModal(this._group);
|
||||
global.stage.set_key_focus(this._entry);
|
||||
},
|
||||
|
||||
@ -147,10 +199,13 @@ RunDialog.prototype = {
|
||||
|
||||
this._isOpen = false;
|
||||
|
||||
this._errorBox.hide();
|
||||
this._commandError = false;
|
||||
|
||||
this._group.hide();
|
||||
this._entry.text = '';
|
||||
|
||||
Main.endModal();
|
||||
Main.popModal(this._group);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(RunDialog.prototype);
|
||||
|
@ -21,21 +21,12 @@ const SIDEBAR_PADDING = 4;
|
||||
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
||||
|
||||
// The maximum height of the sidebar would be extending from just
|
||||
// below the panel to just above the taskbar. Since the taskbar is
|
||||
// just a temporary hack and it would be too hard to do this the right
|
||||
// way, we just hardcode its size.
|
||||
const HARDCODED_TASKBAR_HEIGHT = 24;
|
||||
const MAXIMUM_SIDEBAR_HEIGHT = Shell.Global.get().screen_height - Panel.PANEL_HEIGHT - HARDCODED_TASKBAR_HEIGHT;
|
||||
|
||||
function Sidebar() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Sidebar.prototype = {
|
||||
_init : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
// The top-left corner of the sidebar is fixed at:
|
||||
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
|
||||
// (The negative X is so that we don't see the rounded
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
@ -41,9 +42,17 @@ const Tweener = imports.tweener.tweener;
|
||||
// calls any of these is almost certainly wrong anyway, because they
|
||||
// affect the entire application.)
|
||||
|
||||
let slowDownFactor = 1.0;
|
||||
|
||||
// Called from Main.start
|
||||
function init() {
|
||||
let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
|
||||
if (slowdownEnv) {
|
||||
let factor = parseFloat(slowdownEnv);
|
||||
if (!isNaN(factor) && factor > 0.0)
|
||||
slowDownFactor = factor;
|
||||
}
|
||||
|
||||
Tweener.setFrameTicker(new ClutterFrameTicker());
|
||||
}
|
||||
|
||||
@ -208,11 +217,10 @@ ClutterFrameTicker.prototype = {
|
||||
this._startTime = -1;
|
||||
this._currentTime = -1;
|
||||
|
||||
let me = this;
|
||||
this._timeline.connect('new-frame',
|
||||
this._timeline.connect('new-frame', Lang.bind(this,
|
||||
function(timeline, frame) {
|
||||
me._onNewFrame(frame);
|
||||
});
|
||||
this._onNewFrame(frame);
|
||||
}));
|
||||
},
|
||||
|
||||
_onNewFrame : function(frame) {
|
||||
@ -225,7 +233,7 @@ ClutterFrameTicker.prototype = {
|
||||
this._startTime = this._timeline.get_elapsed_time();
|
||||
|
||||
// currentTime is in milliseconds
|
||||
this._currentTime = this._timeline.get_elapsed_time() - this._startTime;
|
||||
this._currentTime = (this._timeline.get_elapsed_time() - this._startTime) / slowDownFactor;
|
||||
this.emit('prepare-frame');
|
||||
},
|
||||
|
||||
|
@ -163,7 +163,6 @@ ClockWidget.prototype = {
|
||||
},
|
||||
|
||||
_updateCairo: function(time) {
|
||||
let global = Shell.Global.get();
|
||||
Shell.draw_clock(this.collapsedActor,
|
||||
time.getHours() % 12,
|
||||
time.getMinutes());
|
||||
|
@ -296,7 +296,7 @@ WidgetBox.prototype = {
|
||||
this.state == Widget.STATE_POPPING_OUT)) {
|
||||
// If moving into another actor within this._hbox, let the
|
||||
// event be propagated
|
||||
let into = Shell.get_event_related(event);
|
||||
let into = event.get_related();
|
||||
while (into) {
|
||||
if (into == this._hbox)
|
||||
return false;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const AltTab = imports.ui.altTab;
|
||||
const Main = imports.ui.main;
|
||||
@ -17,10 +17,8 @@ function WindowManager() {
|
||||
|
||||
WindowManager.prototype = {
|
||||
_init : function() {
|
||||
let me = this;
|
||||
let shellwm = global.window_manager;
|
||||
|
||||
this._global = Shell.Global.get();
|
||||
this._shellwm = this._global.window_manager;
|
||||
this._minimizing = [];
|
||||
this._maximizing = [];
|
||||
this._unmaximizing = [];
|
||||
@ -28,60 +26,20 @@ WindowManager.prototype = {
|
||||
this._destroying = [];
|
||||
|
||||
this._switchData = null;
|
||||
this._shellwm.connect('switch-workspace',
|
||||
function(o, from, to, direction) {
|
||||
let actors = me._shellwm.get_switch_workspace_actors();
|
||||
me._switchWorkspace(actors, from, to, direction);
|
||||
});
|
||||
this._shellwm.connect('kill-switch-workspace',
|
||||
function(o) {
|
||||
me._switchWorkspaceDone();
|
||||
});
|
||||
this._shellwm.connect('minimize',
|
||||
function(o, actor) {
|
||||
me._minimizeWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-minimize',
|
||||
function(o, actor) {
|
||||
me._minimizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('maximize',
|
||||
function(o, actor, tx, ty, tw, th) {
|
||||
me._maximizeWindow(actor, tx, ty, tw, th);
|
||||
});
|
||||
this._shellwm.connect('kill-maximize',
|
||||
function(o, actor) {
|
||||
me._maximizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('unmaximize',
|
||||
function(o, actor, tx, ty, tw, th) {
|
||||
me._unmaximizeWindow(actor, tx, ty, tw, th);
|
||||
});
|
||||
this._shellwm.connect('kill-unmaximize',
|
||||
function(o, actor) {
|
||||
me._unmaximizeWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('map',
|
||||
function(o, actor) {
|
||||
me._mapWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-map',
|
||||
function(o, actor) {
|
||||
me._mapWindowDone(actor);
|
||||
});
|
||||
this._shellwm.connect('destroy',
|
||||
function(o, actor) {
|
||||
me._destroyWindow(actor);
|
||||
});
|
||||
this._shellwm.connect('kill-destroy',
|
||||
function(o, actor) {
|
||||
me._destroyWindowDone(actor);
|
||||
});
|
||||
shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
|
||||
shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
|
||||
shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
|
||||
shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
|
||||
shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
|
||||
shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
|
||||
shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
|
||||
shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
|
||||
shellwm.connect('map', Lang.bind(this, this._mapWindow));
|
||||
shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
|
||||
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
|
||||
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
|
||||
|
||||
this._shellwm.connect('begin-alt-tab',
|
||||
function(o, handler) {
|
||||
me._beginAltTab(handler);
|
||||
});
|
||||
shellwm.connect('begin-alt-tab', Lang.bind(this, this._beginAltTab));
|
||||
},
|
||||
|
||||
_shouldAnimate : function(actor) {
|
||||
@ -101,9 +59,9 @@ WindowManager.prototype = {
|
||||
return false;
|
||||
},
|
||||
|
||||
_minimizeWindow : function(actor) {
|
||||
_minimizeWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,49 +79,49 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._minimizeWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._minimizeWindowOverwritten,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_minimizeWindowDone : function(actor) {
|
||||
_minimizeWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_minimizeWindowOverwritten : function(actor) {
|
||||
_minimizeWindowOverwritten : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
this._shellwm.completed_minimize(actor);
|
||||
shellwm.completed_minimize(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_maximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
this._shellwm.completed_maximize(actor);
|
||||
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_maximize(actor);
|
||||
},
|
||||
|
||||
_maximizeWindowDone : function(actor) {
|
||||
_maximizeWindowDone : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_maximizeWindowOverwrite : function(actor) {
|
||||
_maximizeWindowOverwrite : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_unmaximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
this._shellwm.completed_unmaximize(actor);
|
||||
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
|
||||
shellwm.completed_unmaximize(actor);
|
||||
},
|
||||
|
||||
_unmaximizeWindowDone : function(actor) {
|
||||
_unmaximizeWindowDone : function(shellwm, actor) {
|
||||
},
|
||||
|
||||
_mapWindow : function(actor) {
|
||||
_mapWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -180,31 +138,31 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._mapWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._mapWindowOverwrite,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_mapWindowDone : function(actor) {
|
||||
_mapWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_mapWindowOverwrite : function(actor) {
|
||||
_mapWindowOverwrite : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
this._shellwm.completed_map(actor);
|
||||
shellwm.completed_map(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_destroyWindow : function(actor) {
|
||||
_destroyWindow : function(shellwm, actor) {
|
||||
if (!this._shouldAnimate(actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,33 +177,35 @@ WindowManager.prototype = {
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._destroyWindowDone,
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [actor],
|
||||
onCompleteParams: [shellwm, actor],
|
||||
onOverwrite: this._destroyWindowOverwrite,
|
||||
onOverwriteScope: this,
|
||||
onOverwriteParams: [actor]
|
||||
onOverwriteParams: [shellwm, actor]
|
||||
});
|
||||
},
|
||||
|
||||
_destroyWindowDone : function(actor) {
|
||||
_destroyWindowDone : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._destroying, actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
Tweener.removeTweens(actor);
|
||||
actor.set_scale(1.0, 1.0);
|
||||
}
|
||||
},
|
||||
|
||||
_destroyWindowOverwrite : function(actor) {
|
||||
_destroyWindowOverwrite : function(shellwm, actor) {
|
||||
if (this._removeEffect(this._destroying, actor)) {
|
||||
this._shellwm.completed_destroy(actor);
|
||||
shellwm.completed_destroy(actor);
|
||||
}
|
||||
},
|
||||
|
||||
_switchWorkspace : function(windows, from, to, direction) {
|
||||
_switchWorkspace : function(shellwm, from, to, direction) {
|
||||
if (!this._shouldAnimate()) {
|
||||
this._shellwm.completed_switch_workspace();
|
||||
shellwm.completed_switch_workspace();
|
||||
return;
|
||||
}
|
||||
|
||||
let windows = shellwm.get_switch_workspace_actors();
|
||||
|
||||
/* @direction is the direction that the "camera" moves, so the
|
||||
* screen contents have to move one screen's worth in the
|
||||
* opposite direction.
|
||||
@ -255,20 +215,20 @@ WindowManager.prototype = {
|
||||
if (direction == Meta.MotionDirection.UP ||
|
||||
direction == Meta.MotionDirection.UP_LEFT ||
|
||||
direction == Meta.MotionDirection.UP_RIGHT)
|
||||
yDest = this._global.screen_height;
|
||||
yDest = global.screen_height;
|
||||
else if (direction == Meta.MotionDirection.DOWN ||
|
||||
direction == Meta.MotionDirection.DOWN_LEFT ||
|
||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||
yDest = -this._global.screen_height;
|
||||
yDest = -global.screen_height;
|
||||
|
||||
if (direction == Meta.MotionDirection.LEFT ||
|
||||
direction == Meta.MotionDirection.UP_LEFT ||
|
||||
direction == Meta.MotionDirection.DOWN_LEFT)
|
||||
xDest = this._global.screen_width;
|
||||
xDest = global.screen_width;
|
||||
else if (direction == Meta.MotionDirection.RIGHT ||
|
||||
direction == Meta.MotionDirection.UP_RIGHT ||
|
||||
direction == Meta.MotionDirection.DOWN_RIGHT)
|
||||
xDest = -this._global.screen_width;
|
||||
xDest = -global.screen_width;
|
||||
|
||||
let switchData = {};
|
||||
this._switchData = switchData;
|
||||
@ -276,7 +236,7 @@ WindowManager.prototype = {
|
||||
switchData.outGroup = new Clutter.Group();
|
||||
switchData.windows = [];
|
||||
|
||||
let wgroup = this._global.window_group;
|
||||
let wgroup = global.window_group;
|
||||
wgroup.add_actor(switchData.inGroup);
|
||||
wgroup.add_actor(switchData.outGroup);
|
||||
|
||||
@ -307,7 +267,8 @@ WindowManager.prototype = {
|
||||
time: WINDOW_ANIMATION_TIME,
|
||||
transition: "easeOutQuad",
|
||||
onComplete: this._switchWorkspaceDone,
|
||||
onCompleteScope: this
|
||||
onCompleteScope: this,
|
||||
onCompleteParams: [shellwm]
|
||||
});
|
||||
Tweener.addTween(switchData.inGroup,
|
||||
{ x: 0,
|
||||
@ -317,7 +278,7 @@ WindowManager.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
_switchWorkspaceDone : function() {
|
||||
_switchWorkspaceDone : function(shellwm) {
|
||||
let switchData = this._switchData;
|
||||
if (!switchData)
|
||||
return;
|
||||
@ -336,10 +297,10 @@ WindowManager.prototype = {
|
||||
switchData.inGroup.destroy();
|
||||
switchData.outGroup.destroy();
|
||||
|
||||
this._shellwm.completed_switch_workspace();
|
||||
shellwm.completed_switch_workspace();
|
||||
},
|
||||
|
||||
_beginAltTab : function(handler) {
|
||||
_beginAltTab : function(shellwm, handler) {
|
||||
let popup = new AltTab.AltTabPopup();
|
||||
|
||||
handler.connect('window-added', function(handler, window) { popup.addWindow(window); });
|
||||
|
@ -25,6 +25,12 @@ const WINDOWCLONE_TITLE_COLOR = new Clutter.Color();
|
||||
WINDOWCLONE_TITLE_COLOR.from_pixel(0xffffffff);
|
||||
const FRAME_COLOR = new Clutter.Color();
|
||||
FRAME_COLOR.from_pixel(0xffffffff);
|
||||
const LIGHTBOX_COLOR = new Clutter.Color();
|
||||
LIGHTBOX_COLOR.from_pixel(0x00000044);
|
||||
|
||||
const SCROLL_SCALE_AMOUNT = 100 / 5;
|
||||
|
||||
const ZOOM_OVERLAY_FADE_TIME = 0.15;
|
||||
|
||||
// Define a layout scheme for small window counts. For larger
|
||||
// counts we fall back to an algorithm. We need more schemes here
|
||||
@ -40,13 +46,53 @@ const POSITIONS = {
|
||||
5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]]
|
||||
};
|
||||
|
||||
|
||||
function _interpolate(start, end, step) {
|
||||
return start + (end - start) * step;
|
||||
}
|
||||
|
||||
function _clamp(value, min, max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
// Spacing between workspaces. At the moment, the same spacing is used
|
||||
// in both zoomed-in and zoomed-out views; this is slightly
|
||||
// metaphor-breaking, but the alternatives are also weird.
|
||||
const GRID_SPACING = 15;
|
||||
const FRAME_SIZE = GRID_SPACING / 3;
|
||||
|
||||
let buttonSize = false;
|
||||
function ScaledPoint(x, y, scaleX, scaleY) {
|
||||
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
|
||||
}
|
||||
|
||||
ScaledPoint.prototype = {
|
||||
getPosition : function() {
|
||||
return [this.x, this.y];
|
||||
},
|
||||
|
||||
getScale : function() {
|
||||
return [this.scaleX, this.scaleY];
|
||||
},
|
||||
|
||||
setPosition : function(x, y) {
|
||||
[this.x, this.y] = arguments;
|
||||
},
|
||||
|
||||
setScale : function(scaleX, scaleY) {
|
||||
[this.scaleX, this.scaleY] = arguments;
|
||||
},
|
||||
|
||||
interpPosition : function(other, step) {
|
||||
return [_interpolate(this.x, other.x, step),
|
||||
_interpolate(this.y, other.y, step)];
|
||||
},
|
||||
|
||||
interpScale : function(other, step) {
|
||||
return [_interpolate(this.scaleX, other.scaleX, step),
|
||||
_interpolate(this.scaleY, other.scaleY, step)];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function WindowClone(realWindow) {
|
||||
this._init(realWindow);
|
||||
@ -61,12 +107,18 @@ WindowClone.prototype = {
|
||||
this.actor._delegate = this;
|
||||
this.realWindow = realWindow;
|
||||
this.metaWindow = realWindow.meta_window;
|
||||
this.metaWindow._delegate = this;
|
||||
this.origX = realWindow.x;
|
||||
this.origY = realWindow.y;
|
||||
|
||||
this._title = null;
|
||||
|
||||
this.actor.connect('button-release-event',
|
||||
Lang.bind(this, this._onButtonRelease));
|
||||
|
||||
this.actor.connect('scroll-event',
|
||||
Lang.bind(this, this._onScroll));
|
||||
|
||||
this.actor.connect('enter-event',
|
||||
Lang.bind(this, this._onEnter));
|
||||
this.actor.connect('leave-event',
|
||||
@ -79,6 +131,18 @@ WindowClone.prototype = {
|
||||
this._inDrag = false;
|
||||
},
|
||||
|
||||
setVisibleWithChrome: function(visible) {
|
||||
if (visible) {
|
||||
this.actor.show();
|
||||
if (this._title)
|
||||
this._title.show();
|
||||
} else {
|
||||
this.actor.hide();
|
||||
if (this._title)
|
||||
this._title.hide();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.actor.destroy();
|
||||
if (this._title)
|
||||
@ -104,12 +168,103 @@ WindowClone.prototype = {
|
||||
return;
|
||||
|
||||
this._havePointer = false;
|
||||
|
||||
if (Tweener.isTweening(this.actor))
|
||||
return;
|
||||
|
||||
actor.raise(this.stackAbove);
|
||||
this._updateTitle();
|
||||
|
||||
if (this._zoomStep)
|
||||
this._zoomEnd();
|
||||
},
|
||||
|
||||
_onScroll : function (actor, event) {
|
||||
let direction = event.get_scroll_direction();
|
||||
if (direction == Clutter.ScrollDirection.UP) {
|
||||
if (this._zoomStep == undefined)
|
||||
this._zoomStart();
|
||||
if (this._zoomStep < 100) {
|
||||
this._zoomStep += SCROLL_SCALE_AMOUNT;
|
||||
this._zoomUpdate();
|
||||
}
|
||||
} else if (direction == Clutter.ScrollDirection.DOWN) {
|
||||
if (this._zoomStep > 0) {
|
||||
this._zoomStep -= SCROLL_SCALE_AMOUNT;
|
||||
this._zoomStep = Math.max(0, this._zoomStep);
|
||||
this._zoomUpdate();
|
||||
}
|
||||
if (this._zoomStep <= 0.0)
|
||||
this._zoomEnd();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
_zoomUpdate : function () {
|
||||
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.interpPosition(this._zoomTarget, this._zoomStep / 100);
|
||||
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.interpScale(this._zoomTarget, this._zoomStep / 100);
|
||||
|
||||
let [width, height] = this.actor.get_transformed_size();
|
||||
|
||||
this.actor.x = _clamp(this.actor.x, 0, global.screen_width - width);
|
||||
this.actor.y = _clamp(this.actor.y, Panel.PANEL_HEIGHT, global.screen_height - height);
|
||||
},
|
||||
|
||||
_zoomStart : function () {
|
||||
this._zoomOverlay = new Clutter.Rectangle({ reactive: true,
|
||||
color: LIGHTBOX_COLOR,
|
||||
border_width: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: global.screen_width,
|
||||
height: global.screen_height,
|
||||
opacity: 0 });
|
||||
this._zoomOverlay.show();
|
||||
global.stage.add_actor(this._zoomOverlay);
|
||||
Tweener.addTween(this._zoomOverlay,
|
||||
{ opacity: 255,
|
||||
time: ZOOM_OVERLAY_FADE_TIME,
|
||||
transition: "easeOutQuad"
|
||||
});
|
||||
|
||||
this._zoomLocalOrig = new ScaledPoint(this.actor.x, this.actor.y, this.actor.scale_x, this.actor.scale_y);
|
||||
this._zoomGlobalOrig = new ScaledPoint();
|
||||
let parent = this._origParent = this.actor.get_parent();
|
||||
[width, height] = this.actor.get_transformed_size();
|
||||
this._zoomGlobalOrig.setPosition.apply(this._zoomGlobalOrig, this.actor.get_transformed_position());
|
||||
this._zoomGlobalOrig.setScale(width / this.actor.width, height / this.actor.height);
|
||||
|
||||
this._zoomOverlay.raise_top();
|
||||
this._zoomOverlay.show();
|
||||
|
||||
this.actor.reparent(global.stage);
|
||||
|
||||
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.getPosition();
|
||||
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.getScale();
|
||||
|
||||
this.actor.raise_top();
|
||||
|
||||
this._zoomTarget = new ScaledPoint(0, 0, 1.0, 1.0);
|
||||
this._zoomTarget.setPosition(this.actor.x - (this.actor.width - width) / 2, this.actor.y - (this.actor.height - height) / 2);
|
||||
this._zoomStep = 0;
|
||||
|
||||
this._hideEventId = Main.overview.connect('hiding', Lang.bind(this, function () { this._zoomEnd(); }));
|
||||
this._zoomUpdate();
|
||||
},
|
||||
|
||||
_zoomEnd : function () {
|
||||
this.actor.reparent(this._origParent);
|
||||
|
||||
[this.actor.x, this.actor.y] = this._zoomLocalOrig.getPosition();
|
||||
[this.actor.scale_x, this.actor.scale_y] = this._zoomLocalOrig.getScale();
|
||||
|
||||
this._adjustTitle();
|
||||
|
||||
this._zoomOverlay.destroy();
|
||||
Main.overview.disconnect(this._hideEventId);
|
||||
|
||||
this._zoomLocalPosition = undefined;
|
||||
this._zoomLocalScale = undefined;
|
||||
this._zoomGlobalPosition = undefined;
|
||||
this._zoomGlobalScale = undefined;
|
||||
this._zoomTargetPosition = undefined;
|
||||
this._zoomStep = undefined;
|
||||
this._zoomOverlay = undefined;
|
||||
},
|
||||
|
||||
_onButtonRelease : function (actor, event) {
|
||||
@ -231,7 +386,6 @@ DesktopClone.prototype = {
|
||||
this.actor = new Clutter.Clone({ source: window.get_texture(),
|
||||
reactive: true });
|
||||
} else {
|
||||
let global = Shell.Global.get();
|
||||
this.actor = new Clutter.Rectangle({ color: global.stage.color,
|
||||
reactive: true,
|
||||
width: global.screen_width,
|
||||
@ -262,9 +416,6 @@ function Workspace(workspaceNum, parentActor) {
|
||||
|
||||
Workspace.prototype = {
|
||||
_init : function(workspaceNum, parentActor) {
|
||||
let me = this;
|
||||
let global = Shell.Global.get();
|
||||
|
||||
this.workspaceNum = workspaceNum;
|
||||
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
|
||||
|
||||
@ -280,6 +431,14 @@ Workspace.prototype = {
|
||||
this.actor.height = global.screen_height;
|
||||
this.scale = 1.0;
|
||||
|
||||
this._lightbox = new Clutter.Rectangle({ color: LIGHTBOX_COLOR });
|
||||
this.actor.connect('notify::allocation', Lang.bind(this, function () {
|
||||
let [width, height] = this.actor.get_size();
|
||||
this._lightbox.set_size(width, height);
|
||||
}));
|
||||
this.actor.add_actor(this._lightbox);
|
||||
this._lightbox.hide();
|
||||
|
||||
let windows = global.get_windows().filter(this._isMyWindow, this);
|
||||
|
||||
// Find the desktop window
|
||||
@ -311,6 +470,9 @@ Workspace.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
// A filter for what windows we display
|
||||
this._showOnlyWindows = null;
|
||||
|
||||
// Track window changes
|
||||
this._windowAddedId = this._metaWorkspace.connect('window-added',
|
||||
Lang.bind(this, this._windowAdded));
|
||||
@ -326,7 +488,6 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
updateRemovable : function() {
|
||||
let global = Shell.Global.get();
|
||||
let removable = (this._windows.length == 1 /* just desktop */ &&
|
||||
this.workspaceNum != 0 &&
|
||||
this.workspaceNum == global.screen.n_workspaces - 1);
|
||||
@ -335,8 +496,8 @@ Workspace.prototype = {
|
||||
if (this._removeButton)
|
||||
return;
|
||||
|
||||
this._removeButton = new Clutter.Texture({ width: buttonSize,
|
||||
height: buttonSize,
|
||||
this._removeButton = new Clutter.Texture({ width: Overview.addRemoveButtonSize,
|
||||
height: Overview.addRemoveButtonSize,
|
||||
reactive: true
|
||||
});
|
||||
this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
|
||||
@ -381,11 +542,60 @@ Workspace.prototype = {
|
||||
return -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* lookupCloneForMetaWindow:
|
||||
* @metaWindow: A #MetaWindow
|
||||
*
|
||||
* Given a #MetaWindow instance, find the WindowClone object
|
||||
* which represents it in the workspaces display.
|
||||
*/
|
||||
lookupCloneForMetaWindow: function (metaWindow) {
|
||||
let index = this._lookupIndex (metaWindow);
|
||||
return index < 0 ? null : this._windows[index];
|
||||
},
|
||||
|
||||
containsMetaWindow: function (metaWindow) {
|
||||
return this._lookupIndex(metaWindow) >= 0;
|
||||
},
|
||||
|
||||
setShowOnlyWindows: function(showOnlyWindows, reposition) {
|
||||
this._showOnlyWindows = showOnlyWindows;
|
||||
this._resetCloneVisibility();
|
||||
if (reposition)
|
||||
this.positionWindows(false);
|
||||
},
|
||||
|
||||
/**
|
||||
* setLightboxMode:
|
||||
* @showLightbox: If true, dim background and allow highlighting a specific window
|
||||
*
|
||||
* This function also resets the highlighted window state.
|
||||
*/
|
||||
setLightboxMode: function (showLightbox) {
|
||||
if (showLightbox) {
|
||||
this.setHighlightWindow(null);
|
||||
this._lightbox.show();
|
||||
} else {
|
||||
this._lightbox.hide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* setHighlightWindow:
|
||||
* @metaWindow: A #MetaWindow
|
||||
*
|
||||
* Draw the user's attention to the given window @metaWindow.
|
||||
*/
|
||||
setHighlightWindow: function (metaWindow) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
this._windows[i].actor.lower(this._lightbox);
|
||||
}
|
||||
if (metaWindow != null) {
|
||||
let clone = this.lookupCloneForMetaWindow(metaWindow);
|
||||
clone.actor.raise(this._lightbox);
|
||||
}
|
||||
},
|
||||
|
||||
_adjustRemoveButton : function() {
|
||||
this._removeButton.set_scale(1.0 / this.actor.scale_x,
|
||||
1.0 / this.actor.scale_y);
|
||||
@ -402,7 +612,6 @@ Workspace.prototype = {
|
||||
|
||||
// Mark the workspace selected/not-selected
|
||||
setSelected : function(selected) {
|
||||
let global = Shell.Global.get();
|
||||
// Don't draw a frame if we only have one workspace
|
||||
if (selected && global.screen.n_workspaces > 1) {
|
||||
if (this._frame)
|
||||
@ -434,18 +643,51 @@ Workspace.prototype = {
|
||||
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
|
||||
},
|
||||
|
||||
// Reposition all windows in their zoomed-to-Overview position. if workspaceZooming
|
||||
// is true, then the workspace is moving at the same time and we need to take
|
||||
// that into account
|
||||
positionWindows : function(workspaceZooming) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
_resetCloneVisibility: function () {
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let icon = this._windowIcons[i];
|
||||
clone.stackAbove = this._windows[i - 1].actor;
|
||||
|
||||
let [xCenter, yCenter, fraction] = this._computeWindowPosition(i);
|
||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows)) {
|
||||
clone.setVisibleWithChrome(false);
|
||||
icon.hide();
|
||||
} else {
|
||||
clone.setVisibleWithChrome(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* positionWindows:
|
||||
* @workspaceZooming: If true, then the workspace is moving at the same time and we need to take that into account.
|
||||
*/
|
||||
positionWindows : function(workspaceZooming) {
|
||||
let totalVisible = 0;
|
||||
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
|
||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||
continue;
|
||||
|
||||
totalVisible += 1;
|
||||
}
|
||||
|
||||
let previousWindow = this._windows[0];
|
||||
let visibleIndex = 0;
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let icon = this._windowIcons[i];
|
||||
|
||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||
continue;
|
||||
|
||||
clone.stackAbove = previousWindow.actor;
|
||||
previousWindow = clone;
|
||||
|
||||
visibleIndex += 1;
|
||||
|
||||
let [xCenter, yCenter, fraction] = this._computeWindowPosition(visibleIndex, totalVisible);
|
||||
xCenter = xCenter * global.screen_width;
|
||||
yCenter = yCenter * global.screen_height;
|
||||
|
||||
@ -508,6 +750,8 @@ Workspace.prototype = {
|
||||
for (let i = 1; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let icon = this._windowIcons[i];
|
||||
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
|
||||
continue;
|
||||
this._fadeInWindowIcon(clone, icon);
|
||||
}
|
||||
},
|
||||
@ -520,7 +764,6 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
let global = Shell.Global.get();
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
// find the position of the window in our list
|
||||
@ -672,8 +915,6 @@ Workspace.prototype = {
|
||||
|
||||
// Animates the addition of a new (empty) workspace
|
||||
slideIn : function(oldScale) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (this.gridCol > this.gridRow) {
|
||||
this.actor.set_position(global.screen_width, this.gridY);
|
||||
this.actor.set_scale(oldScale, oldScale);
|
||||
@ -695,7 +936,6 @@ Workspace.prototype = {
|
||||
|
||||
// Animates the removal of a workspace
|
||||
slideOut : function(onComplete) {
|
||||
let global = Shell.Global.get();
|
||||
let destX = this.actor.x, destY = this.actor.y;
|
||||
|
||||
this._hideAllIcons();
|
||||
@ -722,8 +962,6 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
Tweener.removeTweens(this.actor);
|
||||
this.actor.destroy();
|
||||
this.actor = null;
|
||||
@ -745,11 +983,8 @@ Workspace.prototype = {
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
_isOverviewWindow : function (win) {
|
||||
let wintype = win.get_window_type();
|
||||
if (wintype == Meta.WindowType.DESKTOP ||
|
||||
wintype == Meta.WindowType.DOCK)
|
||||
return false;
|
||||
return !win.is_override_redirect();
|
||||
let appMon = Shell.AppMonitor.get_default()
|
||||
return appMon.is_window_usage_tracked(win.get_meta_window());
|
||||
},
|
||||
|
||||
_createWindowIcon: function(window) {
|
||||
@ -797,10 +1032,10 @@ Workspace.prototype = {
|
||||
return clone;
|
||||
},
|
||||
|
||||
_computeWindowPosition : function(index) {
|
||||
_computeWindowPosition : function(index, totalWindows) {
|
||||
// ignore this._windows[0], which is the desktop
|
||||
let windowIndex = index - 1;
|
||||
let numberOfWindows = this._windows.length - 1;
|
||||
let numberOfWindows = totalWindows;
|
||||
|
||||
if (numberOfWindows in POSITIONS)
|
||||
return POSITIONS[numberOfWindows][windowIndex];
|
||||
@ -823,7 +1058,6 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
_removeSelf : function(actor, event) {
|
||||
let global = Shell.Global.get();
|
||||
let screen = global.screen;
|
||||
let workspace = screen.get_workspace_by_index(this.workspaceNum);
|
||||
|
||||
@ -833,8 +1067,6 @@ Workspace.prototype = {
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
if (source instanceof WindowClone) {
|
||||
let win = source.realWindow;
|
||||
if (this._isMyWindow(win))
|
||||
@ -865,25 +1097,25 @@ Workspace.prototype = {
|
||||
|
||||
Signals.addSignalMethods(Workspace.prototype);
|
||||
|
||||
function Workspaces(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
|
||||
this._init(width, height, x, y, addButtonSize, addButtonX, addButtonY);
|
||||
function Workspaces(width, height, x, y) {
|
||||
this._init(width, height, x, y);
|
||||
}
|
||||
|
||||
Workspaces.prototype = {
|
||||
_init : function(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
_init : function(width, height, x, y) {
|
||||
this.actor = new Clutter.Group();
|
||||
|
||||
let screenHeight = global.screen_height;
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._x = x;
|
||||
this._y = y;
|
||||
|
||||
this._windowSelectionAppId = null;
|
||||
|
||||
this._workspaces = [];
|
||||
|
||||
|
||||
this._highlightWindow = null;
|
||||
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace;
|
||||
|
||||
@ -896,17 +1128,7 @@ Workspaces.prototype = {
|
||||
}
|
||||
}
|
||||
activeWorkspace.actor.raise_top();
|
||||
this._positionWorkspaces(global, activeWorkspace);
|
||||
|
||||
// Save the button size as a global variable so we can us it to create
|
||||
// matching button sizes for workspace remove buttons.
|
||||
buttonSize = addButtonSize;
|
||||
|
||||
// Create (+) button
|
||||
this.addButton = new AddWorkspaceButton(addButtonSize, addButtonX, addButtonY, Lang.bind(this, this._addWorkspaceAcceptDrop));
|
||||
this.addButton.actor.connect('button-release-event', Lang.bind(this, this._appendNewWorkspace));
|
||||
this.actor.add_actor(this.addButton.actor);
|
||||
this.addButton.actor.lower_bottom();
|
||||
this._positionWorkspaces();
|
||||
|
||||
let lastWorkspace = this._workspaces[this._workspaces.length - 1];
|
||||
lastWorkspace.updateRemovable(true);
|
||||
@ -930,6 +1152,14 @@ Workspaces.prototype = {
|
||||
Lang.bind(this, this._activeWorkspaceChanged));
|
||||
},
|
||||
|
||||
_lookupWorkspaceForMetaWindow: function (metaWindow) {
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
if (this._workspaces[i].containsMetaWindow(metaWindow))
|
||||
return this._workspaces[i];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_lookupCloneForMetaWindow: function (metaWindow) {
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
|
||||
@ -939,9 +1169,64 @@ Workspaces.prototype = {
|
||||
return null;
|
||||
},
|
||||
|
||||
// Should only be called from active Overview context
|
||||
activateWindowFromOverview: function (metaWindow, time) {
|
||||
let global = Shell.Global.get();
|
||||
setHighlightWindow: function (metaWindow) {
|
||||
// Looping over all workspaces is easier than keeping track of the last
|
||||
// highlighted window while trying to handle the window or workspace possibly
|
||||
// going away.
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
this._workspaces[i].setHighlightWindow(null);
|
||||
}
|
||||
if (metaWindow != null) {
|
||||
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
|
||||
workspace.setHighlightWindow(metaWindow);
|
||||
}
|
||||
},
|
||||
|
||||
_clearApplicationWindowSelection: function(reposition) {
|
||||
if (this._windowSelectionAppId == null)
|
||||
return;
|
||||
this._windowSelectionAppId = null;
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
this._workspaces[i].setLightboxMode(false);
|
||||
this._workspaces[i].setShowOnlyWindows(null, reposition);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* setApplicationWindowSelection:
|
||||
* @appid: Application identifier string
|
||||
*
|
||||
* Enter a mode which shows only the windows owned by the
|
||||
* given application, and allow highlighting of a specific
|
||||
* window with setHighlightWindow().
|
||||
*/
|
||||
setApplicationWindowSelection: function (appId) {
|
||||
if (appId == null) {
|
||||
this._clearApplicationWindowSelection(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (appId == this._windowSelectionAppId)
|
||||
return;
|
||||
|
||||
this._windowSelectionAppId = appId;
|
||||
|
||||
let appSys = Shell.AppMonitor.get_default();
|
||||
|
||||
let showOnlyWindows = {};
|
||||
let windows = appSys.get_windows_for_app(appId);
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
showOnlyWindows[windows[i]] = 1;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspaces.length; i++) {
|
||||
this._workspaces[i].setLightboxMode(true);
|
||||
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
|
||||
}
|
||||
},
|
||||
|
||||
_activateWindowInternal: function (metaWindow, time) {
|
||||
let activeWorkspaceNum = global.screen.get_active_workspace_index();
|
||||
let windowWorkspaceNum = metaWindow.get_workspace().index();
|
||||
|
||||
@ -956,12 +1241,27 @@ Workspaces.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* activateWindowFromOverview:
|
||||
* @metaWindow: A #MetaWindow
|
||||
* @time: Integer even timestamp
|
||||
*
|
||||
* This function exits the overview, switching to the given @metaWindow.
|
||||
* If an application filter is in effect, it will be cleared.
|
||||
*/
|
||||
activateWindowFromOverview: function (metaWindow, time) {
|
||||
if (this._windowSelectionAppId != null) {
|
||||
this._clearApplicationWindowSelection(false);
|
||||
}
|
||||
this._activateWindowInternal(metaWindow, time);
|
||||
Main.overview.hide();
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
let global = Shell.Global.get();
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
|
||||
this._positionWorkspaces(global, activeWorkspace);
|
||||
this._positionWorkspaces();
|
||||
activeWorkspace.actor.raise_top();
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
@ -969,8 +1269,6 @@ Workspaces.prototype = {
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++)
|
||||
this._workspaces[w].destroy();
|
||||
this._workspaces = [];
|
||||
@ -988,7 +1286,6 @@ Workspaces.prototype = {
|
||||
|
||||
// Get the grid position of the active workspace.
|
||||
getActiveWorkspacePosition : function() {
|
||||
let global = Shell.Global.get();
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
|
||||
@ -1005,12 +1302,7 @@ Workspaces.prototype = {
|
||||
// first row.)
|
||||
//
|
||||
// FIXME: need to make the metacity internal layout agree with this!
|
||||
_positionWorkspaces : function(global, activeWorkspace) {
|
||||
if (!activeWorkspace) {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
activeWorkspace = this._workspaces[activeWorkspaceIndex];
|
||||
}
|
||||
|
||||
_positionWorkspaces : function() {
|
||||
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
|
||||
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
|
||||
|
||||
@ -1048,8 +1340,6 @@ Workspaces.prototype = {
|
||||
},
|
||||
|
||||
_workspacesChanged : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
let oldNumWorkspaces = this._workspaces.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
|
||||
@ -1082,7 +1372,7 @@ Workspaces.prototype = {
|
||||
newLastWorkspace.updateRemovable();
|
||||
|
||||
// Figure out the new layout
|
||||
this._positionWorkspaces(global);
|
||||
this._positionWorkspaces();
|
||||
let newScale = this._workspaces[0].scale;
|
||||
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
|
||||
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
|
||||
@ -1133,42 +1423,13 @@ Workspaces.prototype = {
|
||||
this.actor.add_actor(workspace.actor);
|
||||
},
|
||||
|
||||
_appendNewWorkspace : function() {
|
||||
let global = Shell.Global.get();
|
||||
|
||||
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
|
||||
},
|
||||
|
||||
// Creates a new workspace and drops the dropActor there
|
||||
_addWorkspaceAcceptDrop : function(source, dropActor, x, y, time) {
|
||||
this._appendNewWorkspace();
|
||||
// Handles a drop onto the (+) button; assumes the new workspace
|
||||
// has already been added
|
||||
acceptNewWorkspaceDrop : function(source, dropActor, x, y, time) {
|
||||
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
|
||||
}
|
||||
};
|
||||
|
||||
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
|
||||
}
|
||||
|
||||
AddWorkspaceButton.prototype = {
|
||||
_init : function(buttonSize, buttonX, buttonY, acceptDropCallback) {
|
||||
this.actor = new Clutter.Texture({ x: buttonX,
|
||||
y: buttonY,
|
||||
width: buttonSize,
|
||||
height: buttonSize,
|
||||
reactive: true });
|
||||
this._acceptDropCallback = acceptDropCallback;
|
||||
let global = Shell.Global.get();
|
||||
this.actor._delegate = this;
|
||||
this.actor.set_from_file(global.imagedir + 'add-workspace.svg');
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
return this._acceptDropCallback(source, actor, x, y, time);
|
||||
}
|
||||
};
|
||||
|
||||
// Create a SpecialPropertyModifier to let us move windows in a
|
||||
// straight line on the screen even though their containing workspace
|
||||
// is also moving.
|
||||
|
@ -1,6 +1,8 @@
|
||||
ca
|
||||
cs
|
||||
da
|
||||
de
|
||||
en_GB
|
||||
es
|
||||
fr
|
||||
ga
|
||||
@ -10,7 +12,9 @@ it
|
||||
ko
|
||||
nb
|
||||
nl
|
||||
pa
|
||||
pl
|
||||
pt_BR
|
||||
sv
|
||||
tr
|
||||
zh_CN
|
||||
|
108
po/ca.po
108
po/ca.po
@ -7,88 +7,99 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-14 20:38+0200\n"
|
||||
"PO-Revision-Date: 2009-08-14 23:59+0100\n"
|
||||
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
|
||||
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
|
||||
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language-Team: \n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestió de finestres i execució d'aplicacions"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Activitats"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:412
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:235
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Cerca aplicacions o documents"
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Cerca..."
|
||||
|
||||
#: ../js/ui/dash.js:336
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Navega"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(mostra tot)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:472
|
||||
#: ../js/ui/dash.js:545
|
||||
#: ../js/ui/dash.js:633
|
||||
#: ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONS"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:477
|
||||
#: ../js/ui/dash.js:570
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTS RECENTS"
|
||||
|
||||
#. **** Places ****
|
||||
#: ../js/ui/dash.js:563
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "LLOCS"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660
|
||||
#: ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTS RECENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTATS DE LA CERCA"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduïu una ordre:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:242
|
||||
msgid "Manager"
|
||||
msgstr "Gestor"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Fa menys d'un minut"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Fa %d minut"
|
||||
msgstr[1] "Fa %d minuts"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Fa %d hora"
|
||||
msgstr[1] "Fa %d hores"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Fa %d dia"
|
||||
msgstr[1] "Fa %d dies"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -107,7 +118,7 @@ msgstr "No es pot blocar la pantalla: %s"
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "No es pot establir temporalment l'estalviador de pantalles a pantalla negra: %s"
|
||||
msgstr "No es pot establir temporalment l'estalvi de pantalla a pantalla negra: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
@ -145,3 +156,34 @@ msgstr "Surt..."
|
||||
msgid "Shut Down..."
|
||||
msgstr "Atura..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Carpeta d'inici"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Sistema de fitxers"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Cerca"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Cerca aplicacions o documents"
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Gestor"
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
|
||||
|
||||
|
119
po/cs.po
119
po/cs.po
@ -1,15 +1,15 @@
|
||||
# Czech translation of gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# Copyright (C) 2009 the author(s) of gnome-shell.
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Andre Klapper <ak-47@gmx.net>, 2009.
|
||||
#
|
||||
# Petr Kovar <pknbe@volny.cz>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-15 15:25+0200\n"
|
||||
"PO-Revision-Date: 2009-08-15 13:23+0000\n"
|
||||
"Last-Translator: Andre Klapper <ak-47@gmx.net>\n"
|
||||
"POT-Creation-Date: 2009-08-30 17:37+0200\n"
|
||||
"PO-Revision-Date: 2009-08-30 17:33+0200\n"
|
||||
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
|
||||
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -18,95 +18,95 @@ msgstr ""
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr ""
|
||||
msgstr "Prostředí GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
#, fuzzy
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Správa oken"
|
||||
msgstr "Správa oken a spouštění aplikací"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr ""
|
||||
msgstr "Činnosti"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:412
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr ""
|
||||
msgstr "%a, %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:235
|
||||
msgid "Find apps or documents"
|
||||
msgstr ""
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Najít..."
|
||||
|
||||
#: ../js/ui/dash.js:336
|
||||
#, fuzzy
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Procházet"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(zobrazit vše)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLIKACE"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "NEDÁVNÉ DOKUMENTY"
|
||||
|
||||
#. **** Places ****
|
||||
#: ../js/ui/dash.js:563
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "MÍSTA"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "NEDÁVNÉ DOKUMENTY"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "VÝSLEDKY HLEDÁNÍ"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr ""
|
||||
msgstr "Zadejte prosím příkaz:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:242
|
||||
msgid "Manager"
|
||||
msgstr "Správce"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#, fuzzy
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Dříve než před minutou"
|
||||
msgstr "Před méně než minutou"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuta nazpět"
|
||||
msgstr[1] "%d minuty nazpět"
|
||||
msgstr[2] "%d minut nazpět"
|
||||
msgstr[0] "Před %d minutou"
|
||||
msgstr[1] "Před %d minutami"
|
||||
msgstr[2] "Před %d minutami"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d hodina nazpět"
|
||||
msgstr[1] "%d hodiny nazpět"
|
||||
msgstr[2] "%d hodin nazpět"
|
||||
msgstr[0] "Před %d hodinou"
|
||||
msgstr[1] "Před %d hodinami"
|
||||
msgstr[2] "Před %d hodinami"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d den nazpět"
|
||||
msgstr[1] "%d dny nazpět"
|
||||
msgstr[2] "%d dnů nazpět"
|
||||
msgstr[0] "Před %d dnem"
|
||||
msgstr[1] "Před %d dny"
|
||||
msgstr[2] "Před %d dny"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d týden nazpět"
|
||||
msgstr[1] "%d týdny nazpět"
|
||||
msgstr[2] "%d týdnů nazpět"
|
||||
msgstr[0] "Před %d týdnem"
|
||||
msgstr[1] "Před %d týdny"
|
||||
msgstr[2] "Před %d týdny"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
@ -132,9 +132,8 @@ msgid "Account Information..."
|
||||
msgstr "Informace o účtu..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
#, fuzzy
|
||||
msgid "Sidebar"
|
||||
msgstr "Boční panel"
|
||||
msgstr "Postranní lišta"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
@ -179,6 +178,12 @@ msgstr "Hledat"
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Správce"
|
||||
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
|
||||
|
188
po/da.po
Normal file
188
po/da.po
Normal file
@ -0,0 +1,188 @@
|
||||
# Danish translation of gnome-shell
|
||||
# Copyright (C) 2009 gnome-shell
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Kris Thomsen <lakristho@gmail.com>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
|
||||
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
|
||||
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
|
||||
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "Skal til GNOME"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Vinduehåndtering og åbning af programmer"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Find..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Gennemse"
|
||||
|
||||
#: ../js/ui/dash.js:511
|
||||
msgid "(see all)"
|
||||
msgstr "(se alle)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAMMER"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:725
|
||||
msgid "PLACES"
|
||||
msgstr "STEDER"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SENESTE DOKUMENTER"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SØGERESULTATER"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Indtast en kommando:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre end et minut siden"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minut siden"
|
||||
msgstr[1] "%d minutter siden"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d time siden"
|
||||
msgstr[1] "%d timer siden"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag siden"
|
||||
msgstr[1] "%d dage siden"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d uge siden"
|
||||
msgstr[1] "%d uger siden"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Ukendt"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Kan ikke låse skærm: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Kan ikke midlertidigt sætte pauseskærm til blank skærm: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Kan ikke logge ud: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Kontoinformation..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Sidebjælke"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Systemindstillinger..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Lås skærm"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Skift bruger"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Log ud..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Luk ned..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Hjemmemappe"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Filsystem"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Søg"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Find programmer eller dokumenter"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Håndtering"
|
||||
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
#~ msgstr "Brugerhåndteringsobjektet, denne bruger er styret af."
|
184
po/en_GB.po
Normal file
184
po/en_GB.po
Normal file
@ -0,0 +1,184 @@
|
||||
# British English translation for gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-12 12:41+0000\n"
|
||||
"PO-Revision-Date: 2009-09-12 12:41+0000\n"
|
||||
"Last-Translator: Philip Withnall <philip@tecnocode.co.uk>\n"
|
||||
"Language-Team: British English <en_GB@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Window management and application launching"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Activities"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:283
|
||||
msgid "Find..."
|
||||
msgstr "Find…"
|
||||
|
||||
#: ../js/ui/dash.js:400
|
||||
msgid "Browse"
|
||||
msgstr "Browse"
|
||||
|
||||
#: ../js/ui/dash.js:536
|
||||
msgid "(see all)"
|
||||
msgstr "(see all)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APPLICATIONS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:773
|
||||
msgid "PLACES"
|
||||
msgstr "PLACES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "RECENT DOCUMENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SEARCH RESULTS"
|
||||
|
||||
#: ../js/ui/dash.js:814
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCES"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Please enter a command:"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Less than a minute ago"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minute ago"
|
||||
msgstr[1] "%d minutes ago"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d hour ago"
|
||||
msgstr[1] "%d hours ago"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d day ago"
|
||||
msgstr[1] "%d days ago"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d week ago"
|
||||
msgstr[1] "%d weeks ago"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Unknown"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Can't lock screen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "Can't temporarily set screensaver to blank screen: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Can't logout: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Account Information…"
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Sidebar"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "System Preferences…"
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Lock Screen"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Switch User"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Log Out…"
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Shut Down…"
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Home Folder"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "File System"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Search"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
56
po/es.po
56
po/es.po
@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-08-21 22:23+0000\n"
|
||||
"PO-Revision-Date: 2009-08-22 12:21+0200\n"
|
||||
"POT-Creation-Date: 2009-09-11 21:48+0000\n"
|
||||
"PO-Revision-Date: 2009-09-12 14:40+0200\n"
|
||||
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
|
||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Content-Transfer-Encoding: UTF-8\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
@ -26,80 +26,83 @@ msgid "Window management and application launching"
|
||||
msgstr "Gestión de ventanas e inicio de aplicaciones"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Encuentre aplicaciones o documentos"
|
||||
#: ../js/ui/dash.js:283
|
||||
msgid "Find..."
|
||||
msgstr "Buscar…"
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
#: ../js/ui/dash.js:400
|
||||
msgid "Browse"
|
||||
msgstr "Examine"
|
||||
|
||||
#: ../js/ui/dash.js:536
|
||||
msgid "(see all)"
|
||||
msgstr "(ver todo)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
||||
#: ../js/ui/dash.js:736 ../js/ui/dash.js:792
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONES"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:576
|
||||
#: ../js/ui/dash.js:756
|
||||
msgid "PLACES"
|
||||
msgstr "LUGARES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:583
|
||||
#: ../js/ui/dash.js:763 ../js/ui/dash.js:802
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECIENTES"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:602
|
||||
#: ../js/ui/dash.js:782 ../js/ui/dash.js:907
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTADOS DE LA BÚSQUEDA"
|
||||
|
||||
#: ../js/ui/dash.js:615
|
||||
#| msgid "RECENT DOCUMENTS"
|
||||
msgid "DOCUMENTS"
|
||||
msgstr "DOCUMENTOS"
|
||||
#: ../js/ui/dash.js:797
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCIAS"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduzca un comando:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Hace menos de un minuto"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Hace %d minuto"
|
||||
msgstr[1] "Hace %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Hace %d hora"
|
||||
msgstr[1] "Hace %d horas"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Hace %d día"
|
||||
msgstr[1] "Hace %d días"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -182,6 +185,13 @@ msgstr "Buscar"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Encuentre aplicaciones o documentos"
|
||||
|
||||
#~| msgid "RECENT DOCUMENTS"
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOCUMENTOS"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Gestor"
|
||||
|
||||
|
177
po/fr.po
177
po/fr.po
@ -1,21 +1,182 @@
|
||||
# French translations for gnome-shell package.
|
||||
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Colin Walters <walters@verbum.org>, 2009.
|
||||
#
|
||||
# Mathieu Bridon <bochecha@fedoraproject.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell 0.0.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-07-27 15:09-0400\n"
|
||||
"PO-Revision-Date: 2009-07-27 15:23-0400\n"
|
||||
"Last-Translator: Colin Walters <walters@verbum.org>\n"
|
||||
"Language-Team: French\n"
|
||||
"Project-Id-Version: HEAD\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-09 21:30+0000\n"
|
||||
"PO-Revision-Date: 2009-09-11 21:40+0200\n"
|
||||
"Last-Translator: Mathieu Bridon <bochecha@fedoraproject.org>\n"
|
||||
"Language-Team: GNOME French Team\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: ../js/ui/panel.js:74
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestion des fenêtres et lancement des applications"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Activités"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:255
|
||||
msgid "Find..."
|
||||
msgstr "Rechercher..."
|
||||
|
||||
#: ../js/ui/dash.js:372
|
||||
msgid "Browse"
|
||||
msgstr "Parcourir"
|
||||
|
||||
#: ../js/ui/dash.js:508
|
||||
msgid "(see all)"
|
||||
msgstr "(tout afficher)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APPLICATIONS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:720
|
||||
msgid "PLACES"
|
||||
msgstr "RACCOURCIS"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTS RÉCENTS"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RÉSULTATS DE LA RECHERCHE"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Veuillez saisir une commande :"
|
||||
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Il y a moins d'une minute"
|
||||
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Il y a %d minute"
|
||||
msgstr[1] "Il y a %d minutes"
|
||||
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Il y a %d heure"
|
||||
msgstr[1] "Il y a %d heures"
|
||||
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Il y a %d jour"
|
||||
msgstr[1] "Il y a %d jours"
|
||||
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "Il y a %d semaine"
|
||||
msgstr[1] "Il y a %d semaines"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "Inconnu"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "Impossible de verrouiller l'écran : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr ""
|
||||
"Impossible de régler temporairement l'écran de veille sur un écran vide : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "Impossible de fermer la session : %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "Informations personnelles..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "Barre latérale"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "Préférences du système..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "Verrouiller l'écran"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "Changer d'utilisateur"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "Fermer la session..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "Éteindre..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "Dossier personnel"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "Système de fichiers"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "Recherche"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s : %2$s"
|
||||
|
56
po/gl.po
56
po/gl.po
@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-22 16:39+0200\n"
|
||||
"PO-Revision-Date: 2009-08-18 21:20+0100\n"
|
||||
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
|
||||
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
|
||||
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
|
||||
"Language-Team: Galician <gnome@mancomun.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -25,80 +25,83 @@ msgid "Window management and application launching"
|
||||
msgstr "Xestor de xanelas e lanzado de aplicativos"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Atopar aplicativos ou documentos"
|
||||
#: ../js/ui/dash.js:283
|
||||
msgid "Find..."
|
||||
msgstr "Buscar..."
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
#: ../js/ui/dash.js:400
|
||||
msgid "Browse"
|
||||
msgstr "Explorar"
|
||||
|
||||
#: ../js/ui/dash.js:536
|
||||
msgid "(see all)"
|
||||
msgstr "(ver todos)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
||||
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICATIVOS"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:576
|
||||
#: ../js/ui/dash.js:773
|
||||
msgid "PLACES"
|
||||
msgstr "LUGARES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:583
|
||||
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:602
|
||||
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "RESULTADOS DA BÚSQUEDA"
|
||||
|
||||
#: ../js/ui/dash.js:814
|
||||
msgid "PREFERENCES"
|
||||
msgstr ""
|
||||
|
||||
#: ../js/ui/dash.js:615
|
||||
#, fuzzy
|
||||
msgid "DOCUMENTS"
|
||||
msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
#: ../js/ui/runDialog.js:96
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Insira unha orde:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Menos de un minuto"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "fai %d minuto"
|
||||
msgstr[1] "fai %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "fai %d hora"
|
||||
msgstr[1] "fai %d horas"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "fai %d día"
|
||||
msgstr[1] "fai %d días"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -180,5 +183,12 @@ msgstr "Buscar"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Atopar aplicativos ou documentos"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOCUMENTOS RECENTES"
|
||||
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Xestor"
|
||||
|
59
po/it.po
59
po/it.po
@ -6,9 +6,10 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-20 23:25+0200\n"
|
||||
"PO-Revision-Date: 2009-08-20 23:26+0200\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
|
||||
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
|
||||
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
|
||||
"Language-Team: Italian <tp@lists.linux.it>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -25,72 +26,80 @@ msgid "Window management and application launching"
|
||||
msgstr "Gestione finestre e avvio applicazioni"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Attività"
|
||||
|
||||
# (ndt) proviamo col k, se non funge, sappiamo il perché...
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %k.%M"
|
||||
|
||||
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
|
||||
#: ../js/ui/dash.js:251
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Trova programmi e documenti"
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Trova..."
|
||||
|
||||
#: ../js/ui/dash.js:369
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Esplora"
|
||||
|
||||
#: ../js/ui/dash.js:511
|
||||
msgid "(see all)"
|
||||
msgstr "(vedi tutto)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
||||
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "Applicazioni"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Documenti recenti"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:598
|
||||
#: ../js/ui/dash.js:725
|
||||
msgid "PLACES"
|
||||
msgstr "Risorse"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Documenti recenti"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "Risultati ricerca"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Inserire un comando:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Meno di un minuto fa"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuto fa"
|
||||
msgstr[1] "%d minuti fa"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d ora fa"
|
||||
msgstr[1] "%d ore fa"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d giorno fa"
|
||||
msgstr[1] "%d giorni fa"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -175,6 +184,10 @@ msgstr "Cerca"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Trova programmi e documenti"
|
||||
|
||||
# (ndt) no idea...
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Manager"
|
||||
|
44
po/nl.po
44
po/nl.po
@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-24 22:30+0200\n"
|
||||
"PO-Revision-Date: 2009-08-24 22:38+0200\n"
|
||||
"POT-Creation-Date: 2009-08-29 14:37+0200\n"
|
||||
"PO-Revision-Date: 2009-08-29 15:10+0200\n"
|
||||
"Last-Translator: Sander Dijkhuis <sander.dijkhuis@gmail.com>\n"
|
||||
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -25,79 +25,79 @@ msgid "Window management and application launching"
|
||||
msgstr "Vensterbeheer en toepassingen starten"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Activiteiten"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:451
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %k:%M"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Zoeken"
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Zoeken…"
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Bladeren"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(alles tonen)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
|
||||
#: ../js/ui/dash.js:634 ../js/ui/dash.js:682
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "TOEPASSINGEN"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:576
|
||||
#: ../js/ui/dash.js:654
|
||||
msgid "PLACES"
|
||||
msgstr "LOCATIES"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:583
|
||||
#: ../js/ui/dash.js:661 ../js/ui/dash.js:694
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "RECENTE DOCUMENTEN"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:602
|
||||
#: ../js/ui/dash.js:680
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "ZOEKRESULTATEN"
|
||||
|
||||
#: ../js/ui/dash.js:615
|
||||
msgid "DOCUMENTS"
|
||||
msgstr "DOCUMENTEN"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Voer een opdracht in:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Korter dan een minuut geleden"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuut geleden"
|
||||
msgstr[1] "%d minuten geleden"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d uur geleden"
|
||||
msgstr[1] "%d uur geleden"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag geleden"
|
||||
msgstr[1] "%d dagen geleden"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
|
182
po/pa.po
Normal file
182
po/pa.po
Normal file
@ -0,0 +1,182 @@
|
||||
# Punjabi translation for gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# A S Alam <aalam@users.sf.net>, 2009.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
|
||||
"cgi?product=gnome-shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-08-31 22:31+0000\n"
|
||||
"PO-Revision-Date: 2009-09-01 06:51+0530\n"
|
||||
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
|
||||
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 1.0\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "ਗਨੋਮ ਸ਼ੈਲ"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "ਵਿੰਡੋ ਪਰਬੰਧ ਅਤੇ ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਓ"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "ਸਰਗਰਮੀਆਂ"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "ਖੋਜ..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "ਝਲਕ"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(ਸਭ ਵੇਖੋ)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "ਥਾਵਾਂ"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "ਖੋਜ ਨਤੀਜੇ"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "ਇੱਕ ਮਿੰਟ ਤੋਂ ਘੱਟ ਚਿਰ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d ਹਫ਼ਤਾ ਪਹਿਲਾਂ"
|
||||
msgstr[1] "%d ਹਫ਼ਤੇ ਪਹਿਲਾਂ"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "ਅਣਜਾਣ"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "ਸਕਰੀਨ ਲਾਕ ਨਹੀਂ ਹੋ ਸਕਦੀ: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "ਸਕਰੀਨ ਬੰਦ ਕਰਨ ਲਈ ਆਰਜ਼ੀ ਰੂਪ ਵਿੱਚ ਸਕਰੀਨ-ਸੇਵਰ ਨਹੀਂ ਸੈੱਟ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "ਲਾਗਆਉਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "ਅਕਾਊਂਟ ਜਾਣਕਾਰੀ..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "ਬਾਹੀ"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "ਸਿਸਟਮ ਪਸੰਦ..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "ਸਕਰੀਨ ਲਾਕ ਕਰੋ"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "ਯੂਜ਼ਰ ਬਦਲੋ"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "ਲਾਗਆਉਟ..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "ਬੰਦ ਕਰੋ..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "ਘਰ ਫੋਲਡਰ"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "ਫਾਇਲ ਸਿਸਟਮ"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "ਖੋਜ"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
59
po/pl.po
59
po/pl.po
@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-18 23:25+0200\n"
|
||||
"PO-Revision-Date: 2009-08-18 23:23+0100\n"
|
||||
"POT-Creation-Date: 2009-09-09 03:06+0200\n"
|
||||
"PO-Revision-Date: 2009-09-09 03:02+0100\n"
|
||||
"Last-Translator: Tomasz Dominikowski <dominikowski@gmail.com>\n"
|
||||
"Language-Team: Polish <gnomepl@aviary.pl>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -29,57 +29,58 @@ msgid "Window management and application launching"
|
||||
msgstr "Zarządzanie oknami i uruchamianiem programów"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:269
|
||||
msgid "Activities"
|
||||
msgstr "Czynności"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:452
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a, %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:251
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Wyszukuje programy lub dokumenty"
|
||||
#: ../js/ui/dash.js:255
|
||||
msgid "Find..."
|
||||
msgstr "Znajdź..."
|
||||
|
||||
#: ../js/ui/dash.js:369
|
||||
#: ../js/ui/dash.js:372
|
||||
msgid "Browse"
|
||||
msgstr "Przeglądaj"
|
||||
|
||||
#: ../js/ui/dash.js:508
|
||||
msgid "(see all)"
|
||||
msgstr "(wyświetl wszystko)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
|
||||
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "Programy"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Ostatnie dokumenty"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:598
|
||||
#: ../js/ui/dash.js:720
|
||||
msgid "PLACES"
|
||||
msgstr "Miejsca"
|
||||
|
||||
#: ../js/ui/runDialog.js:74
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "Ostatnie dokumenty"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "Wyniki wyszukiwania"
|
||||
|
||||
#: ../js/ui/runDialog.js:90
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Proszę wprowadzić polecenie:"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:243
|
||||
msgid "Manager"
|
||||
msgstr "Menedżer"
|
||||
|
||||
#: ../src/gdmuser/gdm-user.c:244
|
||||
msgid "The user manager object this user is controlled by."
|
||||
msgstr "Obiekt menedżera użytkowników, który steruje tym użytkownikiem."
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:799
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mniej niż minutę temu"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:802
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
@ -87,7 +88,7 @@ msgstr[0] "%d minuta temu"
|
||||
msgstr[1] "%d minuty temu"
|
||||
msgstr[2] "%d minut temu"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:805
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
@ -95,7 +96,7 @@ msgstr[0] "%d godzina temu"
|
||||
msgstr[1] "%d godziny temu"
|
||||
msgstr[2] "%d godzin temu"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:808
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
@ -103,7 +104,7 @@ msgstr[0] "%d dzień temu"
|
||||
msgstr[1] "%d dni temu"
|
||||
msgstr[2] "%d dni temu"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:811
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
|
51
po/sv.po
51
po/sv.po
@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-25 07:48+0200\n"
|
||||
"PO-Revision-Date: 2009-08-25 07:48+0100\n"
|
||||
"POT-Creation-Date: 2009-09-01 00:31+0200\n"
|
||||
"PO-Revision-Date: 2009-09-01 00:31+0100\n"
|
||||
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
|
||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -25,80 +25,81 @@ msgid "Window management and application launching"
|
||||
msgstr "Fönsterhantering och programstarter"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:266
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:433
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H.%M"
|
||||
|
||||
#: ../js/ui/dash.js:250
|
||||
msgid "Find apps or documents"
|
||||
msgstr "Hitta program eller dokument"
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "Sök..."
|
||||
|
||||
#: ../js/ui/dash.js:368
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "Bläddra"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(se alla)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:556
|
||||
#: ../js/ui/dash.js:606
|
||||
#: ../js/ui/dash.js:633
|
||||
#: ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAM"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:576
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "PLATSER"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:583
|
||||
#: ../js/ui/dash.js:660
|
||||
#: ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "SENASTE DOKUMENT"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:602
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "SÖKRESULTAT"
|
||||
|
||||
#: ../js/ui/dash.js:615
|
||||
msgid "DOCUMENTS"
|
||||
msgstr "DOKUMENT"
|
||||
|
||||
#: ../js/ui/runDialog.js:75
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Ange ett kommando:"
|
||||
|
||||
#: ../src/shell-global.c:841
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre än en minut sedan"
|
||||
|
||||
#: ../src/shell-global.c:844
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minut sedan"
|
||||
msgstr[1] "%d minuter sedan"
|
||||
|
||||
#: ../src/shell-global.c:847
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d timme sedan"
|
||||
msgstr[1] "%d timmar sedan"
|
||||
|
||||
#: ../src/shell-global.c:850
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag sedan"
|
||||
msgstr[1] "%d dagar sedan"
|
||||
|
||||
#: ../src/shell-global.c:853
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -179,6 +180,10 @@ msgstr "Sök"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Find apps or documents"
|
||||
#~ msgstr "Hitta program eller dokument"
|
||||
#~ msgid "DOCUMENTS"
|
||||
#~ msgstr "DOKUMENT"
|
||||
#~ msgid "Manager"
|
||||
#~ msgstr "Hanterare"
|
||||
#~ msgid "The user manager object this user is controlled by."
|
||||
|
176
po/zh_CN.po
Normal file
176
po/zh_CN.po
Normal file
@ -0,0 +1,176 @@
|
||||
# Chinese (China) translation for gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Ray Wang <raywang@gnome.org>, 2009.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2009-08-29 19:32+0000\n"
|
||||
"PO-Revision-Date: 2009-08-30 00:08+0800\n"
|
||||
"Last-Translator: Ray Wang <raywang@gnome.org>\n"
|
||||
"Language-Team: Chinese (Simplified) <i18n-zh@googlegroups.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: utf-8\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:1
|
||||
msgid "GNOME Shell"
|
||||
msgstr "GNOME Shell"
|
||||
|
||||
#: ../data/gnome-shell.desktop.in.in.h:2
|
||||
msgid "Window management and application launching"
|
||||
msgstr "窗口管理和应用程序启动"
|
||||
|
||||
#. left side
|
||||
#: ../js/ui/panel.js:271
|
||||
msgid "Activities"
|
||||
msgstr "活动"
|
||||
|
||||
#. Translators: This is a time format.
|
||||
#: ../js/ui/panel.js:454
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%A %H:%M"
|
||||
|
||||
#: ../js/ui/dash.js:256
|
||||
msgid "Find..."
|
||||
msgstr "查找..."
|
||||
|
||||
#: ../js/ui/dash.js:374
|
||||
msgid "Browse"
|
||||
msgstr "浏览"
|
||||
|
||||
#: ../js/ui/dash.js:451
|
||||
msgid "(see all)"
|
||||
msgstr "(查看所有)"
|
||||
|
||||
#. **** Applications ****
|
||||
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "应用程序"
|
||||
|
||||
#. **** Places ****
|
||||
#. Translators: This is in the sense of locations for documents,
|
||||
#. network locations, etc.
|
||||
#: ../js/ui/dash.js:653
|
||||
msgid "PLACES"
|
||||
msgstr "位置"
|
||||
|
||||
#. **** Documents ****
|
||||
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
|
||||
msgid "RECENT DOCUMENTS"
|
||||
msgstr "最近的文档"
|
||||
|
||||
#. **** Search Results ****
|
||||
#: ../js/ui/dash.js:679
|
||||
msgid "SEARCH RESULTS"
|
||||
msgstr "搜索结果"
|
||||
|
||||
#: ../js/ui/runDialog.js:82
|
||||
msgid "Please enter a command:"
|
||||
msgstr "请输入一个命令:"
|
||||
|
||||
#: ../src/shell-global.c:840
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "少于一分钟前"
|
||||
|
||||
#: ../src/shell-global.c:843
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d 分钟前"
|
||||
|
||||
#: ../src/shell-global.c:846
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d 小时前"
|
||||
|
||||
#: ../src/shell-global.c:849
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d 天前"
|
||||
|
||||
#: ../src/shell-global.c:852
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
msgstr[0] "%d 周前"
|
||||
|
||||
#: ../src/shell-status-menu.c:156
|
||||
msgid "Unknown"
|
||||
msgstr "未知"
|
||||
|
||||
#: ../src/shell-status-menu.c:212
|
||||
#, c-format
|
||||
msgid "Can't lock screen: %s"
|
||||
msgstr "不能锁住屏幕:%s"
|
||||
|
||||
#: ../src/shell-status-menu.c:227
|
||||
#, c-format
|
||||
msgid "Can't temporarily set screensaver to blank screen: %s"
|
||||
msgstr "不能临时将屏幕保护设置成空白屏幕:%s"
|
||||
|
||||
#: ../src/shell-status-menu.c:351
|
||||
#, c-format
|
||||
msgid "Can't logout: %s"
|
||||
msgstr "不能退出:%s"
|
||||
|
||||
#: ../src/shell-status-menu.c:492
|
||||
msgid "Account Information..."
|
||||
msgstr "帐户信息..."
|
||||
|
||||
#: ../src/shell-status-menu.c:502
|
||||
msgid "Sidebar"
|
||||
msgstr "侧边栏"
|
||||
|
||||
#: ../src/shell-status-menu.c:510
|
||||
msgid "System Preferences..."
|
||||
msgstr "系统首选项..."
|
||||
|
||||
#: ../src/shell-status-menu.c:525
|
||||
msgid "Lock Screen"
|
||||
msgstr "锁住屏幕"
|
||||
|
||||
#: ../src/shell-status-menu.c:535
|
||||
msgid "Switch User"
|
||||
msgstr "切换用户"
|
||||
|
||||
#. Only show switch user if there are other users
|
||||
#. Log Out
|
||||
#: ../src/shell-status-menu.c:546
|
||||
msgid "Log Out..."
|
||||
msgstr "退出..."
|
||||
|
||||
#. Shut down
|
||||
#: ../src/shell-status-menu.c:557
|
||||
msgid "Shut Down..."
|
||||
msgstr "关机..."
|
||||
|
||||
#: ../src/shell-uri-util.c:87
|
||||
msgid "Home Folder"
|
||||
msgstr "主文件夹"
|
||||
|
||||
#. Translators: this is the same string as the one found in
|
||||
#. * nautilus
|
||||
#: ../src/shell-uri-util.c:102
|
||||
msgid "File System"
|
||||
msgstr "文件系统"
|
||||
|
||||
#: ../src/shell-uri-util.c:248
|
||||
msgid "Search"
|
||||
msgstr "搜索"
|
||||
|
||||
#. Translators: the first string is the name of a gvfs
|
||||
#. * method, and the second string is a path. For
|
||||
#. * example, "Trash: some-directory". It means that the
|
||||
#. * directory called "some-directory" is in the trash.
|
||||
#.
|
||||
#: ../src/shell-uri-util.c:298
|
||||
#, c-format
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
@ -1,9 +1,11 @@
|
||||
NULL =
|
||||
BUILT_SOURCES =
|
||||
CLEANFILES =
|
||||
EXTRA_DIST =
|
||||
EXTRA_DIST =
|
||||
libexec_PROGRAMS =
|
||||
noinst_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES =
|
||||
|
||||
.AUTOPARALLEL:
|
||||
|
||||
bin_SCRIPTS = gnome-shell
|
||||
|
||||
@ -14,6 +16,7 @@ gnome-shell: gnome-shell.in
|
||||
-e "s|@libexecdir[@]|$(libexecdir)|" \
|
||||
-e "s|@libdir[@]|$(libdir)|" \
|
||||
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
|
||||
-e "s|@PYTHON[@]|$(PYTHON)|" \
|
||||
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
|
||||
$< > $@ && chmod a+x $@
|
||||
CLEANFILES += gnome-shell
|
||||
@ -72,6 +75,8 @@ libgnome_shell_la_SOURCES = \
|
||||
shell-generic-container.h \
|
||||
shell-gtk-embed.c \
|
||||
shell-gtk-embed.h \
|
||||
shell-menu.c \
|
||||
shell-menu.h \
|
||||
shell-overflow-list.c \
|
||||
shell-overflow-list.h \
|
||||
shell-process.c \
|
||||
@ -161,6 +166,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
|
||||
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
|
||||
--include=Clutter-1.0 \
|
||||
--include=Meta-2.27 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--add-include-path=$(builddir) \
|
||||
--include=Big-1.0 \
|
||||
--program=mutter \
|
||||
@ -180,12 +186,13 @@ Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
|
||||
Shell-0.1.gir -o $@
|
||||
CLEANFILES += Shell-0.1.typelib
|
||||
|
||||
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
|
||||
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir)/big-enum-types.h Makefile
|
||||
$(AM_V_GEN) $(G_IR_SCANNER) \
|
||||
--namespace=Big \
|
||||
--nsversion=1.0 \
|
||||
--include=Clutter-1.0 \
|
||||
--include=GdkPixbuf-2.0 \
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--program=mutter \
|
||||
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
|
||||
$(addprefix $(srcdir)/,$(big_source_h)) \
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#!@PYTHON@
|
||||
|
||||
import atexit
|
||||
import optparse
|
||||
@ -253,6 +253,7 @@ if options.debug:
|
||||
normal_exit = False
|
||||
|
||||
try:
|
||||
shell = None
|
||||
if options.xephyr:
|
||||
xephyr = start_xephyr()
|
||||
# This makes us not grab the org.gnome.Panel name
|
||||
@ -281,7 +282,9 @@ finally:
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if shell.returncode == 0:
|
||||
if shell is None:
|
||||
print "Failed to start shell"
|
||||
elif shell.returncode == 0:
|
||||
normal_exit = True
|
||||
if options.verbose:
|
||||
print "Shell exited normally"
|
||||
|
@ -345,7 +345,7 @@ window_is_tracked (MetaWindow *window)
|
||||
}
|
||||
|
||||
/**
|
||||
* window_is_usage_tracked:
|
||||
* shell_app_monitor_is_window_usage_tracked:
|
||||
*
|
||||
* Determine if it makes sense to track the given window for application
|
||||
* usage. An example of a window we don't want to track is the root
|
||||
@ -358,12 +358,15 @@ window_is_tracked (MetaWindow *window)
|
||||
*
|
||||
* Returns: %TRUE iff we want to record focus time spent in this window
|
||||
*/
|
||||
static gboolean
|
||||
window_is_usage_tracked (MetaWindow *window)
|
||||
gboolean
|
||||
shell_app_monitor_is_window_usage_tracked (MetaWindow *window)
|
||||
{
|
||||
if (!window_is_tracked (window))
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_is_skip_taskbar (window))
|
||||
return FALSE;
|
||||
|
||||
switch (meta_window_get_window_type (window))
|
||||
{
|
||||
/* Definitely ignore these. */
|
||||
@ -434,9 +437,10 @@ get_app_for_window_direct (MetaWindow *window)
|
||||
|
||||
if (id != NULL)
|
||||
result = shell_app_system_load_from_desktop_file (appsys, id, NULL);
|
||||
else
|
||||
result = create_transient_app_for_window (window);
|
||||
}
|
||||
if (result == NULL)
|
||||
result = create_transient_app_for_window (window);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -562,7 +566,7 @@ get_active_window (ShellAppMonitor *monitor)
|
||||
display = meta_screen_get_display (screen);
|
||||
window = meta_display_get_focus_window (display);
|
||||
|
||||
if (window != NULL && window_is_usage_tracked (window))
|
||||
if (window != NULL && shell_app_monitor_is_window_usage_tracked (window))
|
||||
return window;
|
||||
return NULL;
|
||||
}
|
||||
@ -756,7 +760,7 @@ track_window (ShellAppMonitor *self,
|
||||
* tracked it doesn't count for the purposes of an application
|
||||
* running.
|
||||
*/
|
||||
if (!window_is_usage_tracked (window))
|
||||
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||
return;
|
||||
|
||||
usage = get_app_usage_from_window (self, window);
|
||||
@ -812,7 +816,7 @@ disassociate_window (ShellAppMonitor *self,
|
||||
if (window == self->watched_window)
|
||||
self->watched_window = NULL;
|
||||
|
||||
if (window_is_usage_tracked (window))
|
||||
if (shell_app_monitor_is_window_usage_tracked (window))
|
||||
{
|
||||
AppUsage *usage;
|
||||
const char *context;
|
||||
@ -930,7 +934,7 @@ shell_app_monitor_get_windows_for_app (ShellAppMonitor *self,
|
||||
ShellAppInfo *app = value;
|
||||
const char *id = shell_app_info_get_id (app);
|
||||
|
||||
if (!window_is_usage_tracked (window))
|
||||
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||
continue;
|
||||
|
||||
if (strcmp (id, appid) != 0)
|
||||
@ -1181,7 +1185,7 @@ shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
|
||||
if (strcmp (get_window_context (window), context) != 0)
|
||||
continue;
|
||||
|
||||
if (!window_is_usage_tracked (window))
|
||||
if (!shell_app_monitor_is_window_usage_tracked (window))
|
||||
continue;
|
||||
|
||||
id = shell_app_info_get_id (app);
|
||||
|
@ -44,6 +44,8 @@ GList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
|
||||
|
||||
GSList *shell_app_monitor_get_windows_for_app (ShellAppMonitor *monitor, const char *appid);
|
||||
|
||||
gboolean shell_app_monitor_is_window_usage_tracked (MetaWindow *window);
|
||||
|
||||
/* Get whatever's running right now */
|
||||
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor, const char *context);
|
||||
|
||||
|
@ -52,10 +52,13 @@ struct _ShellAppSystemPrivate {
|
||||
GList *cached_favorites; /* utf8 */
|
||||
|
||||
gint app_monitor_id;
|
||||
|
||||
guint app_change_timeout_id;
|
||||
};
|
||||
|
||||
static void shell_app_system_finalize (GObject *object);
|
||||
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
|
||||
static gboolean on_tree_changed (gpointer user_data);
|
||||
static void on_tree_changed_cb (GMenuTree *tree, gpointer user_data);
|
||||
static void reread_menus (ShellAppSystem *self);
|
||||
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
|
||||
static void reread_favorite_apps (ShellAppSystem *system);
|
||||
@ -233,8 +236,10 @@ shell_app_system_init (ShellAppSystem *self)
|
||||
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
|
||||
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
|
||||
|
||||
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed, self);
|
||||
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed, self);
|
||||
priv->app_change_timeout_id = 0;
|
||||
|
||||
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed_cb, self);
|
||||
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed_cb, self);
|
||||
|
||||
reread_menus (self);
|
||||
|
||||
@ -251,8 +256,8 @@ shell_app_system_finalize (GObject *object)
|
||||
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
|
||||
ShellAppSystemPrivate *priv = self->priv;
|
||||
|
||||
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed, self);
|
||||
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed, self);
|
||||
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed_cb, self);
|
||||
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed_cb, self);
|
||||
|
||||
gmenu_tree_unref (priv->apps_tree);
|
||||
gmenu_tree_unref (priv->settings_tree);
|
||||
@ -410,14 +415,39 @@ reread_menus (ShellAppSystem *self)
|
||||
cache_by_id (self, self->priv->cached_settings, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_tree_changed (gpointer user_data)
|
||||
{
|
||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
||||
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
||||
reread_menus (self);
|
||||
self->priv->app_change_timeout_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_tree_changed (GMenuTree *monitor, gpointer user_data)
|
||||
on_tree_changed_cb (GMenuTree *monitor, gpointer user_data)
|
||||
{
|
||||
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
|
||||
|
||||
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
|
||||
/* GMenu currently gives us a separate notification on the entire
|
||||
* menu tree for each node in the tree that might potentially have
|
||||
* changed. (See http://bugzilla.gnome.org/show_bug.cgi?id=172046.)
|
||||
* We need to compress these to avoid doing large extra amounts of
|
||||
* work.
|
||||
*
|
||||
* Even when that bug is fixed, compression is still useful; for one
|
||||
* thing we want to need to compress across notifications of changes
|
||||
* to the settings tree. Second we want to compress if multiple
|
||||
* changes are made to the desktop files at different times but in
|
||||
* short succession.
|
||||
*/
|
||||
|
||||
reread_menus (self);
|
||||
if (self->priv->app_change_timeout_id != 0)
|
||||
return;
|
||||
self->priv->app_change_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 3000,
|
||||
(GSourceFunc) on_tree_changed,
|
||||
self, NULL);
|
||||
}
|
||||
|
||||
static GList *
|
||||
|
@ -14,6 +14,7 @@
|
||||
G_DEFINE_TYPE(ShellButtonBox, shell_button_box, BIG_TYPE_BOX);
|
||||
|
||||
struct _ShellButtonBoxPrivate {
|
||||
gboolean active;
|
||||
gboolean held;
|
||||
gboolean hover;
|
||||
gboolean pressed;
|
||||
@ -29,12 +30,23 @@ enum
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
PROP_ACTIVE,
|
||||
PROP_HOVER,
|
||||
PROP_PRESSED,
|
||||
};
|
||||
|
||||
static guint shell_button_box_signals [LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
set_active (ShellButtonBox *box,
|
||||
gboolean active)
|
||||
{
|
||||
if (box->priv->active == active)
|
||||
return;
|
||||
box->priv->active = active;
|
||||
g_object_notify (G_OBJECT (box), "active");
|
||||
}
|
||||
|
||||
static void
|
||||
set_hover (ShellButtonBox *box,
|
||||
gboolean hover)
|
||||
@ -67,28 +79,34 @@ shell_button_box_contains (ShellButtonBox *box,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_button_box_on_enter (ShellButtonBox *box,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
shell_button_box_enter_event (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
if (shell_button_box_contains (box, event->crossing.related))
|
||||
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||
|
||||
if (shell_button_box_contains (box, event->related))
|
||||
return TRUE;
|
||||
if (!shell_button_box_contains (box, clutter_event_get_source (event)))
|
||||
if (!shell_button_box_contains (box, event->source))
|
||||
return TRUE;
|
||||
|
||||
set_hover (box, TRUE);
|
||||
g_object_freeze_notify (G_OBJECT (actor));
|
||||
|
||||
if (box->priv->held)
|
||||
set_pressed (box, TRUE);
|
||||
set_hover (box, TRUE);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (actor));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_button_box_on_leave (ShellButtonBox *box,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
shell_button_box_leave_event (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
if (shell_button_box_contains (box, event->crossing.related))
|
||||
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||
|
||||
if (shell_button_box_contains (box, event->related))
|
||||
return TRUE;
|
||||
|
||||
set_hover (box, FALSE);
|
||||
@ -98,17 +116,18 @@ shell_button_box_on_leave (ShellButtonBox *box,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_button_box_on_press (ShellButtonBox *box,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
shell_button_box_button_press_event (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
ClutterActor *source;
|
||||
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||
|
||||
if (event->button != 1 || event->click_count != 1)
|
||||
return FALSE;
|
||||
|
||||
if (box->priv->held)
|
||||
return TRUE;
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (!shell_button_box_contains (box, source))
|
||||
if (!shell_button_box_contains (box, event->source))
|
||||
return FALSE;
|
||||
|
||||
box->priv->held = TRUE;
|
||||
@ -120,38 +139,68 @@ shell_button_box_on_press (ShellButtonBox *box,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_button_box_on_release (ShellButtonBox *box,
|
||||
ClutterEvent *event,
|
||||
gpointer user_data)
|
||||
shell_button_box_button_release_event (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
ClutterActor *source;
|
||||
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
|
||||
|
||||
if (event->button != 1 || event->click_count != 1)
|
||||
return FALSE;
|
||||
|
||||
if (!box->priv->held)
|
||||
return TRUE;
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
|
||||
box->priv->held = FALSE;
|
||||
clutter_ungrab_pointer ();
|
||||
|
||||
if (!shell_button_box_contains (box, source))
|
||||
if (!shell_button_box_contains (box, event->source))
|
||||
return FALSE;
|
||||
|
||||
set_pressed (box, FALSE);
|
||||
|
||||
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0);
|
||||
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0, event);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_button_box_fake_release:
|
||||
* @box:
|
||||
*
|
||||
* If this button box is holding a pointer grab, this function will
|
||||
* will ungrab it, and reset the pressed state. The effect is
|
||||
* similar to if the user had released the mouse button, but without
|
||||
* emitting the activate signal.
|
||||
*
|
||||
* This function is useful if for example you want to do something after the user
|
||||
* is holding the mouse button for a given period of time, breaking the
|
||||
* grab.
|
||||
*/
|
||||
void
|
||||
shell_button_box_fake_release (ShellButtonBox *box)
|
||||
{
|
||||
if (!box->priv->held)
|
||||
return;
|
||||
|
||||
box->priv->held = FALSE;
|
||||
clutter_ungrab_pointer ();
|
||||
|
||||
set_pressed (box, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_button_box_set_property(GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ShellButtonBox *box = SHELL_BUTTON_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIVE:
|
||||
set_active (box, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -168,6 +217,9 @@ shell_button_box_get_property(GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTIVE:
|
||||
g_value_set_boolean (value, box->priv->active);
|
||||
break;
|
||||
case PROP_PRESSED:
|
||||
g_value_set_boolean (value, box->priv->pressed);
|
||||
break;
|
||||
@ -184,13 +236,20 @@ static void
|
||||
shell_button_box_class_init (ShellButtonBoxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = shell_button_box_get_property;
|
||||
gobject_class->set_property = shell_button_box_set_property;
|
||||
|
||||
actor_class->enter_event = shell_button_box_enter_event;
|
||||
actor_class->leave_event = shell_button_box_leave_event;
|
||||
actor_class->button_press_event = shell_button_box_button_press_event;
|
||||
actor_class->button_release_event = shell_button_box_button_release_event;
|
||||
|
||||
/**
|
||||
* ShellButtonBox::activate
|
||||
* @box: The #ShellButtonBox
|
||||
* @event: Release event which triggered the activation
|
||||
*
|
||||
* This signal is emitted when the button should take the action
|
||||
* associated with button click+release.
|
||||
@ -202,7 +261,22 @@ shell_button_box_class_init (ShellButtonBoxClass *klass)
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT);
|
||||
|
||||
/**
|
||||
* ShellButtonBox:active
|
||||
*
|
||||
* The property allows the button to be used as a "toggle button"; it's up to the
|
||||
* application to update the active property in response to the activate signal;
|
||||
* it doesn't happen automatically.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ACTIVE,
|
||||
g_param_spec_boolean ("active",
|
||||
"Active",
|
||||
"Whether the button persistently active",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* ShellButtonBox:hover
|
||||
@ -240,9 +314,4 @@ shell_button_box_init (ShellButtonBox *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_BUTTON_BOX,
|
||||
ShellButtonBoxPrivate);
|
||||
|
||||
g_signal_connect (G_OBJECT (self), "enter-event", G_CALLBACK(shell_button_box_on_enter), NULL);
|
||||
g_signal_connect (G_OBJECT (self), "leave-event", G_CALLBACK(shell_button_box_on_leave), NULL);
|
||||
g_signal_connect (G_OBJECT (self), "button-press-event", G_CALLBACK(shell_button_box_on_press), NULL);
|
||||
g_signal_connect (G_OBJECT (self), "button-release-event", G_CALLBACK(shell_button_box_on_release), NULL);
|
||||
}
|
||||
|
@ -30,4 +30,6 @@ struct _ShellButtonBoxClass
|
||||
|
||||
GType shell_button_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void shell_button_box_fake_release (ShellButtonBox *box);
|
||||
|
||||
#endif /* __SHELL_BUTTON_BOX_H__ */
|
||||
|
@ -146,79 +146,33 @@ shell_draw_clock (ClutterCairoTexture *texture,
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_glow (cairo_t *cr, double red, double green, double blue, double alpha)
|
||||
{
|
||||
cairo_pattern_t *gradient;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
gradient = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
|
||||
cairo_pattern_add_color_stop_rgba (gradient, 0.0, red, green, blue, alpha);
|
||||
cairo_pattern_add_color_stop_rgba (gradient, 0.7, red, green, blue, alpha * 0.7);
|
||||
cairo_pattern_add_color_stop_rgba (gradient, 1.0, red, green, blue, alpha * 0.3);
|
||||
cairo_set_source (cr, gradient);
|
||||
|
||||
cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
cairo_pattern_destroy (gradient);
|
||||
}
|
||||
|
||||
void
|
||||
shell_draw_app_highlight (ClutterCairoTexture *texture,
|
||||
int num_windows,
|
||||
double red,
|
||||
double green,
|
||||
double blue,
|
||||
double alpha)
|
||||
shell_draw_box_pointer (ClutterCairoTexture *texture,
|
||||
ClutterColor *border_color,
|
||||
ClutterColor *background_color)
|
||||
{
|
||||
cairo_t *cr;
|
||||
guint width, height;
|
||||
|
||||
g_return_if_fail (num_windows > 0);
|
||||
cairo_t *cr;
|
||||
|
||||
clutter_cairo_texture_get_surface_size (texture, &width, &height);
|
||||
|
||||
clutter_cairo_texture_clear (texture);
|
||||
cr = clutter_cairo_texture_create (texture);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
if (num_windows == 1)
|
||||
{
|
||||
cairo_scale (cr, width / 2.0, height / 2.0);
|
||||
draw_glow (cr, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
int num_circles, i;
|
||||
double scale, highlight_width;
|
||||
clutter_cairo_set_source_color (cr, border_color);
|
||||
|
||||
num_circles = num_windows == 2 ? 2 : 3;
|
||||
cairo_move_to (cr, width, 0);
|
||||
cairo_line_to (cr, 0, floor (height * 0.5));
|
||||
cairo_line_to (cr, width, height);
|
||||
|
||||
/* The circles will have radius 1.0 (diameter 2.0) and overlap
|
||||
* by 0.2, so the total width of the highlight is:
|
||||
*/
|
||||
highlight_width = 2.0 * num_circles - 0.2 * (num_circles - 1);
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
scale = MIN (height / 2.0, width / highlight_width);
|
||||
cairo_scale (cr, scale, scale);
|
||||
clutter_cairo_set_source_color (cr, background_color);
|
||||
|
||||
/* The leftmost circle's left side is at -highlight_width/2, so
|
||||
* its center is that plus 1.
|
||||
*/
|
||||
cairo_translate (cr, -highlight_width / 2.0 + 1.0, 0.0);
|
||||
for (i = 0; i < num_circles; i++)
|
||||
{
|
||||
draw_glow (cr, red, green, blue, alpha);
|
||||
cairo_translate (cr, 1.8, 0.0);
|
||||
}
|
||||
}
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,14 @@ ClutterCairoTexture *shell_create_vertical_gradient (ClutterColor *top,
|
||||
ClutterCairoTexture *shell_create_horizontal_gradient (ClutterColor *left,
|
||||
ClutterColor *right);
|
||||
|
||||
void shell_draw_box_pointer (ClutterCairoTexture *texture,
|
||||
ClutterColor *border_color,
|
||||
ClutterColor *background_color);
|
||||
|
||||
void shell_draw_clock (ClutterCairoTexture *texture,
|
||||
int hour,
|
||||
int minute);
|
||||
|
||||
void shell_draw_app_highlight (ClutterCairoTexture *texture,
|
||||
int num_windows,
|
||||
double red,
|
||||
double blue,
|
||||
double green,
|
||||
double alpha);
|
||||
|
||||
guint shell_add_hook_paint_red_border (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -295,47 +295,6 @@ shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_get_event_key_symbol:
|
||||
*
|
||||
* Return value: Clutter key value for the key press and release events,
|
||||
* as specified in clutter-keysyms.h
|
||||
*/
|
||||
guint16
|
||||
shell_get_event_key_symbol(ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail(event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE, 0);
|
||||
|
||||
return event->key.keyval;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_get_button_event_click_count:
|
||||
*
|
||||
* Return value: click count for button press and release events
|
||||
*/
|
||||
guint16
|
||||
shell_get_button_event_click_count(ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail(event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_BUTTON_RELEASE, 0);
|
||||
return event->button.click_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_get_event_related:
|
||||
*
|
||||
* Return value: (transfer none): related actor
|
||||
*/
|
||||
ClutterActor *
|
||||
shell_get_event_related (ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event->type == CLUTTER_ENTER ||
|
||||
event->type == CLUTTER_LEAVE, NULL);
|
||||
return event->crossing.related;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_global_get:
|
||||
*
|
||||
|
@ -36,10 +36,6 @@ GType shell_global_get_type (void) G_GNUC_CONST;
|
||||
gboolean shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
|
||||
GdkPixbuf *pixbuf);
|
||||
|
||||
guint16 shell_get_event_key_symbol(ClutterEvent *event);
|
||||
|
||||
guint16 shell_get_button_event_click_count(ClutterEvent *event);
|
||||
|
||||
ClutterActor *shell_get_event_related(ClutterEvent *event);
|
||||
|
||||
ShellGlobal *shell_global_get (void);
|
||||
|
335
src/shell-menu.c
Normal file
335
src/shell-menu.c
Normal file
@ -0,0 +1,335 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* SECTION:shell-menu
|
||||
* @short_description: A box which acts like a popup menu
|
||||
*
|
||||
* A #BigBox subclass which adds methods and signals useful for implementing
|
||||
* popup-menu like actors.
|
||||
*/
|
||||
|
||||
#include "shell-menu.h"
|
||||
|
||||
G_DEFINE_TYPE(ShellMenu, shell_menu, BIG_TYPE_BOX);
|
||||
|
||||
struct _ShellMenuPrivate {
|
||||
gboolean popped_up;
|
||||
gboolean have_grab;
|
||||
|
||||
gboolean released_on_source;
|
||||
ClutterActor *source_actor;
|
||||
|
||||
ClutterActor *selected;
|
||||
};
|
||||
|
||||
/* Signals */
|
||||
enum
|
||||
{
|
||||
UNSELECTED,
|
||||
SELECTED,
|
||||
ACTIVATE,
|
||||
CANCELLED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint shell_menu_signals [LAST_SIGNAL] = { 0 };
|
||||
|
||||
static gboolean
|
||||
container_contains (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
while (actor != NULL && actor != (ClutterActor*)container)
|
||||
{
|
||||
actor = clutter_actor_get_parent (actor);
|
||||
}
|
||||
return actor != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
shell_menu_popdown_nosignal (ShellMenu *box)
|
||||
{
|
||||
box->priv->popped_up = FALSE;
|
||||
if (box->priv->have_grab)
|
||||
clutter_ungrab_pointer ();
|
||||
clutter_actor_hide (CLUTTER_ACTOR (box));
|
||||
}
|
||||
|
||||
static void
|
||||
on_selected_destroy (ClutterActor *actor,
|
||||
ShellMenu *box)
|
||||
{
|
||||
box->priv->selected = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_selected (ShellMenu *box,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
if (actor == box->priv->selected)
|
||||
return;
|
||||
if (box->priv->selected)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (box->priv->selected, G_CALLBACK(on_selected_destroy), box);
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[UNSELECTED], 0, box->priv->selected);
|
||||
}
|
||||
box->priv->selected = actor;
|
||||
if (box->priv->selected)
|
||||
{
|
||||
g_signal_connect (box->priv->selected, "destroy", G_CALLBACK(on_selected_destroy), box);
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[SELECTED], 0, box->priv->selected);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_menu_enter_event (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
ShellMenu *box = SHELL_MENU (actor);
|
||||
|
||||
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
|
||||
return TRUE;
|
||||
|
||||
if (event->source == (ClutterActor*)box)
|
||||
return TRUE;
|
||||
|
||||
if (g_object_get_data (G_OBJECT (event->source), "shell-is-separator"))
|
||||
return TRUE;
|
||||
|
||||
set_selected (box, event->source);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_menu_leave_event (ClutterActor *actor,
|
||||
ClutterCrossingEvent *event)
|
||||
{
|
||||
ShellMenu *box = SHELL_MENU (actor);
|
||||
|
||||
set_selected (box, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shell_menu_button_release_event (ClutterActor *actor,
|
||||
ClutterButtonEvent *event)
|
||||
{
|
||||
ShellMenu *box = SHELL_MENU (actor);
|
||||
|
||||
if (event->button != 1)
|
||||
return FALSE;
|
||||
|
||||
if (box->priv->source_actor && !box->priv->released_on_source)
|
||||
{
|
||||
if (box->priv->source_actor == event->source ||
|
||||
(CLUTTER_IS_CONTAINER (box->priv->source_actor) &&
|
||||
container_contains (CLUTTER_CONTAINER (box->priv->source_actor), event->source)))
|
||||
{
|
||||
/* On the next release, we want to pop down the menu regardless */
|
||||
box->priv->released_on_source = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
shell_menu_popdown_nosignal (box);
|
||||
|
||||
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
|
||||
{
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (box->priv->selected == NULL)
|
||||
{
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[ACTIVATE], 0, box->priv->selected);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
shell_menu_popup (ShellMenu *box,
|
||||
guint button,
|
||||
guint32 activate_time)
|
||||
{
|
||||
if (box->priv->popped_up)
|
||||
return;
|
||||
box->priv->popped_up = TRUE;
|
||||
box->priv->have_grab = TRUE;
|
||||
box->priv->released_on_source = FALSE;
|
||||
clutter_grab_pointer (CLUTTER_ACTOR (box));
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_menu_popdown:
|
||||
* @box:
|
||||
*
|
||||
* If the menu is currently active, hide it, emitting the 'cancelled' signal.
|
||||
*/
|
||||
void
|
||||
shell_menu_popdown (ShellMenu *box)
|
||||
{
|
||||
if (!box->priv->popped_up)
|
||||
return;
|
||||
shell_menu_popdown_nosignal (box);
|
||||
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_destroyed (ClutterActor *actor,
|
||||
ShellMenu *box)
|
||||
{
|
||||
box->priv->source_actor = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_menu_set_persistent_source:
|
||||
* @box:
|
||||
* @source: Actor to use as menu origin
|
||||
*
|
||||
* This function changes the menu behavior on button release. Normally
|
||||
* when the mouse is released anywhere, the menu "pops down"; when this
|
||||
* function is called, if the mouse is released over the source actor,
|
||||
* the menu stays.
|
||||
*
|
||||
* The given @source actor must be reactive for this function to work.
|
||||
*/
|
||||
void
|
||||
shell_menu_set_persistent_source (ShellMenu *box,
|
||||
ClutterActor *source)
|
||||
{
|
||||
if (box->priv->source_actor)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (box->priv->source_actor),
|
||||
G_CALLBACK (on_source_destroyed),
|
||||
box);
|
||||
}
|
||||
box->priv->source_actor = source;
|
||||
if (box->priv->source_actor)
|
||||
{
|
||||
g_signal_connect (G_OBJECT (box->priv->source_actor),
|
||||
"destroy",
|
||||
G_CALLBACK (on_source_destroyed),
|
||||
box);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_menu_append_separator:
|
||||
* @box:
|
||||
* @separator: An actor which functions as a menu separator
|
||||
* @flags: Packing flags
|
||||
*
|
||||
* Actors added to the menu with default functions are treated like
|
||||
* menu items; this function will add an actor that should instead
|
||||
* be treated like a menu separator. The current practical effect
|
||||
* is that the separators will not be selectable.
|
||||
*/
|
||||
void
|
||||
shell_menu_append_separator (ShellMenu *box,
|
||||
ClutterActor *separator,
|
||||
BigBoxPackFlags flags)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (separator), "shell-is-separator", GUINT_TO_POINTER(TRUE));
|
||||
big_box_append (BIG_BOX (box), separator, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_menu_dispose (GObject *gobject)
|
||||
{
|
||||
ShellMenu *self = SHELL_MENU (gobject);
|
||||
|
||||
shell_menu_set_persistent_source (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (shell_menu_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_menu_class_init (ShellMenuClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = shell_menu_dispose;
|
||||
|
||||
actor_class->enter_event = shell_menu_enter_event;
|
||||
actor_class->leave_event = shell_menu_leave_event;
|
||||
actor_class->button_release_event = shell_menu_button_release_event;
|
||||
|
||||
/**
|
||||
* ShellMenu::unselected
|
||||
* @box: The #ShellMenu
|
||||
* @actor: The previously hovered-over menu item
|
||||
*
|
||||
* This signal is emitted when a menu item transitions to
|
||||
* an unselected state.
|
||||
*/
|
||||
shell_menu_signals[UNSELECTED] =
|
||||
g_signal_new ("unselected",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* ShellMenu::selected
|
||||
* @box: The #ShellMenu
|
||||
* @actor: The hovered-over menu item
|
||||
*
|
||||
* This signal is emitted when a menu item is in a selected state.
|
||||
*/
|
||||
shell_menu_signals[SELECTED] =
|
||||
g_signal_new ("selected",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* ShellMenu::activate
|
||||
* @box: The #ShellMenu
|
||||
* @actor: The clicked menu item
|
||||
*
|
||||
* This signal is emitted when a menu item is selected.
|
||||
*/
|
||||
shell_menu_signals[ACTIVATE] =
|
||||
g_signal_new ("activate",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* ShellMenu::cancelled
|
||||
* @box: The #ShellMenu
|
||||
*
|
||||
* This signal is emitted when the menu is closed without an option selected.
|
||||
*/
|
||||
shell_menu_signals[CANCELLED] =
|
||||
g_signal_new ("cancelled",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (ShellMenuPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
shell_menu_init (ShellMenu *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_MENU,
|
||||
ShellMenuPrivate);
|
||||
}
|
41
src/shell-menu.h
Normal file
41
src/shell-menu.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __SHELL_MENU_H__
|
||||
#define __SHELL_MENU_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "big/box.h"
|
||||
|
||||
#define SHELL_TYPE_MENU (shell_menu_get_type ())
|
||||
#define SHELL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_MENU, ShellMenu))
|
||||
#define SHELL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_MENU, ShellMenuClass))
|
||||
#define SHELL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_MENU))
|
||||
#define SHELL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_MENU))
|
||||
#define SHELL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_MENU, ShellMenuClass))
|
||||
|
||||
typedef struct _ShellMenu ShellMenu;
|
||||
typedef struct _ShellMenuClass ShellMenuClass;
|
||||
|
||||
typedef struct _ShellMenuPrivate ShellMenuPrivate;
|
||||
|
||||
struct _ShellMenu
|
||||
{
|
||||
BigBox parent;
|
||||
|
||||
ShellMenuPrivate *priv;
|
||||
};
|
||||
|
||||
struct _ShellMenuClass
|
||||
{
|
||||
BigBoxClass parent_class;
|
||||
};
|
||||
|
||||
GType shell_menu_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void shell_menu_popup (ShellMenu *behavior, guint button, guint32 activate_time);
|
||||
|
||||
void shell_menu_set_persistent_source (ShellMenu *behavior, ClutterActor *source);
|
||||
|
||||
void shell_menu_append_separator (ShellMenu *behavior, ClutterActor *separator, BigBoxPackFlags flags);
|
||||
|
||||
void shell_menu_popdown (ShellMenu *behavior);
|
||||
|
||||
#endif /* __SHELL_MENU_H__ */
|
@ -1236,6 +1236,35 @@ shell_texture_cache_evict_recent_thumbnail (ShellTextureCache *cache,
|
||||
shell_texture_cache_evict_thumbnail (cache, gtk_recent_info_get_uri (info));
|
||||
}
|
||||
|
||||
static size_t
|
||||
pixbuf_byte_size (GdkPixbuf *pixbuf)
|
||||
{
|
||||
/* This bit translated from gtk+/gdk-pixbuf/gdk-pixbuf.c:gdk_pixbuf_copy. The comment
|
||||
* there was:
|
||||
*
|
||||
* Calculate a semi-exact size. Here we copy with full rowstrides;
|
||||
* maybe we should copy each row individually with the minimum
|
||||
* rowstride?
|
||||
*/
|
||||
return (gdk_pixbuf_get_height (pixbuf) - 1) * gdk_pixbuf_get_rowstride (pixbuf) +
|
||||
+ gdk_pixbuf_get_width (pixbuf) * ((gdk_pixbuf_get_n_channels (pixbuf)* gdk_pixbuf_get_bits_per_sample (pixbuf) + 7) / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_texture_cache_pixbuf_equal:
|
||||
*
|
||||
* Returns: %TRUE iff the given pixbufs are bytewise-equal
|
||||
*/
|
||||
gboolean
|
||||
shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b)
|
||||
{
|
||||
size_t size_a = pixbuf_byte_size (a);
|
||||
size_t size_b = pixbuf_byte_size (b);
|
||||
if (size_a != size_b)
|
||||
return FALSE;
|
||||
return memcmp (gdk_pixbuf_get_pixels (a), gdk_pixbuf_get_pixels (b), size_a) == 0;
|
||||
}
|
||||
|
||||
static ShellTextureCache *instance = NULL;
|
||||
|
||||
/**
|
||||
|
@ -79,4 +79,6 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
|
||||
int available_height,
|
||||
GError **error);
|
||||
|
||||
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
|
||||
|
||||
#endif /* __SHELL_TEXTURE_CACHE_H__ */
|
||||
|
@ -53,7 +53,8 @@ fi
|
||||
#
|
||||
# Non-devel packages needed by gnome-shell and its deps:
|
||||
# glxinfo, gstreamer-plugins-base, gstreamer-plugins-good,
|
||||
# python, Xephyr, xeyes*, xlogo*, xterm*, zenity
|
||||
# python, pygobject, gnome-python (gconf),
|
||||
# Xephyr, xeyes*, xlogo*, xterm*, zenity
|
||||
#
|
||||
# (*)ed packages are only needed because gnome-shell launches them
|
||||
# when running in Xephyr mode, and we should probably change it to use
|
||||
@ -80,8 +81,8 @@ if test x$system = xUbuntu -o x$system = xDebian ; then
|
||||
automake bison flex git-core gnome-common gtk-doc-tools \
|
||||
libdbus-glib-1-dev libgconf2-dev libgtk2.0-dev libffi-dev \
|
||||
libgnome-menu-dev libgnome-desktop-dev librsvg2-dev libwnck-dev libgl1-mesa-dev \
|
||||
mesa-common-dev mesa-utils python-dev libreadline5-dev xulrunner-dev \
|
||||
xserver-xephyr \
|
||||
libreadline5-dev mesa-common-dev mesa-utils python-dev python-gconf python-gobject \
|
||||
xulrunner-dev xserver-xephyr \
|
||||
libgstreamer0.10-dev gstreamer0.10-plugins-base gstreamer0.10-plugins-good \
|
||||
; do
|
||||
if ! dpkg_is_installed $pkg; then
|
||||
@ -101,9 +102,9 @@ if test x$system = xFedora ; then
|
||||
binutils curl gcc make \
|
||||
automake bison flex git gnome-common gnome-doc-utils intltool \
|
||||
libtool pkgconfig \
|
||||
dbus-glib-devel GConf2-devel gnome-menus-devel gtk2-devel libffi-devel gnome-desktop-devel \
|
||||
librsvg2-devel libwnck-devel mesa-libGL-devel python-devel readline-devel \
|
||||
xulrunner-devel libXdamage-devel \
|
||||
dbus-glib-devel GConf2-devel gnome-menus-devel gnome-python2-gconf gtk2-devel libffi-devel \
|
||||
gnome-desktop-devel librsvg2-devel libwnck-devel mesa-libGL-devel python-devel pygobject2 \
|
||||
readline-devel xulrunner-devel libXdamage-devel \
|
||||
gstreamer-devel gstreamer-plugins-base gstreamer-plugins-good \
|
||||
glx-utils xorg-x11-apps xorg-x11-server-Xephyr xterm zenity \
|
||||
; do
|
||||
|
Reference in New Issue
Block a user