[gnome-shell] windowPreviews: Replace border with scale effect
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] windowPreviews: Replace border with scale effect
- Date: Tue, 2 Feb 2021 12:24:39 +0000 (UTC)
commit 30f27412c2274abd857aeebffc8eea66675144cb
Author: Florian Müllner <fmuellner gnome org>
Date: Fri Jan 8 13:27:10 2021 +0100
windowPreviews: Replace border with scale effect
We currently use a thick border to indicate the hovered/focused preview. It
works well for that purpose, but is a bit in the face. Slightly scaling up
the preview still provides a clear indication, but in a more subtle and
elegant way.
https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/81
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1605>
.../gnome-shell-sass/widgets/_window-picker.scss | 16 ---
js/ui/windowPreview.js | 122 +++++++++++----------
2 files changed, 62 insertions(+), 76 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_window-picker.scss
b/data/theme/gnome-shell-sass/widgets/_window-picker.scss
index 4cf3e12e2f..a39af155fb 100644
--- a/data/theme/gnome-shell-sass/widgets/_window-picker.scss
+++ b/data/theme/gnome-shell-sass/widgets/_window-picker.scss
@@ -3,31 +3,15 @@
$window_picker_spacing: $base_spacing; // 6px
$window_picker_padding: $base_padding * 2; // 12px
-$window_thumbnail_border_color:transparentize($selected_fg_color, 0.65);
-
$window_close_button_size: 24px;
$window_close_button_padding: 3px;
-$window_clone_border_size: 6px;
-
// Window picker
.window-picker {
// Space between window thumbnails
spacing: $window_picker_spacing;
}
-// Borders on window thumbnails
-.window-clone-border {
- border-width: $window_clone_border_size;
- border-style: solid;
- border-color: $window_thumbnail_border_color;
- border-radius: $base_border_radius + 2;
- // For window decorations with round corners we can't match
- // the exact shape when the window is scaled. So apply a shadow
- // to fix that case
- box-shadow: inset 0 0 0 1px transparentize($borders_color, 0.8);
-}
-
// Window titles
.window-caption {
color: $osd_fg_color;
diff --git a/js/ui/windowPreview.js b/js/ui/windowPreview.js
index e860f06471..3c12b4708d 100644
--- a/js/ui/windowPreview.js
+++ b/js/ui/windowPreview.js
@@ -11,6 +11,9 @@ var WINDOW_DND_SIZE = 256;
var WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
var WINDOW_OVERLAY_FADE_TIME = 200;
+var WINDOW_SCALE_TIME = 200;
+var WINDOW_ACTIVE_SCALE = 1.02;
+
var DRAGGING_WINDOW_OPACITY = 100;
const ICON_SIZE = 64;
@@ -220,7 +223,11 @@ var WindowPreview = GObject.registerClass({
offscreen_redirect: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY,
});
- this._windowContainer = new Clutter.Actor();
+ this._windowContainer = new Clutter.Actor({
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ });
+ this._windowContainer.connect('notify::scale-x',
+ () => this._adjustOverlayOffsets());
// gjs currently can't handle setting an actors layout manager during
// the initialization of the actor if that layout manager keeps track
// of its container, so set the layout manager after creating the
@@ -282,34 +289,6 @@ var WindowPreview = GObject.registerClass({
this._closeRequested = false;
this._idleHideOverlayId = 0;
- this._border = new St.Widget({
- visible: false,
- style_class: 'window-clone-border',
- });
- this._borderConstraint = new Clutter.BindConstraint({
- source: this._windowContainer,
- coordinate: Clutter.BindCoordinate.SIZE,
- });
- this._border.add_constraint(this._borderConstraint);
- this._border.add_constraint(new Clutter.AlignConstraint({
- source: this._windowContainer,
- align_axis: Clutter.AlignAxis.BOTH,
- factor: 0.5,
- }));
- this._borderCenter = new Clutter.Actor();
- this._borderCenterConstraint = new Clutter.BindConstraint({
- source: this._windowContainer,
- coordinate: Clutter.BindCoordinate.SIZE,
- });
- this._borderCenter.add_constraint(this._borderCenterConstraint);
- this._borderCenter.add_constraint(new Clutter.AlignConstraint({
- source: this._windowContainer,
- align_axis: Clutter.AlignAxis.BOTH,
- factor: 0.5,
- }));
- this._border.connect('style-changed',
- this._onBorderStyleChanged.bind(this));
-
const tracker = Shell.WindowTracker.get_default();
const app = tracker.get_window_app(this.metaWindow);
this._icon = app.create_icon_texture(ICON_SIZE);
@@ -319,16 +298,16 @@ var WindowPreview = GObject.registerClass({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
});
this._icon.add_constraint(new Clutter.BindConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._icon.add_constraint(new Clutter.AlignConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
factor: 0.5,
}));
this._icon.add_constraint(new Clutter.AlignConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }),
factor: 1,
@@ -378,25 +357,23 @@ var WindowPreview = GObject.registerClass({
child: new St.Icon({ icon_name: 'window-close-symbolic' }),
});
this._closeButton.add_constraint(new Clutter.BindConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._closeButton.add_constraint(new Clutter.AlignConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
pivot_point: new Graphene.Point({ x: 0.5, y: -1 }),
factor: this._closeButtonSide === St.Side.LEFT ? 0 : 1,
}));
this._closeButton.add_constraint(new Clutter.AlignConstraint({
- source: this._borderCenter,
+ source: this._windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: 0.5 }),
factor: 0,
}));
this._closeButton.connect('clicked', () => this._deleteAll());
- this.add_child(this._borderCenter);
- this.add_child(this._border);
this.add_child(this._title);
this.add_child(this._icon);
this.add_child(this._closeButton);
@@ -405,7 +382,6 @@ var WindowPreview = GObject.registerClass({
if (!this.realized)
return;
- this._border.ensure_style();
this._title.ensure_style();
this._icon.ensure_style();
});
@@ -438,16 +414,6 @@ var WindowPreview = GObject.registerClass({
child.allocate_available_size(0, 0, box.get_width(), box.get_height());
}
- _onBorderStyleChanged() {
- let borderNode = this._border.get_theme_node();
- this._borderSize = borderNode.get_border_width(St.Side.TOP);
-
- // Increase the size of the border actor so the border outlines
- // the bounding box
- this._borderConstraint.offset = this._borderSize * 2;
- this._borderCenterConstraint.offset = this._borderSize;
- }
-
_windowCanClose() {
return this.metaWindow.can_close() &&
!this._hasAttachedDialogs();
@@ -475,9 +441,8 @@ var WindowPreview = GObject.registerClass({
const [, closeButtonHeight] = this._closeButton.get_preferred_height(-1);
const [, iconHeight] = this._icon.get_preferred_height(-1);
- const topOversize = this._borderSize / 2 + closeButtonHeight / 2;
- const bottomOversize =
- this._borderSize / 2 + (1 - ICON_OVERLAP) * iconHeight;
+ const topOversize = closeButtonHeight / 2;
+ const bottomOversize = (1 - ICON_OVERLAP) * iconHeight;
return [topOversize, bottomOversize];
}
@@ -486,11 +451,11 @@ var WindowPreview = GObject.registerClass({
const [, closeButtonWidth] = this._closeButton.get_preferred_width(-1);
const leftOversize = this._closeButtonSide === St.Side.LEFT
- ? (this._borderSize / 2) + (closeButtonWidth / 2)
- : this._borderSize;
+ ? closeButtonWidth / 2
+ : 0;
const rightOversize = this._closeButtonSide === St.Side.LEFT
- ? this._borderSize
- : (this._borderSize / 2) + (closeButtonWidth / 2);
+ ? 0
+ : closeButtonWidth / 2;
return [leftOversize, rightOversize];
}
@@ -507,15 +472,15 @@ var WindowPreview = GObject.registerClass({
// If we're supposed to animate and an animation in our direction
// is already happening, let that one continue
- const ongoingTransition = this._border.get_transition('opacity');
+ const ongoingTransition = this._title.get_transition('opacity');
if (animate &&
ongoingTransition &&
ongoingTransition.get_interval().peek_final_value() === 255)
return;
const toShow = this._windowCanClose()
- ? [this._border, this._title, this._closeButton]
- : [this._border, this._title];
+ ? [this._title, this._closeButton]
+ : [this._title];
toShow.forEach(a => {
a.opacity = 0;
@@ -527,6 +492,13 @@ var WindowPreview = GObject.registerClass({
});
});
+ this._windowContainer.ease({
+ scale_x: WINDOW_ACTIVE_SCALE,
+ scale_y: WINDOW_ACTIVE_SCALE,
+ duration: animate ? WINDOW_SCALE_TIME : 0,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+
this.emit('show-chrome');
}
@@ -539,13 +511,13 @@ var WindowPreview = GObject.registerClass({
// If we're supposed to animate and an animation in our direction
// is already happening, let that one continue
- const ongoingTransition = this._border.get_transition('opacity');
+ const ongoingTransition = this._title.get_transition('opacity');
if (animate &&
ongoingTransition &&
ongoingTransition.get_interval().peek_final_value() === 0)
return;
- [this._border, this._title, this._closeButton].forEach(a => {
+ [this._title, this._closeButton].forEach(a => {
a.opacity = 255;
a.ease({
opacity: 0,
@@ -554,6 +526,36 @@ var WindowPreview = GObject.registerClass({
onComplete: () => a.hide(),
});
});
+
+ this._windowContainer.ease({
+ scale_x: 1,
+ scale_y: 1,
+ duration: animate ? WINDOW_SCALE_TIME : 0,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ }
+
+ _adjustOverlayOffsets() {
+ // Assume that scale-x and scale-y update always set
+ // in lock-step; that allows us to not use separate
+ // handlers for horizontal and vertical offsets
+ const previewScale = this._windowContainer.scale_x;
+ const [previewWidth, previewHeight] =
+ this._windowContainer.allocation.get_size();
+
+ const heightIncrease =
+ Math.floor(previewHeight * (previewScale - 1) / 2);
+ const widthIncrease =
+ Math.floor(previewWidth * (previewScale - 1) / 2);
+
+ const closeAlign = this._closeButtonSide === St.Side.LEFT ? -1 : 1;
+
+ this._icon.translation_y = heightIncrease;
+ this._title.translation_y = heightIncrease;
+ this._closeButton.set({
+ translation_x: closeAlign * widthIncrease,
+ translation_y: -heightIncrease,
+ });
}
_addWindow(metaWindow) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]