ags: sync

- workspace indicator: no more goofy notch, now cairo-drawn to ensure accuracy and maintain animations
- made notification icons a bit smaller
This commit is contained in:
end-4 2023-12-30 21:17:14 +07:00
parent 89fe9488b9
commit 7d4374d52b
17 changed files with 694 additions and 809 deletions

View file

@ -4,7 +4,7 @@ import { App, Utils } from './imports.js';
// Widgets
import Bar from './widgets/bar/main.js';
import Cheatsheet from './widgets/cheatsheet/main.js';
import DesktopBackground from './widgets/desktopbackground/main.js';
// import DesktopBackground from './widgets/desktopbackground/main.js';
import Dock from './widgets/dock/main.js';
import { CornerTopleft, CornerTopright, CornerBottomleft, CornerBottomright } from './widgets/screencorners/main.js';
import Indicator from './widgets/indicators/main.js';
@ -39,12 +39,11 @@ export default {
'osk': CLOSE_ANIM_TIME,
},
windows: [
// Bar() is below
CornerTopleft(),
CornerTopright(),
CornerBottomleft(),
CornerBottomright(),
DesktopBackground(),
// DesktopBackground(),
Dock(), // Buggy
Overview(),
Indicator(),
@ -53,6 +52,6 @@ export default {
SideRight(),
Osk(), // On-screen keyboard
Session(), // Power menu, if that's what you like to call it
Bar()
Bar(),
],
};

View file

@ -57,7 +57,7 @@ const NotificationIcon = (notifObject) => {
const styleContext = self.get_parent().get_style_context();
const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
self.size = Math.max(width * 0.9, height * 0.9, 1); // im too lazy to add another box lol
self.size = Math.max(width * 0.7, height * 0.7, 1); // im too lazy to add another box lol
}),
})
:
@ -185,7 +185,7 @@ export default ({
child: NotificationIcon(notifObject),
overlays: isPopup ? [AnimatedCircProg({
className: `notif-circprog-${notifObject.urgency}`,
valign: Gtk.Align.CENTER,
vpack: 'center', hpack: 'center',
initFrom: (isPopup ? 100 : 0),
initTo: 0,
initAnimTime: popupTimeout,
@ -245,7 +245,7 @@ export default ({
notifTextPreview.revealChild = true;
notifTextExpanded.revealChild = false;
self.child.label = 'expand_more';
expanded = true;
expanded = false;
}
},
child: MaterialIcon('expand_more', 'norm', {
@ -338,7 +338,7 @@ export default ({
if (widget.window)
widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
if (initDirVertical == 1 && offset_y > MOVE_THRESHOLD && !expanded) {
notifTextPreview.revealChild = false;
notifTextExpanded.revealChild = true;

View file

@ -87,9 +87,9 @@
"BLACK_500": "#393634",
"BLACK_700": "#33302F",
"BLACK_900": "#2B2928",
"accent_bg_color": "#d8baff",
"accent_fg_color": "#3e1b6f",
"accent_color": "#d8baff",
"accent_bg_color": "#ffabf1",
"accent_fg_color": "#551251",
"accent_color": "#ffabf1",
"destructive_bg_color": "#ffb4a9",
"destructive_fg_color": "#680003",
"destructive_color": "#ffb4a9",
@ -99,22 +99,22 @@
"warning_fg_color": "rgba(0, 0, 0, 0.87)",
"error_bg_color": "#ffb4a9",
"error_fg_color": "#680003",
"window_bg_color": "#111012",
"window_fg_color": "#e7e1e6",
"view_bg_color": "#1d1b1e",
"view_fg_color": "#e7e1e6",
"window_bg_color": "#120F11",
"window_fg_color": "#eae0e4",
"view_bg_color": "#1f1a1d",
"view_fg_color": "#eae0e4",
"headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)",
"headerbar_fg_color": "#eaddf7",
"headerbar_border_color": "#4b4357",
"headerbar_fg_color": "#f8daee",
"headerbar_border_color": "#554050",
"headerbar_backdrop_color": "@headerbar_bg_color",
"headerbar_shade_color": "rgba(0, 0, 0, 0.09)",
"card_bg_color": "#111012",
"card_fg_color": "#eaddf7",
"card_bg_color": "#120F11",
"card_fg_color": "#f8daee",
"card_shade_color": "rgba(0, 0, 0, 0.09)",
"dialog_bg_color": "#4b4357",
"dialog_fg_color": "#eaddf7",
"popover_bg_color": "#4b4357",
"popover_fg_color": "#eaddf7",
"dialog_bg_color": "#554050",
"dialog_fg_color": "#f8daee",
"popover_bg_color": "#554050",
"popover_fg_color": "#f8daee",
"thumbnail_bg_color": "#1a1b26",
"thumbnail_fg_color": "#AEE5FA",
"shade_color": "rgba(0, 0, 0, 0.36)",

View file

@ -1,27 +1,16 @@
// Made to be pixel-perfect with 11pt font size
// 1rem = 11pt = 14.6666666667px
// Init
$black: black;
$white: white;
$notchSecondaryContainer: $secondaryContainer;
$notchOnSecondaryContainer: $onSecondaryContainer;
$notchPrimary: $primary;
$notchOnPrimary: $onPrimary;
$bar_ws_width: 1.774rem;
// Check dark mode. Set colors accordingly for the fake snotch that's always black
@if $darkmode ==true {
$notchSecondaryContainer: $secondaryContainer;
$notchOnSecondaryContainer: $onSecondaryContainer;
$notchPrimary: $primary;
$notchOnPrimary: $onPrimary;
@mixin bar-group-rounding {
@include small-rounding;
}
@else {
$notchSecondaryContainer: $onSecondaryContainer;
$notchOnSecondaryContainer: $secondaryContainer;
$notchPrimary: $primaryContainer;
$notchOnPrimary: $onPrimaryContainer;
.bar-height {
min-height: 2.727rem;
}
.bar-bg {
@ -34,31 +23,16 @@ $notchOnPrimary: $onPrimary;
}
.bar-group-margin {
padding: 0.2rem;
padding: 0.273rem 0rem;
}
.bar-group {
// @include elevation-border;
background-color: $t_surface;
}
.bar-group-center {
border-bottom-left-radius: 1.364rem;
border-bottom-right-radius: 1.364rem;
padding: 0.2rem;
// background-color: $t_surface;
background-color: $black; // Hard code: fake notch
}
.corner-bar-group {
border-radius: 1.364rem; // Half of bar height
border-width: 0.068rem;
// background-color: $t_surface;
background-color: $black; // Hard code: fake notch
background-color: $l_l_t_surfaceVariant;
}
.bar-group-pad {
padding: 0rem 1.023rem;
// padding: 0rem 1.023rem;
padding: 0.205rem;
}
.bar-group-pad-less {
@ -94,7 +68,7 @@ $notchOnPrimary: $onPrimary;
}
.bar-group-standalone {
border-radius: 1.364rem;
@include bar-group-rounding;
-gtk-outline-radius: 1.364rem;
}
@ -123,7 +97,28 @@ $notchOnPrimary: $onPrimary;
}
.bar-ws-width {
min-width: 18.614rem;
min-width: 18.341rem;
}
.bar-ws {
min-width: $bar_ws_width;
color: mix($onBackground, $background, 40%);
@if $darkmode ==true {
color: mix($onBackground, $background, 45%);
}
}
.bar-ws-active {
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.bar-ws-occupied {
background-color: mix($surfaceVariant, $primary, 89%);
@if $darkmode ==true {
background-color: $surfaceVariant;
}
color: $onSurfaceVariant;
}
.bar-separator {
@ -146,95 +141,12 @@ $notchOnPrimary: $onPrimary;
color: $onBackground;
}
.bar-ws {
min-height: 1.636rem;
min-width: 1.772rem;
font-size: 1.091rem;
@include mainfont;
border-top: 0.068rem solid;
border-bottom: 0.068rem solid;
border-color: transparent;
color: $white;
}
.bar-ws-active-box {
transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1);
}
.bar-ws-active {
min-height: 1.5rem;
min-width: 1.5rem;
font-size: 1.091rem;
@include mainfont;
background-color: $notchPrimary;
color: $notchOnPrimary;
border-radius: 999px;
margin: 0.068rem;
// background-color: red;
}
.bar-ws-active-middledecor {
min-width: 0.682rem;
min-height: 0.682rem;
border-radius: 9999px;
background-color: $black;
margin: 0rem 0.409rem;
}
.bar-ws-occupied {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.772rem;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
}
.bar-ws-occupied-left {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.704rem;
border-top-left-radius: 999px;
border-bottom-left-radius: 999px;
border-left: 0.068rem solid $notchOnSecondaryContainer;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
border-right: 0px solid transparent;
}
.bar-ws-occupied-right {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.704rem;
border-top-right-radius: 999px;
border-bottom-right-radius: 999px;
border-right: 0.068rem solid $notchOnSecondaryContainer;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
border-left: 0px solid transparent;
}
.bar-ws-occupied-left-right {
@include full-rounding;
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.636rem;
border: 0.068rem solid $notchOnSecondaryContainer;
}
.bar-ws-empty {
color: $onBackground;
border-color: transparent;
}
.bar-batt {
@include full-rounding;
padding: 0rem 0.341rem;
background-color: $t_secondaryContainer;
color: $t_onSecondaryContainer;
// border: 1px solid $onSecondaryContainer;
// border: 0.068rem solid $outline;
}
.bar-sidemodule {
@ -262,8 +174,8 @@ $notchOnPrimary: $onPrimary;
}
.bar-music-playstate {
min-height: 1.770rem;
min-width: 1.770rem;
min-height: 1.77rem;
min-width: 1.77rem;
border-radius: 10rem;
background-color: $secondaryContainer;
color: $onSecondaryContainer;
@ -272,15 +184,15 @@ $notchOnPrimary: $onPrimary;
.bar-music-circprog {
@include fluent_decel_long;
min-width: 0.068rem; // line width
min-height: 1.770rem;
min-height: 1.636rem;
padding: 0rem;
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.bar-music-playstate-playing {
min-height: 1.770rem;
min-width: 1.770rem;
min-height: 1.77rem;
min-width: 1.77rem;
border-radius: 10rem;
background-color: $secondaryContainer;
color: $onSecondaryContainer;
@ -363,8 +275,8 @@ $notchOnPrimary: $onPrimary;
}
progress {
min-height: 0.680rem;
min-width: 0.680rem;
min-height: 0.68rem;
min-width: 0.68rem;
margin: 0rem 0.137rem;
border-radius: 10rem;
background-color: $t_onSecondaryContainer;
@ -424,7 +336,7 @@ $notchOnPrimary: $onPrimary;
}
.corner-black {
background-color: $black; // Hard code because fake screen corner
background-color: $black; // Hard code: fake screen corner
@include large-rounding;
}
@ -438,17 +350,17 @@ $notchOnPrimary: $onPrimary;
padding: 0.341rem;
}
.bar-space-button>box:first-child {
.bar-space-button > box:first-child {
@include full-rounding;
padding: 0rem 0.682rem;
}
.bar-space-button:hover>box:first-child,
.bar-space-button:focus>box:first-child {
.bar-space-button:hover > box:first-child,
.bar-space-button:focus > box:first-child {
background-color: $hovercolor;
}
.bar-space-button:active>box:first-child {
.bar-space-button:active > box:first-child {
background-color: $activecolor;
}
@ -458,7 +370,7 @@ $notchOnPrimary: $onPrimary;
}
}
.bar-space-area-rightmost>box {
.bar-space-area-rightmost > box {
padding-right: 2.386rem;
}
@ -477,7 +389,7 @@ $notchOnPrimary: $onPrimary;
.bar-statusicons {
@include full-rounding;
@include menu_decel;
margin: 0.2rem;
margin: 0.273rem;
padding: 0rem 0.614rem;
}
@ -487,4 +399,4 @@ $notchOnPrimary: $onPrimary;
.bar-statusicons-active {
background-color: mix($t_background, $t_onBackground, 80%);
}
}

View file

@ -5,15 +5,18 @@ $transparency_enabled: false;
@if $transparency_enabled ==false {
@if $darkmode ==true {
$primary: mix($primary, white, 70%);
$primaryContainer: mix($primaryContainer, white, 90%);
$background: mix(mix($background, $primary, 94%), #000000, 50%);
$surface: mix($surface, $primaryContainer, 98%);
$surfaceVariant: mix($surfaceVariant, #000000, 55%);
$surfaceVariant: mix($surfaceVariant, #000000, 75%);
// $secondaryContainer: mix($secondaryContainer, $primaryContainer, 90%);
}
@if $darkmode ==false {
$background: mix($background, $primary, 87%);
$surface: mix($surface, $primary, 93%);
$surfaceVariant: mix($surfaceVariant, #FFFFFF, 55%);
$surfaceVariant: mix($surfaceVariant, #FFFFFF, 25%);
}
}

View file

@ -254,6 +254,14 @@
margin-bottom: 0rem;
}
.spacing-h-4>* {
margin-right: 0.273rem;
}
.spacing-h-4>*:last-child {
margin-right: 0rem;
}
.spacing-h-5>* {
margin-right: 0.341rem;
}

View file

@ -1,29 +1,29 @@
$darkmode: true;
$primary: #d8baff;
$onPrimary: #3e1b6f;
$primaryContainer: #563587;
$onPrimaryContainer: #eedcff;
$secondary: #cec2da;
$onSecondary: #352d40;
$secondaryContainer: #4b4357;
$onSecondaryContainer: #eaddf7;
$tertiary: #f1b7c2;
$onTertiary: #4a252e;
$tertiaryContainer: #643b44;
$onTertiaryContainer: #ffd9e1;
$primary: #ffabf1;
$onPrimary: #551251;
$primaryContainer: #702c69;
$onPrimaryContainer: #ffd6f5;
$secondary: #dbbed2;
$onSecondary: #3d2b39;
$secondaryContainer: #554050;
$onSecondaryContainer: #f8daee;
$tertiary: #f5b9a6;
$onTertiary: #4c2619;
$tertiaryContainer: #663c2e;
$onTertiaryContainer: #ffdbcf;
$error: #ffb4a9;
$onError: #680003;
$errorContainer: #930006;
$onErrorContainer: #ffb4a9;
$colorbarbg: #111012;
$background: #111012;
$onBackground: #e7e1e6;
$surface: #1d1b1e;
$onSurface: #e7e1e6;
$surfaceVariant: #4a454e;
$onSurfaceVariant: #cbc4ce;
$outline: #958f99;
$colorbarbg: #120F11;
$background: #120F11;
$onBackground: #eae0e4;
$surface: #1f1a1d;
$onSurface: #eae0e4;
$surfaceVariant: #4e444b;
$onSurfaceVariant: #d1c2cb;
$outline: #9a8d95;
$shadow: #000000;
$inverseSurface: #e7e1e6;
$inverseOnSurface: #323033;
$inversePrimary: #6e4da1;
$inverseSurface: #eae0e4;
$inverseOnSurface: #342f32;
$inversePrimary: #8c4483;

View file

@ -4,11 +4,11 @@
@import './musicwal';
@import './colors';
@import './lib_mixins';
$music_gradient1: mix($color1, $background, 30%);
$music_gradient1: mix($color1, $background, 50%);
@if $darkmode ==true {
$music_gradient1: mix($color1, $background, 30%);
}
// @if $darkmode ==true {
// $music_gradient1: mix($color1, $background, 30%);
// }
$music_gradient2: $color3;
$music_gradient3: $color5;
@ -17,6 +17,9 @@ $music_extra_transparentize: 0.15;
$secondaryContainer: transparentize(mix(mix($background, $color2, 50%), $color6, 80%), 0.5);
$onSecondaryContainer: mix($color7, $color2, 90%);
@if $darkmode ==false {
$onSecondaryContainer: mix($onSecondaryContainer, black, 50%);
}
.osd-music {
@include menu_decel;

View file

@ -1,29 +1 @@
$darkmode: true;
$primary: #c4c0ff;
$onPrimary: #251a8c;
$primaryContainer: #3c36a1;
$onPrimaryContainer: #e3dfff;
$secondary: #c7c4dd;
$onSecondary: #2f2e42;
$secondaryContainer: #464559;
$onSecondaryContainer: #e3dff9;
$tertiary: #eab9d1;
$onTertiary: #472639;
$tertiaryContainer: #603c50;
$onTertiaryContainer: #ffd8eb;
$error: #ffb4a9;
$onError: #680003;
$errorContainer: #930006;
$onErrorContainer: #ffb4a9;
$colorbarbg: #101012;
$background: #101012;
$onBackground: #e5e1e6;
$surface: #1c1b1f;
$onSurface: #e5e1e6;
$surfaceVariant: #47464f;
$onSurfaceVariant: #c8c5d0;
$outline: #928f9a;
$shadow: #000000;
$inverseSurface: #e5e1e6;
$inverseOnSurface: #313033;
$inversePrimary: #5550bb;

View file

@ -1,26 +1 @@
// SCSS Variables
// Generated by 'wal'
$wallpaper: "/home/end/.cache/ags/media/375d6eb3358763763a73710dca3bbfad1a5434d8";
// Special
$background: #0a0919;
$foreground: #bfacd9;
$cursor: #bfacd9;
// Colors
$color0: #0a0919;
$color1: #2E2693;
$color2: #382FA6;
$color3: #4C2F99;
$color4: #4839B3;
$color5: #5A49B4;
$color6: #5C4CC7;
$color7: #bfacd9;
$color8: #857897;
$color9: #2E2693;
$color10: #382FA6;
$color11: #4C2F99;
$color12: #4839B3;
$color13: #5A49B4;
$color14: #5C4CC7;
$color15: #bfacd9;

View file

@ -134,7 +134,7 @@ $notif_surface: $t_background;
.notif-circprog-low {
transition: 0ms linear;
min-width: 0.136rem; // line width
min-height: 3.409rem;
min-height: 3.136rem;
padding: 0rem;
color: $onSecondaryContainer;
}
@ -142,7 +142,7 @@ $notif_surface: $t_background;
.notif-circprog-normal {
transition: 0ms linear;
min-width: 0.136rem; // line width
min-height: 3.409rem;
min-height: 3.136rem;
padding: 0rem;
color: $onSecondaryContainer;
}
@ -150,7 +150,7 @@ $notif_surface: $t_background;
.notif-circprog-critical {
transition: 0ms linear;
min-width: 0.136rem; // line width
min-height: 3.409rem;
min-height: 3.136rem;
padding: 0rem;
color: $secondaryContainer;
}
@ -164,43 +164,43 @@ $notif_surface: $t_background;
}
.notif-action-low {
background-color: $l_t_surfaceVariant;
background-color: mix($t_onSurfaceVariant, $t_surface, 10%);
color: $onSurfaceVariant;
}
.notif-action-low:focus,
.notif-action-low:hover {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 10%);
background-color: mix($t_onSurfaceVariant, $t_surface, 18%);
}
.notif-action-low:active {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 15%);
background-color: mix($t_onSurfaceVariant, $t_surface, 23%);
}
.notif-action-normal {
background-color: $l_t_surfaceVariant;
background-color: mix($t_onSurfaceVariant, $t_surface, 10%);
color: $onSurfaceVariant;
}
.notif-action-normal:focus,
.notif-action-normal:hover {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 10%);
background-color: mix($t_onSurfaceVariant, $t_surface, 18%);
}
.notif-action-normal:active {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 15%);
background-color: mix($t_onSurfaceVariant, $t_surface, 23%);
}
.notif-action-critical {
background-color: $t_onSurfaceVariant;
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 10%);
color: $onSurfaceVariant;
}
.notif-action-critical:focus,
.notif-action-critical:hover {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 10%);
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 18%);
}
.notif-action-critical:active {
background-color: mix($t_onSurfaceVariant, $l_t_surfaceVariant, 15%);
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 23%);
}

File diff suppressed because it is too large Load diff

View file

@ -6,19 +6,19 @@ import { ModuleLeftSpace } from "./leftspace.js";
import { ModuleMusic } from "./music.js";
import { ModuleRightSpace } from "./rightspace.js";
import { ModuleSystem } from "./system.js";
import { ModuleWorkspaces } from "./workspaces.js";
import ModuleWorkspaces from "./workspaces.js";
import { RoundedCorner } from "../../lib/roundedcorner.js";
const left = Widget.Box({
className: 'bar-sidemodule',
children: [ModuleMusic()],
children: [
ModuleMusic()
],
});
const center = Widget.Box({
children: [
RoundedCorner('topright', { className: 'corner-bar-group' }),
ModuleWorkspaces(),
RoundedCorner('topleft', { className: 'corner-bar-group' }),
],
});
@ -36,7 +36,7 @@ export default () => Widget.Window({
className: 'bar-bg',
startWidget: ModuleLeftSpace(),
centerWidget: Widget.Box({
className: 'spacing-h--20',
className: 'spacing-h-4',
children: [
left,
center,

View file

@ -14,7 +14,7 @@ const TrackProgress = () => {
}
return AnimatedCircProg({
className: 'bar-music-circprog',
vpack: 'center',
vpack: 'center', hpack: 'center',
connections: [ // Update on change/once every 3 seconds
[Mpris, _updateProgress],
[3000, _updateProgress]

View file

@ -25,7 +25,7 @@ const SysTrayItem = item => Button({
export const Tray = (props = {}) => {
const trayContent = Box({
className: 'bar-systray bar-group spacing-h-10',
className: 'bar-systray spacing-h-10',
properties: [
['items', new Map()],
['onAdded', (box, id) => {

View file

@ -1,98 +1,165 @@
const { GLib, Gdk, Gtk } = imports.gi;
const Lang = imports.lang;
const Cairo = imports.cairo;
const Pango = imports.gi.Pango;
const PangoCairo = imports.gi.PangoCairo;
import { App, Service, Utils, Widget } from '../../imports.js';
const { Box, DrawingArea, EventBox } = Widget;
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
const WORKSPACE_SIDE_PAD = 0.546; // rem
const NUM_OF_WORKSPACES = 10;
let lastWorkspace = 0;
const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
const activeWorkspaceIndicator = Widget.Box({
css: `
padding: 0rem ${WORKSPACE_SIDE_PAD}rem;
`,
children: [
Widget.Box({
vpack: 'center',
hpack: 'start',
className: 'bar-ws-active-box',
setup: (self) => self.hook(Hyprland.active.workspace, (box) => {
const ws = Hyprland.active.workspace.id;
box.setCss(`
margin-left: ${1.774 * (ws - 1) + 0.068}rem;
`);
lastWorkspace = ws;
}),
children: [
Widget.Label({
vpack: 'center',
className: 'bar-ws-active',
label: ``,
})
]
})
]
});
// Font size = workspace id
const WorkspaceContents = (count = 10) => {
return DrawingArea({
properties: [
['workspaceMask', 0],
],
css: `transition: 500ms cubic-bezier(0.1, 1, 0, 1);`,
setup: (area) => area
.hook(Hyprland.active.workspace, (area) =>
area.setCss(`font-size: ${Hyprland.active.workspace.id}px;`)
)
.hook(Hyprland, (area) => {
const workspaces = Hyprland.workspaces;
let workspaceMask = 0;
for (let i = 0; i < workspaces.length; i++) {
const ws = workspaces[i];
if (ws.id < 0) continue; // Ignore scratchpads
if (ws.id > count) return; // Not rendered
if (workspaces[i].windows > 0) {
workspaceMask |= (1 << ws.id);
}
}
area._workspaceMask = workspaceMask;
}, 'notify::workspaces')
.on('draw', Lang.bind(area, (area, cr) => {
const allocation = area.get_allocation();
const { width, height } = allocation;
export const ModuleWorkspaces = () => Widget.EventBox({
onScrollUp: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace -1 &']),
onScrollDown: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace +1 &']),
const workspaceStyleContext = dummyWs.get_style_context();
const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
const workspaceRadius = workspaceDiameter / 2;
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
area.set_size_request(workspaceDiameter * count, -1);
const widgetStyleContext = area.get_style_context();
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
const activeWsCenterY = height / 2;
// Font
const layout = PangoCairo.create_layout(cr);
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${workspaceFontSize}`);
layout.set_font_description(fontDesc);
// Get kinda min radius for number indicators
layout.set_text("0".repeat(count.toString().length), -1);
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.2; // a bit smaller than sqrt(2)*radius
const indicatorGap = workspaceRadius - indicatorRadius;
// Draw workspace numbers
for (let i = 1; i <= count; i++) {
if (area._workspaceMask & (1 << i)) {
// Draw bg highlight
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
const wsCenterY = height / 2;
if (!(area._workspaceMask & (1 << (i - 1)))) { // Left
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
cr.fill();
}
else {
cr.rectangle(wsCenterX - workspaceRadius , wsCenterY - workspaceRadius, workspaceRadius , workspaceRadius * 2)
cr.fill();
}
if (!(area._workspaceMask & (1 << (i + 1)))) { // Right
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
cr.fill();
}
else {
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius , workspaceRadius * 2)
cr.fill();
}
// Set color for text
cr.setSourceRGBA(occupiedfg.red, occupiedfg.green, occupiedfg.blue, occupiedfg.alpha);
}
else
cr.setSourceRGBA(wsfg.red, wsfg.green, wsfg.blue, wsfg.alpha);
layout.set_text(`${i}`, -1);
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
const y = (height - layoutHeight) / 2;
cr.moveTo(x, y);
// cr.showText(text);
PangoCairo.show_layout(cr, layout);
cr.stroke();
}
// Draw active ws
// base
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
cr.fill();
// inner decor
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius * 0.19, 0, 2 * Math.PI);
cr.fill();
}))
,
})
}
export default () => EventBox({
onScrollUp: () => Hyprland.sendMessage(`dispatch workspace -1`),
onScrollDown: () => Hyprland.sendMessage(`dispatch workspace +1`),
onMiddleClickRelease: () => App.toggleWindow('overview'),
onSecondaryClickRelease: () => App.toggleWindow('osk'),
child: Widget.Box({
properties: [
['clicked', false],
],
child: Box({
homogeneous: true,
className: 'bar-ws-width',
children: [
Widget.Overlay({
passThrough: true,
child: Widget.Box({
homogeneous: true,
className: 'bar-group-center',
children: [Widget.Box({
className: 'bar-group-standalone bar-group-pad',
})]
}),
overlays: [
Widget.Overlay({
setup: (self) => self.set_overlay_pass_through(self.get_children()[1], true),
child: Widget.Box({
hpack: 'center',
css: `
padding: 0rem ${WORKSPACE_SIDE_PAD}rem;
`,
// homogeneous: true,
children: Array.from({ length: NUM_OF_WORKSPACES }, (_, i) => i + 1).map(i => Widget.Button({
onPrimaryClick: () => Utils.execAsync(['bash', '-c', `hyprctl dispatch workspace ${i} &`]).catch(print),
child: Widget.Label({
vpack: 'center',
label: `${i}`,
className: 'bar-ws txt',
}),
})),
setup: (self) => self.hook(Hyprland, (box) => {
// console.log('update');
const kids = box.children;
for (let i = 0; i < kids.length; i++) {
const child = kids[i];
child.child.toggleClassName('bar-ws-occupied', false);
child.child.toggleClassName('bar-ws-occupied-left', false);
child.child.toggleClassName('bar-ws-occupied-right', false);
child.child.toggleClassName('bar-ws-occupied-left-right', false);
}
const occupied = Array.from({ length: NUM_OF_WORKSPACES }, (_, i) => Hyprland.getWorkspace(i + 1)?.windows > 0);
for (let i = 0; i < occupied.length; i++) {
if (!occupied[i]) continue;
const child = kids[i];
child.child.toggleClassName(`bar-ws-occupied${!occupied[i - 1] ? '-left' : ''}${!occupied[i + 1] ? '-right' : ''}`, true);
}
}, 'notify::workspaces'),
}),
overlays: [
activeWorkspaceIndicator,
]
})
],
})
]
})
});
className: 'bar-group-margin',
children: [Box({
className: 'bar-group bar-group-standalone bar-group-pad',
css: 'min-width: 2px;',
children: [
WorkspaceContents(10),
]
})]
}),
setup: (self) => {
self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
self.on('motion-notify-event', (self, event) => {
if (!self._clicked) return;
const [_, cursorX, cursorY] = event.get_coords();
const widgetWidth = self.get_allocation().width;
const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
Hyprland.sendMessage(`dispatch workspace ${wsId}`)
})
self.on('button-press-event', (self, event) => {
self._clicked = true;
const [_, cursorX, cursorY] = event.get_coords();
const widgetWidth = self.get_allocation().width;
const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
Hyprland.sendMessage(`dispatch workspace ${wsId}`);
})
self.on('button-release-event', (self) => self._clicked = false);
}
})

View file

@ -330,7 +330,8 @@ const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) =>
export const SearchAndWindows = () => {
var _appSearchResults = [];
const clickOutsideToClose = Widget.EventBox({
const ClickToClose = ({ ...props }) => Widget.EventBox({
...props,
onPrimaryClick: () => App.closeWindow('overview'),
onSecondaryClick: () => App.closeWindow('overview'),
onMiddleClick: () => App.closeWindow('overview'),
@ -506,9 +507,12 @@ export const SearchAndWindows = () => {
return Widget.Box({
vertical: true,
className: 'overview-window',
children: [
clickOutsideToClose,
ClickToClose({ // Top margin. Also works as a click-outside-to-close thing
child: Widget.Box({
className: 'bar-height',
})
}),
Widget.Box({
hpack: 'center',
children: [