Make Dash horizontal
And move it to the bottom of the overview. Change the height-based calculation of the icon sizes to be width-based. Put the DashFader in a vertical box, and make all corners of the Dash equally rounded. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1559>
This commit is contained in:
parent
bd850c3110
commit
97eb4560ef
@ -7,14 +7,10 @@ $dash_border_radius: $modal_radius * 1.5;
|
|||||||
#dash {
|
#dash {
|
||||||
@extend %overview_panel;
|
@extend %overview_panel;
|
||||||
@include fontsize($base_font_size - 2);
|
@include fontsize($base_font_size - 2);
|
||||||
|
margin: $base_margin * 4 $base_margin * 2;
|
||||||
padding: ($dash_spacing / 2) 0;
|
padding: ($dash_spacing / 2) 0;
|
||||||
|
|
||||||
border-radius: 0 $dash_border_radius $dash_border_radius 0;
|
border-radius: $dash_border_radius;
|
||||||
border-left-width: 0;
|
|
||||||
&:rtl {
|
|
||||||
border-radius: $dash_border_radius 0 0 $dash_border_radius;
|
|
||||||
border-right-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder {
|
.placeholder {
|
||||||
// background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
|
// background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
|
||||||
@ -43,7 +39,7 @@ $dash_border_radius: $modal_radius * 1.5;
|
|||||||
color: $osd_fg_color;
|
color: $osd_fg_color;
|
||||||
padding: $base_padding $base_padding + 2px;
|
padding: $base_padding $base_padding + 2px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
-x-offset: $base_margin * 2; // distance from the dash edge
|
-y-offset: $base_margin * 3; // distance from the dash edge
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show apps button
|
// Show apps button
|
||||||
|
@ -105,21 +105,16 @@ class DashItemContainer extends St.Widget {
|
|||||||
|
|
||||||
let [stageX, stageY] = this.get_transformed_position();
|
let [stageX, stageY] = this.get_transformed_position();
|
||||||
|
|
||||||
let itemHeight = this.allocation.y2 - this.allocation.y1;
|
const itemWidth = this.allocation.get_width();
|
||||||
|
|
||||||
let labelHeight = this.label.get_height();
|
const labelWidth = this.label.get_width();
|
||||||
let yOffset = Math.floor((itemHeight - labelHeight) / 2);
|
const xOffset = Math.floor((itemWidth - labelWidth) / 2);
|
||||||
|
const x = Math.clamp(stageX + xOffset, 0, global.stage.width - labelWidth);
|
||||||
let y = stageY + yOffset;
|
|
||||||
|
|
||||||
let node = this.label.get_theme_node();
|
let node = this.label.get_theme_node();
|
||||||
let xOffset = node.get_length('-x-offset');
|
const yOffset = node.get_length('-y-offset');
|
||||||
|
|
||||||
let x;
|
const y = stageY - this.label.height - yOffset;
|
||||||
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
|
|
||||||
x = stageX - this.label.get_width() - xOffset;
|
|
||||||
else
|
|
||||||
x = stageX + this.get_width() + xOffset;
|
|
||||||
|
|
||||||
this.label.set_position(x, y);
|
this.label.set_position(x, y);
|
||||||
this.label.ease({
|
this.label.ease({
|
||||||
@ -283,51 +278,51 @@ class EmptyDropTargetItem extends DashItemContainer {
|
|||||||
var DashActor = GObject.registerClass(
|
var DashActor = GObject.registerClass(
|
||||||
class DashActor extends St.Widget {
|
class DashActor extends St.Widget {
|
||||||
_init() {
|
_init() {
|
||||||
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
|
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL });
|
||||||
super._init({
|
super._init({
|
||||||
name: 'dash',
|
name: 'dash',
|
||||||
layout_manager: layout,
|
layout_manager: layout,
|
||||||
clip_to_allocation: true,
|
clip_to_allocation: true,
|
||||||
y_align: Clutter.ActorAlign.CENTER,
|
x_align: Clutter.ActorAlign.CENTER,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
vfunc_allocate(box) {
|
vfunc_allocate(box) {
|
||||||
let contentBox = this.get_theme_node().get_content_box(box);
|
let contentBox = this.get_theme_node().get_content_box(box);
|
||||||
let availWidth = contentBox.x2 - contentBox.x1;
|
const availHeight = contentBox.get_height();
|
||||||
|
|
||||||
this.set_allocation(box);
|
this.set_allocation(box);
|
||||||
|
|
||||||
let [appIcons, showAppsButton] = this.get_children();
|
let [appIcons, showAppsButton] = this.get_children();
|
||||||
let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
|
const [, showAppsNatWidth] = showAppsButton.get_preferred_width(availHeight);
|
||||||
|
|
||||||
let childBox = new Clutter.ActorBox();
|
let childBox = new Clutter.ActorBox();
|
||||||
childBox.x1 = contentBox.x1;
|
childBox.x1 = contentBox.x1;
|
||||||
childBox.y1 = contentBox.y1;
|
childBox.y1 = contentBox.y1;
|
||||||
childBox.x2 = contentBox.x2;
|
childBox.x2 = contentBox.x2 - showAppsNatWidth;
|
||||||
childBox.y2 = contentBox.y2 - showAppsNatHeight;
|
childBox.y2 = contentBox.y2;
|
||||||
appIcons.allocate(childBox);
|
appIcons.allocate(childBox);
|
||||||
|
|
||||||
childBox.y1 = contentBox.y2 - showAppsNatHeight;
|
childBox.x1 = contentBox.x2 - showAppsNatWidth;
|
||||||
childBox.y2 = contentBox.y2;
|
childBox.x2 = contentBox.x2;
|
||||||
showAppsButton.allocate(childBox);
|
showAppsButton.allocate(childBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
vfunc_get_preferred_height(forWidth) {
|
vfunc_get_preferred_width(forHeight) {
|
||||||
// We want to request the natural height of all our children
|
// We want to request the natural width of all our children
|
||||||
// as our natural height, so we chain up to StWidget (which
|
// as our natural width, so we chain up to StWidget (which
|
||||||
// then calls BoxLayout), but we only request the showApps
|
// then calls BoxLayout), but we only request the showApps
|
||||||
// button as the minimum size
|
// button as the minimum size
|
||||||
|
|
||||||
let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
|
const [, natWidth] = super.vfunc_get_preferred_width(forHeight);
|
||||||
|
|
||||||
let themeNode = this.get_theme_node();
|
let themeNode = this.get_theme_node();
|
||||||
let adjustedForWidth = themeNode.adjust_for_width(forWidth);
|
const adjustedForHeight = themeNode.adjust_for_height(forHeight);
|
||||||
let [, showAppsButton] = this.get_children();
|
let [, showAppsButton] = this.get_children();
|
||||||
let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth);
|
let [minWidth] = showAppsButton.get_preferred_width(adjustedForHeight);
|
||||||
[minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight);
|
[minWidth] = themeNode.adjust_preferred_width(minWidth, natWidth);
|
||||||
|
|
||||||
return [minHeight, natHeight];
|
return [minWidth, natWidth];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -337,7 +332,7 @@ var Dash = GObject.registerClass({
|
|||||||
Signals: { 'icon-size-changed': {} },
|
Signals: { 'icon-size-changed': {} },
|
||||||
}, class Dash extends St.Bin {
|
}, class Dash extends St.Bin {
|
||||||
_init() {
|
_init() {
|
||||||
this._maxHeight = -1;
|
this._maxWidth = -1;
|
||||||
this.iconSize = 64;
|
this.iconSize = 64;
|
||||||
this._shownInitially = false;
|
this._shownInitially = false;
|
||||||
|
|
||||||
@ -349,8 +344,7 @@ var Dash = GObject.registerClass({
|
|||||||
this._labelShowing = false;
|
this._labelShowing = false;
|
||||||
|
|
||||||
this._container = new DashActor();
|
this._container = new DashActor();
|
||||||
this._box = new St.BoxLayout({ vertical: true,
|
this._box = new St.BoxLayout({ clip_to_allocation: true });
|
||||||
clip_to_allocation: true });
|
|
||||||
this._box._delegate = this;
|
this._box._delegate = this;
|
||||||
this._container.add_actor(this._box);
|
this._container.add_actor(this._box);
|
||||||
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
|
||||||
@ -365,10 +359,10 @@ var Dash = GObject.registerClass({
|
|||||||
this._container.add_actor(this._showAppsIcon);
|
this._container.add_actor(this._showAppsIcon);
|
||||||
|
|
||||||
super._init({ child: this._container });
|
super._init({ child: this._container });
|
||||||
this.connect('notify::height', () => {
|
this.connect('notify::width', () => {
|
||||||
if (this._maxHeight != this.height)
|
if (this._maxWidth !== this.width)
|
||||||
this._queueRedisplay();
|
this._queueRedisplay();
|
||||||
this._maxHeight = this.height;
|
this._maxWidth = this.width;
|
||||||
});
|
});
|
||||||
|
|
||||||
this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
|
this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
|
||||||
@ -567,15 +561,18 @@ var Dash = GObject.registerClass({
|
|||||||
|
|
||||||
iconChildren.push(this._showAppsIcon);
|
iconChildren.push(this._showAppsIcon);
|
||||||
|
|
||||||
if (this._maxHeight == -1)
|
if (this._maxWidth === -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let themeNode = this._container.get_theme_node();
|
let themeNode = this._container.get_theme_node();
|
||||||
let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
|
const maxAllocation = new Clutter.ActorBox({
|
||||||
x2: 42 /* whatever */,
|
x1: 0,
|
||||||
y2: this._maxHeight });
|
y1: 0,
|
||||||
|
x2: this._maxWidth,
|
||||||
|
y2: 42, /* whatever */
|
||||||
|
});
|
||||||
let maxContent = themeNode.get_content_box(maxAllocation);
|
let maxContent = themeNode.get_content_box(maxAllocation);
|
||||||
let availHeight = maxContent.y2 - maxContent.y1;
|
let availWidth = maxContent.x2 - maxContent.x1;
|
||||||
let spacing = themeNode.get_length('spacing');
|
let spacing = themeNode.get_length('spacing');
|
||||||
|
|
||||||
let firstButton = iconChildren[0].child;
|
let firstButton = iconChildren[0].child;
|
||||||
@ -583,14 +580,14 @@ var Dash = GObject.registerClass({
|
|||||||
|
|
||||||
// Enforce valid spacings during the size request
|
// Enforce valid spacings during the size request
|
||||||
firstIcon.icon.ensure_style();
|
firstIcon.icon.ensure_style();
|
||||||
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
|
let [, iconWidth] = firstIcon.icon.get_preferred_width(-1);
|
||||||
let [, buttonHeight] = firstButton.get_preferred_height(-1);
|
let [, buttonWidth] = firstButton.get_preferred_width(-1);
|
||||||
|
|
||||||
// Subtract icon padding and box spacing from the available height
|
// Subtract icon padding and box spacing from the available width
|
||||||
availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
|
availWidth -= iconChildren.length * (buttonWidth - iconWidth) +
|
||||||
(iconChildren.length - 1) * spacing;
|
(iconChildren.length - 1) * spacing;
|
||||||
|
|
||||||
let availSize = availHeight / iconChildren.length;
|
let availSize = availWidth / iconChildren.length;
|
||||||
|
|
||||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||||
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
|
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
|
||||||
@ -787,7 +784,7 @@ var Dash = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDragOver(source, actor, x, y, _time) {
|
handleDragOver(source, actor, x, _y, _time) {
|
||||||
let app = getAppFromSource(source);
|
let app = getAppFromSource(source);
|
||||||
|
|
||||||
// Don't allow favoriting of transient apps
|
// Don't allow favoriting of transient apps
|
||||||
@ -804,19 +801,19 @@ var Dash = GObject.registerClass({
|
|||||||
|
|
||||||
let children = this._box.get_children();
|
let children = this._box.get_children();
|
||||||
let numChildren = children.length;
|
let numChildren = children.length;
|
||||||
let boxHeight = this._box.height;
|
let boxWidth = this._box.width;
|
||||||
|
|
||||||
// Keep the placeholder out of the index calculation; assuming that
|
// Keep the placeholder out of the index calculation; assuming that
|
||||||
// the remove target has the same size as "normal" items, we don't
|
// the remove target has the same size as "normal" items, we don't
|
||||||
// need to do the same adjustment there.
|
// need to do the same adjustment there.
|
||||||
if (this._dragPlaceholder) {
|
if (this._dragPlaceholder) {
|
||||||
boxHeight -= this._dragPlaceholder.height;
|
boxWidth -= this._dragPlaceholder.width;
|
||||||
numChildren--;
|
numChildren--;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos;
|
let pos;
|
||||||
if (!this._emptyDropTarget)
|
if (!this._emptyDropTarget)
|
||||||
pos = Math.floor(y * numChildren / boxHeight);
|
pos = Math.floor(x * numChildren / boxWidth);
|
||||||
else
|
else
|
||||||
pos = 0; // always insert at the top when dash is empty
|
pos = 0; // always insert at the top when dash is empty
|
||||||
|
|
||||||
|
@ -339,32 +339,35 @@ class ThumbnailsSlider extends SlidingControl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var DashSlider = GObject.registerClass(
|
var DashFader = GObject.registerClass(
|
||||||
class DashSlider extends SlidingControl {
|
class DashFader extends FaderControl {
|
||||||
_init(dash) {
|
_init(dash) {
|
||||||
super._init({ slideDirection: SlideDirection.LEFT });
|
super._init({
|
||||||
|
y_expand: true,
|
||||||
|
x_expand: true,
|
||||||
|
y_align: Clutter.ActorAlign.END,
|
||||||
|
});
|
||||||
|
|
||||||
this._dash = dash;
|
this._dash = dash;
|
||||||
|
this.add_child(this._dash);
|
||||||
// SlideLayout reads the actor's expand flags to decide
|
|
||||||
// whether to allocate the natural size to its child, or the whole
|
|
||||||
// available allocation
|
|
||||||
this._dash.x_expand = true;
|
|
||||||
|
|
||||||
this.x_expand = true;
|
|
||||||
this.x_align = Clutter.ActorAlign.START;
|
|
||||||
this.y_expand = true;
|
|
||||||
|
|
||||||
this.add_actor(this._dash);
|
|
||||||
|
|
||||||
this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSlide() {
|
vfunc_allocate(box) {
|
||||||
if (this._visible || this._inDrag)
|
this.set_allocation(box);
|
||||||
return 1;
|
|
||||||
else
|
box = this.get_theme_node().get_content_box(box);
|
||||||
return 0;
|
|
||||||
|
const availWidth = Math.round(box.get_width());
|
||||||
|
const availHeight = Math.round(box.get_height());
|
||||||
|
const [, natHeight] = this._dash.get_preferred_height(availWidth);
|
||||||
|
|
||||||
|
const actorBox = new Clutter.ActorBox();
|
||||||
|
actorBox.x1 = box.x1;
|
||||||
|
actorBox.x2 = actorBox.x1 + availWidth;
|
||||||
|
actorBox.y1 = box.y1;
|
||||||
|
actorBox.y2 = actorBox.y1 + (this._dash.y_expand ? availHeight : natHeight);
|
||||||
|
|
||||||
|
this._dash.allocate(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWindowDragBegin() {
|
_onWindowDragBegin() {
|
||||||
@ -412,8 +415,8 @@ class ControlsManager extends St.Widget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.dash = new Dash.Dash();
|
this.dash = new Dash.Dash();
|
||||||
this._dashSlider = new DashSlider(this.dash);
|
this._dashFader = new DashFader(this.dash);
|
||||||
this._dashSpacer = new DashSpacer(this._dashSlider);
|
this._dashSpacer = new DashSpacer(this._dashFader);
|
||||||
|
|
||||||
let workspaceManager = global.workspace_manager;
|
let workspaceManager = global.workspace_manager;
|
||||||
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
|
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
|
||||||
@ -441,15 +444,25 @@ class ControlsManager extends St.Widget {
|
|||||||
this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
|
this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
|
||||||
this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
|
this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
|
||||||
|
|
||||||
this._group = new St.BoxLayout({ name: 'overview-group',
|
this._group = new St.BoxLayout({
|
||||||
x_expand: true, y_expand: true });
|
name: 'overview-group',
|
||||||
|
vertical: true,
|
||||||
|
x_expand: true,
|
||||||
|
y_expand: true,
|
||||||
|
});
|
||||||
this.add_actor(this._group);
|
this.add_actor(this._group);
|
||||||
|
|
||||||
this.add_actor(this._dashSlider);
|
this.add_actor(this._dashFader);
|
||||||
|
|
||||||
|
const box = new St.BoxLayout({
|
||||||
|
x_expand: true,
|
||||||
|
y_expand: true,
|
||||||
|
});
|
||||||
|
box.add_child(this.viewSelector);
|
||||||
|
box.add_child(this._thumbnailsSlider);
|
||||||
|
|
||||||
|
this._group.add_child(box);
|
||||||
this._group.add_actor(this._dashSpacer);
|
this._group.add_actor(this._dashSpacer);
|
||||||
this._group.add_child(this.viewSelector);
|
|
||||||
this._group.add_actor(this._thumbnailsSlider);
|
|
||||||
|
|
||||||
this.connect('destroy', this._onDestroy.bind(this));
|
this.connect('destroy', this._onDestroy.bind(this));
|
||||||
}
|
}
|
||||||
@ -481,15 +494,8 @@ class ControlsManager extends St.Widget {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
let activePage = this.viewSelector.getActivePage();
|
let activePage = this.viewSelector.getActivePage();
|
||||||
let dashVisible = activePage == ViewSelector.ViewPage.WINDOWS ||
|
|
||||||
activePage == ViewSelector.ViewPage.APPS;
|
|
||||||
let thumbnailsVisible = activePage == ViewSelector.ViewPage.WINDOWS;
|
let thumbnailsVisible = activePage == ViewSelector.ViewPage.WINDOWS;
|
||||||
|
|
||||||
if (dashVisible)
|
|
||||||
this._dashSlider.slideIn();
|
|
||||||
else
|
|
||||||
this._dashSlider.slideOut();
|
|
||||||
|
|
||||||
if (thumbnailsVisible)
|
if (thumbnailsVisible)
|
||||||
this._thumbnailsSlider.slideIn();
|
this._thumbnailsSlider.slideIn();
|
||||||
else
|
else
|
||||||
@ -497,7 +503,6 @@ class ControlsManager extends St.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onPageEmpty() {
|
_onPageEmpty() {
|
||||||
this._dashSlider.pageEmpty();
|
|
||||||
this._thumbnailsSlider.pageEmpty();
|
this._thumbnailsSlider.pageEmpty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user