Added ags
TODO copy ags config
This commit is contained in:
111
roles/ags/files/widget/osd/OSD.ts
Normal file
111
roles/ags/files/widget/osd/OSD.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { icon } from "lib/utils"
|
||||
import icons from "lib/icons"
|
||||
import Progress from "./Progress"
|
||||
import brightness from "service/brightness"
|
||||
import options from "options"
|
||||
|
||||
const audio = await Service.import("audio")
|
||||
const { progress, microphone } = options.osd
|
||||
|
||||
const DELAY = 2500
|
||||
|
||||
function OnScreenProgress(vertical: boolean) {
|
||||
const indicator = Widget.Icon({
|
||||
size: 42,
|
||||
vpack: "start",
|
||||
})
|
||||
const progress = Progress({
|
||||
vertical,
|
||||
width: vertical ? 42 : 300,
|
||||
height: vertical ? 300 : 42,
|
||||
child: indicator,
|
||||
})
|
||||
|
||||
const revealer = Widget.Revealer({
|
||||
transition: "slide_left",
|
||||
child: progress,
|
||||
})
|
||||
|
||||
let count = 0
|
||||
function show(value: number, icon: string) {
|
||||
revealer.reveal_child = true
|
||||
indicator.icon = icon
|
||||
progress.setValue(value)
|
||||
count++
|
||||
Utils.timeout(DELAY, () => {
|
||||
count--
|
||||
|
||||
if (count === 0)
|
||||
revealer.reveal_child = false
|
||||
})
|
||||
}
|
||||
|
||||
return revealer
|
||||
.hook(brightness, () => show(
|
||||
brightness.screen,
|
||||
icons.brightness.screen,
|
||||
), "notify::screen")
|
||||
.hook(brightness, () => show(
|
||||
brightness.kbd,
|
||||
icons.brightness.keyboard,
|
||||
), "notify::kbd")
|
||||
.hook(audio.speaker, () => show(
|
||||
audio.speaker.volume,
|
||||
icon(audio.speaker.icon_name || "", icons.audio.type.speaker),
|
||||
), "notify::volume")
|
||||
}
|
||||
|
||||
function MicrophoneMute() {
|
||||
const icon = Widget.Icon({
|
||||
class_name: "microphone",
|
||||
})
|
||||
|
||||
const revealer = Widget.Revealer({
|
||||
transition: "slide_up",
|
||||
child: icon,
|
||||
})
|
||||
|
||||
let count = 0
|
||||
let mute = audio.microphone.stream?.is_muted ?? false
|
||||
|
||||
return revealer.hook(audio.microphone, () => Utils.idle(() => {
|
||||
if (mute !== audio.microphone.stream?.is_muted) {
|
||||
mute = audio.microphone.stream!.is_muted
|
||||
icon.icon = icons.audio.mic[mute ? "muted" : "high"]
|
||||
revealer.reveal_child = true
|
||||
count++
|
||||
|
||||
Utils.timeout(DELAY, () => {
|
||||
count--
|
||||
if (count === 0)
|
||||
revealer.reveal_child = false
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
export default (monitor: number) => Widget.Window({
|
||||
monitor,
|
||||
name: `indicator${monitor}`,
|
||||
class_name: "indicator",
|
||||
layer: "overlay",
|
||||
click_through: true,
|
||||
anchor: ["right", "left", "top", "bottom"],
|
||||
child: Widget.Box({
|
||||
css: "padding: 2px;",
|
||||
expand: true,
|
||||
child: Widget.Overlay(
|
||||
{ child: Widget.Box({ expand: true }) },
|
||||
Widget.Box({
|
||||
hpack: progress.pack.h.bind(),
|
||||
vpack: progress.pack.v.bind(),
|
||||
child: progress.vertical.bind().as(OnScreenProgress),
|
||||
}),
|
||||
Widget.Box({
|
||||
hpack: microphone.pack.h.bind(),
|
||||
vpack: microphone.pack.v.bind(),
|
||||
child: MicrophoneMute(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
})
|
||||
74
roles/ags/files/widget/osd/Progress.ts
Normal file
74
roles/ags/files/widget/osd/Progress.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type Gtk from "gi://Gtk?version=3.0"
|
||||
import GLib from "gi://GLib?version=2.0"
|
||||
import { range } from "lib/utils"
|
||||
import options from "options"
|
||||
|
||||
type ProgressProps = {
|
||||
height?: number
|
||||
width?: number
|
||||
vertical?: boolean
|
||||
child: Gtk.Widget
|
||||
}
|
||||
|
||||
export default ({
|
||||
height = 18,
|
||||
width = 180,
|
||||
vertical = false,
|
||||
child,
|
||||
}: ProgressProps) => {
|
||||
const fill = Widget.Box({
|
||||
class_name: "fill",
|
||||
hexpand: vertical,
|
||||
vexpand: !vertical,
|
||||
hpack: vertical ? "fill" : "start",
|
||||
vpack: vertical ? "end" : "fill",
|
||||
child,
|
||||
})
|
||||
|
||||
const container = Widget.Box({
|
||||
class_name: "progress",
|
||||
child: fill,
|
||||
css: `
|
||||
min-width: ${width}px;
|
||||
min-height: ${height}px;
|
||||
`,
|
||||
})
|
||||
|
||||
let fill_size = 0
|
||||
let animations: number[] = []
|
||||
|
||||
return Object.assign(container, {
|
||||
setValue(value: number) {
|
||||
if (value < 0)
|
||||
return
|
||||
|
||||
if (animations.length > 0) {
|
||||
for (const id of animations)
|
||||
GLib.source_remove(id)
|
||||
|
||||
animations = []
|
||||
}
|
||||
|
||||
const axis = vertical ? "height" : "width"
|
||||
const axisv = vertical ? height : width
|
||||
const min = vertical ? width : height
|
||||
const preferred = (axisv - min) * value + min
|
||||
|
||||
if (!fill_size) {
|
||||
fill_size = preferred
|
||||
fill.css = `min-${axis}: ${preferred}px;`
|
||||
return
|
||||
}
|
||||
|
||||
const frames = options.transition.value / 10
|
||||
const goal = preferred - fill_size
|
||||
const step = goal / frames
|
||||
|
||||
animations = range(frames, 0).map(i => Utils.timeout(5 * i, () => {
|
||||
fill_size += step
|
||||
fill.css = `min-${axis}: ${fill_size}px`
|
||||
animations.shift()
|
||||
}))
|
||||
},
|
||||
})
|
||||
}
|
||||
26
roles/ags/files/widget/osd/osd.scss
Normal file
26
roles/ags/files/widget/osd/osd.scss
Normal file
@@ -0,0 +1,26 @@
|
||||
window.indicator {
|
||||
.progress {
|
||||
@include floating-widget;
|
||||
padding: $padding * .5;
|
||||
border-radius: if($radius >0, calc($radius + $padding*.5), 0);
|
||||
@debug $radius;
|
||||
|
||||
.fill {
|
||||
border-radius: $radius;
|
||||
background-color: $primary-bg;
|
||||
color: $primary-fg;
|
||||
|
||||
image {
|
||||
-gtk-icon-transform: scale(0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.microphone {
|
||||
@include floating-widget;
|
||||
margin: $spacing * 2;
|
||||
padding: $popover-padding * 2;
|
||||
font-size: 58px;
|
||||
color: transparentize($fg, .1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user