mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:37:43 +00:00
WindowServer: Add WindowStack concept
This patch moves the window stack out of WindowManager and into its own WindowStack class. A WindowStack is an ordered list of windows with an optional highlight window. The highlight window mechanism is used during Super+Tab window switching to temporarily bring a window to the front. This is mostly mechanical, just moving the code to its own class.
This commit is contained in:
parent
906d3e9f44
commit
d257f58306
8 changed files with 267 additions and 197 deletions
|
@ -25,6 +25,7 @@ set(SOURCES
|
||||||
Window.cpp
|
Window.cpp
|
||||||
WindowFrame.cpp
|
WindowFrame.cpp
|
||||||
WindowManager.cpp
|
WindowManager.cpp
|
||||||
|
WindowStack.cpp
|
||||||
WindowSwitcher.cpp
|
WindowSwitcher.cpp
|
||||||
WindowServerEndpoint.h
|
WindowServerEndpoint.h
|
||||||
WindowClientEndpoint.h
|
WindowClientEndpoint.h
|
||||||
|
|
|
@ -130,7 +130,7 @@ void Compositor::compose()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark window regions as dirty that need to be re-rendered
|
// Mark window regions as dirty that need to be re-rendered
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& window) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||||
auto frame_rect = window.frame().render_rect();
|
auto frame_rect = window.frame().render_rect();
|
||||||
for (auto& dirty_rect : dirty_screen_rects.rects()) {
|
for (auto& dirty_rect : dirty_screen_rects.rects()) {
|
||||||
auto invalidate_rect = dirty_rect.intersected(frame_rect);
|
auto invalidate_rect = dirty_rect.intersected(frame_rect);
|
||||||
|
@ -148,14 +148,14 @@ void Compositor::compose()
|
||||||
// Any windows above or below a given window that need to be re-rendered
|
// Any windows above or below a given window that need to be re-rendered
|
||||||
// also require us to re-render that window's intersecting area, regardless
|
// also require us to re-render that window's intersecting area, regardless
|
||||||
// of whether that window has any dirty rectangles
|
// of whether that window has any dirty rectangles
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& window) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||||
auto& transparency_rects = window.transparency_rects();
|
auto& transparency_rects = window.transparency_rects();
|
||||||
if (transparency_rects.is_empty())
|
if (transparency_rects.is_empty())
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
auto frame_rect = window.frame().render_rect();
|
auto frame_rect = window.frame().render_rect();
|
||||||
auto& dirty_rects = window.dirty_rects();
|
auto& dirty_rects = window.dirty_rects();
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& w) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& w) {
|
||||||
if (&w == &window)
|
if (&w == &window)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
auto frame_rect2 = w.frame().render_rect();
|
auto frame_rect2 = w.frame().render_rect();
|
||||||
|
@ -402,7 +402,7 @@ void Compositor::compose()
|
||||||
compose_window(*fullscreen_window);
|
compose_window(*fullscreen_window);
|
||||||
fullscreen_window->clear_dirty_rects();
|
fullscreen_window->clear_dirty_rects();
|
||||||
} else {
|
} else {
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& window) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||||
compose_window(window);
|
compose_window(window);
|
||||||
window.clear_dirty_rects();
|
window.clear_dirty_rects();
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
@ -639,7 +639,7 @@ void Compositor::run_animations(Gfx::DisjointRectSet& flush_rects)
|
||||||
Gfx::PainterStateSaver saver(painter);
|
Gfx::PainterStateSaver saver(painter);
|
||||||
painter.set_draw_op(Gfx::Painter::DrawOp::Invert);
|
painter.set_draw_op(Gfx::Painter::DrawOp::Invert);
|
||||||
|
|
||||||
WindowManager::the().for_each_window([&](Window& window) {
|
WindowManager::the().window_stack().for_each_window([&](Window& window) {
|
||||||
if (window.in_minimize_animation()) {
|
if (window.in_minimize_animation()) {
|
||||||
int animation_index = window.minimize_animation_index();
|
int animation_index = window.minimize_animation_index();
|
||||||
|
|
||||||
|
@ -824,7 +824,7 @@ bool Compositor::any_opaque_window_above_this_one_contains_rect(const Window& a_
|
||||||
{
|
{
|
||||||
bool found_containing_window = false;
|
bool found_containing_window = false;
|
||||||
bool checking = false;
|
bool checking = false;
|
||||||
WindowManager::the().for_each_visible_window_from_back_to_front([&](Window& window) {
|
WindowManager::the().window_stack().for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||||
if (&window == &a_window) {
|
if (&window == &a_window) {
|
||||||
checking = true;
|
checking = true;
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
@ -849,7 +849,7 @@ bool Compositor::any_opaque_window_above_this_one_contains_rect(const Window& a_
|
||||||
void Compositor::recompute_occlusions()
|
void Compositor::recompute_occlusions()
|
||||||
{
|
{
|
||||||
auto& wm = WindowManager::the();
|
auto& wm = WindowManager::the();
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& window) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& window) {
|
||||||
if (wm.m_switcher.is_visible()) {
|
if (wm.m_switcher.is_visible()) {
|
||||||
window.set_occluded(false);
|
window.set_occluded(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -866,7 +866,7 @@ void Compositor::recompute_occlusions()
|
||||||
auto screen_rect = Screen::the().rect();
|
auto screen_rect = Screen::the().rect();
|
||||||
|
|
||||||
if (auto* fullscreen_window = wm.active_fullscreen_window()) {
|
if (auto* fullscreen_window = wm.active_fullscreen_window()) {
|
||||||
WindowManager::the().for_each_visible_window_from_front_to_back([&](Window& w) {
|
WindowManager::the().window_stack().for_each_visible_window_from_front_to_back([&](Window& w) {
|
||||||
auto& visible_opaque = w.opaque_rects();
|
auto& visible_opaque = w.opaque_rects();
|
||||||
auto& transparency_rects = w.transparency_rects();
|
auto& transparency_rects = w.transparency_rects();
|
||||||
auto& transparency_wallpaper_rects = w.transparency_wallpaper_rects();
|
auto& transparency_wallpaper_rects = w.transparency_wallpaper_rects();
|
||||||
|
@ -892,7 +892,7 @@ void Compositor::recompute_occlusions()
|
||||||
} else {
|
} else {
|
||||||
Gfx::DisjointRectSet visible_rects(screen_rect);
|
Gfx::DisjointRectSet visible_rects(screen_rect);
|
||||||
bool have_transparent = false;
|
bool have_transparent = false;
|
||||||
WindowManager::the().for_each_visible_window_from_front_to_back([&](Window& w) {
|
WindowManager::the().window_stack().for_each_visible_window_from_front_to_back([&](Window& w) {
|
||||||
w.transparency_wallpaper_rects().clear();
|
w.transparency_wallpaper_rects().clear();
|
||||||
auto& visible_opaque = w.opaque_rects();
|
auto& visible_opaque = w.opaque_rects();
|
||||||
auto& transparency_rects = w.transparency_rects();
|
auto& transparency_rects = w.transparency_rects();
|
||||||
|
@ -917,7 +917,7 @@ void Compositor::recompute_occlusions()
|
||||||
|
|
||||||
Gfx::DisjointRectSet opaque_covering;
|
Gfx::DisjointRectSet opaque_covering;
|
||||||
bool found_this_window = false;
|
bool found_this_window = false;
|
||||||
WindowManager::the().for_each_visible_window_from_back_to_front([&](Window& w2) {
|
WindowManager::the().window_stack().for_each_visible_window_from_back_to_front([&](Window& w2) {
|
||||||
if (!found_this_window) {
|
if (!found_this_window) {
|
||||||
if (&w == &w2)
|
if (&w == &w2)
|
||||||
found_this_window = true;
|
found_this_window = true;
|
||||||
|
@ -979,7 +979,7 @@ void Compositor::recompute_occlusions()
|
||||||
|
|
||||||
if (have_transparent) {
|
if (have_transparent) {
|
||||||
// Determine what transparent window areas need to render the wallpaper first
|
// Determine what transparent window areas need to render the wallpaper first
|
||||||
WindowManager::the().for_each_visible_window_from_back_to_front([&](Window& w) {
|
WindowManager::the().window_stack().for_each_visible_window_from_back_to_front([&](Window& w) {
|
||||||
auto& transparency_wallpaper_rects = w.transparency_wallpaper_rects();
|
auto& transparency_wallpaper_rects = w.transparency_wallpaper_rects();
|
||||||
if (w.is_minimized()) {
|
if (w.is_minimized()) {
|
||||||
transparency_wallpaper_rects.clear();
|
transparency_wallpaper_rects.clear();
|
||||||
|
@ -1007,7 +1007,7 @@ void Compositor::recompute_occlusions()
|
||||||
dbgln(" wallpaper opaque: {}", r);
|
dbgln(" wallpaper opaque: {}", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
wm.for_each_visible_window_from_back_to_front([&](Window& w) {
|
wm.window_stack().for_each_visible_window_from_back_to_front([&](Window& w) {
|
||||||
auto window_frame_rect = w.frame().render_rect().intersected(screen_rect);
|
auto window_frame_rect = w.frame().render_rect().intersected(screen_rect);
|
||||||
if (w.is_minimized() || window_frame_rect.is_empty())
|
if (w.is_minimized() || window_frame_rect.is_empty())
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
|
@ -240,7 +240,7 @@ Gfx::WindowTheme::WindowState WindowFrame::window_state_for_theme() const
|
||||||
if (m_flash_timer && m_flash_timer->is_active())
|
if (m_flash_timer && m_flash_timer->is_active())
|
||||||
return m_flash_counter & 1 ? Gfx::WindowTheme::WindowState::Active : Gfx::WindowTheme::WindowState::Inactive;
|
return m_flash_counter & 1 ? Gfx::WindowTheme::WindowState::Active : Gfx::WindowTheme::WindowState::Inactive;
|
||||||
|
|
||||||
if (&m_window == wm.m_highlight_window)
|
if (&m_window == wm.highlight_window())
|
||||||
return Gfx::WindowTheme::WindowState::Highlighted;
|
return Gfx::WindowTheme::WindowState::Highlighted;
|
||||||
if (&m_window == wm.m_move_window)
|
if (&m_window == wm.m_move_window)
|
||||||
return Gfx::WindowTheme::WindowState::Moving;
|
return Gfx::WindowTheme::WindowState::Moving;
|
||||||
|
|
|
@ -8,18 +8,14 @@
|
||||||
#include "Compositor.h"
|
#include "Compositor.h"
|
||||||
#include "EventLoop.h"
|
#include "EventLoop.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "MenuItem.h"
|
|
||||||
#include "Menubar.h"
|
|
||||||
#include "Screen.h"
|
#include "Screen.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibGUI/WindowManagerServerConnection.h>
|
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/CharacterBitmap.h>
|
#include <LibGfx/CharacterBitmap.h>
|
||||||
#include <LibGfx/Font.h>
|
#include <LibGfx/Font.h>
|
||||||
#include <LibGfx/Painter.h>
|
|
||||||
#include <LibGfx/StylePainter.h>
|
#include <LibGfx/StylePainter.h>
|
||||||
#include <LibGfx/SystemTheme.h>
|
#include <LibGfx/SystemTheme.h>
|
||||||
#include <WindowServer/AppletManager.h>
|
#include <WindowServer/AppletManager.h>
|
||||||
|
@ -27,11 +23,6 @@
|
||||||
#include <WindowServer/ClientConnection.h>
|
#include <WindowServer/ClientConnection.h>
|
||||||
#include <WindowServer/Cursor.h>
|
#include <WindowServer/Cursor.h>
|
||||||
#include <WindowServer/WindowClientEndpoint.h>
|
#include <WindowServer/WindowClientEndpoint.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <serenity.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
|
@ -109,7 +100,7 @@ bool WindowManager::set_resolution(int width, int height, int scale)
|
||||||
client.notify_about_new_screen_rect(Screen::the().rect());
|
client.notify_about_new_screen_rect(Screen::the().rect());
|
||||||
});
|
});
|
||||||
if (success) {
|
if (success) {
|
||||||
for_each_window([](Window& window) {
|
m_window_stack.for_each_window([](Window& window) {
|
||||||
window.recalculate_rect();
|
window.recalculate_rect();
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
@ -174,9 +165,9 @@ int WindowManager::scale_factor() const
|
||||||
|
|
||||||
void WindowManager::add_window(Window& window)
|
void WindowManager::add_window(Window& window)
|
||||||
{
|
{
|
||||||
bool is_first_window = m_windows_in_order.is_empty();
|
bool is_first_window = m_window_stack.is_empty();
|
||||||
|
|
||||||
m_windows_in_order.append(window);
|
m_window_stack.windows().append(window);
|
||||||
|
|
||||||
if (window.is_fullscreen()) {
|
if (window.is_fullscreen()) {
|
||||||
Core::EventLoop::current().post_event(window, make<ResizeEvent>(Screen::the().rect()));
|
Core::EventLoop::current().post_event(window, make<ResizeEvent>(Screen::the().rect()));
|
||||||
|
@ -228,10 +219,7 @@ void WindowManager::move_to_front_and_make_active(Window& window)
|
||||||
|
|
||||||
void WindowManager::do_move_to_front(Window& window, bool make_active, bool make_input)
|
void WindowManager::do_move_to_front(Window& window, bool make_active, bool make_input)
|
||||||
{
|
{
|
||||||
if (m_windows_in_order.last() != &window)
|
m_window_stack.move_to_front(window);
|
||||||
window.invalidate();
|
|
||||||
m_windows_in_order.remove(window);
|
|
||||||
m_windows_in_order.append(window);
|
|
||||||
|
|
||||||
if (make_active)
|
if (make_active)
|
||||||
set_active_window(&window, make_input);
|
set_active_window(&window, make_input);
|
||||||
|
@ -252,7 +240,7 @@ void WindowManager::do_move_to_front(Window& window, bool make_active, bool make
|
||||||
|
|
||||||
void WindowManager::remove_window(Window& window)
|
void WindowManager::remove_window(Window& window)
|
||||||
{
|
{
|
||||||
m_windows_in_order.remove(window);
|
m_window_stack.remove(window);
|
||||||
auto* active = active_window();
|
auto* active = active_window();
|
||||||
auto* active_input = active_input_window();
|
auto* active_input = active_input_window();
|
||||||
if (active == &window || active_input == &window || (active && window.is_descendant_of(*active)) || (active_input && active_input != active && window.is_descendant_of(*active_input)))
|
if (active == &window || active_input == &window || (active && window.is_descendant_of(*active)) || (active_input && active_input != active && window.is_descendant_of(*active_input)))
|
||||||
|
@ -279,7 +267,7 @@ void WindowManager::greet_window_manager(WMClientConnection& conn)
|
||||||
if (conn.window_id() < 0)
|
if (conn.window_id() < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_window([&](Window& other_window) {
|
m_window_stack.for_each_window([&](Window& other_window) {
|
||||||
//if (conn.window_id() != other_window.window_id()) {
|
//if (conn.window_id() != other_window.window_id()) {
|
||||||
tell_wm_about_window(conn, other_window);
|
tell_wm_about_window(conn, other_window);
|
||||||
tell_wm_about_window_icon(conn, other_window);
|
tell_wm_about_window_icon(conn, other_window);
|
||||||
|
@ -456,7 +444,7 @@ bool WindowManager::pick_new_active_window(Window* previous_active)
|
||||||
{
|
{
|
||||||
bool new_window_picked = false;
|
bool new_window_picked = false;
|
||||||
Window* first_candidate = nullptr;
|
Window* first_candidate = nullptr;
|
||||||
for_each_visible_window_from_front_to_back([&](Window& candidate) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](Window& candidate) {
|
||||||
if (candidate.type() != WindowType::Normal && candidate.type() != WindowType::ToolWindow)
|
if (candidate.type() != WindowType::Normal && candidate.type() != WindowType::ToolWindow)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
if (candidate.is_destroyed())
|
if (candidate.is_destroyed())
|
||||||
|
@ -762,7 +750,7 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win
|
||||||
|
|
||||||
if (event.type() == Event::MouseMove) {
|
if (event.type() == Event::MouseMove) {
|
||||||
// We didn't let go of the drag yet, see if we should send some drag move events..
|
// We didn't let go of the drag yet, see if we should send some drag move events..
|
||||||
for_each_visible_window_from_front_to_back([&](Window& window) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](Window& window) {
|
||||||
if (!window.rect().contains(event.position()))
|
if (!window.rect().contains(event.position()))
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
|
@ -778,7 +766,7 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
hovered_window = nullptr;
|
hovered_window = nullptr;
|
||||||
for_each_visible_window_from_front_to_back([&](auto& window) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](auto& window) {
|
||||||
if (window.hit_test(event.position())) {
|
if (window.hit_test(event.position())) {
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
@ -976,7 +964,7 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
|
||||||
|
|
||||||
if (MenuManager::the().has_open_menu()
|
if (MenuManager::the().has_open_menu()
|
||||||
|| hitting_menu_in_window_with_active_menu) {
|
|| hitting_menu_in_window_with_active_menu) {
|
||||||
for_each_visible_window_of_type_from_front_to_back(WindowType::Applet, [&](auto& window) {
|
m_window_stack.for_each_visible_window_of_type_from_front_to_back(WindowType::Applet, [&](auto& window) {
|
||||||
if (!window.rect_in_applet_area().contains(event.position()))
|
if (!window.rect_in_applet_area().contains(event.position()))
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
|
@ -1007,7 +995,7 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
|
||||||
m_active_input_tracking_window = nullptr;
|
m_active_input_tracking_window = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_visible_window_from_front_to_back([&](auto& window) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](auto& window) {
|
||||||
if (window.hit_test(event.position())) {
|
if (window.hit_test(event.position())) {
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
@ -1079,7 +1067,7 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
|
||||||
if (auto* fullscreen_window = active_fullscreen_window()) {
|
if (auto* fullscreen_window = active_fullscreen_window()) {
|
||||||
process_mouse_event_for_window(*fullscreen_window);
|
process_mouse_event_for_window(*fullscreen_window);
|
||||||
} else {
|
} else {
|
||||||
for_each_visible_window_from_front_to_back([&](Window& window) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](Window& window) {
|
||||||
if (!window.hit_test(event.position()))
|
if (!window.hit_test(event.position()))
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
process_mouse_event_for_window(window);
|
process_mouse_event_for_window(window);
|
||||||
|
@ -1092,8 +1080,8 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
|
||||||
set_active_window(nullptr);
|
set_active_window(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reverse_iterator = m_windows_in_order.rbegin();
|
auto reverse_iterator = m_window_stack.windows().rbegin();
|
||||||
for (; reverse_iterator != m_windows_in_order.rend(); ++reverse_iterator) {
|
for (; reverse_iterator != m_window_stack.windows().rend(); ++reverse_iterator) {
|
||||||
auto& window = *reverse_iterator;
|
auto& window = *reverse_iterator;
|
||||||
if (received_mouse_event == &window)
|
if (received_mouse_event == &window)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1124,7 +1112,7 @@ void WindowManager::reevaluate_hovered_window(Window* updated_window)
|
||||||
if (fullscreen_window->hit_test(cursor_location))
|
if (fullscreen_window->hit_test(cursor_location))
|
||||||
hovered_window = fullscreen_window;
|
hovered_window = fullscreen_window;
|
||||||
} else {
|
} else {
|
||||||
for_each_visible_window_from_front_to_back([&](Window& window) {
|
m_window_stack.for_each_visible_window_from_front_to_back([&](Window& window) {
|
||||||
if (!window.hit_test(cursor_location))
|
if (!window.hit_test(cursor_location))
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
hovered_window = &window;
|
hovered_window = &window;
|
||||||
|
@ -1298,19 +1286,19 @@ void WindowManager::event(Core::Event& event)
|
||||||
Core::Object::event(event);
|
Core::Object::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::set_highlight_window(Window* window)
|
void WindowManager::set_highlight_window(Window* new_highlight_window)
|
||||||
{
|
{
|
||||||
if (window == m_highlight_window)
|
if (new_highlight_window == m_window_stack.highlight_window())
|
||||||
return;
|
return;
|
||||||
auto* previous_highlight_window = m_highlight_window.ptr();
|
auto* previous_highlight_window = m_window_stack.highlight_window();
|
||||||
m_highlight_window = window;
|
m_window_stack.set_highlight_window(new_highlight_window);
|
||||||
if (previous_highlight_window) {
|
if (previous_highlight_window) {
|
||||||
previous_highlight_window->invalidate(true, true);
|
previous_highlight_window->invalidate(true, true);
|
||||||
Compositor::the().invalidate_screen(previous_highlight_window->frame().render_rect());
|
Compositor::the().invalidate_screen(previous_highlight_window->frame().render_rect());
|
||||||
}
|
}
|
||||||
if (m_highlight_window) {
|
if (new_highlight_window) {
|
||||||
m_highlight_window->invalidate(true, true);
|
new_highlight_window->invalidate(true, true);
|
||||||
Compositor::the().invalidate_screen(m_highlight_window->frame().render_rect());
|
Compositor::the().invalidate_screen(new_highlight_window->frame().render_rect());
|
||||||
}
|
}
|
||||||
// Invalidate occlusions in case the state change changes geometry
|
// Invalidate occlusions in case the state change changes geometry
|
||||||
Compositor::the().invalidate_occlusions();
|
Compositor::the().invalidate_occlusions();
|
||||||
|
@ -1507,7 +1495,7 @@ Gfx::IntRect WindowManager::maximized_window_rect(const Window& window) const
|
||||||
rect.set_height(rect.height() - window.frame().titlebar_rect().height() - window.frame().menubar_rect().height());
|
rect.set_height(rect.height() - window.frame().titlebar_rect().height() - window.frame().menubar_rect().height());
|
||||||
|
|
||||||
// Subtract taskbar window height if present
|
// Subtract taskbar window height if present
|
||||||
const_cast<WindowManager*>(this)->for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, [&rect](Window& taskbar_window) {
|
const_cast<WindowManager*>(this)->m_window_stack.for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, [&rect](Window& taskbar_window) {
|
||||||
rect.set_height(rect.height() - taskbar_window.height());
|
rect.set_height(rect.height() - taskbar_window.height());
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
});
|
});
|
||||||
|
@ -1553,7 +1541,7 @@ void WindowManager::invalidate_after_theme_or_font_change()
|
||||||
{
|
{
|
||||||
Compositor::the().set_background_color(m_config->read_entry("Background", "Color", palette().desktop_background().to_string()));
|
Compositor::the().set_background_color(m_config->read_entry("Background", "Color", palette().desktop_background().to_string()));
|
||||||
WindowFrame::reload_config();
|
WindowFrame::reload_config();
|
||||||
for_each_window([&](Window& window) {
|
m_window_stack.for_each_window([&](Window& window) {
|
||||||
window.frame().theme_changed();
|
window.frame().theme_changed();
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
@ -1618,7 +1606,7 @@ Gfx::IntPoint WindowManager::get_recommended_window_position(const Gfx::IntPoint
|
||||||
int taskbar_height = 28;
|
int taskbar_height = 28;
|
||||||
|
|
||||||
const Window* overlap_window = nullptr;
|
const Window* overlap_window = nullptr;
|
||||||
for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, [&](Window& window) {
|
m_window_stack.for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, [&](Window& window) {
|
||||||
if (window.default_positioned() && (!overlap_window || overlap_window->window_id() < window.window_id())) {
|
if (window.default_positioned() && (!overlap_window || overlap_window->window_id() < window.window_id())) {
|
||||||
overlap_window = &window;
|
overlap_window = &window;
|
||||||
}
|
}
|
||||||
|
@ -1650,7 +1638,7 @@ void WindowManager::reload_icon_bitmaps_after_scale_change(bool allow_hidpi_icon
|
||||||
{
|
{
|
||||||
m_allow_hidpi_icons = allow_hidpi_icons;
|
m_allow_hidpi_icons = allow_hidpi_icons;
|
||||||
reload_config();
|
reload_config();
|
||||||
for_each_window([&](Window& window) {
|
m_window_stack.for_each_window([&](Window& window) {
|
||||||
auto& window_frame = window.frame();
|
auto& window_frame = window.frame();
|
||||||
window_frame.theme_changed();
|
window_frame.theme_changed();
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "WindowStack.h"
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include <WindowServer/MenuManager.h>
|
#include <WindowServer/MenuManager.h>
|
||||||
#include <WindowServer/Menubar.h>
|
#include <WindowServer/Menubar.h>
|
||||||
#include <WindowServer/WMClientConnection.h>
|
#include <WindowServer/WMClientConnection.h>
|
||||||
#include <WindowServer/Window.h>
|
|
||||||
#include <WindowServer/WindowSwitcher.h>
|
#include <WindowServer/WindowSwitcher.h>
|
||||||
#include <WindowServer/WindowType.h>
|
#include <WindowServer/WindowType.h>
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public:
|
||||||
const Window* window_with_active_menu() const { return m_window_with_active_menu; }
|
const Window* window_with_active_menu() const { return m_window_with_active_menu; }
|
||||||
void set_window_with_active_menu(Window*);
|
void set_window_with_active_menu(Window*);
|
||||||
|
|
||||||
const Window* highlight_window() const { return m_highlight_window.ptr(); }
|
Window const* highlight_window() const { return m_window_stack.highlight_window(); }
|
||||||
void set_highlight_window(Window*);
|
void set_highlight_window(Window*);
|
||||||
|
|
||||||
void move_to_front_and_make_active(Window&);
|
void move_to_front_and_make_active(Window&);
|
||||||
|
@ -231,6 +231,8 @@ public:
|
||||||
void reevaluate_hovered_window(Window* = nullptr);
|
void reevaluate_hovered_window(Window* = nullptr);
|
||||||
Window* hovered_window() const { return m_hovered_window.ptr(); }
|
Window* hovered_window() const { return m_hovered_window.ptr(); }
|
||||||
|
|
||||||
|
WindowStack& window_stack() { return m_window_stack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NonnullRefPtr<Cursor> get_cursor(const String& name);
|
NonnullRefPtr<Cursor> get_cursor(const String& name);
|
||||||
|
|
||||||
|
@ -240,24 +242,10 @@ private:
|
||||||
bool process_ongoing_window_move(MouseEvent&, Window*& hovered_window);
|
bool process_ongoing_window_move(MouseEvent&, Window*& hovered_window);
|
||||||
bool process_ongoing_drag(MouseEvent&, Window*& hovered_window);
|
bool process_ongoing_drag(MouseEvent&, Window*& hovered_window);
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision for_each_visible_window_of_type_from_back_to_front(WindowType, Callback, bool ignore_highlight = false);
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision for_each_visible_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false);
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision for_each_visible_window_from_front_to_back(Callback);
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision for_each_visible_window_from_back_to_front(Callback);
|
|
||||||
template<typename Callback>
|
|
||||||
void for_each_window(Callback);
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision for_each_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false);
|
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void for_each_window_manager(Callback);
|
void for_each_window_manager(Callback);
|
||||||
|
|
||||||
virtual void event(Core::Event&) override;
|
virtual void event(Core::Event&) override;
|
||||||
void paint_window_frame(const Window&);
|
|
||||||
void tell_wm_about_window(WMClientConnection& conn, Window&);
|
void tell_wm_about_window(WMClientConnection& conn, Window&);
|
||||||
void tell_wm_about_window_icon(WMClientConnection& conn, Window&);
|
void tell_wm_about_window_icon(WMClientConnection& conn, Window&);
|
||||||
void tell_wm_about_window_rect(WMClientConnection& conn, Window&);
|
void tell_wm_about_window_rect(WMClientConnection& conn, Window&);
|
||||||
|
@ -283,7 +271,7 @@ private:
|
||||||
RefPtr<Cursor> m_wait_cursor;
|
RefPtr<Cursor> m_wait_cursor;
|
||||||
RefPtr<Cursor> m_crosshair_cursor;
|
RefPtr<Cursor> m_crosshair_cursor;
|
||||||
|
|
||||||
Window::List m_windows_in_order;
|
WindowStack m_window_stack;
|
||||||
|
|
||||||
struct DoubleClickInfo {
|
struct DoubleClickInfo {
|
||||||
struct ClickMetadata {
|
struct ClickMetadata {
|
||||||
|
@ -322,7 +310,6 @@ private:
|
||||||
|
|
||||||
WeakPtr<Window> m_active_window;
|
WeakPtr<Window> m_active_window;
|
||||||
WeakPtr<Window> m_hovered_window;
|
WeakPtr<Window> m_hovered_window;
|
||||||
WeakPtr<Window> m_highlight_window;
|
|
||||||
WeakPtr<Window> m_active_input_window;
|
WeakPtr<Window> m_active_input_window;
|
||||||
WeakPtr<Window> m_active_input_tracking_window;
|
WeakPtr<Window> m_active_input_tracking_window;
|
||||||
WeakPtr<Window> m_window_with_active_menu;
|
WeakPtr<Window> m_window_with_active_menu;
|
||||||
|
@ -355,100 +342,6 @@ private:
|
||||||
RefPtr<Gfx::Bitmap> m_dnd_bitmap;
|
RefPtr<Gfx::Bitmap> m_dnd_bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision WindowManager::for_each_visible_window_of_type_from_back_to_front(WindowType type, Callback callback, bool ignore_highlight)
|
|
||||||
{
|
|
||||||
bool do_highlight_window_at_end = false;
|
|
||||||
for (auto& window : m_windows_in_order) {
|
|
||||||
if (!window.is_visible())
|
|
||||||
continue;
|
|
||||||
if (window.is_minimized())
|
|
||||||
continue;
|
|
||||||
if (window.type() != type)
|
|
||||||
continue;
|
|
||||||
if (!ignore_highlight && m_highlight_window == &window) {
|
|
||||||
do_highlight_window_at_end = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (callback(window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
if (do_highlight_window_at_end) {
|
|
||||||
if (callback(*m_highlight_window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision WindowManager::for_each_visible_window_from_back_to_front(Callback callback)
|
|
||||||
{
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Desktop, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Normal, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::ToolWindow, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::AppletArea, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Notification, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Tooltip, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Menu, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
return for_each_visible_window_of_type_from_back_to_front(WindowType::WindowSwitcher, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision WindowManager::for_each_visible_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight)
|
|
||||||
{
|
|
||||||
if (!ignore_highlight && m_highlight_window && m_highlight_window->type() == type && m_highlight_window->is_visible()) {
|
|
||||||
if (callback(*m_highlight_window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto reverse_iterator = m_windows_in_order.rbegin();
|
|
||||||
for (; reverse_iterator != m_windows_in_order.rend(); ++reverse_iterator) {
|
|
||||||
auto& window = *reverse_iterator;
|
|
||||||
if (!window.is_visible())
|
|
||||||
continue;
|
|
||||||
if (window.is_minimized())
|
|
||||||
continue;
|
|
||||||
if (window.type() != type)
|
|
||||||
continue;
|
|
||||||
if (!ignore_highlight && &window == m_highlight_window)
|
|
||||||
continue;
|
|
||||||
if (callback(window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision WindowManager::for_each_visible_window_from_front_to_back(Callback callback)
|
|
||||||
{
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::WindowSwitcher, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Menu, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Tooltip, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Notification, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::AppletArea, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Taskbar, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::ToolWindow, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, callback) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
return for_each_visible_window_of_type_from_front_to_back(WindowType::Desktop, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void WindowManager::for_each_window_manager(Callback callback)
|
void WindowManager::for_each_window_manager(Callback callback)
|
||||||
{
|
{
|
||||||
|
@ -461,36 +354,4 @@ void WindowManager::for_each_window_manager(Callback callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
void WindowManager::for_each_window(Callback callback)
|
|
||||||
{
|
|
||||||
auto reverse_iterator = m_windows_in_order.rbegin();
|
|
||||||
for (; reverse_iterator != m_windows_in_order.rend(); ++reverse_iterator) {
|
|
||||||
auto& window = *reverse_iterator;
|
|
||||||
if (callback(window) == IterationDecision::Break)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Callback>
|
|
||||||
IterationDecision WindowManager::for_each_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight)
|
|
||||||
{
|
|
||||||
if (!ignore_highlight && m_highlight_window && m_highlight_window->type() == type && m_highlight_window->is_visible()) {
|
|
||||||
if (callback(*m_highlight_window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto reverse_iterator = m_windows_in_order.rbegin();
|
|
||||||
for (; reverse_iterator != m_windows_in_order.rend(); ++reverse_iterator) {
|
|
||||||
auto& window = *reverse_iterator;
|
|
||||||
if (window.type() != type)
|
|
||||||
continue;
|
|
||||||
if (!ignore_highlight && &window == m_highlight_window)
|
|
||||||
continue;
|
|
||||||
if (callback(window) == IterationDecision::Break)
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
45
Userland/Services/WindowServer/WindowStack.cpp
Normal file
45
Userland/Services/WindowServer/WindowStack.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WindowStack.h"
|
||||||
|
|
||||||
|
namespace WindowServer {
|
||||||
|
|
||||||
|
WindowStack::WindowStack()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowStack::~WindowStack()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowStack::add(Window& window)
|
||||||
|
{
|
||||||
|
m_windows.append(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowStack::remove(Window& window)
|
||||||
|
{
|
||||||
|
m_windows.remove(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowStack::move_to_front(Window& window)
|
||||||
|
{
|
||||||
|
if (m_windows.last() != &window)
|
||||||
|
window.invalidate();
|
||||||
|
m_windows.remove(window);
|
||||||
|
m_windows.append(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowStack::set_highlight_window(Window* window)
|
||||||
|
{
|
||||||
|
if (!window)
|
||||||
|
m_highlight_window = nullptr;
|
||||||
|
else
|
||||||
|
m_highlight_window = window->make_weak_ptr<Window>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
175
Userland/Services/WindowServer/WindowStack.h
Normal file
175
Userland/Services/WindowServer/WindowStack.h
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
namespace WindowServer {
|
||||||
|
|
||||||
|
class WindowStack {
|
||||||
|
public:
|
||||||
|
WindowStack();
|
||||||
|
~WindowStack();
|
||||||
|
|
||||||
|
bool is_empty() const { return m_windows.is_empty(); }
|
||||||
|
void add(Window&);
|
||||||
|
void remove(Window&);
|
||||||
|
void move_to_front(Window&);
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
IterationDecision for_each_visible_window_from_back_to_front(Callback);
|
||||||
|
template<typename Callback>
|
||||||
|
IterationDecision for_each_visible_window_from_front_to_back(Callback);
|
||||||
|
template<typename Callback>
|
||||||
|
IterationDecision for_each_visible_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false);
|
||||||
|
template<typename Callback>
|
||||||
|
IterationDecision for_each_visible_window_of_type_from_back_to_front(WindowType, Callback, bool ignore_highlight = false);
|
||||||
|
template<typename Callback>
|
||||||
|
IterationDecision for_each_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false);
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_window(Callback);
|
||||||
|
|
||||||
|
Window::List& windows() { return m_windows; }
|
||||||
|
|
||||||
|
Window* highlight_window() { return m_highlight_window; }
|
||||||
|
Window const* highlight_window() const { return m_highlight_window; }
|
||||||
|
void set_highlight_window(Window*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WeakPtr<Window> m_highlight_window;
|
||||||
|
|
||||||
|
Window::List m_windows;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline IterationDecision WindowStack::for_each_visible_window_of_type_from_back_to_front(WindowType type, Callback callback, bool ignore_highlight)
|
||||||
|
{
|
||||||
|
bool do_highlight_window_at_end = false;
|
||||||
|
for (auto& window : m_windows) {
|
||||||
|
if (!window.is_visible())
|
||||||
|
continue;
|
||||||
|
if (window.is_minimized())
|
||||||
|
continue;
|
||||||
|
if (window.type() != type)
|
||||||
|
continue;
|
||||||
|
if (!ignore_highlight && m_highlight_window == &window) {
|
||||||
|
do_highlight_window_at_end = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (callback(window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
if (do_highlight_window_at_end) {
|
||||||
|
if (callback(*m_highlight_window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline IterationDecision WindowStack::for_each_visible_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight)
|
||||||
|
{
|
||||||
|
if (!ignore_highlight && m_highlight_window && m_highlight_window->type() == type && m_highlight_window->is_visible()) {
|
||||||
|
if (callback(*m_highlight_window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reverse_iterator = m_windows.rbegin();
|
||||||
|
for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) {
|
||||||
|
auto& window = *reverse_iterator;
|
||||||
|
if (!window.is_visible())
|
||||||
|
continue;
|
||||||
|
if (window.is_minimized())
|
||||||
|
continue;
|
||||||
|
if (window.type() != type)
|
||||||
|
continue;
|
||||||
|
if (!ignore_highlight && &window == m_highlight_window)
|
||||||
|
continue;
|
||||||
|
if (callback(window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline void WindowStack::for_each_window(Callback callback)
|
||||||
|
{
|
||||||
|
auto reverse_iterator = m_windows.rbegin();
|
||||||
|
for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) {
|
||||||
|
auto& window = *reverse_iterator;
|
||||||
|
if (callback(window) == IterationDecision::Break)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline IterationDecision WindowStack::for_each_visible_window_from_back_to_front(Callback callback)
|
||||||
|
{
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Desktop, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Normal, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::ToolWindow, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Taskbar, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::AppletArea, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Notification, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Tooltip, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_back_to_front(WindowType::Menu, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
return for_each_visible_window_of_type_from_back_to_front(WindowType::WindowSwitcher, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline IterationDecision WindowStack::for_each_visible_window_from_front_to_back(Callback callback)
|
||||||
|
{
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::WindowSwitcher, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Menu, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Tooltip, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Notification, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::AppletArea, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Taskbar, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::ToolWindow, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
if (for_each_visible_window_of_type_from_front_to_back(WindowType::Normal, callback) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
return for_each_visible_window_of_type_from_front_to_back(WindowType::Desktop, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
inline IterationDecision WindowStack::for_each_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight)
|
||||||
|
{
|
||||||
|
if (!ignore_highlight && m_highlight_window && m_highlight_window->type() == type && m_highlight_window->is_visible()) {
|
||||||
|
if (callback(*m_highlight_window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reverse_iterator = m_windows.rbegin();
|
||||||
|
for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) {
|
||||||
|
auto& window = *reverse_iterator;
|
||||||
|
if (window.type() != type)
|
||||||
|
continue;
|
||||||
|
if (!ignore_highlight && &window == m_highlight_window)
|
||||||
|
continue;
|
||||||
|
if (callback(window) == IterationDecision::Break)
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -202,7 +202,7 @@ void WindowSwitcher::refresh()
|
||||||
m_selected_index = 0;
|
m_selected_index = 0;
|
||||||
int window_count = 0;
|
int window_count = 0;
|
||||||
int longest_title_width = 0;
|
int longest_title_width = 0;
|
||||||
wm.for_each_window_of_type_from_front_to_back(
|
wm.window_stack().for_each_window_of_type_from_front_to_back(
|
||||||
WindowType::Normal, [&](Window& window) {
|
WindowType::Normal, [&](Window& window) {
|
||||||
if (window.is_frameless())
|
if (window.is_frameless())
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue