diff --git a/js/Makefile.am b/js/Makefile.am
index 7606f32b1..29187da2e 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -49,7 +49,6 @@ nobase_dist_js_DATA = \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
- ui/flashspot.js \
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
@@ -74,11 +73,11 @@ nobase_dist_js_DATA = \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/runDialog.js \
+ ui/screenshot.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
ui/searchDisplay.js \
- ui/selectArea.js \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/keyboard.js \
diff --git a/js/ui/flashspot.js b/js/ui/flashspot.js
deleted file mode 100644
index eabbac657..000000000
--- a/js/ui/flashspot.js
+++ /dev/null
@@ -1,45 +0,0 @@
-// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-
-const Lang = imports.lang;
-
-const Lightbox = imports.ui.lightbox;
-const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
-
-const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
-
-const Flashspot = new Lang.Class({
- Name: 'Flashspot',
- Extends: Lightbox.Lightbox,
-
- _init: function(area) {
- this.parent(Main.uiGroup, { inhibitEvents: true,
- width: area.width,
- height: area.height });
-
- this.actor.style_class = 'flashspot';
- this.actor.set_position(area.x, area.y);
- },
-
- fire: function() {
- this.actor.opacity = 0;
- Tweener.addTween(this.actor,
- { opacity: 255,
- time: FLASHSPOT_ANIMATION_TIME,
- transition: 'linear',
- onComplete: Lang.bind(this, this._onFireShowComplete)
- });
- this.actor.show();
- },
-
- _onFireShowComplete: function() {
- Tweener.addTween(this.actor,
- { opacity: 0,
- time: FLASHSPOT_ANIMATION_TIME,
- transition: 'linear',
- onComplete: Lang.bind(this, function() {
- this.destroy();
- })
- });
- }
-});
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
new file mode 100644
index 000000000..12cf18642
--- /dev/null
+++ b/js/ui/screenshot.js
@@ -0,0 +1,281 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Shell = imports.gi.Shell;
+const Signals = imports.signals;
+const St = imports.gi.St;
+
+const Lightbox = imports.ui.lightbox;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+
+const ScreenshotIface =
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+;
+
+const ScreenshotService = new Lang.Class({
+ Name: 'ScreenshotService',
+
+ _init: function() {
+ this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ScreenshotIface, this);
+ this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Screenshot');
+
+ Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
+ },
+
+ _onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
+ if (flash && result) {
+ let flashspot = new Flashspot(area);
+ flashspot.fire();
+ }
+
+ let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
+ invocation.return_value(retval);
+ },
+
+ ScreenshotAreaAsync : function (params, invocation) {
+ let [x, y, width, height, flash, filename, callback] = params;
+ let screenshot = new Shell.Screenshot();
+ screenshot.screenshot_area (x, y, width, height, filename,
+ Lang.bind(this, this._onScreenshotComplete,
+ flash, invocation));
+ },
+
+ ScreenshotWindowAsync : function (params, invocation) {
+ let [include_frame, include_cursor, flash, filename] = params;
+ let screenshot = new Shell.Screenshot();
+ screenshot.screenshot_window (include_frame, include_cursor, filename,
+ Lang.bind(this, this._onScreenshotComplete,
+ flash, invocation));
+ },
+
+ ScreenshotAsync : function (params, invocation) {
+ let [include_cursor, flash, filename] = params;
+ let screenshot = new Shell.Screenshot();
+ screenshot.screenshot(include_cursor, filename,
+ Lang.bind(this, this._onScreenshotComplete,
+ flash, invocation));
+ },
+
+ SelectAreaAsync: function (params, invocation) {
+ let selectArea = new SelectArea();
+ selectArea.show();
+ selectArea.connect('finished', Lang.bind(this,
+ function(selectArea, areaRectangle) {
+ if (areaRectangle) {
+ let retval = GLib.Variant.new('(iiii)',
+ [areaRectangle.x, areaRectangle.y,
+ areaRectangle.width, areaRectangle.height]);
+ invocation.return_value(retval);
+ } else {
+ invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
+ "Operation was cancelled");
+ }
+ }));
+ },
+
+ FlashArea: function(x, y, width, height) {
+ let flashspot = new Flashspot({ x : x, y : y, width: width, height: height});
+ flashspot.fire();
+ }
+});
+
+const SelectArea = new Lang.Class({
+ Name: 'SelectArea',
+
+ _init: function() {
+ this._startX = -1;
+ this._startY = -1;
+ this._lastX = 0;
+ this._lastY = 0;
+
+ this._initRubberbandColors();
+
+ this._group = new St.Widget({ visible: false,
+ reactive: true,
+ x: 0,
+ y: 0 });
+ Main.uiGroup.add_actor(this._group);
+
+ this._group.connect('button-press-event',
+ Lang.bind(this, this._onButtonPress));
+ this._group.connect('button-release-event',
+ Lang.bind(this, this._onButtonRelease));
+ this._group.connect('key-press-event',
+ Lang.bind(this, this._onKeyPress));
+ this._group.connect('motion-event',
+ Lang.bind(this, this._onMotionEvent));
+
+ let constraint = new Clutter.BindConstraint({ source: global.stage,
+ coordinate: Clutter.BindCoordinate.ALL });
+ this._group.add_constraint(constraint);
+
+ this._rubberband = new Clutter.Rectangle({ color: this._background,
+ has_border: true,
+ border_width: 1,
+ border_color: this._border });
+ this._group.add_actor(this._rubberband);
+ },
+
+ show: function() {
+ if (!Main.pushModal(this._group) || this._group.visible)
+ return;
+
+ global.set_cursor(Shell.Cursor.CROSSHAIR);
+ this._group.visible = true;
+ },
+
+ _initRubberbandColors: function() {
+ function colorFromRGBA(rgba) {
+ return new Clutter.Color({ red: rgba.red * 255,
+ green: rgba.green * 255,
+ blue: rgba.blue * 255,
+ alpha: rgba.alpha * 255 });
+ }
+
+ let path = new Gtk.WidgetPath();
+ path.append_type(Gtk.IconView);
+
+ let context = new Gtk.StyleContext();
+ context.set_path(path);
+ context.add_class('rubberband');
+
+ this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
+ this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
+ },
+
+ _getGeometry: function() {
+ return { x: Math.min(this._startX, this._lastX),
+ y: Math.min(this._startY, this._lastY),
+ width: Math.abs(this._startX - this._lastX),
+ height: Math.abs(this._startY - this._lastY) };
+ },
+
+ _onKeyPress: function(actor, event) {
+ if (event.get_key_symbol() == Clutter.Escape)
+ this._destroy(null, false);
+
+ return;
+ },
+
+ _onMotionEvent: function(actor, event) {
+ if (this._startX == -1 || this._startY == -1)
+ return false;
+
+ [this._lastX, this._lastY] = event.get_coords();
+ let geometry = this._getGeometry();
+
+ this._rubberband.set_position(geometry.x, geometry.y);
+ this._rubberband.set_size(geometry.width, geometry.height);
+
+ return false;
+ },
+
+ _onButtonPress: function(actor, event) {
+ [this._startX, this._startY] = event.get_coords();
+ this._rubberband.set_position(this._startX, this._startY);
+
+ return false;
+ },
+
+ _onButtonRelease: function(actor, event) {
+ this._destroy(this._getGeometry(), true);
+ return false;
+ },
+
+ _destroy: function(geometry, fade) {
+ Tweener.addTween(this._group,
+ { opacity: 0,
+ time: fade ? 0.2 : 0,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ Main.popModal(this._group);
+ this._group.destroy();
+ global.unset_cursor();
+
+ this.emit('finished', geometry);
+ })
+ });
+ }
+});
+Signals.addSignalMethods(SelectArea.prototype);
+
+const FLASHSPOT_ANIMATION_TIME = 0.25; // seconds
+
+const Flashspot = new Lang.Class({
+ Name: 'Flashspot',
+ Extends: Lightbox.Lightbox,
+
+ _init: function(area) {
+ this.parent(Main.uiGroup, { inhibitEvents: true,
+ width: area.width,
+ height: area.height });
+
+ this.actor.style_class = 'flashspot';
+ this.actor.set_position(area.x, area.y);
+ },
+
+ fire: function() {
+ this.actor.opacity = 0;
+ Tweener.addTween(this.actor,
+ { opacity: 255,
+ time: FLASHSPOT_ANIMATION_TIME,
+ transition: 'linear',
+ onComplete: Lang.bind(this, this._onFireShowComplete)
+ });
+ this.actor.show();
+ },
+
+ _onFireShowComplete: function() {
+ Tweener.addTween(this.actor,
+ { opacity: 0,
+ time: FLASHSPOT_ANIMATION_TIME,
+ transition: 'linear',
+ onComplete: Lang.bind(this, function() {
+ this.destroy();
+ })
+ });
+ }
+});
diff --git a/js/ui/selectArea.js b/js/ui/selectArea.js
deleted file mode 100644
index b5bbdc74d..000000000
--- a/js/ui/selectArea.js
+++ /dev/null
@@ -1,134 +0,0 @@
-// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-
-const Cairo = imports.cairo;
-const Clutter = imports.gi.Clutter;
-const Gdk = imports.gi.Gdk;
-const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
-const Shell = imports.gi.Shell;
-const Signals = imports.signals;
-const St = imports.gi.St;
-
-const Main = imports.ui.main;
-const Tweener = imports.ui.tweener;
-
-const SelectArea = new Lang.Class({
- Name: 'SelectArea',
-
- _init: function() {
- this._startX = -1;
- this._startY = -1;
- this._lastX = 0;
- this._lastY = 0;
-
- this._initRubberbandColors();
-
- this._group = new St.Widget({ visible: false,
- reactive: true,
- x: 0,
- y: 0 });
- Main.uiGroup.add_actor(this._group);
-
- this._group.connect('button-press-event',
- Lang.bind(this, this._onButtonPress));
- this._group.connect('button-release-event',
- Lang.bind(this, this._onButtonRelease));
- this._group.connect('key-press-event',
- Lang.bind(this, this._onKeyPress));
- this._group.connect('motion-event',
- Lang.bind(this, this._onMotionEvent));
-
- let constraint = new Clutter.BindConstraint({ source: global.stage,
- coordinate: Clutter.BindCoordinate.ALL });
- this._group.add_constraint(constraint);
-
- this._rubberband = new Clutter.Rectangle({ color: this._background,
- has_border: true,
- border_width: 1,
- border_color: this._border });
- this._group.add_actor(this._rubberband);
- },
-
- show: function() {
- if (!Main.pushModal(this._group) || this._group.visible)
- return;
-
- global.set_cursor(Shell.Cursor.CROSSHAIR);
- this._group.visible = true;
- },
-
- _initRubberbandColors: function() {
- function colorFromRGBA(rgba) {
- return new Clutter.Color({ red: rgba.red * 255,
- green: rgba.green * 255,
- blue: rgba.blue * 255,
- alpha: rgba.alpha * 255 });
- }
-
- let path = new Gtk.WidgetPath();
- path.append_type(Gtk.IconView);
-
- let context = new Gtk.StyleContext();
- context.set_path(path);
- context.add_class('rubberband');
-
- this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
- this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
- },
-
- _getGeometry: function() {
- return { x: Math.min(this._startX, this._lastX),
- y: Math.min(this._startY, this._lastY),
- width: Math.abs(this._startX - this._lastX),
- height: Math.abs(this._startY - this._lastY) };
- },
-
- _onKeyPress: function(actor, event) {
- if (event.get_key_symbol() == Clutter.Escape)
- this._destroy(null, false);
-
- return;
- },
-
- _onMotionEvent: function(actor, event) {
- if (this._startX == -1 || this._startY == -1)
- return false;
-
- [this._lastX, this._lastY] = event.get_coords();
- let geometry = this._getGeometry();
-
- this._rubberband.set_position(geometry.x, geometry.y);
- this._rubberband.set_size(geometry.width, geometry.height);
-
- return false;
- },
-
- _onButtonPress: function(actor, event) {
- [this._startX, this._startY] = event.get_coords();
- this._rubberband.set_position(this._startX, this._startY);
-
- return false;
- },
-
- _onButtonRelease: function(actor, event) {
- this._destroy(this._getGeometry(), true);
- return false;
- },
-
- _destroy: function(geometry, fade) {
- Tweener.addTween(this._group,
- { opacity: 0,
- time: fade ? 0.2 : 0,
- transition: 'easeOutQuad',
- onComplete: Lang.bind(this,
- function() {
- Main.popModal(this._group);
- this._group.destroy();
- global.unset_cursor();
-
- this.emit('finished', geometry);
- })
- });
- }
-});
-Signals.addSignalMethods(SelectArea.prototype);
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index f2d91a9ab..97ffe4104 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -9,9 +9,8 @@ const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const ExtensionUtils = imports.misc.extensionUtils;
-const Flashspot = imports.ui.flashspot;
const Main = imports.ui.main;
-const SelectArea = imports.ui.selectArea;
+const Screenshot = imports.ui.screenshot;
const GnomeShellIface =
@@ -19,43 +18,6 @@ const GnomeShellIface =
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -86,6 +48,7 @@ const GnomeShell = new Lang.Class({
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
this._extensionsSerivce = new GnomeShellExtensions();
+ this._screenshotService = new Screenshot.ScreenshotService();
},
/**
@@ -121,108 +84,6 @@ const GnomeShell = new Lang.Class({
return [success, returnValue];
},
- _onScreenshotComplete: function(obj, result, area, filenameUsed, flash, invocation) {
- if (flash && result) {
- let flashspot = new Flashspot.Flashspot(area);
- flashspot.fire();
- }
-
- let retval = GLib.Variant.new('(bs)', [result, filenameUsed]);
- invocation.return_value(retval);
- },
-
- /**
- * ScreenshotArea:
- * @x: The X coordinate of the area
- * @y: The Y coordinate of the area
- * @width: The width of the area
- * @height: The height of the area
- * @flash: Whether to flash the area or not
- * @filename: The filename for the screenshot
- *
- * Takes a screenshot of the passed in area and saves it
- * in @filename as png image, it returns a boolean
- * indicating whether the operation was successful or not.
- * @filename can either be an absolute path or a basename, in
- * which case the screenshot will be saved in the $XDG_PICTURES_DIR
- * or the home directory if it doesn't exist.
- *
- */
- ScreenshotAreaAsync : function (params, invocation) {
- let [x, y, width, height, flash, filename, callback] = params;
- let screenshot = new Shell.Screenshot();
- screenshot.screenshot_area (x, y, width, height, filename,
- Lang.bind(this, this._onScreenshotComplete,
- flash, invocation));
- },
-
- /**
- * ScreenshotWindow:
- * @include_frame: Whether to include the frame or not
- * @include_cursor: Whether to include the cursor image or not
- * @flash: Whether to flash the window area or not
- * @filename: The filename for the screenshot
- *
- * Takes a screenshot of the focused window (optionally omitting the frame)
- * and saves it in @filename as png image, it returns a boolean
- * indicating whether the operation was successful or not.
- * @filename can either be an absolute path or a basename, in
- * which case the screenshot will be saved in the $XDG_PICTURES_DIR
- * or the home directory if it doesn't exist.
- *
- */
- ScreenshotWindowAsync : function (params, invocation) {
- let [include_frame, include_cursor, flash, filename] = params;
- let screenshot = new Shell.Screenshot();
- screenshot.screenshot_window (include_frame, include_cursor, filename,
- Lang.bind(this, this._onScreenshotComplete,
- flash, invocation));
- },
-
- /**
- * Screenshot:
- * @filename: The filename for the screenshot
- * @include_cursor: Whether to include the cursor image or not
- * @flash: Whether to flash the screen or not
- *
- * Takes a screenshot of the whole screen and saves it
- * in @filename as png image, it returns a boolean
- * indicating whether the operation was successful or not.
- * @filename can either be an absolute path or a basename, in
- * which case the screenshot will be saved in the $XDG_PICTURES_DIR
- * or the home directory if it doesn't exist.
- *
- */
- ScreenshotAsync : function (params, invocation) {
- let [include_cursor, flash, filename] = params;
- let screenshot = new Shell.Screenshot();
- screenshot.screenshot(include_cursor, filename,
- Lang.bind(this, this._onScreenshotComplete,
- flash, invocation));
- },
-
- SelectAreaAsync: function (params, invocation) {
- let selectArea = new SelectArea.SelectArea();
- selectArea.show();
- selectArea.connect('finished', Lang.bind(this,
- function(selectArea, areaRectangle) {
- if (areaRectangle) {
- let retval = GLib.Variant.new('(iiii)',
- [areaRectangle.x, areaRectangle.y,
- areaRectangle.width, areaRectangle.height]);
- invocation.return_value(retval);
- } else {
- invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
- "Operation was cancelled");
- }
- }));
- },
-
- FlashArea: function(x, y, width, height) {
- let flashspot = new Flashspot.Flashspot({ x : x, y : y, width: width, height: height});
- flashspot.fire();
- },
-
Mode: global.session_mode,
get OverviewActive() {