[gnome-shell] Scroll wheel should zoom windows in the overview
- From: Dan Winship <danw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell] Scroll wheel should zoom windows in the overview
- Date: Tue, 8 Sep 2009 21:37:43 +0000 (UTC)
commit 4b727ef40d347ec8770d1cd1ec858f2a068eec98
Author: Dan Winship <danw gnome org>
Date: Fri Sep 4 15:25:17 2009 -0400
Scroll wheel should zoom windows in the overview
Allow using the scroll wheel to zoom in on windows in the overview.
Original patch from JP St. Pierre.
http://bugzilla.gnome.org/show_bug.cgi?id=591849
js/ui/workspaces.js | 151 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 147 insertions(+), 4 deletions(-)
---
diff --git a/js/ui/workspaces.js b/js/ui/workspaces.js
index 2a1b2ed..c6c9a9a 100644
--- a/js/ui/workspaces.js
+++ b/js/ui/workspaces.js
@@ -28,6 +28,10 @@ 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
// unless we have a really good algorithm.
@@ -42,6 +46,15 @@ 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.
@@ -50,6 +63,39 @@ 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);
}
@@ -71,6 +117,9 @@ WindowClone.prototype = {
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',
@@ -131,12 +180,106 @@ WindowClone.prototype = {
return;
this._havePointer = false;
+ this._updateTitle();
- if (Tweener.isTweening(this.actor))
- return;
+ if (this._zoomStep)
+ this._zoomEnd();
+ },
- actor.raise(this.stackAbove);
- this._updateTitle();
+ _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 () {
+ let global = Shell.Global.get();
+
+ [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 () {
+ let global = Shell.Global.get();
+ 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) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]