Skip to content

Commit

Permalink
WindowServer: Flash modal window when clicking on window blocked by it
Browse files Browse the repository at this point in the history
This makes window modality a bit more discoverable by indicating to the
user that the modal window must be closed before mouse interaction is
possible in the clicked window.
  • Loading branch information
awesomekling committed Jan 1, 2021
1 parent 2e8db65 commit af7800d
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Services/WindowServer/WindowFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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();
}

}
7 changes: 7 additions & 0 deletions Services/WindowServer/WindowFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include <AK/Forward.h>
#include <AK/NonnullOwnPtrVector.h>
#include <AK/RefPtr.h>
#include <LibCore/Forward.h>
#include <LibGfx/Forward.h>
#include <LibGfx/WindowTheme.h>

Expand Down Expand Up @@ -58,6 +60,8 @@ class WindowFrame {
void layout_buttons();
void set_button_icons();

void start_flash_animation();

private:
void paint_notification_frame(Gfx::Painter&);
void paint_normal_frame(Gfx::Painter&);
Expand All @@ -69,6 +73,9 @@ class WindowFrame {
Button* m_close_button { nullptr };
Button* m_maximize_button { nullptr };
Button* m_minimize_button { nullptr };

RefPtr<Core::Timer> m_flash_timer;
size_t m_flash_counter { 0 };
};

}
5 changes: 5 additions & 0 deletions Services/WindowServer/WindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit af7800d

Please sign in to comment.