mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-02 10:32:07 -04:00
Compare commits
2 Commits
61ee5f4336
...
blur
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e6416c8ba | ||
|
|
a0b2debd7e |
@@ -1,40 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/blur"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var blurCmd = &cobra.Command{
|
|
||||||
Use: "blur",
|
|
||||||
Short: "Background blur utilities",
|
|
||||||
}
|
|
||||||
|
|
||||||
var blurCheckCmd = &cobra.Command{
|
|
||||||
Use: "check",
|
|
||||||
Short: "Check if the compositor supports background blur (ext-background-effect-v1)",
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
Run: runBlurCheck,
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
blurCmd.AddCommand(blurCheckCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func runBlurCheck(cmd *cobra.Command, args []string) {
|
|
||||||
supported, err := blur.ProbeSupport()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch supported {
|
|
||||||
case true:
|
|
||||||
fmt.Println("supported")
|
|
||||||
default:
|
|
||||||
fmt.Println("unsupported")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -525,6 +525,5 @@ func getCommonCommands() []*cobra.Command {
|
|||||||
configCmd,
|
configCmd,
|
||||||
dlCmd,
|
dlCmd,
|
||||||
randrCmd,
|
randrCmd,
|
||||||
blurCmd,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
package blur
|
|
||||||
|
|
||||||
import (
|
|
||||||
wlhelpers "github.com/AvengeMedia/DankMaterialShell/core/internal/wayland/client"
|
|
||||||
client "github.com/AvengeMedia/DankMaterialShell/core/pkg/go-wayland/wayland/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
const extBackgroundEffectInterface = "ext_background_effect_manager_v1"
|
|
||||||
|
|
||||||
func ProbeSupport() (bool, error) {
|
|
||||||
display, err := client.Connect("")
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer display.Context().Close()
|
|
||||||
|
|
||||||
registry, err := display.GetRegistry()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
found := false
|
|
||||||
registry.SetGlobalHandler(func(e client.RegistryGlobalEvent) {
|
|
||||||
switch e.Interface {
|
|
||||||
case extBackgroundEffectInterface:
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := wlhelpers.Roundtrip(display, display.Context()); err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return found, nil
|
|
||||||
}
|
|
||||||
@@ -137,7 +137,7 @@ bind = SUPER, bracketright, layoutmsg, preselect r
|
|||||||
|
|
||||||
# === Sizing & Layout ===
|
# === Sizing & Layout ===
|
||||||
bind = SUPER, R, layoutmsg, togglesplit
|
bind = SUPER, R, layoutmsg, togglesplit
|
||||||
bind = SUPER CTRL, F, resizeactive, exact 100% 100%
|
bind = SUPER CTRL, F, resizeactive, exact 100%
|
||||||
|
|
||||||
# === Move/resize windows with mainMod + LMB/RMB and dragging ===
|
# === Move/resize windows with mainMod + LMB/RMB and dragging ===
|
||||||
bindmd = SUPER, mouse:272, Move window, movewindow
|
bindmd = SUPER, mouse:272, Move window, movewindow
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ windowrule = tile on, match:class ^(gnome-control-center)$
|
|||||||
windowrule = tile on, match:class ^(pavucontrol)$
|
windowrule = tile on, match:class ^(pavucontrol)$
|
||||||
windowrule = tile on, match:class ^(nm-connection-editor)$
|
windowrule = tile on, match:class ^(nm-connection-editor)$
|
||||||
|
|
||||||
windowrule = float on, match:class ^(org\.gnome\.Calculator)$
|
|
||||||
windowrule = float on, match:class ^(gnome-calculator)$
|
windowrule = float on, match:class ^(gnome-calculator)$
|
||||||
windowrule = float on, match:class ^(galculator)$
|
windowrule = float on, match:class ^(galculator)$
|
||||||
windowrule = float on, match:class ^(blueman-manager)$
|
windowrule = float on, match:class ^(blueman-manager)$
|
||||||
|
|||||||
@@ -444,21 +444,20 @@ func GetFocusedMonitor() string {
|
|||||||
|
|
||||||
type outputInfo struct {
|
type outputInfo struct {
|
||||||
x, y int32
|
x, y int32
|
||||||
scale float64
|
|
||||||
transform int32
|
transform int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllOutputInfos() map[string]*outputInfo {
|
func getOutputInfo(outputName string) (*outputInfo, bool) {
|
||||||
display, err := client.Connect("")
|
display, err := client.Connect("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
ctx := display.Context()
|
ctx := display.Context()
|
||||||
defer ctx.Close()
|
defer ctx.Close()
|
||||||
|
|
||||||
registry, err := display.GetRegistry()
|
registry, err := display.GetRegistry()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputManager *wlr_output_management.ZwlrOutputManagerV1
|
var outputManager *wlr_output_management.ZwlrOutputManagerV1
|
||||||
@@ -477,17 +476,16 @@ func getAllOutputInfos() map[string]*outputInfo {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
|
if err := wlhelpers.Roundtrip(display, ctx); err != nil {
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
if outputManager == nil {
|
if outputManager == nil {
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
type headState struct {
|
type headState struct {
|
||||||
name string
|
name string
|
||||||
x, y int32
|
x, y int32
|
||||||
scale float64
|
|
||||||
transform int32
|
transform int32
|
||||||
}
|
}
|
||||||
heads := make(map[*wlr_output_management.ZwlrOutputHeadV1]*headState)
|
heads := make(map[*wlr_output_management.ZwlrOutputHeadV1]*headState)
|
||||||
@@ -503,9 +501,6 @@ func getAllOutputInfos() map[string]*outputInfo {
|
|||||||
state.x = pe.X
|
state.x = pe.X
|
||||||
state.y = pe.Y
|
state.y = pe.Y
|
||||||
})
|
})
|
||||||
e.Head.SetScaleHandler(func(se wlr_output_management.ZwlrOutputHeadV1ScaleEvent) {
|
|
||||||
state.scale = se.Scale
|
|
||||||
})
|
|
||||||
e.Head.SetTransformHandler(func(te wlr_output_management.ZwlrOutputHeadV1TransformEvent) {
|
e.Head.SetTransformHandler(func(te wlr_output_management.ZwlrOutputHeadV1TransformEvent) {
|
||||||
state.transform = te.Transform
|
state.transform = te.Transform
|
||||||
})
|
})
|
||||||
@@ -516,32 +511,21 @@ func getAllOutputInfos() map[string]*outputInfo {
|
|||||||
|
|
||||||
for !done {
|
for !done {
|
||||||
if err := ctx.Dispatch(); err != nil {
|
if err := ctx.Dispatch(); err != nil {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make(map[string]*outputInfo, len(heads))
|
|
||||||
for _, state := range heads {
|
|
||||||
if state.name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result[state.name] = &outputInfo{
|
|
||||||
x: state.x,
|
|
||||||
y: state.y,
|
|
||||||
scale: state.scale,
|
|
||||||
transform: state.transform,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOutputInfo(outputName string) (*outputInfo, bool) {
|
|
||||||
infos := getAllOutputInfos()
|
|
||||||
if infos == nil {
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
info, ok := infos[outputName]
|
}
|
||||||
return info, ok
|
|
||||||
|
for _, state := range heads {
|
||||||
|
if state.name == outputName {
|
||||||
|
return &outputInfo{
|
||||||
|
x: state.x,
|
||||||
|
y: state.y,
|
||||||
|
transform: state.transform,
|
||||||
|
}, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDWLActiveWindow() (*WindowGeometry, error) {
|
func getDWLActiveWindow() (*WindowGeometry, error) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package screenshot
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||||
@@ -305,20 +304,22 @@ func (s *Screenshoter) captureAllScreens() (*CaptureResult, error) {
|
|||||||
if len(outputs) == 0 {
|
if len(outputs) == 0 {
|
||||||
return nil, fmt.Errorf("no outputs available")
|
return nil, fmt.Errorf("no outputs available")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(outputs) == 1 {
|
if len(outputs) == 1 {
|
||||||
return s.captureWholeOutput(outputs[0])
|
return s.captureWholeOutput(outputs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
wlrInfos := getAllOutputInfos()
|
// Capture all outputs first to get actual buffer sizes
|
||||||
|
type capturedOutput struct {
|
||||||
type pendingOutput struct {
|
output *WaylandOutput
|
||||||
result *CaptureResult
|
result *CaptureResult
|
||||||
logX float64
|
physX int
|
||||||
logY float64
|
physY int
|
||||||
scale float64
|
|
||||||
}
|
}
|
||||||
var pending []pendingOutput
|
captured := make([]capturedOutput, 0, len(outputs))
|
||||||
maxScale := 1.0
|
|
||||||
|
var minX, minY, maxX, maxY int
|
||||||
|
first := true
|
||||||
|
|
||||||
for _, output := range outputs {
|
for _, output := range outputs {
|
||||||
result, err := s.captureWholeOutput(output)
|
result, err := s.captureWholeOutput(output)
|
||||||
@@ -327,74 +328,50 @@ func (s *Screenshoter) captureAllScreens() (*CaptureResult, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logX, logY := float64(output.x), float64(output.y)
|
outX, outY := output.x, output.y
|
||||||
scale := float64(output.scale)
|
scale := float64(output.scale)
|
||||||
|
|
||||||
switch DetectCompositor() {
|
switch DetectCompositor() {
|
||||||
case CompositorHyprland:
|
case CompositorHyprland:
|
||||||
if hx, hy, _, _, ok := GetHyprlandMonitorGeometry(output.name); ok {
|
if hx, hy, _, _, ok := GetHyprlandMonitorGeometry(output.name); ok {
|
||||||
logX, logY = float64(hx), float64(hy)
|
outX, outY = hx, hy
|
||||||
}
|
}
|
||||||
if hs := GetHyprlandMonitorScale(output.name); hs > 0 {
|
if s := GetHyprlandMonitorScale(output.name); s > 0 {
|
||||||
scale = hs
|
scale = s
|
||||||
}
|
}
|
||||||
default:
|
case CompositorDWL:
|
||||||
if wlrInfos != nil {
|
if info, ok := getOutputInfo(output.name); ok {
|
||||||
if info, ok := wlrInfos[output.name]; ok {
|
outX, outY = info.x, info.y
|
||||||
logX, logY = float64(info.x), float64(info.y)
|
|
||||||
if info.scale > 0 {
|
|
||||||
scale = info.scale
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if scale <= 0 {
|
if scale <= 0 {
|
||||||
scale = 1.0
|
scale = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pending = append(pending, pendingOutput{result: result, logX: logX, logY: logY, scale: scale})
|
physX := int(float64(outX) * scale)
|
||||||
if scale > maxScale {
|
physY := int(float64(outY) * scale)
|
||||||
maxScale = scale
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pending) == 0 {
|
captured = append(captured, capturedOutput{
|
||||||
return nil, fmt.Errorf("failed to capture any outputs")
|
output: output,
|
||||||
}
|
result: result,
|
||||||
if len(pending) == 1 {
|
physX: physX,
|
||||||
return pending[0].result, nil
|
physY: physY,
|
||||||
}
|
})
|
||||||
|
|
||||||
type layoutEntry struct {
|
right := physX + result.Buffer.Width
|
||||||
result *CaptureResult
|
bottom := physY + result.Buffer.Height
|
||||||
canvasX int
|
|
||||||
canvasY int
|
|
||||||
canvasW int
|
|
||||||
canvasH int
|
|
||||||
}
|
|
||||||
entries := make([]layoutEntry, len(pending))
|
|
||||||
var minX, minY, maxX, maxY int
|
|
||||||
|
|
||||||
for i, p := range pending {
|
if first {
|
||||||
cx := int(math.Round(p.logX * maxScale))
|
minX, minY = physX, physY
|
||||||
cy := int(math.Round(p.logY * maxScale))
|
maxX, maxY = right, bottom
|
||||||
cw := int(math.Round(float64(p.result.Buffer.Width) * maxScale / p.scale))
|
first = false
|
||||||
ch := int(math.Round(float64(p.result.Buffer.Height) * maxScale / p.scale))
|
|
||||||
|
|
||||||
entries[i] = layoutEntry{result: p.result, canvasX: cx, canvasY: cy, canvasW: cw, canvasH: ch}
|
|
||||||
|
|
||||||
right := cx + cw
|
|
||||||
bottom := cy + ch
|
|
||||||
if i == 0 {
|
|
||||||
minX, minY, maxX, maxY = cx, cy, right, bottom
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cx < minX {
|
|
||||||
minX = cx
|
if physX < minX {
|
||||||
|
minX = physX
|
||||||
}
|
}
|
||||||
if cy < minY {
|
if physY < minY {
|
||||||
minY = cy
|
minY = physY
|
||||||
}
|
}
|
||||||
if right > maxX {
|
if right > maxX {
|
||||||
maxX = right
|
maxX = right
|
||||||
@@ -404,26 +381,35 @@ func (s *Screenshoter) captureAllScreens() (*CaptureResult, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(captured) == 0 {
|
||||||
|
return nil, fmt.Errorf("failed to capture any outputs")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(captured) == 1 {
|
||||||
|
return captured[0].result, nil
|
||||||
|
}
|
||||||
|
|
||||||
totalW := maxX - minX
|
totalW := maxX - minX
|
||||||
totalH := maxY - minY
|
totalH := maxY - minY
|
||||||
composite, err := CreateShmBuffer(totalW, totalH, totalW*4)
|
|
||||||
|
compositeStride := totalW * 4
|
||||||
|
composite, err := CreateShmBuffer(totalW, totalH, compositeStride)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for _, e := range entries {
|
for _, c := range captured {
|
||||||
e.result.Buffer.Close()
|
c.result.Buffer.Close()
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("create composite buffer: %w", err)
|
return nil, fmt.Errorf("create composite buffer: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
composite.Clear()
|
composite.Clear()
|
||||||
|
|
||||||
var format uint32
|
var format uint32
|
||||||
for _, e := range entries {
|
for _, c := range captured {
|
||||||
if format == 0 {
|
if format == 0 {
|
||||||
format = e.result.Format
|
format = c.result.Format
|
||||||
}
|
}
|
||||||
s.blitBufferScaled(composite, e.result.Buffer,
|
s.blitBuffer(composite, c.result.Buffer, c.physX-minX, c.physY-minY, c.result.YInverted)
|
||||||
e.canvasX-minX, e.canvasY-minY, e.canvasW, e.canvasH,
|
c.result.Buffer.Close()
|
||||||
e.result.YInverted)
|
|
||||||
e.result.Buffer.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CaptureResult{
|
return &CaptureResult{
|
||||||
@@ -433,44 +419,32 @@ func (s *Screenshoter) captureAllScreens() (*CaptureResult, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Screenshoter) blitBufferScaled(dst, src *ShmBuffer, dstX, dstY, dstW, dstH int, yInverted bool) {
|
func (s *Screenshoter) blitBuffer(dst, src *ShmBuffer, dstX, dstY int, yInverted bool) {
|
||||||
if dstW <= 0 || dstH <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
srcData := src.Data()
|
srcData := src.Data()
|
||||||
dstData := dst.Data()
|
dstData := dst.Data()
|
||||||
|
|
||||||
for dy := 0; dy < dstH; dy++ {
|
for srcY := 0; srcY < src.Height; srcY++ {
|
||||||
canvasY := dstY + dy
|
actualSrcY := srcY
|
||||||
if canvasY < 0 || canvasY >= dst.Height {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
srcY := dy * src.Height / dstH
|
|
||||||
if yInverted {
|
if yInverted {
|
||||||
srcY = src.Height - 1 - srcY
|
actualSrcY = src.Height - 1 - srcY
|
||||||
}
|
}
|
||||||
if srcY < 0 || srcY >= src.Height {
|
|
||||||
|
dy := dstY + srcY
|
||||||
|
if dy < 0 || dy >= dst.Height {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
srcRowOff := srcY * src.Stride
|
srcRowOff := actualSrcY * src.Stride
|
||||||
dstRowOff := canvasY * dst.Stride
|
dstRowOff := dy * dst.Stride
|
||||||
|
|
||||||
for dx := 0; dx < dstW; dx++ {
|
for srcX := 0; srcX < src.Width; srcX++ {
|
||||||
canvasX := dstX + dx
|
dx := dstX + srcX
|
||||||
if canvasX < 0 || canvasX >= dst.Width {
|
if dx < 0 || dx >= dst.Width {
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
srcX := dx * src.Width / dstW
|
|
||||||
if srcX >= src.Width {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
si := srcRowOff + srcX*4
|
si := srcRowOff + srcX*4
|
||||||
di := dstRowOff + canvasX*4
|
di := dstRowOff + dx*4
|
||||||
|
|
||||||
if si+3 >= len(srcData) || di+3 >= len(dstData) {
|
if si+3 >= len(srcData) || di+3 >= len(dstData) {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -369,7 +369,9 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function previous(): void {
|
function previous(): void {
|
||||||
MprisController.previousOrRewind();
|
if (MprisController.activePlayer && MprisController.activePlayer.canGoPrevious) {
|
||||||
|
MprisController.activePlayer.previous();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function next(): void {
|
function next(): void {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Item {
|
|||||||
property real animationOffset: Theme.spacingL
|
property real animationOffset: Theme.spacingL
|
||||||
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
property list<real> animationEnterCurve: Theme.expressiveCurves.expressiveDefaultSpatial
|
||||||
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
property list<real> animationExitCurve: Theme.expressiveCurves.emphasized
|
||||||
property color backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
property color backgroundColor: Theme.surfaceContainer
|
||||||
property color borderColor: Theme.outlineMedium
|
property color borderColor: Theme.outlineMedium
|
||||||
property real borderWidth: 0
|
property real borderWidth: 0
|
||||||
property real cornerRadius: Theme.cornerRadius
|
property real cornerRadius: Theme.cornerRadius
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ DankModal {
|
|||||||
|
|
||||||
modalWidth: 680
|
modalWidth: 680
|
||||||
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 680
|
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 680
|
||||||
backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
backgroundColor: Theme.surfaceContainer
|
||||||
cornerRadius: Theme.cornerRadius
|
cornerRadius: Theme.cornerRadius
|
||||||
borderColor: Theme.outlineMedium
|
borderColor: Theme.outlineMedium
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ FocusScope {
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: !editMode && !(root.parentModal?.isClosing ?? false)
|
visible: !editMode
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: footerBar
|
id: footerBar
|
||||||
@@ -737,6 +737,8 @@ FocusScope {
|
|||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - searchField.height - categoryRow.height - fileFilterRow.height - actionPanel.height - Theme.spacingXS * ((categoryRow.visible ? 1 : 0) + (fileFilterRow.visible ? 1 : 0) + 2)
|
height: parent.height - searchField.height - categoryRow.height - fileFilterRow.height - actionPanel.height - Theme.spacingXS * ((categoryRow.visible ? 1 : 0) + (fileFilterRow.visible ? 1 : 0) + 2)
|
||||||
|
opacity: root.parentModal?.isClosing ? 0 : 1
|
||||||
|
|
||||||
ResultsList {
|
ResultsList {
|
||||||
id: resultsList
|
id: resultsList
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
@@ -324,8 +324,6 @@ Item {
|
|||||||
height: 24
|
height: 24
|
||||||
z: 100
|
z: 100
|
||||||
visible: {
|
visible: {
|
||||||
if (BlurService.enabled)
|
|
||||||
return false;
|
|
||||||
if (mainListView.contentHeight <= mainListView.height)
|
if (mainListView.contentHeight <= mainListView.height)
|
||||||
return false;
|
return false;
|
||||||
var atBottom = mainListView.contentY >= mainListView.contentHeight - mainListView.height + mainListView.originY - 5;
|
var atBottom = mainListView.contentY >= mainListView.contentHeight - mainListView.height + mainListView.originY - 5;
|
||||||
@@ -451,7 +449,7 @@ Item {
|
|||||||
case "apps":
|
case "apps":
|
||||||
return "apps";
|
return "apps";
|
||||||
default:
|
default:
|
||||||
return "search_off";
|
return root.controller?.searchQuery?.length > 0 ? "search_off" : "search";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -487,9 +485,9 @@ Item {
|
|||||||
case "plugins":
|
case "plugins":
|
||||||
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
|
||||||
case "apps":
|
case "apps":
|
||||||
return I18n.tr("No apps found");
|
return hasQuery ? I18n.tr("No apps found") : I18n.tr("Type to search apps");
|
||||||
default:
|
default:
|
||||||
return I18n.tr("No results found");
|
return hasQuery ? I18n.tr("No results found") : I18n.tr("Type to search");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ DankPopout {
|
|||||||
QtObject {
|
QtObject {
|
||||||
id: modalAdapter
|
id: modalAdapter
|
||||||
property bool spotlightOpen: appDrawerPopout.shouldBeVisible
|
property bool spotlightOpen: appDrawerPopout.shouldBeVisible
|
||||||
readonly property bool isClosing: !appDrawerPopout.shouldBeVisible
|
property bool isClosing: false
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
appDrawerPopout.close();
|
appDrawerPopout.close();
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ PluginComponent {
|
|||||||
id: detailRoot
|
id: detailRoot
|
||||||
implicitHeight: detailColumn.implicitHeight + Theme.spacingM * 2
|
implicitHeight: detailColumn.implicitHeight + Theme.spacingM * 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
|
color: Theme.surfaceContainerHigh
|
||||||
|
|
||||||
DankActionButton {
|
DankActionButton {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
@@ -252,7 +252,7 @@ PluginComponent {
|
|||||||
width: parent ? parent.width : 300
|
width: parent ? parent.width : 300
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceLight
|
color: Theme.surfaceContainerHighest
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: Theme.outlineLight
|
border.color: Theme.outlineLight
|
||||||
opacity: 1.0
|
opacity: 1.0
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ Row {
|
|||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
color: Theme.surfaceContainer
|
||||||
border.color: Theme.primarySelected
|
border.color: Theme.primarySelected
|
||||||
border.width: 0
|
border.width: 0
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|||||||
@@ -207,9 +207,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: deviceMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: modelData === AudioService.source ? Theme.primary : Theme.outlineLight
|
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: modelData === AudioService.source ? 2 : 1
|
border.width: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|||||||
@@ -218,9 +218,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: deviceMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: modelData === AudioService.sink ? Theme.primary : Theme.outlineLight
|
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: modelData === AudioService.sink ? 2 : 1
|
border.width: 0
|
||||||
|
|
||||||
DankRipple {
|
DankRipple {
|
||||||
id: deviceRipple
|
id: deviceRipple
|
||||||
@@ -397,9 +397,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceLight
|
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: modelData === AudioService.sink ? Theme.primary : Theme.outlineLight
|
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: modelData === AudioService.sink ? 2 : 1
|
border.width: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|||||||
@@ -129,9 +129,8 @@ Rectangle {
|
|||||||
width: (parent.width - Theme.spacingM) / 2
|
width: (parent.width - Theme.spacingM) / 2
|
||||||
height: 64
|
height: 64
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceLight
|
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: Theme.outlineLight
|
border.width: 0
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -165,9 +164,8 @@ Rectangle {
|
|||||||
width: (parent.width - Theme.spacingM) / 2
|
width: (parent.width - Theme.spacingM) / 2
|
||||||
height: 64
|
height: 64
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceLight
|
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: Theme.outlineLight
|
border.width: 0
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ Item {
|
|||||||
width: 320
|
width: 320
|
||||||
height: contentColumn.implicitHeight + Theme.spacingL * 2
|
height: contentColumn.implicitHeight + Theme.spacingL * 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
color: Theme.surfaceContainer
|
||||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
|
||||||
border.width: 0
|
border.width: 0
|
||||||
opacity: modalVisible ? 1 : 0
|
opacity: modalVisible ? 1 : 0
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
border.width: 0
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (!isConnected)
|
if (!isConnected)
|
||||||
@@ -242,8 +243,8 @@ Rectangle {
|
|||||||
if (isConnecting)
|
if (isConnecting)
|
||||||
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12);
|
return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.12);
|
||||||
if (deviceMouseArea.containsMouse)
|
if (deviceMouseArea.containsMouse)
|
||||||
return Theme.primaryHoverLight;
|
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08);
|
||||||
return Theme.surfaceLight;
|
return Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency);
|
||||||
}
|
}
|
||||||
|
|
||||||
border.color: {
|
border.color: {
|
||||||
@@ -251,9 +252,8 @@ Rectangle {
|
|||||||
return Theme.warning;
|
return Theme.warning;
|
||||||
if (isConnected)
|
if (isConnected)
|
||||||
return Theme.primary;
|
return Theme.primary;
|
||||||
return Theme.outlineLight;
|
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12);
|
||||||
}
|
}
|
||||||
border.width: (isConnecting || isConnected) ? 2 : 1
|
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -490,9 +490,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 50
|
height: 50
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: availableMouseArea.containsMouse && isInteractive ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: availableMouseArea.containsMouse && isInteractive ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: Theme.outlineLight
|
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: 1
|
border.width: 0
|
||||||
opacity: isInteractive ? 1 : 0.6
|
opacity: isInteractive ? 1 : 0.6
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: 80
|
height: 80
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceLight
|
color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: modelData.mount === currentMountPath ? Theme.primary : Theme.outlineLight
|
border.color: modelData.mount === currentMountPath ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: modelData.mount === currentMountPath ? 2 : 1
|
border.width: modelData.mount === currentMountPath ? 2 : 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|||||||
@@ -308,9 +308,9 @@ Rectangle {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
height: wiredContentRow.implicitHeight + Theme.spacingM * 2
|
height: wiredContentRow.implicitHeight + Theme.spacingM * 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: wiredNetworkMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: wiredNetworkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: isActive ? Theme.primary : Theme.outlineLight
|
border.color: Theme.primary
|
||||||
border.width: isActive ? 2 : 1
|
border.width: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: wiredContentRow
|
id: wiredContentRow
|
||||||
@@ -565,9 +565,9 @@ Rectangle {
|
|||||||
width: wifiContent.width
|
width: wifiContent.width
|
||||||
height: wifiContentRow.implicitHeight + Theme.spacingM * 2
|
height: wifiContentRow.implicitHeight + Theme.spacingM * 2
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: networkMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.surfaceLight
|
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
|
||||||
border.color: wifiDelegate.isConnected ? Theme.primary : Theme.outlineLight
|
border.color: wifiDelegate.isConnected ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
|
||||||
border.width: wifiDelegate.isConnected ? 2 : 1
|
border.width: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: wifiContentRow
|
id: wifiContentRow
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ BasePill {
|
|||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
id: cpuBaseline
|
id: cpuBaseline
|
||||||
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
|
||||||
text: "100%"
|
text: "88%"
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledTextMetrics {
|
StyledTextMetrics {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ BasePill {
|
|||||||
|
|
||||||
if (isMouseWheelY) {
|
if (isMouseWheelY) {
|
||||||
if (deltaY > 0) {
|
if (deltaY > 0) {
|
||||||
MprisController.previousOrRewind();
|
activePlayer.previous();
|
||||||
} else {
|
} else {
|
||||||
activePlayer.next();
|
activePlayer.next();
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ BasePill {
|
|||||||
scrollAccumulatorY += deltaY;
|
scrollAccumulatorY += deltaY;
|
||||||
if (Math.abs(scrollAccumulatorY) >= touchpadThreshold) {
|
if (Math.abs(scrollAccumulatorY) >= touchpadThreshold) {
|
||||||
if (scrollAccumulatorY > 0) {
|
if (scrollAccumulatorY > 0) {
|
||||||
MprisController.previousOrRewind();
|
activePlayer.previous();
|
||||||
} else {
|
} else {
|
||||||
activePlayer.next();
|
activePlayer.next();
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ BasePill {
|
|||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
activePlayer.togglePlaying();
|
activePlayer.togglePlaying();
|
||||||
} else if (mouse.button === Qt.MiddleButton) {
|
} else if (mouse.button === Qt.MiddleButton) {
|
||||||
MprisController.previousOrRewind();
|
activePlayer.previous();
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
activePlayer.next();
|
activePlayer.next();
|
||||||
}
|
}
|
||||||
@@ -370,7 +370,11 @@ BasePill {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: root.playerAvailable
|
enabled: root.playerAvailable
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: MprisController.previousOrRewind()
|
onClicked: {
|
||||||
|
if (activePlayer) {
|
||||||
|
activePlayer.previous();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,46 +20,6 @@ Item {
|
|||||||
property var blurBarWindow: null
|
property var blurBarWindow: null
|
||||||
property var hyprlandOverviewLoader: null
|
property var hyprlandOverviewLoader: null
|
||||||
property var parentScreen: null
|
property var parentScreen: null
|
||||||
|
|
||||||
readonly property real _leftMargin: {
|
|
||||||
if (isVertical)
|
|
||||||
return 0;
|
|
||||||
root.x;
|
|
||||||
if (!root.parent)
|
|
||||||
return 0;
|
|
||||||
const gap = root.mapToItem(null, 0, 0).x;
|
|
||||||
return (gap > 0 && gap < 30) ? gap + 5 : 0;
|
|
||||||
}
|
|
||||||
readonly property real _rightMargin: {
|
|
||||||
if (isVertical)
|
|
||||||
return 0;
|
|
||||||
root.x;
|
|
||||||
root.width;
|
|
||||||
if (!root.parent || !blurBarWindow)
|
|
||||||
return 0;
|
|
||||||
const gap = blurBarWindow.width - root.mapToItem(null, root.width, 0).x;
|
|
||||||
return (gap > 0 && gap < 30) ? gap + 5 : 0;
|
|
||||||
}
|
|
||||||
readonly property real _topMargin: {
|
|
||||||
if (!isVertical)
|
|
||||||
return 0;
|
|
||||||
root.y;
|
|
||||||
if (!root.parent)
|
|
||||||
return 0;
|
|
||||||
const gap = root.mapToItem(null, 0, 0).y;
|
|
||||||
return (gap > 0 && gap < 30) ? gap + 5 : 0;
|
|
||||||
}
|
|
||||||
readonly property real _bottomMargin: {
|
|
||||||
if (!isVertical)
|
|
||||||
return 0;
|
|
||||||
root.y;
|
|
||||||
root.height;
|
|
||||||
if (!root.parent || !blurBarWindow)
|
|
||||||
return 0;
|
|
||||||
const gap = blurBarWindow.height - root.mapToItem(null, 0, root.height).y;
|
|
||||||
return (gap > 0 && gap < 30) ? gap + 5 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
property int _desktopEntriesUpdateTrigger: 0
|
property int _desktopEntriesUpdateTrigger: 0
|
||||||
readonly property var sortedToplevels: {
|
readonly property var sortedToplevels: {
|
||||||
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName);
|
return CompositorService.filterCurrentWorkspace(CompositorService.sortedToplevels, screenName);
|
||||||
@@ -579,60 +539,6 @@ Item {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchToWorkspaceByModelData(data) {
|
|
||||||
if (!data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (root.useExtWorkspace && (data.id || data.name)) {
|
|
||||||
ExtWorkspaceService.activateWorkspace(data.id || data.name, data.groupID || "");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (CompositorService.compositor) {
|
|
||||||
case "niri":
|
|
||||||
if (data.idx !== undefined)
|
|
||||||
NiriService.switchToWorkspace(data.idx);
|
|
||||||
break;
|
|
||||||
case "hyprland":
|
|
||||||
if (data.id)
|
|
||||||
Hyprland.dispatch(`workspace ${data.id}`);
|
|
||||||
break;
|
|
||||||
case "dwl":
|
|
||||||
if (data.tag !== undefined)
|
|
||||||
DwlService.switchToTag(root.screenName, data.tag);
|
|
||||||
break;
|
|
||||||
case "sway":
|
|
||||||
case "scroll":
|
|
||||||
case "miracle":
|
|
||||||
if (data.num)
|
|
||||||
try {
|
|
||||||
I3.dispatch(`workspace number ${data.num}`);
|
|
||||||
} catch (_) {}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findClosestWorkspaceIndex(localX, localY) {
|
|
||||||
if (workspaceRepeater.count === 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
let closestIdx = -1;
|
|
||||||
let closestDist = Infinity;
|
|
||||||
|
|
||||||
for (let i = 0; i < workspaceRepeater.count; i++) {
|
|
||||||
const item = workspaceRepeater.itemAt(i);
|
|
||||||
if (!item)
|
|
||||||
continue;
|
|
||||||
const center = item.mapToItem(root, item.width / 2, item.height / 2);
|
|
||||||
const dist = isVertical ? Math.abs(localY - center.y) : Math.abs(localX - center.x);
|
|
||||||
if (dist < closestDist) {
|
|
||||||
closestDist = dist;
|
|
||||||
closestIdx = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return closestIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
function switchWorkspace(direction) {
|
function switchWorkspace(direction) {
|
||||||
if (useExtWorkspace) {
|
if (useExtWorkspace) {
|
||||||
const realWorkspaces = getRealWorkspaces();
|
const realWorkspaces = getRealWorkspaces();
|
||||||
@@ -846,15 +752,8 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: edgeMouseArea
|
anchors.fill: parent
|
||||||
z: -1
|
acceptedButtons: Qt.RightButton
|
||||||
x: -root._leftMargin
|
|
||||||
y: -root._topMargin
|
|
||||||
width: root.width + root._leftMargin + root._rightMargin
|
|
||||||
height: root.height + root._topMargin + root._bottomMargin
|
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
|
|
||||||
property real touchpadAccumulator: 0
|
property real touchpadAccumulator: 0
|
||||||
property real mouseAccumulator: 0
|
property real mouseAccumulator: 0
|
||||||
@@ -867,20 +766,12 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: mouse => {
|
onClicked: mouse => {
|
||||||
const rootPos = edgeMouseArea.mapToItem(root, mouse.x, mouse.y);
|
if (mouse.button === Qt.RightButton) {
|
||||||
switch (mouse.button) {
|
|
||||||
case Qt.RightButton:
|
|
||||||
if (CompositorService.isNiri) {
|
if (CompositorService.isNiri) {
|
||||||
NiriService.toggleOverview();
|
NiriService.toggleOverview();
|
||||||
} else if (CompositorService.isHyprland && root.hyprlandOverviewLoader?.item) {
|
} else if (CompositorService.isHyprland && root.hyprlandOverviewLoader?.item) {
|
||||||
root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen;
|
root.hyprlandOverviewLoader.item.overviewOpen = !root.hyprlandOverviewLoader.item.overviewOpen;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case Qt.LeftButton:
|
|
||||||
const idx = root.findClosestWorkspaceIndex(rootPos.x, rootPos.y);
|
|
||||||
if (idx >= 0)
|
|
||||||
root.switchToWorkspaceByModelData(root.workspaceList[idx]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -487,7 +487,17 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: MprisController.previousOrRewind()
|
onClicked: {
|
||||||
|
if (!activePlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activePlayer.position > 8 && activePlayer.canSeek) {
|
||||||
|
activePlayer.position = 0;
|
||||||
|
} else {
|
||||||
|
activePlayer.previous();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,14 @@ Card {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: MprisController.previousOrRewind()
|
onClicked: {
|
||||||
|
if (!activePlayer) return
|
||||||
|
if (activePlayer.position > 8 && activePlayer.canSeek) {
|
||||||
|
activePlayer.position = 0
|
||||||
|
} else {
|
||||||
|
activePlayer.previous()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1338,7 +1338,7 @@ Item {
|
|||||||
enabled: MprisController.activePlayer?.canGoPrevious ?? false
|
enabled: MprisController.activePlayer?.canGoPrevious ?? false
|
||||||
hoverEnabled: enabled
|
hoverEnabled: enabled
|
||||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
onClicked: MprisController.previousOrRewind()
|
onClicked: MprisController.activePlayer?.previous()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -51,14 +52,15 @@ Column {
|
|||||||
height: implicitHeight
|
height: implicitHeight
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
Row {
|
RowLayout {
|
||||||
|
width: parent.width
|
||||||
spacing: Theme.spacingM
|
spacing: Theme.spacingM
|
||||||
|
|
||||||
DankIcon {
|
DankIcon {
|
||||||
name: root.titleIcon
|
name: root.titleIcon
|
||||||
size: Theme.iconSize
|
size: Theme.iconSize
|
||||||
color: Theme.primary
|
color: Theme.primary
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
@@ -66,7 +68,7 @@ Column {
|
|||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
font.weight: Font.Medium
|
font.weight: Font.Medium
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,26 +981,10 @@ Column {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: [
|
model: [
|
||||||
{
|
{ label: I18n.tr("Percentage"), mode: 0, icon: "percent" },
|
||||||
label: I18n.tr("Percentage"),
|
{ label: I18n.tr("Total"), mode: 1, icon: "storage" },
|
||||||
mode: 0,
|
{ label: I18n.tr("Remaining"), mode: 2, icon: "hourglass_empty" },
|
||||||
icon: "percent"
|
{ label: I18n.tr("Remaining / Total"), mode: 3, icon: "pie_chart" }
|
||||||
},
|
|
||||||
{
|
|
||||||
label: I18n.tr("Total"),
|
|
||||||
mode: 1,
|
|
||||||
icon: "storage"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: I18n.tr("Remaining"),
|
|
||||||
mode: 2,
|
|
||||||
icon: "hourglass_empty"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: I18n.tr("Remaining / Total"),
|
|
||||||
mode: 3,
|
|
||||||
icon: "pie_chart"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
@@ -1330,7 +1316,20 @@ Column {
|
|||||||
id: longestControlCenterLabelMetrics
|
id: longestControlCenterLabelMetrics
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
text: {
|
text: {
|
||||||
const labels = [I18n.tr("Network"), I18n.tr("VPN"), I18n.tr("Bluetooth"), I18n.tr("Audio"), I18n.tr("Volume"), I18n.tr("Microphone"), I18n.tr("Microphone Volume"), I18n.tr("Brightness"), I18n.tr("Brightness Value"), I18n.tr("Battery"), I18n.tr("Printer"), I18n.tr("Screen Sharing")];
|
const labels = [
|
||||||
|
I18n.tr("Network"),
|
||||||
|
I18n.tr("VPN"),
|
||||||
|
I18n.tr("Bluetooth"),
|
||||||
|
I18n.tr("Audio"),
|
||||||
|
I18n.tr("Volume"),
|
||||||
|
I18n.tr("Microphone"),
|
||||||
|
I18n.tr("Microphone Volume"),
|
||||||
|
I18n.tr("Brightness"),
|
||||||
|
I18n.tr("Brightness Value"),
|
||||||
|
I18n.tr("Battery"),
|
||||||
|
I18n.tr("Printer"),
|
||||||
|
I18n.tr("Screen Sharing")
|
||||||
|
];
|
||||||
let longest = "";
|
let longest = "";
|
||||||
for (let i = 0; i < labels.length; i++) {
|
for (let i = 0; i < labels.length; i++) {
|
||||||
if (labels[i].length > longest.length)
|
if (labels[i].length > longest.length)
|
||||||
@@ -1341,7 +1340,6 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: groupRepeater
|
|
||||||
model: controlCenterContextMenu.controlCenterGroups
|
model: controlCenterContextMenu.controlCenterGroups
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
@@ -1571,6 +1569,8 @@ Column {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id: groupRepeater
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
|
||||||
import Quickshell.Wayland // ! Import is needed despite what qmlls says
|
import Quickshell.Wayland // ! Import is needed despite what qmlls says
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool quickshellSupported: false
|
property bool available: false
|
||||||
property bool compositorSupported: false
|
|
||||||
property bool available: quickshellSupported && compositorSupported
|
|
||||||
readonly property bool enabled: available && (SettingsData.blurEnabled ?? false)
|
readonly property bool enabled: available && (SettingsData.blurEnabled ?? false)
|
||||||
|
|
||||||
readonly property color borderColor: {
|
readonly property color borderColor: {
|
||||||
@@ -75,27 +72,6 @@ Singleton {
|
|||||||
region.destroy();
|
region.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: blurProbe
|
|
||||||
running: false
|
|
||||||
command: ["dms", "blur", "check"]
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
root.compositorSupported = text.trim() === "supported";
|
|
||||||
if (root.compositorSupported)
|
|
||||||
console.info("BlurService: Compositor supports ext-background-effect-v1");
|
|
||||||
else
|
|
||||||
console.info("BlurService: Compositor does not support ext-background-effect-v1");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExited: exitCode => {
|
|
||||||
if (exitCode !== 0)
|
|
||||||
console.warn("BlurService: blur probe failed with code:", exitCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
try {
|
try {
|
||||||
const test = Qt.createQmlObject(`
|
const test = Qt.createQmlObject(`
|
||||||
@@ -103,9 +79,8 @@ Singleton {
|
|||||||
Region { radius: 0 }
|
Region { radius: 0 }
|
||||||
`, root, "BlurAvailabilityTest");
|
`, root, "BlurAvailabilityTest");
|
||||||
test.destroy();
|
test.destroy();
|
||||||
quickshellSupported = true;
|
available = true;
|
||||||
console.info("BlurService: Quickshell blur support available");
|
console.info("BlurService: Initialized with blur support");
|
||||||
blurProbe.running = true;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.info("BlurService: BackgroundEffect not available - blur disabled. Requires a newer version of Quickshell.");
|
console.info("BlurService: BackgroundEffect not available - blur disabled. Requires a newer version of Quickshell.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,20 +10,4 @@ Singleton {
|
|||||||
|
|
||||||
readonly property list<MprisPlayer> availablePlayers: Mpris.players.values
|
readonly property list<MprisPlayer> availablePlayers: Mpris.players.values
|
||||||
property MprisPlayer activePlayer: availablePlayers.find(p => p.isPlaying) ?? availablePlayers.find(p => p.canControl && p.canPlay) ?? null
|
property MprisPlayer activePlayer: availablePlayers.find(p => p.isPlaying) ?? availablePlayers.find(p => p.canControl && p.canPlay) ?? null
|
||||||
|
|
||||||
Timer {
|
|
||||||
interval: 1000
|
|
||||||
running: root.activePlayer?.playbackState === MprisPlaybackState.Playing
|
|
||||||
repeat: true
|
|
||||||
onTriggered: root.activePlayer?.positionChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
function previousOrRewind(): void {
|
|
||||||
if (!activePlayer)
|
|
||||||
return;
|
|
||||||
if (activePlayer.position > 8 && activePlayer.canSeek)
|
|
||||||
activePlayer.position = 0;
|
|
||||||
else if (activePlayer.canGoPrevious)
|
|
||||||
activePlayer.previous();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Row {
|
|||||||
width: Math.max(contentItem.implicitWidth + root.buttonPadding * 2, root.minButtonWidth) + (selected ? 4 : 0)
|
width: Math.max(contentItem.implicitWidth + root.buttonPadding * 2, root.minButtonWidth) + (selected ? 4 : 0)
|
||||||
height: root.buttonHeight
|
height: root.buttonHeight
|
||||||
|
|
||||||
color: selected ? Theme.buttonBg : Theme.withAlpha(Theme.surfaceVariant, Theme.popupTransparency)
|
color: selected ? Theme.buttonBg : Theme.surfaceVariant
|
||||||
border.color: "transparent"
|
border.color: "transparent"
|
||||||
border.width: 0
|
border.width: 0
|
||||||
|
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ PanelWindow {
|
|||||||
scale: shouldBeVisible ? 1 : 0.9
|
scale: shouldBeVisible ? 1 : 0.9
|
||||||
|
|
||||||
property bool childHovered: false
|
property bool childHovered: false
|
||||||
readonly property real popupSurfaceAlpha: Theme.popupTransparency
|
readonly property real popupSurfaceAlpha: SettingsData.popupTransparency
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: background
|
id: background
|
||||||
@@ -286,7 +286,7 @@ PanelWindow {
|
|||||||
level: Theme.elevationLevel3
|
level: Theme.elevationLevel3
|
||||||
fallbackOffset: 6
|
fallbackOffset: 6
|
||||||
targetRadius: Theme.cornerRadius
|
targetRadius: Theme.cornerRadius
|
||||||
targetColor: Theme.withAlpha(Theme.surfaceContainer, osdContainer.popupSurfaceAlpha)
|
targetColor: Theme.surfaceContainer
|
||||||
borderColor: Theme.outlineMedium
|
borderColor: Theme.outlineMedium
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
|
||||||
|
|||||||
@@ -576,6 +576,14 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
|
||||||
|
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
|
||||||
|
border.width: BlurService.borderWidth
|
||||||
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: contentLoader
|
id: contentLoader
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@@ -583,21 +591,6 @@ Item {
|
|||||||
asynchronous: false
|
asynchronous: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
x: contentWrapper.x
|
|
||||||
y: contentWrapper.y
|
|
||||||
opacity: contentWrapper.opacity
|
|
||||||
scale: contentWrapper.scale
|
|
||||||
visible: contentWrapper.visible
|
|
||||||
radius: Theme.cornerRadius
|
|
||||||
color: "transparent"
|
|
||||||
border.color: BlurService.enabled ? BlurService.borderColor : Theme.outlineMedium
|
|
||||||
border.width: BlurService.borderWidth
|
|
||||||
z: 100
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ Rectangle {
|
|||||||
width: fieldContent.width + Theme.spacingM * 2
|
width: fieldContent.width + Theme.spacingM * 2
|
||||||
height: 32
|
height: 32
|
||||||
radius: Theme.cornerRadius - 2
|
radius: Theme.cornerRadius - 2
|
||||||
color: Theme.surfaceLight
|
color: Theme.surfaceContainerHigh
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: Theme.outlineLight
|
border.color: Theme.outlineLight
|
||||||
|
|
||||||
@@ -272,9 +272,7 @@ Rectangle {
|
|||||||
checked: configData ? (configData.autoconnect || false) : false
|
checked: configData ? (configData.autoconnect || false) : false
|
||||||
visible: !VPNService.configLoading && configData !== null
|
visible: !VPNService.configLoading && configData !== null
|
||||||
onToggled: checked => {
|
onToggled: checked => {
|
||||||
VPNService.updateConfig(profile.uuid, {
|
VPNService.updateConfig(profile.uuid, {autoconnect: checked});
|
||||||
autoconnect: checked
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user