Serenity Operating System
at portability 272 lines 9.7 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/InlineLinkedList.h> 30#include <AK/String.h> 31#include <LibCore/Object.h> 32#include <LibGfx/Bitmap.h> 33#include <LibGfx/DisjointRectSet.h> 34#include <LibGfx/Rect.h> 35#include <WindowServer/WindowFrame.h> 36#include <WindowServer/WindowType.h> 37 38namespace WindowServer { 39 40class ClientConnection; 41class Cursor; 42class Menu; 43class MouseEvent; 44 45enum WMEventMask { 46 WindowRectChanges = 1 << 0, 47 WindowStateChanges = 1 << 1, 48 WindowIconChanges = 1 << 2, 49 WindowRemovals = 1 << 3, 50}; 51 52enum class WindowTileType { 53 None = 0, 54 Left, 55 Right, 56}; 57 58enum class PopupMenuItem { 59 Minimize = 0, 60 Maximize, 61}; 62 63class Window final : public Core::Object 64 , public InlineLinkedListNode<Window> { 65 C_OBJECT(Window) 66public: 67 Window(ClientConnection&, WindowType, int window_id, bool modal, bool minimizable, bool resizable, bool fullscreen); 68 Window(Core::Object&, WindowType); 69 virtual ~Window() override; 70 71 void popup_window_menu(const Gfx::Point&); 72 void request_close(); 73 74 unsigned wm_event_mask() const { return m_wm_event_mask; } 75 void set_wm_event_mask(unsigned mask) { m_wm_event_mask = mask; } 76 77 bool is_minimized() const { return m_minimized; } 78 void set_minimized(bool); 79 80 bool is_minimizable() const { return m_minimizable; } 81 void set_minimizable(bool); 82 83 bool is_resizable() const { return m_resizable && !m_fullscreen; } 84 void set_resizable(bool); 85 86 bool is_maximized() const { return m_maximized; } 87 void set_maximized(bool); 88 89 bool is_fullscreen() const { return m_fullscreen; } 90 void set_fullscreen(bool); 91 92 WindowTileType tiled() const { return m_tiled; } 93 void set_tiled(WindowTileType); 94 95 bool is_occluded() const { return m_occluded; } 96 void set_occluded(bool); 97 98 bool show_titlebar() const { return m_show_titlebar; } 99 void set_show_titlebar(bool show) { m_show_titlebar = show; } 100 101 bool is_movable() const 102 { 103 return m_type == WindowType::Normal; 104 } 105 106 WindowFrame& frame() { return m_frame; } 107 const WindowFrame& frame() const { return m_frame; } 108 109 bool is_blocked_by_modal_window() const; 110 111 bool listens_to_wm_events() const { return m_listens_to_wm_events; } 112 113 ClientConnection* client() { return m_client; } 114 const ClientConnection* client() const { return m_client; } 115 116 WindowType type() const { return m_type; } 117 int window_id() const { return m_window_id; } 118 119 bool is_internal() const { return m_client_id == -1; } 120 i32 client_id() const { return m_client_id; } 121 122 String title() const { return m_title; } 123 void set_title(const String&); 124 125 float opacity() const { return m_opacity; } 126 void set_opacity(float); 127 128 int x() const { return m_rect.x(); } 129 int y() const { return m_rect.y(); } 130 int width() const { return m_rect.width(); } 131 int height() const { return m_rect.height(); } 132 133 bool is_active() const; 134 135 bool is_visible() const { return m_visible; } 136 void set_visible(bool); 137 138 bool is_modal() const { return m_modal; } 139 140 Gfx::Rect rect() const { return m_rect; } 141 void set_rect(const Gfx::Rect&); 142 void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); } 143 void set_rect_without_repaint(const Gfx::Rect& rect) 144 { 145 ASSERT(!rect.is_empty()); 146 if (m_rect == rect) 147 return; 148 auto old_rect = m_rect; 149 m_rect = rect; 150 m_frame.notify_window_rect_changed(old_rect, rect); 151 } 152 153 void set_taskbar_rect(const Gfx::Rect& rect) { m_taskbar_rect = rect; } 154 const Gfx::Rect& taskbar_rect() const { return m_taskbar_rect; } 155 156 void move_to(const Gfx::Point& position) { set_rect({ position, size() }); } 157 void move_to(int x, int y) { move_to({ x, y }); } 158 159 Gfx::Point position() const { return m_rect.location(); } 160 void set_position(const Gfx::Point& position) { set_rect({ position.x(), position.y(), width(), height() }); } 161 void set_position_without_repaint(const Gfx::Point& position) { set_rect_without_repaint({ position.x(), position.y(), width(), height() }); } 162 163 Gfx::Size size() const { return m_rect.size(); } 164 165 void invalidate(); 166 void invalidate(const Gfx::Rect&); 167 168 virtual void event(Core::Event&) override; 169 170 // Only used by WindowType::MenuApplet. Perhaps it could be a Window subclass? I don't know. 171 void set_rect_in_menubar(const Gfx::Rect& rect) { m_rect_in_menubar = rect; } 172 const Gfx::Rect& rect_in_menubar() const { return m_rect_in_menubar; } 173 174 const Gfx::Bitmap* backing_store() const { return m_backing_store.ptr(); } 175 Gfx::Bitmap* backing_store() { return m_backing_store.ptr(); } 176 177 void set_backing_store(RefPtr<Gfx::Bitmap>&& backing_store) 178 { 179 m_last_backing_store = move(m_backing_store); 180 m_backing_store = move(backing_store); 181 } 182 183 void swap_backing_stores() 184 { 185 swap(m_backing_store, m_last_backing_store); 186 } 187 188 Gfx::Bitmap* last_backing_store() { return m_last_backing_store.ptr(); } 189 190 void set_global_cursor_tracking_enabled(bool); 191 void set_automatic_cursor_tracking_enabled(bool enabled) { m_automatic_cursor_tracking_enabled = enabled; } 192 bool global_cursor_tracking() const { return m_global_cursor_tracking_enabled || m_automatic_cursor_tracking_enabled; } 193 194 bool has_alpha_channel() const { return m_has_alpha_channel; } 195 void set_has_alpha_channel(bool value) { m_has_alpha_channel = value; } 196 197 Gfx::Size size_increment() const { return m_size_increment; } 198 void set_size_increment(const Gfx::Size& increment) { m_size_increment = increment; } 199 200 Gfx::Size base_size() const { return m_base_size; } 201 void set_base_size(const Gfx::Size& size) { m_base_size = size; } 202 203 const Gfx::Bitmap& icon() const { return *m_icon; } 204 void set_icon(NonnullRefPtr<Gfx::Bitmap>&& icon) { m_icon = move(icon); } 205 206 void set_default_icon(); 207 208 const Cursor* override_cursor() const { return m_override_cursor.ptr(); } 209 void set_override_cursor(RefPtr<Cursor>&& cursor) { m_override_cursor = move(cursor); } 210 211 void request_update(const Gfx::Rect&, bool ignore_occlusion = false); 212 Gfx::DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); } 213 214 bool in_minimize_animation() const { return m_minimize_animation_step != -1; } 215 216 int minimize_animation_index() const { return m_minimize_animation_step; } 217 void step_minimize_animation() { m_minimize_animation_step += 1; } 218 void start_minimize_animation() { m_minimize_animation_step = 0; } 219 void end_minimize_animation() { m_minimize_animation_step = -1; } 220 221 // For InlineLinkedList. 222 // FIXME: Maybe make a ListHashSet and then WindowManager can just use that. 223 Window* m_next { nullptr }; 224 Window* m_prev { nullptr }; 225 226 void detach_client(Badge<ClientConnection>); 227 228private: 229 void handle_mouse_event(const MouseEvent&); 230 void update_menu_item_text(PopupMenuItem item); 231 void update_menu_item_enabled(PopupMenuItem item); 232 233 ClientConnection* m_client { nullptr }; 234 String m_title; 235 Gfx::Rect m_rect; 236 Gfx::Rect m_saved_nonfullscreen_rect; 237 Gfx::Rect m_taskbar_rect; 238 WindowType m_type { WindowType::Normal }; 239 bool m_global_cursor_tracking_enabled { false }; 240 bool m_automatic_cursor_tracking_enabled { false }; 241 bool m_visible { true }; 242 bool m_has_alpha_channel { false }; 243 bool m_modal { false }; 244 bool m_minimizable { false }; 245 bool m_resizable { false }; 246 bool m_listens_to_wm_events { false }; 247 bool m_minimized { false }; 248 bool m_maximized { false }; 249 bool m_fullscreen { false }; 250 WindowTileType m_tiled { WindowTileType::None }; 251 Gfx::Rect m_untiled_rect; 252 bool m_occluded { false }; 253 bool m_show_titlebar { true }; 254 RefPtr<Gfx::Bitmap> m_backing_store; 255 RefPtr<Gfx::Bitmap> m_last_backing_store; 256 int m_window_id { -1 }; 257 i32 m_client_id { -1 }; 258 float m_opacity { 1 }; 259 Gfx::Size m_size_increment; 260 Gfx::Size m_base_size; 261 NonnullRefPtr<Gfx::Bitmap> m_icon; 262 RefPtr<Cursor> m_override_cursor; 263 WindowFrame m_frame; 264 unsigned m_wm_event_mask { 0 }; 265 Gfx::DisjointRectSet m_pending_paint_rects; 266 Gfx::Rect m_unmaximized_rect; 267 Gfx::Rect m_rect_in_menubar; 268 RefPtr<Menu> m_window_menu; 269 int m_minimize_animation_step { -1 }; 270}; 271 272}