Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ enum class EWindowCollectionMode {
- `CViewGesture::begin/update/end()` - Swipe gesture handling

### Global Configuration Values
Located in `main.cpp`, registered via `HyprlandAPI::addConfigValue`:
Located in `main.cpp`, registered via `HyprlandAPI::addConfigValueV2`:
- `plugin:hyprview:active_border_color`
- `plugin:hyprview:inactive_border_color`
- `plugin:hyprview:border_width`
Expand Down Expand Up @@ -112,7 +112,7 @@ The plugin provides flexible dispatcher commands with various options:
### Gesture Handling
- 3-finger swipe gestures handled by `CViewGesture`
- Swipe detection uses distance threshold from config
- Gestures blocked when overview is active to prevent conflicts
- Legacy gestures blocked when overview is active to prevent conflicts; Lua callbacks remain available
- Swipe gestures support opening and closing the overview
- Configurable via `hyprview-gesture` keyword

Expand Down
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ https://github.com/user-attachments/assets/c0553bfe-6357-48e5-a4d0-50068096d800
* **Workspace Indicator:** Each window tile shows its workspace ID (displayed as "wsid:N") in a configurable position with customizable size and styling. The indicator color automatically matches the window's border color (active or inactive) for easy navigation across multiple workspaces.
* **Window Selection:** Hover to focus and click to select a window, automatically closing the overview.
* **Trackpad Gestures:** Use swipe gestures to open and close the overview.
* **Gesture Conflict Prevention:** Automatically blocks workspace gestures when overview is active to prevent accidental workspace switches.
* **Gesture Conflict Prevention:** Blocks workspace gestures in legacy configurations. Lua configurations retain their configured gesture callbacks while the overview is open.
* **Smooth Animations:** Animated transitions when opening/closing the overview.
* **Multi-monitor Support:** Provides a separate overview for each monitor with proper scaling and positioning.
* **Customizable Appearance:** Change colors, borders, margins, background dimming, and radii.
Expand All @@ -51,6 +51,32 @@ hyprpm enable hyprview
plugin = /full_path_to/hyprview.so
```

### Lua configuration (Hyprland 0.56)

Load the plugin before invoking its callbacks. The plugin registers settings with
Hyprland's typed configuration API and exposes `hl.plugin.hyprview.toggle(args)`.
It accepts the same arguments as the `hyprview:toggle` dispatcher and returns
`success, error`. Call it inside a gesture or binding callback, after loading:

```lua
hl.gesture({ fingers = 3, direction = "up", action = function()
if hl.plugin.hyprview then
hl.plugin.hyprview.toggle("on all special")
end
end })
hl.gesture({ fingers = 3, direction = "down", action = function()
if hl.plugin.hyprview then
hl.plugin.hyprview.toggle("off")
end
end })
```

An explicit `off` closes an overview opened with `on`; add `monitor:NAME` to
close only that monitor. Lua gestures remain enabled while the overview is open,
so a downward callback can close it. Avoid assigning competing workspace gestures
to the same fingers/direction. Legacy `hyprview-gesture` remains available in
`hyprland.conf`.

### Keybinds

You can bind the overview to a key. The dispatcher accepts optional arguments to control the behavior.
Expand Down
131 changes: 39 additions & 92 deletions src/hyprview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ using Desktop::View::CWindow;
// Helper to find the CHyprView instance for a given animation variable
CHyprView *findInstanceForAnimation(
WP<Hyprutils::Animation::CBaseAnimatedVariable> thisptr) {
if (!thisptr)
return nullptr;
for (auto &[monitor, instance] : g_pHyprViewInstances) {
if (instance && (instance->size.get() == thisptr.lock().get() ||
instance->pos.get() == thisptr.lock().get() ||
instance->scale.get() == thisptr.lock().get())) {
if (instance && (instance->size.get() == thisptr.get() ||
instance->pos.get() == thisptr.get() ||
instance->scale.get() == thisptr.get())) {
return instance.get();
}
}
Expand Down Expand Up @@ -264,91 +266,39 @@ CHyprView::CHyprView(PHLMONITOR pMonitor_, PHLWORKSPACE startedOn_, bool swipe_,
Debug::log(LOG, "[hyprview] CHyprView(): Saved original focused window: {}",
(void *)origWindow.get());

static auto *const *PMARGIN =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:margin")
->getDataStaticPtr();

MARGIN = **PMARGIN;

static auto *const *PACTIVEBORDERCOL =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:active_border_color")
->getDataStaticPtr();
static auto *const *PINACTIVEBORDERCOL =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:inactive_border_color")
->getDataStaticPtr();
static auto *const *PBORDERWIDTH =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:border_width")
->getDataStaticPtr();
static auto *const *PBORDERRADIUS =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:border_radius")
->getDataStaticPtr();
static auto *const *PBGDIM =
(Hyprlang::FLOAT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:bg_dim")
->getDataStaticPtr();
static auto *const *PWORKSPACEINDICATORENABLED =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:workspace_indicator_enabled")
->getDataStaticPtr();
static auto *const *PWORKSPACEINDICATORFONTSIZE =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:workspace_indicator_font_size")
->getDataStaticPtr();
static auto PWORKSPACEINDICATORPOSITION_VAL = HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:workspace_indicator_position");
static auto *const *PWORKSPACEINDICATORBGOPACITY =
(Hyprlang::FLOAT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:workspace_indicator_bg_opacity")
->getDataStaticPtr();
static auto *const *PWINDOWNAMEENABLED =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:window_name_enabled")
->getDataStaticPtr();
static auto *const *PWINDOWNAMEFONTSIZE =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:window_name_font_size")
->getDataStaticPtr();
static auto *const *PWINDOWNAMEBGOPACITY =
(Hyprlang::FLOAT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:window_name_bg_opacity")
->getDataStaticPtr();
static auto *const *PWINDOWTEXTCOLOR =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:window_text_color")
->getDataStaticPtr();

ACTIVE_BORDER_COLOR = **PACTIVEBORDERCOL;
INACTIVE_BORDER_COLOR = **PINACTIVEBORDERCOL;
BORDER_WIDTH = **PBORDERWIDTH;
BORDER_RADIUS = **PBORDERRADIUS;
BG_DIM = **PBGDIM;
WORKSPACE_INDICATOR_ENABLED = **PWORKSPACEINDICATORENABLED != 0;
WORKSPACE_INDICATOR_FONT_SIZE = **PWORKSPACEINDICATORFONTSIZE;
WORKSPACE_INDICATOR_BG_OPACITY = **PWORKSPACEINDICATORBGOPACITY;
static const CConfigValue<Config::INTEGER> PMARGIN("plugin:hyprview:margin");

MARGIN = *PMARGIN;

static const CConfigValue<Config::INTEGER> PACTIVEBORDERCOL("plugin:hyprview:active_border_color");
static const CConfigValue<Config::INTEGER> PINACTIVEBORDERCOL("plugin:hyprview:inactive_border_color");
static const CConfigValue<Config::INTEGER> PBORDERWIDTH("plugin:hyprview:border_width");
static const CConfigValue<Config::INTEGER> PBORDERRADIUS("plugin:hyprview:border_radius");
static const CConfigValue<Config::FLOAT> PBGDIM("plugin:hyprview:bg_dim");
static const CConfigValue<Config::INTEGER> PWORKSPACEINDICATORENABLED("plugin:hyprview:workspace_indicator_enabled");
static const CConfigValue<Config::INTEGER> PWORKSPACEINDICATORFONTSIZE("plugin:hyprview:workspace_indicator_font_size");
static const CConfigValue<Config::STRING> PWORKSPACEINDICATORPOSITION_VAL("plugin:hyprview:workspace_indicator_position");
static const CConfigValue<Config::FLOAT> PWORKSPACEINDICATORBGOPACITY("plugin:hyprview:workspace_indicator_bg_opacity");
static const CConfigValue<Config::INTEGER> PWINDOWNAMEENABLED("plugin:hyprview:window_name_enabled");
static const CConfigValue<Config::INTEGER> PWINDOWNAMEFONTSIZE("plugin:hyprview:window_name_font_size");
static const CConfigValue<Config::FLOAT> PWINDOWNAMEBGOPACITY("plugin:hyprview:window_name_bg_opacity");
static const CConfigValue<Config::INTEGER> PWINDOWTEXTCOLOR("plugin:hyprview:window_text_color");

ACTIVE_BORDER_COLOR = *PACTIVEBORDERCOL;
INACTIVE_BORDER_COLOR = *PINACTIVEBORDERCOL;
BORDER_WIDTH = *PBORDERWIDTH;
BORDER_RADIUS = *PBORDERRADIUS;
BG_DIM = *PBGDIM;
WORKSPACE_INDICATOR_ENABLED = *PWORKSPACEINDICATORENABLED != 0;
WORKSPACE_INDICATOR_FONT_SIZE = *PWORKSPACEINDICATORFONTSIZE;
WORKSPACE_INDICATOR_BG_OPACITY = *PWORKSPACEINDICATORBGOPACITY;
WORKSPACE_INDICATOR_POSITION = "";
WINDOW_NAME_ENABLED = **PWINDOWNAMEENABLED != 0;
WINDOW_NAME_FONT_SIZE = **PWINDOWNAMEFONTSIZE;
WINDOW_NAME_BG_OPACITY = **PWINDOWNAMEBGOPACITY;
WINDOW_TEXT_COLOR = **PWINDOWTEXTCOLOR;

try {
if (PWORKSPACEINDICATORPOSITION_VAL) {
if (auto strPtr =
(Hyprlang::STRING const *)
PWORKSPACEINDICATORPOSITION_VAL->getDataStaticPtr()) {
if (*strPtr) {
WORKSPACE_INDICATOR_POSITION = *strPtr;
}
}
}
} catch (...) {
// Keep default on any exception
}
WINDOW_NAME_ENABLED = *PWINDOWNAMEENABLED != 0;
WINDOW_NAME_FONT_SIZE = *PWINDOWNAMEFONTSIZE;
WINDOW_NAME_BG_OPACITY = *PWINDOWNAMEBGOPACITY;
WINDOW_TEXT_COLOR = *PWINDOWTEXTCOLOR;

WORKSPACE_INDICATOR_POSITION = *PWORKSPACEINDICATORPOSITION_VAL;

std::vector<PHLWINDOW> windowsToRender;

Expand Down Expand Up @@ -1236,15 +1186,12 @@ void CHyprView::onSwipeUpdate(double delta) {
if (swipeWasCommenced)
return;

static auto *const *PDISTANCE =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprview:gesture_distance")
->getDataStaticPtr();
static const CConfigValue<Config::INTEGER> PDISTANCE("plugin:hyprview:gesture_distance");

// Calculate progress percentage based on swipe direction
// For opening: delta 0 -> distance means scale 0 -> 1 (original -> tile)
// For closing: delta 0 -> distance means scale 1 -> 0 (tile -> original)
const float PERC = std::clamp(delta / (double)**PDISTANCE, 0.0, 1.0);
const float PERC = std::clamp(delta / (double)*PDISTANCE, 0.0, 1.0);
scale->setValueAndWarp(closing ? (1.0f - PERC) : PERC);
}

Expand Down
Loading