feat(ags): implement overview into shell
This commit is contained in:
parent
f2bdcffe3f
commit
d82b3cb765
7 changed files with 184 additions and 170 deletions
|
@ -26,6 +26,7 @@ export default {
|
||||||
'notification-center': 500,
|
'notification-center': 500,
|
||||||
'calendar': 500,
|
'calendar': 500,
|
||||||
'powermenu': 500,
|
'powermenu': 500,
|
||||||
|
'overview': 500,
|
||||||
},
|
},
|
||||||
windows: [
|
windows: [
|
||||||
Powermenu,
|
Powermenu,
|
||||||
|
|
|
@ -4,14 +4,26 @@ const { closeWindow, openWindow } = ags.App;
|
||||||
export const PopUp = ({name, child, transition = 'slide_down', ...params}) => Revealer({
|
export const PopUp = ({name, child, transition = 'slide_down', ...params}) => Revealer({
|
||||||
...params,
|
...params,
|
||||||
// FIXME: popups don't work with revealers
|
// FIXME: popups don't work with revealers
|
||||||
setup: () => setTimeout(() => closeWindow(name), 100),
|
setup: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
closeWindow(name);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// my eyes hurt
|
||||||
|
if (name == 'overview') {
|
||||||
|
setTimeout(() => {
|
||||||
|
openWindow(name);
|
||||||
|
closeWindow(name);
|
||||||
|
}, 700);
|
||||||
|
}
|
||||||
|
},
|
||||||
transition,
|
transition,
|
||||||
transitionDuration: 500,
|
transitionDuration: 500,
|
||||||
connections: [[ags.App, (revealer, currentName, visible) => {
|
connections: [[ags.App, (revealer, currentName, visible) => {
|
||||||
if (currentName === name) {
|
if (currentName === name) {
|
||||||
revealer.reveal_child = visible;
|
revealer.reveal_child = visible;
|
||||||
|
|
||||||
if (visible)
|
if (visible && name !== 'overview')
|
||||||
openWindow('closer');
|
openWindow('closer');
|
||||||
}
|
}
|
||||||
}]],
|
}]],
|
||||||
|
|
|
@ -3,6 +3,7 @@ const { Hyprland, Applications } = ags.Service;
|
||||||
const { Gtk } = imports.gi;
|
const { Gtk } = imports.gi;
|
||||||
|
|
||||||
import { EventBox } from '../misc/cursorbox.js';
|
import { EventBox } from '../misc/cursorbox.js';
|
||||||
|
import { PopUp } from '../misc/popup.js';
|
||||||
|
|
||||||
const SCALE = 0.11;
|
const SCALE = 0.11;
|
||||||
const MARGIN = 8;
|
const MARGIN = 8;
|
||||||
|
@ -17,166 +18,159 @@ const DEFAULT_SPECIAL = {
|
||||||
POS_Y: 170,
|
POS_Y: 170,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const WorkspaceRow = className => CenterBox({
|
||||||
|
children: [ null, Box({ className: className }), null ],
|
||||||
|
});
|
||||||
|
|
||||||
|
const OverviewWidget = Box({
|
||||||
|
className: 'overview',
|
||||||
|
vertical: true,
|
||||||
|
children: [
|
||||||
|
WorkspaceRow('normal'),
|
||||||
|
WorkspaceRow('special'),
|
||||||
|
],
|
||||||
|
connections: [
|
||||||
|
[Hyprland, box => {
|
||||||
|
let childI = 0;
|
||||||
|
box._workspaces = [].concat(box.children[childI++].centerWidget.children,
|
||||||
|
box.children[childI].centerWidget.children)
|
||||||
|
.sort((a, b) => a._id - b._id);
|
||||||
|
box._updateWs(box);
|
||||||
|
box._updateApps(box);
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
properties: [
|
||||||
|
['workspaces'],
|
||||||
|
|
||||||
|
['updateApps', box => {
|
||||||
|
ags.Utils.execAsync('hyprctl clients -j')
|
||||||
|
.then(result => {
|
||||||
|
let clients = JSON.parse(result).filter(client => client.class)
|
||||||
|
|
||||||
|
box._workspaces.forEach(workspace => {
|
||||||
|
let fixed = workspace.child.child.children[0];
|
||||||
|
let toRemove = fixed.get_children();
|
||||||
|
|
||||||
|
clients.filter(app => app.workspace.id == workspace._id).forEach(app => {
|
||||||
|
let active = '';
|
||||||
|
if (app.address == Hyprland.active.client.address) {
|
||||||
|
active = 'active';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special workspaces that haven't been opened yet
|
||||||
|
// return a size of 0. We need to set them to default
|
||||||
|
// values to show the workspace properly
|
||||||
|
if (app.size[0] === 0) {
|
||||||
|
app.size[0] = DEFAULT_SPECIAL.SIZE_X;
|
||||||
|
app.size[1] = DEFAULT_SPECIAL.SIZE_Y;
|
||||||
|
app.at[0] = DEFAULT_SPECIAL.POS_X;
|
||||||
|
app.at[1] = DEFAULT_SPECIAL.POS_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let existingApp = fixed.get_children().find(ch => ch._address == app.address);
|
||||||
|
toRemove.splice(toRemove.indexOf(existingApp), 1);
|
||||||
|
|
||||||
|
if (existingApp) {
|
||||||
|
fixed.move(
|
||||||
|
existingApp,
|
||||||
|
app.at[0] * SCALE,
|
||||||
|
app.at[1] * SCALE,
|
||||||
|
);
|
||||||
|
existingApp.child.className = `window ${active}`;
|
||||||
|
existingApp.child.style = `min-width: ${app.size[0] * SCALE - MARGIN}px;
|
||||||
|
min-height: ${app.size[1] * SCALE - MARGIN}px;
|
||||||
|
font-size: ${Math.min(app.size[0] * SCALE - MARGIN,
|
||||||
|
app.size[1] * SCALE - MARGIN) - 5}px;`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fixed.put(
|
||||||
|
Revealer({
|
||||||
|
transition: 'slide_right',
|
||||||
|
connections: [[Hyprland, rev => {
|
||||||
|
rev.revealChild = true;
|
||||||
|
}]],
|
||||||
|
properties: [
|
||||||
|
['address', app.address],
|
||||||
|
['toDestroy', false]
|
||||||
|
],
|
||||||
|
child: Icon({
|
||||||
|
className: `window ${active}`,
|
||||||
|
style: `min-width: ${app.size[0] * SCALE - MARGIN}px;
|
||||||
|
min-height: ${app.size[1] * SCALE - MARGIN}px;
|
||||||
|
font-size: ${Math.min(app.size[0] * SCALE - MARGIN,
|
||||||
|
app.size[1] * SCALE - MARGIN) * 0.8}px;`,
|
||||||
|
icon: app.class,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
app.at[0] * SCALE,
|
||||||
|
app.at[1] * SCALE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fixed.show_all();
|
||||||
|
toRemove.forEach(ch => {
|
||||||
|
if (ch._toDestroy) {
|
||||||
|
ch.destroy();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ch.revealChild = false;
|
||||||
|
ch._toDestroy = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).catch(print);
|
||||||
|
}],
|
||||||
|
|
||||||
|
['updateWs', box => {
|
||||||
|
Hyprland.workspaces.forEach(ws => {
|
||||||
|
let currentWs = box._workspaces.find(ch => ch._id == ws.id);
|
||||||
|
if (!currentWs) {
|
||||||
|
var childI = 0;
|
||||||
|
if (ws.id < 0) {
|
||||||
|
childI = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWs = Revealer({
|
||||||
|
transition: 'slide_right',
|
||||||
|
properties: [
|
||||||
|
['id', ws.id],
|
||||||
|
],
|
||||||
|
connections: [[Hyprland, box => {
|
||||||
|
let active = Hyprland.active.workspace.id === box._id;
|
||||||
|
box.child.child.toggleClassName('active', active);
|
||||||
|
box.revealChild = Hyprland.getWorkspace(box._id)?.windows > 0 || active;
|
||||||
|
}]],
|
||||||
|
child: EventBox({
|
||||||
|
tooltipText: `Workspace: ${ws.id}`,
|
||||||
|
child: Box({
|
||||||
|
className: 'workspace',
|
||||||
|
style: `min-width: ${SCREEN.X * SCALE}px;
|
||||||
|
min-height: ${SCREEN.Y * SCALE}px;`,
|
||||||
|
child: ags.Widget({
|
||||||
|
type: Gtk.Fixed,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
box.children[childI].centerWidget.add(currentWs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
box.show_all();
|
||||||
|
|
||||||
|
// Make sure the order is correct
|
||||||
|
box._workspaces.forEach((workspace, i) => {
|
||||||
|
workspace.get_parent().reorder_child(workspace, i)
|
||||||
|
});
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
export const Overview = Window({
|
export const Overview = Window({
|
||||||
name: 'overview',
|
name: 'overview',
|
||||||
layer: 'overlay',
|
layer: 'overlay',
|
||||||
popup: true,
|
child: PopUp({
|
||||||
anchor: 'top',
|
name: 'overview',
|
||||||
margin: [ 0, 0, 0, 0 ],
|
transition: 'crossfade',
|
||||||
child: Box({
|
child: OverviewWidget,
|
||||||
className: 'overview',
|
|
||||||
vertical: true,
|
|
||||||
children: [
|
|
||||||
CenterBox({
|
|
||||||
children: [
|
|
||||||
null,
|
|
||||||
Box({
|
|
||||||
className: 'normal',
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
CenterBox({
|
|
||||||
children: [
|
|
||||||
null,
|
|
||||||
Box({
|
|
||||||
className: 'special',
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
connections: [
|
|
||||||
[Hyprland, box => {
|
|
||||||
let childI = 0;
|
|
||||||
box._workspaces = [].concat(box.children[childI++].centerWidget.children,
|
|
||||||
box.children[childI].centerWidget.children)
|
|
||||||
.sort((a, b) => a._id - b._id);
|
|
||||||
|
|
||||||
box._updateWs(box);
|
|
||||||
box._updateApps(box);
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
properties: [
|
|
||||||
['workspaces'],
|
|
||||||
|
|
||||||
['updateApps', box => {
|
|
||||||
ags.Utils.execAsync('hyprctl clients -j')
|
|
||||||
.then(result => {
|
|
||||||
let clients = JSON.parse(result).filter(client => client.class)
|
|
||||||
|
|
||||||
box._workspaces.forEach(workspace => {
|
|
||||||
let fixed = workspace.child.child.children[0];
|
|
||||||
let toRemove = fixed.get_children();
|
|
||||||
|
|
||||||
clients.filter(app => app.workspace.id == workspace._id).forEach(app => {
|
|
||||||
let active = '';
|
|
||||||
if (app.address == Hyprland.active.client.address) {
|
|
||||||
active = 'active';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special workspaces that haven't been opened yet
|
|
||||||
// return a size of 0. We need to set them to default
|
|
||||||
// values to show the workspace properly
|
|
||||||
if (app.size[0] === 0) {
|
|
||||||
app.size[0] = DEFAULT_SPECIAL.SIZE_X;
|
|
||||||
app.size[1] = DEFAULT_SPECIAL.SIZE_Y;
|
|
||||||
app.at[0] = DEFAULT_SPECIAL.POS_X;
|
|
||||||
app.at[1] = DEFAULT_SPECIAL.POS_Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
let existingApp = fixed.get_children().find(ch => ch._address == app.address);
|
|
||||||
toRemove.splice(toRemove.indexOf(existingApp), 1);
|
|
||||||
|
|
||||||
if (existingApp) {
|
|
||||||
fixed.move(
|
|
||||||
existingApp,
|
|
||||||
app.at[0] * SCALE,
|
|
||||||
app.at[1] * SCALE,
|
|
||||||
);
|
|
||||||
existingApp.child.className = `window ${active}`;
|
|
||||||
existingApp.child.style = `min-width: ${app.size[0] * SCALE - MARGIN}px;
|
|
||||||
min-height: ${app.size[1] * SCALE - MARGIN}px;`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fixed.put(
|
|
||||||
Revealer({
|
|
||||||
transition: 'slide_right',
|
|
||||||
connections: [[Hyprland, rev => {
|
|
||||||
rev.revealChild = true;
|
|
||||||
}]],
|
|
||||||
properties: [
|
|
||||||
['address', app.address],
|
|
||||||
['toDestroy', false]
|
|
||||||
],
|
|
||||||
child: Icon({
|
|
||||||
className: `window ${active}`,
|
|
||||||
style: `min-width: ${app.size[0] * SCALE - MARGIN}px;
|
|
||||||
min-height: ${app.size[1] * SCALE - MARGIN}px;`,
|
|
||||||
icon: app.class,
|
|
||||||
size: 40,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
app.at[0] * SCALE,
|
|
||||||
app.at[1] * SCALE,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fixed.show_all();
|
|
||||||
toRemove.forEach(ch => {
|
|
||||||
if (ch._toDestroy) {
|
|
||||||
ch.destroy();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ch.revealChild = false;
|
|
||||||
ch._toDestroy = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).catch(print);
|
|
||||||
}],
|
|
||||||
|
|
||||||
['updateWs', box => {
|
|
||||||
Hyprland.workspaces.forEach(ws => {
|
|
||||||
let currentWs = box._workspaces.find(ch => ch._id == ws.id)
|
|
||||||
if (!currentWs) {
|
|
||||||
var childI = 0;
|
|
||||||
if (ws.id < 0) {
|
|
||||||
childI = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentWs = Revealer({
|
|
||||||
transition: 'slide_right',
|
|
||||||
properties: [
|
|
||||||
['id', ws.id],
|
|
||||||
],
|
|
||||||
connections: [[Hyprland, box => {
|
|
||||||
let active = Hyprland.active.workspace.id === box._id;
|
|
||||||
box.child.child.toggleClassName('active', active);
|
|
||||||
box.revealChild = Hyprland.getWorkspace(box._id)?.windows > 0 || active;
|
|
||||||
}]],
|
|
||||||
child: EventBox({
|
|
||||||
tooltipText: `Workspace: ${ws.id}`,
|
|
||||||
child: Box({
|
|
||||||
className: 'workspace',
|
|
||||||
style: `min-width: ${SCREEN.X * SCALE}px;
|
|
||||||
min-height: ${SCREEN.Y * SCALE}px;`,
|
|
||||||
child: ags.Widget({
|
|
||||||
type: Gtk.Fixed,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
box.children[childI].centerWidget.add(currentWs);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
box.show_all();
|
|
||||||
|
|
||||||
// Make sure the order is correct
|
|
||||||
box._workspaces.forEach((workspace, i) => {
|
|
||||||
workspace.get_parent().reorder_child(workspace, i)
|
|
||||||
});
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
.overview {
|
.overview {
|
||||||
|
background-color: $bg;
|
||||||
|
border-radius: 30px;
|
||||||
|
border: 2px solid $contrastbg;
|
||||||
|
padding: 10px;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
min-width: 1px;
|
min-width: 1px;
|
||||||
|
|
||||||
.workspace {
|
.workspace {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
|
transition: border-color 0.2s ease-in-out;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
|
@ -17,7 +22,8 @@
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
transition: min-width 0.2s ease-in-out,
|
transition: min-width 0.2s ease-in-out,
|
||||||
min-height 0.2s ease-in-out,
|
min-height 0.2s ease-in-out,
|
||||||
border-color 0.2s ease-in-out;
|
border-color 0.2s ease-in-out,
|
||||||
|
font-size 0.2s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.normal {
|
.normal {
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
padding: 0px 0px 0px 0px;
|
padding: 0px 0px 0px 0px;
|
||||||
background-color: $bg;
|
background-color: $bg;
|
||||||
border-top-right-radius: 0px;
|
border-radius: 30px 0 30px 30px;
|
||||||
border-top-left-radius: 30px;
|
|
||||||
border-bottom-left-radius: 30px;
|
|
||||||
border-bottom-right-radius: 30px;
|
|
||||||
border: 2px solid $contrastbg;
|
border: 2px solid $contrastbg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,10 +456,7 @@ calendar:indeterminate {
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
padding: 0px 0px 0px 0px;
|
padding: 0px 0px 0px 0px;
|
||||||
background-color: rgba(40, 42, 54, 0.8);
|
background-color: rgba(40, 42, 54, 0.8);
|
||||||
border-top-right-radius: 0px;
|
border-radius: 30px 0 30px 30px;
|
||||||
border-top-left-radius: 30px;
|
|
||||||
border-bottom-left-radius: 30px;
|
|
||||||
border-bottom-right-radius: 30px;
|
|
||||||
border: 2px solid rgba(189, 147, 249, 0.8); }
|
border: 2px solid rgba(189, 147, 249, 0.8); }
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
@ -666,18 +663,23 @@ calendar:indeterminate {
|
||||||
transition: background-color 0.5s ease-in-out; }
|
transition: background-color 0.5s ease-in-out; }
|
||||||
|
|
||||||
.overview {
|
.overview {
|
||||||
|
background-color: rgba(40, 42, 54, 0.8);
|
||||||
|
border-radius: 30px;
|
||||||
|
border: 2px solid rgba(189, 147, 249, 0.8);
|
||||||
|
padding: 10px;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
min-width: 1px; }
|
min-width: 1px; }
|
||||||
.overview .workspace {
|
.overview .workspace {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
|
transition: border-color 0.2s ease-in-out;
|
||||||
border-radius: 10px; }
|
border-radius: 10px; }
|
||||||
.overview .workspace.active {
|
.overview .workspace.active {
|
||||||
border: 2px solid black; }
|
border: 2px solid black; }
|
||||||
.overview .workspace .window {
|
.overview .workspace .window {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
transition: min-width 0.2s ease-in-out, min-height 0.2s ease-in-out, border-color 0.2s ease-in-out; }
|
transition: min-width 0.2s ease-in-out, min-height 0.2s ease-in-out, border-color 0.2s ease-in-out, font-size 0.2s ease-in-out; }
|
||||||
.overview .normal {
|
.overview .normal {
|
||||||
margin-bottom: 5px; }
|
margin-bottom: 5px; }
|
||||||
.overview .normal .workspace .window {
|
.overview .normal .workspace .window {
|
||||||
|
|
|
@ -183,6 +183,8 @@ bind = $mainMod, right, movefocus, r
|
||||||
bind = $mainMod, up, movefocus, u
|
bind = $mainMod, up, movefocus, u
|
||||||
bind = $mainMod, down, movefocus, d
|
bind = $mainMod, down, movefocus, d
|
||||||
|
|
||||||
|
bind = ALT, Tab, exec, ags -t overview
|
||||||
|
|
||||||
# Switch workspaces with mainMod + [0-9]
|
# Switch workspaces with mainMod + [0-9]
|
||||||
bind = $mainMod, 1, workspace, 1
|
bind = $mainMod, 1, workspace, 1
|
||||||
bind = $mainMod, 2, workspace, 2
|
bind = $mainMod, 2, workspace, 2
|
||||||
|
|
Loading…
Reference in a new issue