diff --git a/metadata/pixdecor.xml b/metadata/pixdecor.xml
index 7c50e8a..d801bd4 100644
--- a/metadata/pixdecor.xml
+++ b/metadata/pixdecor.xml
@@ -122,6 +122,11 @@
<_long>Sculpted overlay only: when keyboard focus lands on a window you are not pointing at (a window closed and the next one took over, keyboard switching, an app activating itself), its frame edge lights up for a moment so you can see where typing goes. Clicking or hovering a window, and windows that just opened, do not flash.
true
+
+ <_short>Also when the pointer moves focus
+ <_long>Also flash when focus moves to the window under the pointer: hovering into it with follow-focus, or clicking it.
+ false
+
<_short>Flash width
<_long>Width of the flashing band along the frame's outer edge, in pixels.
diff --git a/src/decoration.cpp b/src/decoration.cpp
index bebd6f4..8bbf7e3 100644
--- a/src/decoration.cpp
+++ b/src/decoration.cpp
@@ -53,6 +53,7 @@ class wayfire_pixdecor : public wf::plugin_interface_t
// Focus flash (focus-flash.hpp). Keyboard focus changes are judged once the
// event loop is idle, so a burst of changes flashes only where focus ends.
wf::option_wrapper_t focus_flash_enabled{"pixdecor/focus_flash"};
+ wf::option_wrapper_t focus_flash_pointer{"pixdecor/focus_flash_pointer"};
std::weak_ptr focused_window; // the app window that last had keyboard focus
wf::wl_idle_call judge_focus;
struct mapped_at_t : public wf::custom_data_t
@@ -103,6 +104,7 @@ class wayfire_pixdecor : public wf::plugin_interface_t
auto at = core.scene()->find_node_at(core.get_cursor_position());
auto under = at ? wf::toplevel_cast(wf::node_to_view(at->node.get())) : nullptr;
change.under_pointer = same_window(under, view);
+ change.pointer_too = focus_flash_pointer;
if (focus_flash::should_flash(change))
{
deco->flash();
diff --git a/src/focus-flash.hpp b/src/focus-flash.hpp
index 40482ae..68de131 100644
--- a/src/focus-flash.hpp
+++ b/src/focus-flash.hpp
@@ -18,11 +18,12 @@ struct change_t
bool same_window = false; // focus was already in this window or one of its dialogs
bool just_mapped = false; // the window appeared moments ago: opening is cue enough
bool under_pointer = false; // the pointer is over the window: clicked, or hovered with follow-focus
+ bool pointer_too = false; // pixdecor/focus_flash_pointer: flash those as well
};
inline bool should_flash(const change_t& c)
{
- return c.enabled && c.framed && !c.same_window && !c.just_mapped && !c.under_pointer;
+ return c.enabled && c.framed && !c.same_window && !c.just_mapped && (!c.under_pointer || c.pointer_too);
}
// How long after mapping a window's first focus counts as part of opening it.
diff --git a/tests/focus-flash-test.cpp b/tests/focus-flash-test.cpp
index 362948d..f37804b 100644
--- a/tests/focus-flash-test.cpp
+++ b/tests/focus-flash-test.cpp
@@ -34,6 +34,12 @@ int main()
c.under_pointer = true;
assert(!should_flash(c));
+ // ... unless pointer focus flashes too (focus_flash_pointer, for follow-focus).
+ c.pointer_too = true;
+ assert(should_flash(c));
+ c.just_mapped = true; // still not for a window that just opened
+ assert(!should_flash(c));
+
// Back to the same window or between a window and its dialogs.
c = keyboard_switch();
c.same_window = true;