diff options
-rw-r--r-- | Base/etc/motd | 2 | ||||
-rw-r--r-- | Kernel/GUITypes.h | 1 | ||||
-rw-r--r-- | Kernel/Process.h | 9 | ||||
-rw-r--r-- | Kernel/ProcessGUI.cpp | 82 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 14 | ||||
-rw-r--r-- | Kernel/Syscall.h | 13 | ||||
-rw-r--r-- | LibC/errno_numbers.h | 4 | ||||
-rw-r--r-- | LibC/gui.cpp | 26 | ||||
-rw-r--r-- | LibC/gui.h | 7 | ||||
-rw-r--r-- | LibGUI/GWidget.cpp | 14 | ||||
-rw-r--r-- | LibGUI/GWidget.h | 4 | ||||
-rw-r--r-- | LibGUI/GWindow.cpp | 36 | ||||
-rw-r--r-- | LibGUI/GWindow.h | 20 | ||||
-rw-r--r-- | SharedGraphics/GraphicsBitmap.h | 2 | ||||
-rw-r--r-- | SharedGraphics/Painter.cpp | 30 | ||||
-rw-r--r-- | SharedGraphics/Painter.h | 5 | ||||
-rw-r--r-- | Terminal/Terminal.cpp | 1 | ||||
-rw-r--r-- | Userland/guitest.cpp | 1 | ||||
-rw-r--r-- | WindowServer/WSEvent.h | 30 | ||||
-rw-r--r-- | WindowServer/WSWindow.cpp | 31 | ||||
-rw-r--r-- | WindowServer/WSWindow.h | 11 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.cpp | 3 |
22 files changed, 244 insertions, 102 deletions
diff --git a/Base/etc/motd b/Base/etc/motd index fd430ea570..1c4b9afe1b 100644 --- a/Base/etc/motd +++ b/Base/etc/motd @@ -7,5 +7,5 @@ [0m Welcome to Serenity OS. -Copyright (C) Andreas Kling, 2018 +Copyright (C) Andreas Kling, 2018-2019 All rights reserved. diff --git a/Kernel/GUITypes.h b/Kernel/GUITypes.h index 49b4de3fdd..9059ed96e4 100644 --- a/Kernel/GUITypes.h +++ b/Kernel/GUITypes.h @@ -34,6 +34,7 @@ struct GUI_WindowParameters { }; struct GUI_WindowBackingStoreInfo { + void* backing_store_id; GUI_Size size; size_t bpp; size_t pitch; diff --git a/Kernel/Process.h b/Kernel/Process.h index 0a33d52996..39f9f681f7 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -20,6 +20,7 @@ class Region; class VMObject; class Zone; class WSWindow; +class GraphicsBitmap; #define COOL_GLOBALS #ifdef COOL_GLOBALS @@ -197,9 +198,12 @@ public: int gui$create_window(const GUI_WindowParameters*); int gui$destroy_window(int window_id); int gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*); + int gui$release_window_backing_store(void* backing_store_id); int gui$invalidate_window(int window_id, const GUI_Rect*); - int gui$get_window_parameters(int window_id, GUI_WindowParameters*); - int gui$set_window_parameters(int window_id, const GUI_WindowParameters*); + int gui$get_window_title(int window_id, char* buffer, size_t size); + int gui$set_window_title(int window_id, const char* title, size_t size); + int gui$get_window_rect(int window_id, GUI_Rect*); + int gui$set_window_rect(int window_id, const GUI_Rect*); DisplayInfo get_display_info(); @@ -360,6 +364,7 @@ private: RetainPtr<Region> m_display_framebuffer_region; HashMap<int, OwnPtr<WSWindow>> m_windows; + Vector<RetainPtr<GraphicsBitmap>> m_retained_backing_stores; Vector<GUI_Event> m_gui_events; Lock m_gui_events_lock; diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index 312850ab6e..8db434ba8e 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -97,13 +97,28 @@ int Process::gui$get_window_backing_store(int window_id, GUI_WindowBackingStoreI if (it == m_windows.end()) return -EBADWINDOW; auto& window = *(*it).value; + WSWindowLocker locker(window); + auto* backing_store = window.backing(); + m_retained_backing_stores.append(backing_store); + info->backing_store_id = backing_store; info->bpp = sizeof(RGBA32); - info->pitch = window.backing()->pitch(); - info->size = window.backing()->size(); - info->pixels = reinterpret_cast<RGBA32*>(window.backing()->client_region()->laddr().as_ptr()); + info->pitch = backing_store->pitch(); + info->size = backing_store->size(); + info->pixels = reinterpret_cast<RGBA32*>(backing_store->client_region()->laddr().as_ptr()); return 0; } +int Process::gui$release_window_backing_store(void* backing_store_id) +{ + for (size_t i = 0; i < m_retained_backing_stores.size(); ++i) { + if (m_retained_backing_stores[i].ptr() == backing_store_id) { + m_retained_backing_stores.remove(i); + return 0; + } + } + return -EBADBACKING; +} + int Process::gui$invalidate_window(int window_id, const GUI_Rect* rect) { if (window_id < 0) @@ -121,39 +136,82 @@ int Process::gui$invalidate_window(int window_id, const GUI_Rect* rect) #endif auto& window = *(*it).value; Rect invalidation_rect; - if (rect) + if (rect) { + WSWindowLocker locker(window); invalidation_rect = *rect; + } WSEventLoop::the().post_event(&window, make<WSWindowInvalidationEvent>(invalidation_rect)); WSEventLoop::the().server_process().request_wakeup(); return 0; } -int Process::gui$get_window_parameters(int window_id, GUI_WindowParameters* params) +int Process::gui$get_window_title(int window_id, char* buffer, size_t size) { if (window_id < 0) return -EINVAL; - if (!validate_write_typed(params)) + if (!validate_write(buffer, size)) return -EFAULT; auto it = m_windows.find(window_id); if (it == m_windows.end()) return -EBADWINDOW; auto& window = *(*it).value; - params->rect = window.rect(); - strcpy(params->title, window.title().characters()); + String title; + { + WSWindowLocker locker(window); + title = window.title(); + } + if (title.length() > size) + return -ERANGE; + memcpy(buffer, title.characters(), title.length()); + return title.length(); + +} + +int Process::gui$set_window_title(int window_id, const char* title, size_t size) +{ + if (window_id < 0) + return -EINVAL; + if (!validate_read(title, size)) + return -EFAULT; + auto it = m_windows.find(window_id); + if (it == m_windows.end()) + return -EBADWINDOW; + auto& window = *(*it).value; + String new_title(title, size); + WSEventLoop::the().post_event(&window, make<WSSetWindowTitle>(move(new_title))); + WSEventLoop::the().server_process().request_wakeup(); return 0; } -int Process::gui$set_window_parameters(int window_id, const GUI_WindowParameters* params) +int Process::gui$get_window_rect(int window_id, GUI_Rect* rect) { if (window_id < 0) return -EINVAL; - if (!validate_read_typed(params)) + if (!validate_write_typed(rect)) return -EFAULT; auto it = m_windows.find(window_id); if (it == m_windows.end()) return -EBADWINDOW; auto& window = *(*it).value; - window.set_rect(params->rect); - window.set_title(params->title); + { + WSWindowLocker locker(window); + *rect = window.rect(); + } + return 0; +} + +int Process::gui$set_window_rect(int window_id, const GUI_Rect* rect) +{ + if (window_id < 0) + return -EINVAL; + if (!validate_read_typed(rect)) + return -EFAULT; + auto it = m_windows.find(window_id); + if (it == m_windows.end()) + return -EBADWINDOW; + auto& window = *(*it).value; + Rect new_rect = *rect; + WSEventLoop::the().post_event(&window, make<WSSetWindowRect>(new_rect)); + WSEventLoop::the().server_process().request_wakeup(); return 0; } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index ee1bc07fb5..d8c73308e4 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -201,12 +201,18 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->gui$destroy_window((int)arg1); case Syscall::SC_gui_get_window_backing_store: return current->gui$get_window_backing_store((int)arg1, (GUI_WindowBackingStoreInfo*)arg2); + case Syscall::SC_gui_release_window_backing_store: + return current->gui$release_window_backing_store((void*)arg1); case Syscall::SC_gui_invalidate_window: return current->gui$invalidate_window((int)arg1, (const GUI_Rect*)arg2); - case Syscall::SC_gui_set_window_parameters: - return current->gui$set_window_parameters((int)arg1, (const GUI_WindowParameters*)arg2); - case Syscall::SC_gui_get_window_parameters: - return current->gui$get_window_parameters((int)arg1, (GUI_WindowParameters*)arg2); + case Syscall::SC_gui_set_window_title: + return current->gui$set_window_title((int)arg1, (const char*)arg2, (size_t)arg3); + case Syscall::SC_gui_get_window_title: + return current->gui$get_window_title((int)arg1, (char*)arg2, (size_t)arg3); + case Syscall::SC_gui_set_window_rect: + return current->gui$set_window_rect((int)arg1, (const GUI_Rect*)arg2); + case Syscall::SC_gui_get_window_rect: + return current->gui$get_window_rect((int)arg1, (GUI_Rect*)arg2); default: kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index bfe7c660ec..663ff3b7cd 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -67,15 +67,18 @@ __ENUMERATE_SYSCALL(utime) \ __ENUMERATE_SYSCALL(sync) \ __ENUMERATE_SYSCALL(ptsname_r) \ + __ENUMERATE_SYSCALL(select) \ + __ENUMERATE_SYSCALL(unlink) \ + __ENUMERATE_SYSCALL(poll) \ __ENUMERATE_SYSCALL(gui_create_window) \ __ENUMERATE_SYSCALL(gui_destroy_window) \ __ENUMERATE_SYSCALL(gui_get_window_backing_store) \ + __ENUMERATE_SYSCALL(gui_release_window_backing_store) \ __ENUMERATE_SYSCALL(gui_invalidate_window) \ - __ENUMERATE_SYSCALL(select) \ - __ENUMERATE_SYSCALL(gui_get_window_parameters) \ - __ENUMERATE_SYSCALL(gui_set_window_parameters) \ - __ENUMERATE_SYSCALL(unlink) \ - __ENUMERATE_SYSCALL(poll) \ + __ENUMERATE_SYSCALL(gui_get_window_title) \ + __ENUMERATE_SYSCALL(gui_set_window_title) \ + __ENUMERATE_SYSCALL(gui_get_window_rect) \ + __ENUMERATE_SYSCALL(gui_set_window_rect) \ struct fd_set; diff --git a/LibC/errno_numbers.h b/LibC/errno_numbers.h index 62fd2c09e2..38f5efe559 100644 --- a/LibC/errno_numbers.h +++ b/LibC/errno_numbers.h @@ -42,7 +42,9 @@ __ERROR(ENOTIMPL, "Not implemented") \ __ERROR(EAFNOSUPPORT, "Address family not supported") \ __ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \ - __ERROR(EBADWINDOW, "Bad Window ID") \ + __ERROR(EBADWINDOW, "Bad window ID") \ + __ERROR(EBADBACKING, "Bad backing store ID") \ + enum __errno_values { #undef __ERROR diff --git a/LibC/gui.cpp b/LibC/gui.cpp index 0a4359453e..37bd1e8907 100644 --- a/LibC/gui.cpp +++ b/LibC/gui.cpp @@ -21,14 +21,32 @@ int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo* info __RETURN_WITH_ERRNO(rc, rc, -1); } -int gui_get_window_parameters(int window_id, GUI_WindowParameters* params) +int gui_release_window_backing_store(void* backing_store_id) { - int rc = syscall(SC_gui_get_window_parameters, window_id, params); + int rc = syscall(SC_gui_release_window_backing_store, backing_store_id); __RETURN_WITH_ERRNO(rc, rc, -1); } -int gui_set_window_parameters(int window_id, const GUI_WindowParameters* params) +int gui_get_window_title(int window_id, char* buffer, size_t size) { - int rc = syscall(SC_gui_set_window_parameters, window_id, params); + int rc = syscall(SC_gui_get_window_title, window_id, buffer, size); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +int gui_set_window_title(int window_id, const char* title, size_t length) +{ + int rc = syscall(SC_gui_set_window_title, window_id, title, length); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +int gui_get_window_rect(int window_id, GUI_Rect* rect) +{ + int rc = syscall(SC_gui_get_window_rect, window_id, rect); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +int gui_set_window_rect(int window_id, const GUI_Rect* rect) +{ + int rc = syscall(SC_gui_set_window_rect, window_id, rect); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/LibC/gui.h b/LibC/gui.h index 7b008fbfba..c4900dc363 100644 --- a/LibC/gui.h +++ b/LibC/gui.h @@ -8,8 +8,11 @@ __BEGIN_DECLS int gui_create_window(const GUI_WindowParameters*); int gui_invalidate_window(int window_id, const GUI_Rect*); int gui_get_window_backing_store(int window_id, GUI_WindowBackingStoreInfo*); -int gui_get_window_parameters(int window_id, GUI_WindowParameters*); -int gui_set_window_parameters(int window_id, const GUI_WindowParameters*); +int gui_release_window_backing_store(void* backing_store_id); +int gui_get_window_title(int window_id, char*, size_t); +int gui_set_window_title(int window_id, const char*, size_t); +int gui_get_window_rect(int window_id, GUI_Rect*); +int gui_set_window_rect(int window_id, const GUI_Rect*); __END_DECLS diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index 25fe852f27..feb84a1f95 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -18,12 +18,13 @@ GWidget::~GWidget() { } -void GWidget::set_relative_rect(const Rect& rect, bool should_update) +void GWidget::set_relative_rect(const Rect& rect) { + if (rect == m_relative_rect) + return; // FIXME: Make some kind of event loop driven ResizeEvent? m_relative_rect = rect; - if (should_update) - update(); + update(); } void GWidget::repaint(const Rect& rect) @@ -147,10 +148,3 @@ void GWidget::set_font(RetainPtr<Font>&& font) else m_font = move(font); } - -GraphicsBitmap* GWidget::backing() -{ - if (auto* w = window()) - return w->backing(); - return nullptr; -} diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h index 70826a2bcd..7f8e06f824 100644 --- a/LibGUI/GWidget.h +++ b/LibGUI/GWidget.h @@ -51,7 +51,7 @@ public: virtual const char* class_name() const override { return "GWidget"; } - void set_relative_rect(const Rect&, bool should_update = true); + void set_relative_rect(const Rect&); Color background_color() const { return m_background_color; } Color foreground_color() const { return m_foreground_color; } @@ -84,8 +84,6 @@ public: const Font& font() const { return *m_font; } void set_font(RetainPtr<Font>&&); - GraphicsBitmap* backing(); - private: GWindow* m_window { nullptr }; diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index 7ded9f4938..8cf791a6b0 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -39,14 +39,6 @@ GWindow::GWindow(GObject* parent) exit(1); } - GUI_WindowBackingStoreInfo backing; - int rc = gui_get_window_backing_store(m_window_id, &backing); - if (rc < 0) { - perror("gui_get_window_backing_store"); - exit(1); - } - m_backing = GraphicsBitmap::create_wrapper(backing.size, backing.pixels); - windows().set(m_window_id, this); } @@ -58,34 +50,16 @@ void GWindow::set_title(String&& title) { dbgprintf("GWindow::set_title \"%s\"\n", title.characters()); GUI_WindowParameters params; - int rc = gui_get_window_parameters(m_window_id, ¶ms); + int rc = gui_set_window_title(m_window_id, title.characters(), title.length()); ASSERT(rc == 0); - strcpy(params.title, title.characters());; - rc = gui_set_window_parameters(m_window_id, ¶ms); - ASSERT(rc == 0); - m_title = move(title); } -void GWindow::set_rect(const Rect& rect) +void GWindow::set_rect(const Rect& a_rect) { - // FIXME: This is a hack to fudge the race with WSWindowManager trying to display @ old rect. - sleep(10); - - dbgprintf("GWindow::set_rect %d,%d %dx%d\n", m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height()); - GUI_WindowParameters params; - int rc = gui_get_window_parameters(m_window_id, ¶ms); - ASSERT(rc == 0); - params.rect = rect; - rc = gui_set_window_parameters(m_window_id, ¶ms); + dbgprintf("GWindow::set_rect! %d,%d %dx%d\n", a_rect.x(), a_rect.y(), a_rect.width(), a_rect.height()); + GUI_Rect rect = a_rect; + int rc = gui_set_window_rect(m_window_id, &rect); ASSERT(rc == 0); - m_rect = rect; - GUI_WindowBackingStoreInfo backing; - rc = gui_get_window_backing_store(m_window_id, &backing); - if (rc < 0) { - perror("gui_get_window_backing_store"); - exit(1); - } - m_backing = GraphicsBitmap::create_wrapper(backing.size, backing.pixels); } void GWindow::event(GEvent& event) diff --git a/LibGUI/GWindow.h b/LibGUI/GWindow.h index 08e79daea6..8d45067672 100644 --- a/LibGUI/GWindow.h +++ b/LibGUI/GWindow.h @@ -16,20 +16,17 @@ public: int window_id() const { return m_window_id; } - String title() const { return m_title; } void set_title(String&&); - int x() const { return m_rect.x(); } - int y() const { return m_rect.y(); } - int width() const { return m_rect.width(); } - int height() const { return m_rect.height(); } + int x() const { return rect().x(); } + int y() const { return rect().y(); } + int width() const { return rect().width(); } + int height() const { return rect().height(); } - const Rect& rect() const { return m_rect; } + Rect rect() const; void set_rect(const Rect&); - void set_rect_without_repaint(const Rect& rect) { m_rect = rect; } - Point position() const { return m_rect.location(); } - void set_position_without_repaint(const Point& position) { set_rect_without_repaint({ position.x(), position.y(), width(), height() }); } + Point position() const { return rect().location(); } virtual void event(GEvent&) override; @@ -41,16 +38,11 @@ public: const GWidget* main_widget() const { return m_main_widget; } void set_main_widget(GWidget*); - GraphicsBitmap* backing() { return m_backing.ptr(); } - void show(); void update(); private: - String m_title; - Rect m_rect; - RetainPtr<GraphicsBitmap> m_backing; int m_window_id { -1 }; GWidget* m_main_widget { nullptr }; diff --git a/SharedGraphics/GraphicsBitmap.h b/SharedGraphics/GraphicsBitmap.h index 050518f3ba..a0796f92a4 100644 --- a/SharedGraphics/GraphicsBitmap.h +++ b/SharedGraphics/GraphicsBitmap.h @@ -1,6 +1,7 @@ #pragma once #include "Color.h" +#include "Rect.h" #include "Size.h" #include <AK/Retainable.h> #include <AK/RetainPtr.h> @@ -20,6 +21,7 @@ public: RGBA32* scanline(int y); const RGBA32* scanline(int y) const; + Rect rect() const { return { {}, m_size }; } Size size() const { return m_size; } int width() const { return m_size.width(); } int height() const { return m_size.height(); } diff --git a/SharedGraphics/Painter.cpp b/SharedGraphics/Painter.cpp index ff20ed7a20..4a5bf7105f 100644 --- a/SharedGraphics/Painter.cpp +++ b/SharedGraphics/Painter.cpp @@ -7,6 +7,8 @@ #ifdef LIBGUI #include <LibGUI/GWidget.h> #include <LibGUI/GWindow.h> +#include <LibC/gui.h> +#include <LibC/stdio.h> #endif #define DEBUG_WIDGET_UNDERDRAW @@ -22,12 +24,20 @@ Painter::Painter(GraphicsBitmap& bitmap) Painter::Painter(GWidget& widget) : m_font(&widget.font()) { - m_target = widget.backing(); + GUI_WindowBackingStoreInfo backing; + int rc = gui_get_window_backing_store(widget.window()->window_id(), &backing); + if (rc < 0) { + perror("gui_get_window_backing_store"); + exit(1); + } + m_backing_store_id = backing.backing_store_id; + m_target = GraphicsBitmap::create_wrapper(backing.size, backing.pixels); ASSERT(m_target); m_window = widget.window(); m_translation.move_by(widget.relative_position()); // NOTE: m_clip_rect is in Window coordinates since we are painting into its backing store. m_clip_rect = widget.relative_rect(); + m_clip_rect.intersect(m_target->rect()); #ifdef DEBUG_WIDGET_UNDERDRAW // If the widget is not opaque, let's not mess it up with debugging color. @@ -39,6 +49,11 @@ Painter::Painter(GWidget& widget) Painter::~Painter() { +#ifdef LIBGUI + m_target = nullptr; + int rc = gui_release_window_backing_store(m_backing_store_id); + ASSERT(rc == 0); +#endif } void Painter::fill_rect(const Rect& a_rect, Color color) @@ -47,6 +62,9 @@ void Painter::fill_rect(const Rect& a_rect, Color color) rect.move_by(m_translation); rect.intersect(m_clip_rect); + if (rect.is_empty()) + return; + RGBA32* dst = m_target->scanline(rect.top()) + rect.left(); const unsigned dst_skip = m_target->width(); @@ -266,3 +284,13 @@ void Painter::blit(const Point& position, const GraphicsBitmap& source, const Re src += src_skip; } } + +void Painter::set_clip_rect(const Rect& rect) +{ + m_clip_rect = Rect::intersection(rect, m_target->rect()); +} + +void Painter::clear_clip_rect() +{ + m_clip_rect = m_target->rect(); +} diff --git a/SharedGraphics/Painter.h b/SharedGraphics/Painter.h index 7deb386af9..5c433d56f8 100644 --- a/SharedGraphics/Painter.h +++ b/SharedGraphics/Painter.h @@ -40,8 +40,8 @@ public: void set_draw_op(DrawOp op) { m_draw_op = op; } DrawOp draw_op() const { return m_draw_op; } - void set_clip_rect(const Rect& rect) { m_clip_rect = rect; } - void clear_clip_rect() { m_clip_rect = { 0, 0, 1024, 768 }; } + void set_clip_rect(const Rect& rect); + void clear_clip_rect(); Rect clip_rect() const { return m_clip_rect; } private: @@ -53,6 +53,7 @@ private: RetainPtr<GraphicsBitmap> m_target; #ifdef LIBGUI GWindow* m_window { nullptr }; + void* m_backing_store_id { nullptr }; #endif DrawOp m_draw_op { DrawOp::Copy }; }; diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp index 9e829f0ef6..f432cc760d 100644 --- a/Terminal/Terminal.cpp +++ b/Terminal/Terminal.cpp @@ -26,6 +26,7 @@ void Terminal::create_window() exit(1); } + // NOTE: We never release the backing store. GUI_WindowBackingStoreInfo info; int rc = gui_get_window_backing_store(m_window_id, &info); if (rc < 0) { diff --git a/Userland/guitest.cpp b/Userland/guitest.cpp index 8f48a5cc75..b6a0401f42 100644 --- a/Userland/guitest.cpp +++ b/Userland/guitest.cpp @@ -30,6 +30,7 @@ int main(int argc, char** argv) return 1; } + // NOTE: We never release the backing store. This is just a simple app. :^) GUI_WindowBackingStoreInfo backing; int rc = gui_get_window_backing_store(window_id, &backing); if (rc < 0) { diff --git a/WindowServer/WSEvent.h b/WindowServer/WSEvent.h index b94a937d40..ea262f50c3 100644 --- a/WindowServer/WSEvent.h +++ b/WindowServer/WSEvent.h @@ -39,6 +39,8 @@ public: WM_Invalidate, WindowActivated, WindowDeactivated, + WM_SetWindowTitle, + WM_SetWindowRect, }; WSEvent() { } @@ -70,6 +72,34 @@ private: Rect m_rect; }; +class WSSetWindowTitle final : public WSEvent { +public: + explicit WSSetWindowTitle(String&& title) + : WSEvent(WSEvent::WM_SetWindowTitle) + , m_title(move(title)) + { + } + + String title() const { return m_title; } + +private: + String m_title; +}; + +class WSSetWindowRect final : public WSEvent { +public: + explicit WSSetWindowRect(const Rect& rect) + : WSEvent(WSEvent::WM_SetWindowRect) + , m_rect(rect) + { + } + + Rect rect() const { return m_rect; } + +private: + Rect m_rect; +}; + class WSPaintEvent final : public WSEvent { public: explicit WSPaintEvent(const Rect& rect = Rect()) diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp index 4ae135863c..a0cae6e7b3 100644 --- a/WindowServer/WSWindow.cpp +++ b/WindowServer/WSWindow.cpp @@ -19,21 +19,28 @@ WSWindow::~WSWindow() void WSWindow::set_title(String&& title) { - if (m_title == title) - return; + { + WSWindowLocker locker(*this); + if (m_title == title) + return; + m_title = move(title); + } - m_title = move(title); WSWindowManager::the().notify_title_changed(*this); } void WSWindow::set_rect(const Rect& rect) { - if (m_rect == rect) - return; - auto old_rect = m_rect; - m_rect = rect; - m_backing = GraphicsBitmap::create(m_process, m_rect.size()); - WSWindowManager::the().notify_rect_changed(*this, old_rect, m_rect); + Rect old_rect; + { + WSWindowLocker locker(*this); + if (m_rect == rect) + return; + old_rect = m_rect; + m_rect = rect; + m_backing = GraphicsBitmap::create(m_process, m_rect.size()); + } + WSWindowManager::the().notify_rect_changed(*this, old_rect, rect); } // FIXME: Just use the same types. @@ -86,6 +93,12 @@ void WSWindow::event(WSEvent& event) case WSEvent::WM_Invalidate: WSWindowManager::the().invalidate(*this, static_cast<WSWindowInvalidationEvent&>(event).rect()); return; + case WSEvent::WM_SetWindowRect: + set_rect(static_cast<WSSetWindowRect&>(event).rect()); + return; + case WSEvent::WM_SetWindowTitle: + set_title(static_cast<WSSetWindowTitle&>(event).title()); + return; case WSEvent::WindowActivated: gui_event.type = GUI_Event::Type::WindowActivated; break; diff --git a/WindowServer/WSWindow.h b/WindowServer/WSWindow.h index 0a771140e9..4e5bc77616 100644 --- a/WindowServer/WSWindow.h +++ b/WindowServer/WSWindow.h @@ -4,11 +4,13 @@ #include <SharedGraphics/GraphicsBitmap.h> #include <AK/AKString.h> #include <AK/InlineLinkedList.h> +#include <AK/Lock.h> #include "WSEventReceiver.h" class Process; class WSWindow final : public WSEventReceiver, public InlineLinkedListNode<WSWindow> { + friend class WSWindowLocker; public: WSWindow(Process&, int window_id); virtual ~WSWindow() override; @@ -46,6 +48,7 @@ public: WSWindow* m_prev { nullptr }; private: + Lock m_lock; String m_title; Rect m_rect; bool m_is_being_dragged { false }; @@ -56,3 +59,11 @@ private: pid_t m_pid { -1 }; }; +class WSWindowLocker { +public: + WSWindowLocker(WSWindow& window) : m_locker(window.m_lock) { } + ~WSWindowLocker() { } +private: + Locker m_locker; +}; + diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index a3cd657cd1..3f069d0cea 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -220,13 +220,13 @@ void WSWindowManager::remove_window(WSWindow& window) void WSWindowManager::notify_title_changed(WSWindow& window) { printf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); + invalidate(outer_window_rect(window.rect())); } void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect, const Rect& new_rect) { printf("[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()); ASSERT_INTERRUPTS_ENABLED(); - LOCKER(m_lock); invalidate(outer_window_rect(old_rect)); invalidate(outer_window_rect(new_rect)); } @@ -335,6 +335,7 @@ void WSWindowManager::compose() m_back_painter->fill_rect(dirty_rect, Color(0, 72, 96)); } for (auto* window = m_windows_in_order.head(); window; window = window->next()) { + WSWindowLocker locker(*window); if (!window->backing()) continue; if (!any_dirty_rect_intersects_window(*window)) |