mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:32:43 +00:00 
			
		
		
		
	 0b7baa7e5a
			
		
	
	
		0b7baa7e5a
		
	
	
	
	
		
			
			https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules "The compiler is more likely to get the default semantics right and you cannot implement these functions better than the compiler."
		
			
				
	
	
		
			154 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include "WindowStack.h"
 | |
| #include "WindowManager.h"
 | |
| 
 | |
| namespace WindowServer {
 | |
| 
 | |
| WindowStack::WindowStack(unsigned row, unsigned column)
 | |
|     : m_row(row)
 | |
|     , m_column(column)
 | |
| {
 | |
| }
 | |
| 
 | |
| void WindowStack::add(Window& window)
 | |
| {
 | |
|     VERIFY(!window.is_on_any_window_stack({}));
 | |
|     m_windows.append(window);
 | |
|     window.set_window_stack({}, this);
 | |
| 
 | |
|     move_always_on_top_windows_to_front();
 | |
| }
 | |
| 
 | |
| void WindowStack::add_to_back(Window& window)
 | |
| {
 | |
|     VERIFY(!window.is_on_any_window_stack({}));
 | |
|     m_windows.prepend(window);
 | |
|     window.set_window_stack({}, this);
 | |
| }
 | |
| 
 | |
| void WindowStack::remove(Window& window)
 | |
| {
 | |
|     VERIFY(&window.window_stack() == this);
 | |
|     m_windows.remove(window);
 | |
|     window.set_window_stack({}, nullptr);
 | |
|     if (m_active_window == &window)
 | |
|         m_active_window = nullptr;
 | |
|     if (m_active_input_window == &window)
 | |
|         m_active_input_window = nullptr;
 | |
|     if (m_active_input_tracking_window == &window)
 | |
|         m_active_input_tracking_window = nullptr;
 | |
| }
 | |
| 
 | |
| void WindowStack::move_to_front(Window& window)
 | |
| {
 | |
|     if (m_windows.last() != &window)
 | |
|         window.invalidate();
 | |
| 
 | |
|     m_windows.remove(window);
 | |
|     m_windows.append(window);
 | |
| 
 | |
|     move_always_on_top_windows_to_front();
 | |
| 
 | |
|     if (window.is_always_on_top()) {
 | |
|         m_windows.remove(window);
 | |
|         m_windows.append(window);
 | |
|         window.invalidate();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void WindowStack::move_always_on_top_windows_to_front()
 | |
| {
 | |
|     Window::List always_on_top_list;
 | |
|     for (auto iterator = m_windows.begin(); iterator != m_windows.end(); ++iterator) {
 | |
|         auto& window = *iterator;
 | |
|         if (window.is_always_on_top()) {
 | |
|             m_windows.remove(window);
 | |
|             always_on_top_list.append(window);
 | |
|             iterator = m_windows.begin();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     while (!always_on_top_list.is_empty()) {
 | |
|         auto& window = *always_on_top_list.begin();
 | |
|         always_on_top_list.remove(window);
 | |
|         m_windows.append(window);
 | |
|         window.invalidate();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void WindowStack::move_all_windows(WindowStack& new_window_stack, Vector<Window*, 32>& windows_moved, MoveAllWindowsTo move_to)
 | |
| {
 | |
|     VERIFY(this != &new_window_stack);
 | |
| 
 | |
|     move_always_on_top_windows_to_front();
 | |
| 
 | |
|     if (move_to == MoveAllWindowsTo::Front) {
 | |
|         while (auto* window = m_windows.take_first()) {
 | |
|             window->set_window_stack({}, nullptr);
 | |
|             new_window_stack.add(*window);
 | |
|             windows_moved.append(window);
 | |
|         }
 | |
|     } else {
 | |
|         while (auto* window = m_windows.take_last()) {
 | |
|             window->set_window_stack({}, nullptr);
 | |
|             new_window_stack.add_to_back(*window);
 | |
|             windows_moved.append(window);
 | |
|         }
 | |
|     }
 | |
|     m_active_window = nullptr;
 | |
|     m_active_input_window = nullptr;
 | |
|     m_active_input_tracking_window = nullptr;
 | |
| }
 | |
| 
 | |
| Window* WindowStack::window_at(Gfx::IntPoint const& position, IncludeWindowFrame include_window_frame) const
 | |
| {
 | |
|     auto result = hit_test(position);
 | |
|     if (!result.has_value())
 | |
|         return nullptr;
 | |
|     if (include_window_frame == IncludeWindowFrame::No && result->is_frame_hit)
 | |
|         return nullptr;
 | |
|     return result->window;
 | |
| }
 | |
| 
 | |
| Window* WindowStack::highlight_window() const
 | |
| {
 | |
|     if (auto* window = WindowManager::the().highlight_window(); window && &window->window_stack() == this)
 | |
|         return window;
 | |
|     return nullptr;
 | |
| }
 | |
| 
 | |
| void WindowStack::set_active_window(Window* window)
 | |
| {
 | |
|     if (!window)
 | |
|         m_active_window = nullptr;
 | |
|     else
 | |
|         m_active_window = window->make_weak_ptr<Window>();
 | |
| }
 | |
| 
 | |
| void WindowStack::set_all_occluded(bool occluded)
 | |
| {
 | |
|     for (auto& window : m_windows) {
 | |
|         if (!WindowManager::is_stationary_window_type(window.type()))
 | |
|             window.set_occluded(occluded);
 | |
|     }
 | |
| }
 | |
| 
 | |
| Optional<HitTestResult> WindowStack::hit_test(Gfx::IntPoint const& position) const
 | |
| {
 | |
|     Optional<HitTestResult> result;
 | |
|     WindowManager::the().for_each_visible_window_from_front_to_back([&](Window& window) {
 | |
|         result = window.hit_test(position);
 | |
|         if (result.has_value())
 | |
|             return IterationDecision::Break;
 | |
|         return IterationDecision::Continue;
 | |
|     },
 | |
|         const_cast<WindowStack*>(this));
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| }
 |