summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Base/etc/motd2
-rw-r--r--Kernel/GUITypes.h1
-rw-r--r--Kernel/Process.h9
-rw-r--r--Kernel/ProcessGUI.cpp82
-rw-r--r--Kernel/Syscall.cpp14
-rw-r--r--Kernel/Syscall.h13
-rw-r--r--LibC/errno_numbers.h4
-rw-r--r--LibC/gui.cpp26
-rw-r--r--LibC/gui.h7
-rw-r--r--LibGUI/GWidget.cpp14
-rw-r--r--LibGUI/GWidget.h4
-rw-r--r--LibGUI/GWindow.cpp36
-rw-r--r--LibGUI/GWindow.h20
-rw-r--r--SharedGraphics/GraphicsBitmap.h2
-rw-r--r--SharedGraphics/Painter.cpp30
-rw-r--r--SharedGraphics/Painter.h5
-rw-r--r--Terminal/Terminal.cpp1
-rw-r--r--Userland/guitest.cpp1
-rw-r--r--WindowServer/WSEvent.h30
-rw-r--r--WindowServer/WSWindow.cpp31
-rw-r--r--WindowServer/WSWindow.h11
-rw-r--r--WindowServer/WSWindowManager.cpp3
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 @@

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, &params);
+ 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, &params);
- 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, &params);
- ASSERT(rc == 0);
- params.rect = rect;
- rc = gui_set_window_parameters(m_window_id, &params);
+ 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))