From 47d270b5774493b5ac3bb5a7f41f164cf8782068 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 5 Apr 2019 15:54:56 +0200 Subject: [PATCH] WindowServer: Factor out window frame logic into a WSWindowFrame class. The window frame is an object that contains a window, its title bar and window border. This way WSWindowManager doesn't have to know about all the different types of window borders, titlebar rects, etc. --- AK/StdLibExtras.h | 2 + Servers/WindowServer/Makefile | 1 + Servers/WindowServer/WSWindow.cpp | 4 +- Servers/WindowServer/WSWindow.h | 15 +- Servers/WindowServer/WSWindowFrame.cpp | 246 +++++++++++++++++++++ Servers/WindowServer/WSWindowFrame.h | 22 ++ Servers/WindowServer/WSWindowManager.cpp | 258 ++--------------------- Servers/WindowServer/WSWindowManager.h | 1 + 8 files changed, 312 insertions(+), 237 deletions(-) create mode 100644 Servers/WindowServer/WSWindowFrame.cpp create mode 100644 Servers/WindowServer/WSWindowFrame.h diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h index 97e6ad57d1..e953d16d6e 100644 --- a/AK/StdLibExtras.h +++ b/AK/StdLibExtras.h @@ -7,6 +7,8 @@ #include #endif +#define UNUSED_PARAM(x) (void)x + #include extern "C" void* mmx_memcpy(void* to, const void* from, size_t); diff --git a/Servers/WindowServer/Makefile b/Servers/WindowServer/Makefile index 3590168ae4..ebed131563 100644 --- a/Servers/WindowServer/Makefile +++ b/Servers/WindowServer/Makefile @@ -22,6 +22,7 @@ WINDOWSERVER_OBJS = \ WSWindowSwitcher.o \ WSClipboard.o \ WSCursor.o \ + WSWindowFrame.o \ main.o APP = WindowServer diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index b14f1b66ef..c186ac510d 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -17,6 +17,7 @@ WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type) : m_internal_owner(&internal_owner) , m_type(type) , m_icon(default_window_icon()) + , m_frame(*this) { WSWindowManager::the().add_window(*this); } @@ -27,6 +28,7 @@ WSWindow::WSWindow(WSClientConnection& client, WSWindowType window_type, int win , m_modal(modal) , m_window_id(window_id) , m_icon(default_window_icon()) + , m_frame(*this) { // FIXME: This should not be hard-coded here. if (m_type == WSWindowType::Taskbar) @@ -57,7 +59,7 @@ void WSWindow::set_rect(const Rect& rect) if (!m_client && (!m_backing_store || old_rect.size() != rect.size())) { m_backing_store = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size()); } - WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); + m_frame.notify_window_rect_changed(old_rect, rect); } // FIXME: Just use the same types. diff --git a/Servers/WindowServer/WSWindow.h b/Servers/WindowServer/WSWindow.h index 165c32cef0..abf8d009ec 100644 --- a/Servers/WindowServer/WSWindow.h +++ b/Servers/WindowServer/WSWindow.h @@ -6,6 +6,7 @@ #include #include "WSMessageReceiver.h" #include +#include class WSClientConnection; class WSCursor; @@ -18,6 +19,9 @@ public: WSWindow(WSMessageReceiver&, WSWindowType); virtual ~WSWindow() override; + WSWindowFrame& frame() { return m_frame; } + const WSWindowFrame& frame() const { return m_frame; } + bool is_blocked_by_modal_window() const; bool listens_to_wm_events() const { return m_listens_to_wm_events; } @@ -52,7 +56,15 @@ public: Rect rect() const { return m_rect; } void set_rect(const Rect&); void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); } - void set_rect_without_repaint(const Rect& rect) { m_rect = rect; } + void set_rect_without_repaint(const Rect& rect) + { + if (m_rect == rect) + return; + auto old_rect = m_rect; + m_rect = rect; + m_frame.notify_window_rect_changed(old_rect, rect); + } + void set_rect_from_window_manager_resize(const Rect&); void move_to(const Point& position) { set_rect({ position, size() }); } @@ -136,4 +148,5 @@ private: Size m_base_size; Retained m_icon; RetainPtr m_override_cursor; + WSWindowFrame m_frame; }; diff --git a/Servers/WindowServer/WSWindowFrame.cpp b/Servers/WindowServer/WSWindowFrame.cpp new file mode 100644 index 0000000000..1e42dca3ac --- /dev/null +++ b/Servers/WindowServer/WSWindowFrame.cpp @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +WSWindowFrame::WSWindowFrame(WSWindow& window) + : m_window(window) +{ +} + +WSWindowFrame::~WSWindowFrame() +{ +} + +static const int window_titlebar_height = 18; + +static inline Rect menu_window_rect(const Rect& rect) +{ + return rect.inflated(2, 2); +} + +static inline Rect title_bar_rect(const Rect& window) +{ + return { + window.x() - 1, + window.y() - window_titlebar_height, + window.width() + 2, + window_titlebar_height + }; +} + +static inline Rect title_bar_icon_rect(const Rect& window) +{ + auto titlebar_rect = title_bar_rect(window); + return { + titlebar_rect.x() + 2, + titlebar_rect.y(), + 16, + titlebar_rect.height(), + }; +} + +static inline Rect title_bar_text_rect(const Rect& window) +{ + auto titlebar_rect = title_bar_rect(window); + auto titlebar_icon_rect = title_bar_icon_rect(window); + return { + titlebar_rect.x() + 2 + titlebar_icon_rect.width() + 2, + titlebar_rect.y(), + titlebar_rect.width() - 4 - titlebar_icon_rect.width() - 2, + titlebar_rect.height() + }; +} + +static inline Rect close_button_rect_for_window(const Rect& window_rect) +{ + auto titlebar_inner_rect = title_bar_text_rect(window_rect); + int close_button_margin = 1; + int close_button_size = titlebar_inner_rect.height() - close_button_margin * 2; + return Rect { + titlebar_inner_rect.right() - close_button_size + 1, + titlebar_inner_rect.top() + close_button_margin, + close_button_size, + close_button_size - 1 + }; +} + +static inline Rect border_window_rect(const Rect& window) +{ + auto titlebar_rect = title_bar_rect(window); + return { titlebar_rect.x() - 1, + titlebar_rect.y() - 1, + titlebar_rect.width() + 2, + window_titlebar_height + window.height() + 3 + }; +} + +static inline Rect outer_window_rect(const Rect& window) +{ + auto rect = border_window_rect(window); + rect.inflate(2, 2); + return rect; +} + +static inline Rect outer_window_rect(const WSWindow& window) +{ + if (window.type() == WSWindowType::Menu) + return menu_window_rect(window.rect()); + if (window.type() == WSWindowType::WindowSwitcher) + return window.rect(); + if (window.type() == WSWindowType::Taskbar) + return window.rect(); + ASSERT(window.type() == WSWindowType::Normal); + return outer_window_rect(window.rect()); +} + +static const char* s_close_button_bitmap_data = { + "## ##" + "### ###" + " ###### " + " #### " + " ## " + " #### " + " ###### " + "### ###" + "## ##" +}; + +static CharacterBitmap* s_close_button_bitmap; +static const int s_close_button_bitmap_width = 8; +static const int s_close_button_bitmap_height = 9; + +void WSWindowFrame::paint(Painter& painter) +{ + //printf("[WM] paint_window_frame {%p}, rect: %d,%d %dx%d\n", &window, window.rect().x(), window.rect().y(), window.rect().width(), window.rect().height()); + + if (m_window.type() == WSWindowType::Menu) { + painter.draw_rect(menu_window_rect(m_window.rect()), Color::LightGray); + return; + } + + if (m_window.type() == WSWindowType::WindowSwitcher) + return; + + if (m_window.type() == WSWindowType::Taskbar) + return; + + auto& window = m_window; + + auto titlebar_rect = title_bar_rect(window.rect()); + auto titlebar_icon_rect = title_bar_icon_rect(window.rect()); + auto titlebar_inner_rect = title_bar_text_rect(window.rect()); + auto outer_rect = outer_window_rect(window); + auto border_rect = border_window_rect(window.rect()); + auto close_button_rect = close_button_rect_for_window(window.rect()); + + auto titlebar_title_rect = titlebar_inner_rect; + titlebar_title_rect.set_width(Font::default_bold_font().width(window.title())); + + Rect inner_border_rect { + window.x() - 1, + window.y() - 1, + window.width() + 2, + window.height() + 2 + }; + + Color title_color; + Color border_color; + Color border_color2; + Color middle_border_color; + + auto& wm = WSWindowManager::the(); + + if (&window == wm.m_highlight_window.ptr()) { + border_color = wm.m_highlight_window_border_color; + border_color2 = wm.m_highlight_window_border_color2; + title_color = wm.m_highlight_window_title_color; + middle_border_color = Color::White; + } else if (&window == wm.m_drag_window.ptr()) { + border_color = wm.m_dragging_window_border_color; + border_color2 = wm.m_dragging_window_border_color2; + title_color = wm.m_dragging_window_title_color; + middle_border_color = Color::from_rgb(0xf9b36a); + } else if (&window == wm.m_active_window.ptr()) { + border_color = wm.m_active_window_border_color; + border_color2 = wm.m_active_window_border_color2; + title_color = wm.m_active_window_title_color; + middle_border_color = Color::from_rgb(0x8f673d); + } else { + border_color = wm.m_inactive_window_border_color; + border_color2 = wm.m_inactive_window_border_color2; + title_color = wm.m_inactive_window_title_color; + middle_border_color = Color::MidGray; + } + + painter.fill_rect_with_gradient(titlebar_rect, border_color, border_color2); + for (int i = 2; i <= titlebar_inner_rect.height() - 4; i += 2) { + painter.draw_line({ titlebar_title_rect.right() + 4, titlebar_inner_rect.y() + i }, { close_button_rect.left() - 3, titlebar_inner_rect.y() + i }, border_color); + } + painter.draw_rect(border_rect, middle_border_color); + painter.draw_rect(outer_rect, border_color); + painter.draw_rect(inner_border_rect, border_color); + + painter.draw_text(titlebar_title_rect, window.title(), wm.window_title_font(), TextAlignment::CenterLeft, title_color); + + painter.blit(titlebar_icon_rect.location(), window.icon(), window.icon().rect()); + + if (!s_close_button_bitmap) + s_close_button_bitmap = &CharacterBitmap::create_from_ascii(s_close_button_bitmap_data, s_close_button_bitmap_width, s_close_button_bitmap_height).leak_ref(); + + StylePainter::paint_button(painter, close_button_rect, ButtonStyle::Normal, false, false); + + auto x_location = close_button_rect.center(); + x_location.move_by(-(s_close_button_bitmap_width / 2), -(s_close_button_bitmap_height / 2)); + painter.draw_bitmap(x_location, *s_close_button_bitmap, Color::Black); +} + +Rect WSWindowFrame::rect() const +{ + if (m_window.type() == WSWindowType::Menu) + return menu_window_rect(m_window.rect()); + if (m_window.type() == WSWindowType::Normal) + return outer_window_rect(m_window); + if (m_window.type() == WSWindowType::WindowSwitcher) + return m_window.rect(); + if (m_window.type() == WSWindowType::Taskbar) + return m_window.rect(); + ASSERT_NOT_REACHED(); +} + +void WSWindowFrame::notify_window_rect_changed(const Rect& old_rect, const Rect& new_rect) +{ + auto& wm = WSWindowManager::the(); + wm.invalidate(outer_window_rect(old_rect)); + wm.invalidate(outer_window_rect(new_rect)); + wm.notify_rect_changed(m_window, old_rect, new_rect); +} + +void WSWindowFrame::on_mouse_event(const WSMouseEvent& event) +{ + auto& wm = WSWindowManager::the(); + if (m_window.type() != WSWindowType::Normal) + return; + if (title_bar_rect(m_window.rect()).contains(event.position())) { + if (event.type() == WSMessage::MouseDown) + wm.move_to_front_and_make_active(m_window); + if (close_button_rect_for_window(m_window.rect()).contains(event.position())) { + handle_close_button_mouse_event(event); + return; + } + if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) + wm.start_window_drag(m_window, event); + } +} + +void WSWindowFrame::handle_close_button_mouse_event(const WSMouseEvent& event) +{ + if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) { + m_window.on_message(WSMessage(WSMessage::WindowCloseRequest)); + return; + } +} diff --git a/Servers/WindowServer/WSWindowFrame.h b/Servers/WindowServer/WSWindowFrame.h new file mode 100644 index 0000000000..9eb47d82e7 --- /dev/null +++ b/Servers/WindowServer/WSWindowFrame.h @@ -0,0 +1,22 @@ +#pragma once + +class Painter; +class Rect; +class WSMouseEvent; +class WSWindow; + +class WSWindowFrame { +public: + WSWindowFrame(WSWindow&); + ~WSWindowFrame(); + + Rect rect() const; + void paint(Painter&); + void on_mouse_event(const WSMouseEvent&); + void notify_window_rect_changed(const Rect& old_rect, const Rect& new_rect); + +private: + void handle_close_button_mouse_event(const WSMouseEvent&); + + WSWindow& m_window; +}; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index d48482dfd1..bab256285b 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "WSMenu.h" #include "WSMenuBar.h" #include "WSMenuItem.h" @@ -23,88 +23,6 @@ static void get_cpu_usage(unsigned& busy, unsigned& idle); -static const int window_titlebar_height = 18; - -static inline Rect menu_window_rect(const Rect& rect) -{ - return rect.inflated(2, 2); -} - -static inline Rect title_bar_rect(const Rect& window) -{ - return { - window.x() - 1, - window.y() - window_titlebar_height, - window.width() + 2, - window_titlebar_height - }; -} - -static inline Rect title_bar_icon_rect(const Rect& window) -{ - auto titlebar_rect = title_bar_rect(window); - return { - titlebar_rect.x() + 2, - titlebar_rect.y(), - 16, - titlebar_rect.height(), - }; -} - -static inline Rect title_bar_text_rect(const Rect& window) -{ - auto titlebar_rect = title_bar_rect(window); - auto titlebar_icon_rect = title_bar_icon_rect(window); - return { - titlebar_rect.x() + 2 + titlebar_icon_rect.width() + 2, - titlebar_rect.y(), - titlebar_rect.width() - 4 - titlebar_icon_rect.width() - 2, - titlebar_rect.height() - }; -} - -static inline Rect close_button_rect_for_window(const Rect& window_rect) -{ - auto titlebar_inner_rect = title_bar_text_rect(window_rect); - int close_button_margin = 1; - int close_button_size = titlebar_inner_rect.height() - close_button_margin * 2; - return Rect { - titlebar_inner_rect.right() - close_button_size + 1, - titlebar_inner_rect.top() + close_button_margin, - close_button_size, - close_button_size - 1 - }; -} - -static inline Rect border_window_rect(const Rect& window) -{ - auto titlebar_rect = title_bar_rect(window); - return { titlebar_rect.x() - 1, - titlebar_rect.y() - 1, - titlebar_rect.width() + 2, - window_titlebar_height + window.height() + 3 - }; -} - -static inline Rect outer_window_rect(const Rect& window) -{ - auto rect = border_window_rect(window); - rect.inflate(2, 2); - return rect; -} - -static inline Rect outer_window_rect(const WSWindow& window) -{ - if (window.type() == WSWindowType::Menu) - return menu_window_rect(window.rect()); - if (window.type() == WSWindowType::WindowSwitcher) - return window.rect(); - if (window.type() == WSWindowType::Taskbar) - return window.rect(); - ASSERT(window.type() == WSWindowType::Normal); - return outer_window_rect(window.rect()); -} - static WSWindowManager* s_the; WSWindowManager& WSWindowManager::the() @@ -387,103 +305,6 @@ void WSWindowManager::set_current_menubar(WSMenuBar* menubar) invalidate(menubar_rect()); } -static const char* s_close_button_bitmap_data = { - "## ##" - "### ###" - " ###### " - " #### " - " ## " - " #### " - " ###### " - "### ###" - "## ##" -}; - -static CharacterBitmap* s_close_button_bitmap; -static const int s_close_button_bitmap_width = 8; -static const int s_close_button_bitmap_height = 9; - -void WSWindowManager::paint_window_frame(const WSWindow& window) -{ - //printf("[WM] paint_window_frame {%p}, rect: %d,%d %dx%d\n", &window, window.rect().x(), window.rect().y(), window.rect().width(), window.rect().height()); - - if (window.type() == WSWindowType::Menu) { - m_back_painter->draw_rect(menu_window_rect(window.rect()), Color::LightGray); - return; - } - - if (window.type() == WSWindowType::WindowSwitcher) - return; - - if (window.type() == WSWindowType::Taskbar) - return; - - auto titlebar_rect = title_bar_rect(window.rect()); - auto titlebar_icon_rect = title_bar_icon_rect(window.rect()); - auto titlebar_inner_rect = title_bar_text_rect(window.rect()); - auto outer_rect = outer_window_rect(window); - auto border_rect = border_window_rect(window.rect()); - auto close_button_rect = close_button_rect_for_window(window.rect()); - - auto titlebar_title_rect = titlebar_inner_rect; - titlebar_title_rect.set_width(Font::default_bold_font().width(window.title())); - - Rect inner_border_rect { - window.x() - 1, - window.y() - 1, - window.width() + 2, - window.height() + 2 - }; - - Color title_color; - Color border_color; - Color border_color2; - Color middle_border_color; - - if (&window == m_highlight_window.ptr()) { - border_color = m_highlight_window_border_color; - border_color2 = m_highlight_window_border_color2; - title_color = m_highlight_window_title_color; - middle_border_color = Color::White; - } else if (&window == m_drag_window.ptr()) { - border_color = m_dragging_window_border_color; - border_color2 = m_dragging_window_border_color2; - title_color = m_dragging_window_title_color; - middle_border_color = Color::from_rgb(0xf9b36a); - } else if (&window == m_active_window.ptr()) { - border_color = m_active_window_border_color; - border_color2 = m_active_window_border_color2; - title_color = m_active_window_title_color; - middle_border_color = Color::from_rgb(0x8f673d); - } else { - border_color = m_inactive_window_border_color; - border_color2 = m_inactive_window_border_color2; - title_color = m_inactive_window_title_color; - middle_border_color = Color::MidGray; - } - - m_back_painter->fill_rect_with_gradient(titlebar_rect, border_color, border_color2); - for (int i = 2; i <= titlebar_inner_rect.height() - 4; i += 2) { - m_back_painter->draw_line({ titlebar_title_rect.right() + 4, titlebar_inner_rect.y() + i }, { close_button_rect.left() - 3, titlebar_inner_rect.y() + i }, border_color); - } - m_back_painter->draw_rect(border_rect, middle_border_color); - m_back_painter->draw_rect(outer_rect, border_color); - m_back_painter->draw_rect(inner_border_rect, border_color); - - m_back_painter->draw_text(titlebar_title_rect, window.title(), window_title_font(), TextAlignment::CenterLeft, title_color); - - m_back_painter->blit(titlebar_icon_rect.location(), window.icon(), window.icon().rect()); - - if (!s_close_button_bitmap) - s_close_button_bitmap = &CharacterBitmap::create_from_ascii(s_close_button_bitmap_data, s_close_button_bitmap_width, s_close_button_bitmap_height).leak_ref(); - - StylePainter::paint_button(*m_back_painter, close_button_rect, ButtonStyle::Normal, false, false); - - auto x_location = close_button_rect.center(); - x_location.move_by(-(s_close_button_bitmap_width / 2), -(s_close_button_bitmap_height / 2)); - m_back_painter->draw_bitmap(x_location, *s_close_button_bitmap, Color::Black); -} - void WSWindowManager::add_window(WSWindow& window) { m_windows.set(&window); @@ -554,7 +375,7 @@ void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window) void WSWindowManager::notify_title_changed(WSWindow& window) { dbgprintf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); - invalidate(outer_window_rect(window)); + invalidate(window.frame().rect()); if (m_switcher.is_visible()) m_switcher.refresh(); @@ -563,14 +384,13 @@ void WSWindowManager::notify_title_changed(WSWindow& window) void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect, const Rect& new_rect) { + UNUSED_PARAM(old_rect); + UNUSED_PARAM(new_rect); #ifdef RESIZE_DEBUG dbgprintf("[WM] WSWindow %p rect changed (%d,%d %dx%d) -> (%d,%d %dx%d)\n", &window, old_rect.x(), old_rect.y(), old_rect.width(), old_rect.height(), new_rect.x(), new_rect.y(), new_rect.width(), new_rect.height()); #endif - invalidate(outer_window_rect(old_rect)); - invalidate(outer_window_rect(new_rect)); if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) m_switcher.refresh(); - tell_wm_listeners_window_state_changed(window); } @@ -616,15 +436,6 @@ void WSWindowManager::handle_menubar_mouse_event(const WSMouseEvent& event) }); } -void WSWindowManager::handle_close_button_mouse_event(WSWindow& window, const WSMouseEvent& event) -{ - if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) { - WSMessage message(WSMessage::WindowCloseRequest); - window.on_message(message); - return; - } -} - void WSWindowManager::start_window_drag(WSWindow& window, const WSMouseEvent& event) { #ifdef DRAG_DEBUG @@ -645,7 +456,7 @@ void WSWindowManager::start_window_resize(WSWindow& window, const WSMouseEvent& { ResizeDirection::Left, ResizeDirection::None, ResizeDirection::Right }, { ResizeDirection::DownLeft, ResizeDirection::Down, ResizeDirection::DownRight }, }; - Rect outer_rect = outer_window_rect(window); + Rect outer_rect = window.frame().rect(); ASSERT(outer_rect.contains(event.position())); int window_relative_x = event.x() - outer_rect.x(); int window_relative_y = event.y() - outer_rect.y(); @@ -681,15 +492,12 @@ bool WSWindowManager::process_ongoing_window_drag(const WSMouseEvent& event, WSW return true; } if (event.type() == WSMessage::MouseMove) { - auto old_window_rect = m_drag_window->rect(); Point pos = m_drag_window_origin; #ifdef DRAG_DEBUG dbgprintf("[WM] Dragging [origin: %d,%d] now: %d,%d\n", m_drag_origin.x(), m_drag_origin.y(), event.x(), event.y()); #endif pos.move_by(event.x() - m_drag_origin.x(), event.y() - m_drag_origin.y()); m_drag_window->set_position_without_repaint(pos); - invalidate(outer_window_rect(old_window_rect)); - invalidate(outer_window_rect(m_drag_window->rect())); return true; } return false; @@ -834,7 +642,11 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*& } for_each_visible_window_from_front_to_back([&] (WSWindow& window) { - if (window.type() == WSWindowType::Normal && outer_window_rect(window).contains(event.position())) { + if (!window.frame().rect().contains(event.position())) + return IterationDecision::Continue; + // First check if we should initiate a drag or resize (Logo+LMB or Logo+RMB). + // In those cases, the event is swallowed by the window manager. + if (window.type() == WSWindowType::Normal) { if (m_keyboard_modifiers == Mod_Logo && event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) { start_window_drag(window, event); return IterationDecision::Abort; @@ -844,18 +656,7 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*& return IterationDecision::Abort; } } - if (window.type() == WSWindowType::Normal && title_bar_rect(window.rect()).contains(event.position())) { - if (event.type() == WSMessage::MouseDown) - move_to_front_and_make_active(window); - if (close_button_rect_for_window(window.rect()).contains(event.position())) { - handle_close_button_mouse_event(window, event); - return IterationDecision::Abort; - } - if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) - start_window_drag(window, event); - return IterationDecision::Abort; - } - + // Well okay, let's see if we're hitting the frame or the window inside the frame. if (window.rect().contains(event.position())) { if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown) move_to_front_and_make_active(window); @@ -868,7 +669,10 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*& } return IterationDecision::Abort; } - return IterationDecision::Continue; + + // We are hitting the frame, pass the event along to WSWindowFrame. + window.frame().on_mouse_event(event); + return IterationDecision::Abort; }); } @@ -892,7 +696,7 @@ void WSWindowManager::compose() // Maybe there's some way we could know this? continue; } - if (outer_window_rect(*window).contains(r)) + if (window->frame().rect().contains(r)) return true; } return false; @@ -914,7 +718,7 @@ void WSWindowManager::compose() return IterationDecision::Continue;; if (window.has_alpha_channel()) return IterationDecision::Continue;; - if (outer_window_rect(window).contains(rect)) { + if (window.frame().rect().contains(rect)) { found = true; return IterationDecision::Abort; } @@ -924,9 +728,9 @@ void WSWindowManager::compose() }; auto any_dirty_rect_intersects_window = [&dirty_rects] (const WSWindow& window) { - auto window_rect = outer_window_rect(window); + auto window_frame_rect = window.frame().rect(); for (auto& dirty_rect : dirty_rects.rects()) { - if (dirty_rect.intersects(window_rect)) + if (dirty_rect.intersects(window_frame_rect)) return true; } return false; @@ -946,13 +750,13 @@ void WSWindowManager::compose() if (!any_dirty_rect_intersects_window(window)) return IterationDecision::Continue; PainterStateSaver saver(*m_back_painter); - m_back_painter->add_clip_rect(outer_window_rect(window)); + m_back_painter->add_clip_rect(window.frame().rect()); for (auto& dirty_rect : dirty_rects.rects()) { if (any_opaque_window_above_this_one_contains_rect(window, dirty_rect)) continue; PainterStateSaver saver(*m_back_painter); m_back_painter->add_clip_rect(dirty_rect); - paint_window_frame(window); + window.frame().paint(*m_back_painter); if (!backing_store) continue; Rect dirty_rect_in_window_coordinates = Rect::intersection(dirty_rect, window.rect()); @@ -1195,23 +999,7 @@ void WSWindowManager::invalidate(const Rect& a_rect, bool should_schedule_compos void WSWindowManager::invalidate(const WSWindow& window) { - if (window.type() == WSWindowType::Menu) { - invalidate(menu_window_rect(window.rect())); - return; - } - if (window.type() == WSWindowType::Normal) { - invalidate(outer_window_rect(window)); - return; - } - if (window.type() == WSWindowType::WindowSwitcher) { - invalidate(window.rect()); - return; - } - if (window.type() == WSWindowType::Taskbar) { - invalidate(window.rect()); - return; - } - ASSERT_NOT_REACHED(); + invalidate(window.frame().rect()); } void WSWindowManager::invalidate(const WSWindow& window, const Rect& rect) @@ -1220,7 +1008,7 @@ void WSWindowManager::invalidate(const WSWindow& window, const Rect& rect) invalidate(window); return; } - auto outer_rect = outer_window_rect(window); + auto outer_rect = window.frame().rect(); auto inner_rect = rect; inner_rect.move_by(window.position()); // FIXME: This seems slightly wrong; the inner rect shouldn't intersect the border part of the outer rect. diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 5c487f2256..a082aea302 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -29,6 +29,7 @@ class GraphicsBitmap; enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft }; class WSWindowManager : public WSMessageReceiver { + friend class WSWindowFrame; friend class WSWindowSwitcher; public: static WSWindowManager& the();