dock #44
No files matched your search
@@ -0,0 +1 @@
|
||||
* @S4NKALP
|
||||
@@ -2,9 +2,8 @@ name: CodeQL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
branches: [macos]
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ name: Commit Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Install Script Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
branches: [macos]
|
||||
paths:
|
||||
- "install.sh"
|
||||
- "src/window/globalmenu/**"
|
||||
@@ -10,7 +10,6 @@ on:
|
||||
- "pyproject.toml"
|
||||
- "uv.lock"
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
paths:
|
||||
- "install.sh"
|
||||
- "src/window/globalmenu/**"
|
||||
|
||||
@@ -2,9 +2,8 @@ name: Pre-commit
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev]
|
||||
branches: [macos]
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -143,6 +143,8 @@ See [Desktop Widgets Guide](docs/desktop_widgets.md) for full docs and examples.
|
||||
|
||||
## Documentation
|
||||
|
||||
> **Note:** These docs were written with the assistance of LLM tools. Some phrasing may reflect that.
|
||||
|
||||
| Doc | What's inside |
|
||||
| --------------------------------------------- | -------------------------------------------------- |
|
||||
| [Installation Guide](docs/installation.md) | Automated & manual install, dependencies |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = { extends: ["@commitlint/config-conventional"] };
|
||||
@@ -14,6 +14,7 @@ from tomlkit import document as toml_document
|
||||
from tomlkit import dump as toml_dump
|
||||
from tomlkit import item as toml_item
|
||||
from tomlkit import load as toml_load
|
||||
from tomlkit import loads as toml_loads
|
||||
|
||||
from utils.gtk_utils import toml_file
|
||||
|
||||
@@ -126,12 +127,13 @@ class ConfigService:
|
||||
self._config = toml_load(f)
|
||||
else:
|
||||
try:
|
||||
from utils.constants import DEFAULT
|
||||
from utils.constants import generate_default_toml
|
||||
|
||||
os.makedirs(os.path.dirname(self._config_file), exist_ok=True)
|
||||
self._config = self._dict_to_toml(DEFAULT)
|
||||
raw = generate_default_toml()
|
||||
self._config = toml_loads(raw)
|
||||
with open(self._config_file, "w") as f:
|
||||
toml_dump(self._config, f)
|
||||
f.write(raw)
|
||||
logger.info(
|
||||
f"[ConfigService] Generated default config at {self._config_file}"
|
||||
)
|
||||
|
||||
+17
-1
@@ -49,7 +49,13 @@ def load_config():
|
||||
service = start_config_service()
|
||||
return service.get_all()
|
||||
except ImportError:
|
||||
# Fallback to direct file loading
|
||||
pass
|
||||
|
||||
try:
|
||||
from utils.constants import generate_default_toml
|
||||
except ImportError:
|
||||
generate_default_toml = None
|
||||
|
||||
config = {}
|
||||
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
@@ -60,6 +66,16 @@ def load_config():
|
||||
config = dict(tomlkit.load(f))
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading config: {e}")
|
||||
elif generate_default_toml:
|
||||
try:
|
||||
raw = generate_default_toml()
|
||||
with open(CONFIG_FILE, "w") as f:
|
||||
f.write(raw)
|
||||
import tomlkit
|
||||
|
||||
config = dict(tomlkit.loads(raw))
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating default config: {e}")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
from tomlkit import document as _document
|
||||
from tomlkit import dumps as _dumps
|
||||
from tomlkit import table as _table
|
||||
|
||||
DEFAULT = {
|
||||
"general": {
|
||||
"debug": False,
|
||||
@@ -11,6 +15,7 @@ DEFAULT = {
|
||||
"always_occluded": False,
|
||||
"icon_size": 52,
|
||||
"hide_special_workspace_apps": True,
|
||||
"hover_scale": 1.6,
|
||||
},
|
||||
"panel": {
|
||||
"imac_button": True,
|
||||
@@ -42,3 +47,61 @@ DEFAULT = {
|
||||
"limited_apps_history": ["Spotify"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def generate_default_toml() -> str:
|
||||
"""Build default config.toml with inline comments."""
|
||||
doc = _document()
|
||||
|
||||
general = _table()
|
||||
general.add("debug", False)
|
||||
general.add("wallpapers_dir", "src/assets/wallpaper_example/")
|
||||
general.add("keyboard_layouts", ["us"])
|
||||
general.add("weather_location", "")
|
||||
doc.add("general", general)
|
||||
|
||||
dock = _table()
|
||||
dock.add("enabled", True)
|
||||
dock.add("auto_hide", True)
|
||||
dock.add("always_occluded", False)
|
||||
dock.add("icon_size", 52)
|
||||
dock.add("hide_special_workspace_apps", True)
|
||||
dock.add("hover_scale", 1.6)
|
||||
dock["hover_scale"].comment(
|
||||
"1.0 (min, no effect) to 2.0 (max) | >2.0 not recommended — icons get blurry/pixelated on hover"
|
||||
)
|
||||
doc.add("dock", dock)
|
||||
|
||||
panel = _table()
|
||||
panel.add("imac_button", True)
|
||||
panel.add("systray", True)
|
||||
panel.add("systray_ignore", ["blueman", "network"])
|
||||
panel.add("control_center", True)
|
||||
panel.add("search", True)
|
||||
panel.add("global_menu", True)
|
||||
panel.add("network", True)
|
||||
panel.add("battery", True)
|
||||
panel.add("notification_center", True)
|
||||
panel.add("workspace_indicator", True)
|
||||
panel.add("bluetooth", True)
|
||||
panel.add("date_time", True)
|
||||
panel.add("night_light_temperature", 4500)
|
||||
panel.add("notch", True)
|
||||
panel.add("osd", True)
|
||||
panel.add("hide_special_workspace", True)
|
||||
panel.add("custom_mods", True)
|
||||
doc.add("panel", panel)
|
||||
|
||||
switcher = _table()
|
||||
switcher.add("live_preview", True)
|
||||
switcher.add("live_preview_delay_ms", 200)
|
||||
switcher.add("window_switcher", True)
|
||||
doc.add("switcher", switcher)
|
||||
|
||||
notification = _table()
|
||||
notification.add("timeout", "5s")
|
||||
notification.add("ignored_apps", ["Hyprshot"])
|
||||
notification.add("limited_apps_history", ["Spotify"])
|
||||
doc.add("notification", notification)
|
||||
|
||||
return _dumps(doc)
|
||||
@@ -41,11 +41,11 @@ from .constants import (
|
||||
INDICATOR_COLOR,
|
||||
INDICATOR_H,
|
||||
INDICATOR_RADIUS,
|
||||
MAX_SCALE,
|
||||
MIN_SCALE,
|
||||
PINNED_APPS_FILE,
|
||||
SEPARATOR_COLOR,
|
||||
SEPARATOR_WIDTH,
|
||||
max_scale,
|
||||
)
|
||||
from .items import DockHitTest, DockItem, DockModel
|
||||
from .layout import DockLayout
|
||||
@@ -126,7 +126,7 @@ class DockCanvas(Gtk.DrawingArea):
|
||||
return int(config().get("dock.icon_size", 52))
|
||||
|
||||
def _icon_cache_size(self) -> int:
|
||||
return int(self._base_icon_size() * MAX_SCALE)
|
||||
return int(self._base_icon_size() * max_scale())
|
||||
|
||||
def _get_desktop_apps(self) -> list:
|
||||
if not self._desktop_apps:
|
||||
@@ -140,7 +140,7 @@ class DockCanvas(Gtk.DrawingArea):
|
||||
def _canvas_height(self) -> int:
|
||||
size = self._base_icon_size()
|
||||
return int(
|
||||
size * MAX_SCALE + CANVAS_TOP_PAD + 2 * BG_PADDING_V + INDICATOR_H + 4
|
||||
size * max_scale() + CANVAS_TOP_PAD + 2 * BG_PADDING_V + INDICATOR_H + 4
|
||||
)
|
||||
|
||||
def _canvas_max_width(self) -> int:
|
||||
@@ -149,7 +149,7 @@ class DockCanvas(Gtk.DrawingArea):
|
||||
return 200
|
||||
size = self._base_icon_size()
|
||||
return int(
|
||||
n * size * MAX_SCALE + max(n - 1, 0) * ICON_GAP + 2 * BG_PADDING_H + 40
|
||||
n * size * max_scale() + max(n - 1, 0) * ICON_GAP + 2 * BG_PADDING_H + 40
|
||||
)
|
||||
|
||||
def _canvas_min_width(self) -> int:
|
||||
@@ -655,7 +655,7 @@ class DockCanvas(Gtk.DrawingArea):
|
||||
bg_h = size + 2 * BG_PADDING_V
|
||||
bg_y = h - INDICATOR_H - bg_h
|
||||
baseline_y = bg_y + BG_PADDING_V + size
|
||||
icon_top_y = baseline_y - size * MAX_SCALE
|
||||
icon_top_y = baseline_y - size * max_scale()
|
||||
self._mouse_inside = (
|
||||
base_start_x <= event.x <= base_start_x + total_base
|
||||
and icon_top_y <= event.y <= baseline_y
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from services.config import config
|
||||
from utils.gtk_utils import toml_file
|
||||
|
||||
PINNED_APPS_FILE = toml_file("dock.toml")
|
||||
@@ -7,7 +8,11 @@ IDLE_THRESHOLD = 0.0005
|
||||
ANIM_FPS = 60
|
||||
ANIM_INTERVAL_MS = 1000 // ANIM_FPS
|
||||
|
||||
MAX_SCALE = 2.0
|
||||
|
||||
def max_scale() -> float:
|
||||
return float(config().get("dock.hover_scale", 2.0))
|
||||
|
||||
|
||||
MIN_SCALE = 1.0
|
||||
SIGMA_FACTOR = 1.3
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ from .constants import (
|
||||
BG_PADDING_V,
|
||||
ICON_GAP,
|
||||
INDICATOR_H,
|
||||
MAX_SCALE,
|
||||
MIN_SCALE,
|
||||
SIGMA_FACTOR,
|
||||
max_scale,
|
||||
)
|
||||
from .items import DockItem
|
||||
|
||||
@@ -27,7 +27,7 @@ class DockLayout:
|
||||
return
|
||||
|
||||
sigma = base_icon_size * SIGMA_FACTOR
|
||||
amplitude = MAX_SCALE - MIN_SCALE
|
||||
amplitude = max_scale() - MIN_SCALE
|
||||
|
||||
n = len(items)
|
||||
base_w = base_icon_size + ICON_GAP
|
||||
|
||||
@@ -135,6 +135,9 @@ class Dock(Window):
|
||||
if config().has_changed("dock.hide_special_workspace_apps", old_config):
|
||||
self.canvas._rebuild_model()
|
||||
|
||||
if config().has_changed("dock.hover_scale", old_config):
|
||||
self.canvas.update_icon_size()
|
||||
|
||||
def _update_visibility(self) -> None:
|
||||
if config().get("dock.enabled", True):
|
||||
self.show()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from fabric.utils import Gdk, Gtk, logger
|
||||
from fabric.utils import Gdk, Gtk
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
@@ -90,12 +90,13 @@ class SettingsEntry(Entry):
|
||||
|
||||
def on_change(self, entry, *args):
|
||||
value = entry.get_text()
|
||||
# Try to convert to int if possible
|
||||
try:
|
||||
if value.isdigit():
|
||||
value = int(value)
|
||||
except Exception as e:
|
||||
logger.error(f"An error occurred: {e}")
|
||||
else:
|
||||
value = float(value)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
config().set(self.config_key, value)
|
||||
config().save()
|
||||
@@ -400,6 +401,11 @@ class SettingsWindow(Gtk.Window):
|
||||
SettingsSwitch("dock.hide_special_workspace_apps"),
|
||||
"Hide apps from special workspace in dock",
|
||||
),
|
||||
SettingsRow(
|
||||
"Hover Scale",
|
||||
SettingsEntry("dock.hover_scale"),
|
||||
"Icon scale on hover (1.0 = off, 1.6 = default, 2.0 = max)",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -99,11 +99,7 @@ class ClipboardPlugin(SpotlightPlugin):
|
||||
def _load_history(self) -> None:
|
||||
result = run_command(["cliphist", "list"], timeout=5)
|
||||
raw = result.stdout if isinstance(result.stdout, str) else ""
|
||||
logger.info(
|
||||
f"[Clipboard] _load_history: stdout type={type(result.stdout).__name__} len={len(raw)} returncode={result.returncode}"
|
||||
)
|
||||
lines = raw.splitlines()
|
||||
logger.info(f"[Clipboard] _load_history: {len(lines)} lines from cliphist")
|
||||
new_entries = []
|
||||
for line in lines[:100]:
|
||||
if "\t" not in line:
|
||||
@@ -122,13 +118,9 @@ class ClipboardPlugin(SpotlightPlugin):
|
||||
if "binary data" in content:
|
||||
entry["type"] = "image"
|
||||
new_entries.append(entry)
|
||||
logger.info(f"[Clipboard] _load_history: parsed {len(new_entries)} entries")
|
||||
with self._history_lock:
|
||||
self._history.clear()
|
||||
self._history.extend(new_entries)
|
||||
logger.info(
|
||||
f"[Clipboard] _load_history: history now has {len(self._history)} entries"
|
||||
)
|
||||
|
||||
def _filter_entries(self, query: str) -> list[dict]:
|
||||
q = query.strip().lower()
|
||||
|
||||
Reference in new issue
Block a user