diff --git a/Services/WindowServer/WindowFrame.cpp b/Services/WindowServer/WindowFrame.cpp index d89530e59bf..6df895aa46a 100644 --- a/Services/WindowServer/WindowFrame.cpp +++ b/Services/WindowServer/WindowFrame.cpp @@ -160,6 +160,10 @@ Gfx::IntRect WindowFrame::title_bar_text_rect() const Gfx::WindowTheme::WindowState WindowFrame::window_state_for_theme() const { auto& wm = WindowManager::the(); + + if (m_flash_timer && m_flash_timer->is_active()) + return m_flash_counter & 1 ? Gfx::WindowTheme::WindowState::Active : Gfx::WindowTheme::WindowState::Inactive; + if (&m_window == wm.m_highlight_window) return Gfx::WindowTheme::WindowState::Highlighted; if (&m_window == wm.m_move_window) @@ -360,4 +364,19 @@ void WindowFrame::on_mouse_event(const MouseEvent& event) if (m_window.is_resizable() && event.type() == Event::MouseDown && event.button() == MouseButton::Left) wm.start_window_resize(m_window, event.translated(rect().location())); } + +void WindowFrame::start_flash_animation() +{ + if (!m_flash_timer) { + m_flash_timer = Core::Timer::construct(100, [this] { + ASSERT(m_flash_counter); + invalidate_title_bar(); + if (!--m_flash_counter) + m_flash_timer->stop(); + }); + } + m_flash_counter = 8; + m_flash_timer->start(); +} + } diff --git a/Services/WindowServer/WindowFrame.h b/Services/WindowServer/WindowFrame.h index b398eb4709a..ace32b8c7c2 100644 --- a/Services/WindowServer/WindowFrame.h +++ b/Services/WindowServer/WindowFrame.h @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include @@ -58,6 +60,8 @@ public: void layout_buttons(); void set_button_icons(); + void start_flash_animation(); + private: void paint_notification_frame(Gfx::Painter&); void paint_normal_frame(Gfx::Painter&); @@ -69,6 +73,9 @@ private: Button* m_close_button { nullptr }; Button* m_maximize_button { nullptr }; Button* m_minimize_button { nullptr }; + + RefPtr m_flash_timer; + size_t m_flash_counter { 0 }; }; } diff --git a/Services/WindowServer/WindowManager.cpp b/Services/WindowServer/WindowManager.cpp index a55c0c31f55..6a473c1caf1 100644 --- a/Services/WindowServer/WindowManager.cpp +++ b/Services/WindowServer/WindowManager.cpp @@ -996,6 +996,11 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind // Well okay, let's see if we're hitting the frame or the window inside the frame. if (window.rect().contains(event.position())) { if (event.type() == Event::MouseDown) { + // We're clicking on something that's blocked by a modal window. + // Flash the modal window to let the user know about it. + if (auto* blocking_modal_window = window.is_blocked_by_modal_window()) + blocking_modal_window->frame().start_flash_animation(); + if (window.type() == WindowType::Normal) move_to_front_and_make_active(window); else if (window.type() == WindowType::Desktop)