1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 01:57:45 +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:
Andreas Kling 2021-06-17 17:28:14 +02:00
parent 906d3e9f44
commit d257f58306
8 changed files with 267 additions and 197 deletions

View file

@ -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
*/
#pragma once
#include "WindowStack.h"
#include <AK/HashMap.h>
#include <AK/HashTable.h>
#include <AK/WeakPtr.h>
@ -21,7 +22,6 @@
#include <WindowServer/MenuManager.h>
#include <WindowServer/Menubar.h>
#include <WindowServer/WMClientConnection.h>
#include <WindowServer/Window.h>
#include <WindowServer/WindowSwitcher.h>
#include <WindowServer/WindowType.h>
@ -100,7 +100,7 @@ public:
const Window* window_with_active_menu() const { return m_window_with_active_menu; }
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 move_to_front_and_make_active(Window&);
@ -231,6 +231,8 @@ public:
void reevaluate_hovered_window(Window* = nullptr);
Window* hovered_window() const { return m_hovered_window.ptr(); }
WindowStack& window_stack() { return m_window_stack; }
private:
NonnullRefPtr<Cursor> get_cursor(const String& name);
@ -240,24 +242,10 @@ private:
bool process_ongoing_window_move(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>
void for_each_window_manager(Callback);
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_icon(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_crosshair_cursor;
Window::List m_windows_in_order;
WindowStack m_window_stack;
struct DoubleClickInfo {
struct ClickMetadata {
@ -322,7 +310,6 @@ private:
WeakPtr<Window> m_active_window;
WeakPtr<Window> m_hovered_window;
WeakPtr<Window> m_highlight_window;
WeakPtr<Window> m_active_input_window;
WeakPtr<Window> m_active_input_tracking_window;
WeakPtr<Window> m_window_with_active_menu;
@ -355,100 +342,6 @@ private:
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>
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;
}
}