Serenity Operating System
at master 182 lines 6.3 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021, networkException <networkexception@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include "Window.h" 11 12namespace WindowServer { 13 14class Compositor; 15 16class WindowStack { 17public: 18 WindowStack(unsigned row, unsigned column); 19 ~WindowStack() = default; 20 21 bool is_empty() const { return m_windows.is_empty(); } 22 void add(Window&); 23 void add_to_back(Window&); 24 void remove(Window&); 25 void move_to_front(Window&); 26 void move_always_on_top_windows_to_front(); 27 28 enum class MoveAllWindowsTo { 29 Front, 30 Back 31 }; 32 void move_all_windows(WindowStack&, Vector<Window*, 32>&, MoveAllWindowsTo); 33 34 enum class IncludeWindowFrame { 35 Yes, 36 No, 37 }; 38 Window* window_at(Gfx::IntPoint, IncludeWindowFrame = IncludeWindowFrame::Yes) const; 39 Window* highlight_window() const; 40 41 template<typename Callback> 42 IterationDecision for_each_visible_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false); 43 template<typename Callback> 44 IterationDecision for_each_visible_window_of_type_from_back_to_front(WindowType, Callback, bool ignore_highlight = false); 45 template<typename Callback> 46 IterationDecision for_each_window_of_type_from_front_to_back(WindowType, Callback, bool ignore_highlight = false); 47 48 template<typename Callback> 49 void for_each_window(Callback); 50 template<typename Callback> 51 IterationDecision for_each_window_from_back_to_front(Callback); 52 53 Window::List& windows() { return m_windows; } 54 55 Window* active_window() { return m_active_window; } 56 Window const* active_window() const { return m_active_window; } 57 void set_active_window(Window*); 58 59 Optional<HitTestResult> hit_test(Gfx::IntPoint) const; 60 61 unsigned row() const { return m_row; } 62 unsigned column() const { return m_column; } 63 64 void set_transition_offset(Badge<Compositor>, Gfx::IntPoint transition_offset) { m_transition_offset = transition_offset; } 65 Gfx::IntPoint transition_offset() const { return m_transition_offset; } 66 67 void set_stationary_window_stack(WindowStack& window_stack) { m_stationary_window_stack = &window_stack; } 68 WindowStack& stationary_window_stack() 69 { 70 VERIFY(m_stationary_window_stack); 71 return *m_stationary_window_stack; 72 } 73 74 void set_all_occluded(bool); 75 76private: 77 WeakPtr<Window> m_active_window; 78 79 Window::List m_windows; 80 unsigned m_row { 0 }; 81 unsigned m_column { 0 }; 82 Gfx::IntPoint m_transition_offset; 83 WindowStack* m_stationary_window_stack { nullptr }; 84}; 85 86template<typename Callback> 87inline IterationDecision WindowStack::for_each_visible_window_of_type_from_back_to_front(WindowType type, Callback callback, bool ignore_highlight) 88{ 89 auto* highlight_window = this->highlight_window(); 90 bool do_highlight_window_at_end = false; 91 for (auto& window : m_windows) { 92 if (!window.is_visible()) 93 continue; 94 if (window.is_minimized()) 95 continue; 96 if (window.type() != type) 97 continue; 98 if (!ignore_highlight && highlight_window == &window) { 99 do_highlight_window_at_end = true; 100 continue; 101 } 102 if (callback(window) == IterationDecision::Break) 103 return IterationDecision::Break; 104 } 105 if (do_highlight_window_at_end) { 106 if (callback(*highlight_window) == IterationDecision::Break) 107 return IterationDecision::Break; 108 } 109 return IterationDecision::Continue; 110} 111 112template<typename Callback> 113inline IterationDecision WindowStack::for_each_visible_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight) 114{ 115 auto* highlight_window = this->highlight_window(); 116 if (!ignore_highlight && highlight_window && highlight_window->type() == type && highlight_window->is_visible() && !highlight_window->is_minimized()) { 117 if (callback(*highlight_window) == IterationDecision::Break) 118 return IterationDecision::Break; 119 } 120 121 auto reverse_iterator = m_windows.rbegin(); 122 for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) { 123 auto& window = *reverse_iterator; 124 if (!window.is_visible()) 125 continue; 126 if (window.is_minimized()) 127 continue; 128 if (window.type() != type) 129 continue; 130 if (!ignore_highlight && &window == highlight_window) 131 continue; 132 if (callback(window) == IterationDecision::Break) 133 return IterationDecision::Break; 134 } 135 return IterationDecision::Continue; 136} 137 138template<typename Callback> 139inline void WindowStack::for_each_window(Callback callback) 140{ 141 auto reverse_iterator = m_windows.rbegin(); 142 for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) { 143 auto& window = *reverse_iterator; 144 if (callback(window) == IterationDecision::Break) 145 return; 146 } 147} 148 149template<typename Callback> 150inline IterationDecision WindowStack::for_each_window_from_back_to_front(Callback callback) 151{ 152 for (auto& window : m_windows) { 153 IterationDecision decision = callback(window); 154 if (decision != IterationDecision::Break) 155 return decision; 156 } 157 return IterationDecision::Continue; 158} 159 160template<typename Callback> 161inline IterationDecision WindowStack::for_each_window_of_type_from_front_to_back(WindowType type, Callback callback, bool ignore_highlight) 162{ 163 auto* highlight_window = this->highlight_window(); 164 if (!ignore_highlight && highlight_window && highlight_window->type() == type && highlight_window->is_visible()) { 165 if (callback(*highlight_window) == IterationDecision::Break) 166 return IterationDecision::Break; 167 } 168 169 auto reverse_iterator = m_windows.rbegin(); 170 for (; reverse_iterator != m_windows.rend(); ++reverse_iterator) { 171 auto& window = *reverse_iterator; 172 if (window.type() != type) 173 continue; 174 if (!ignore_highlight && &window == highlight_window) 175 continue; 176 if (callback(window) == IterationDecision::Break) 177 return IterationDecision::Break; 178 } 179 return IterationDecision::Continue; 180} 181 182}