[gnome-shell] Add a SelectArea() DBus method
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Add a SelectArea() DBus method
- Date: Thu, 3 Jan 2013 11:57:45 +0000 (UTC)
commit dd19459e183d8bb99ac1f6ca230dd4834983031f
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Thu Nov 8 20:19:19 2012 -0500
Add a SelectArea() DBus method
This will be useful for e.g. selecting an area for a screenshot.
https://bugzilla.gnome.org/show_bug.cgi?id=687954
js/Makefile.am | 1 +
js/ui/selectArea.js | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++
js/ui/shellDBus.js | 24 +++++++++
src/shell-global.c | 6 ++
src/shell-global.h | 3 +-
5 files changed, 167 insertions(+), 1 deletions(-)
---
diff --git a/js/Makefile.am b/js/Makefile.am
index d5d8047..7606f32 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -78,6 +78,7 @@ nobase_dist_js_DATA = \
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/selectArea.js b/js/ui/selectArea.js
new file mode 100644
index 0000000..b5bbdc7
--- /dev/null
+++ b/js/ui/selectArea.js
@@ -0,0 +1,134 @@
+// -*- 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 6b88baf..1eba296 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -11,6 +11,7 @@ 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 GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
@@ -40,6 +41,12 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
+<method name="SelectArea">
+ <arg type="i" direction="out" name="x"/>
+ <arg type="i" direction="out" name="y"/>
+ <arg type="i" direction="out" name="width"/>
+ <arg type="i" direction="out" name="height"/>
+</method>
<method name="FlashArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
@@ -182,6 +189,23 @@ const GnomeShell = new Lang.Class({
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();
diff --git a/src/shell-global.c b/src/shell-global.c
index b7198a9..10b1fc1 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -616,6 +616,9 @@ shell_global_set_cursor (ShellGlobal *global,
case SHELL_CURSOR_POINTING_HAND:
name = "hand";
break;
+ case SHELL_CURSOR_CROSSHAIR:
+ name = "crosshair";
+ break;
default:
g_return_if_reached ();
}
@@ -638,6 +641,9 @@ shell_global_set_cursor (ShellGlobal *global,
case SHELL_CURSOR_POINTING_HAND:
cursor_type = GDK_HAND2;
break;
+ case SHELL_CURSOR_CROSSHAIR:
+ cursor_type = GDK_CROSSHAIR;
+ break;
case SHELL_CURSOR_DND_UNSUPPORTED_TARGET:
cursor_type = GDK_X_CURSOR;
break;
diff --git a/src/shell-global.h b/src/shell-global.h
index 95c18e0..7c14892 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -63,7 +63,8 @@ typedef enum {
SHELL_CURSOR_DND_UNSUPPORTED_TARGET,
SHELL_CURSOR_DND_MOVE,
SHELL_CURSOR_DND_COPY,
- SHELL_CURSOR_POINTING_HAND
+ SHELL_CURSOR_POINTING_HAND,
+ SHELL_CURSOR_CROSSHAIR
} ShellCursor;
void shell_global_set_cursor (ShellGlobal *global,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]