diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-01-16 16:03:50 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-01-16 16:03:50 +0100 |
commit | f7ca6d254d452e3524aaeaa1334ac041be3a1279 (patch) | |
tree | 165f54aa32eafbfd79003eb686770370f585c14d | |
parent | e655aebd70bb7d248c2f7be4a12d695ceec707a5 (diff) | |
download | serenity-f7ca6d254d452e3524aaeaa1334ac041be3a1279.zip |
Tear out or duplicate what's unique for WindowServer from Widgets.
This turned into a huge refactoring that somehow also includes
making locks recursive/reentrant.
30 files changed, 757 insertions, 308 deletions
@@ -2,13 +2,14 @@ #include "Assertions.h" #include "Types.h" - -#ifdef SERENITY #include "i386.h" int sched_yield(); -#else -#include <sched.h> -typedef int InterruptDisabler; + +class Process; +extern Process* current; + +#ifndef KERNEL +#error This thing is kernel-only right now. #endif //#define DEBUG_LOCKS @@ -30,70 +31,75 @@ static inline dword CAS(volatile dword* mem, dword newval, dword oldval) return ret; } -// FIXME: Rename to YieldingLock? +// FIXME: Rename to YieldingLock? RecursiveLock? Maybe just Lock? class SpinLock { public: SpinLock() { } ~SpinLock() { } - ALWAYS_INLINE void lock(const char* func = nullptr) - { - (void)func; -#ifdef DEBUG_LOCKS - { - InterruptDisabler dis; - log_try_lock(func); - } -#endif - for (;;) { - if (CAS(&m_lock, 1, 0) == 0) { -#ifdef DEBUG_LOCKS - InterruptDisabler dis; - log_locked(func); -#endif - return; - } - sched_yield(); - } - } + void lock(); + void unlock(); - ALWAYS_INLINE void unlock(const char* func = nullptr) - { - (void)func; - // barrier(); - ASSERT(m_lock); - m_lock = 0; -#ifdef DEBUG_LOCKS - InterruptDisabler dis; - log_unlocked(func); -#endif - } - - void init() - { - m_lock = 0; - } + const Process* holder() const { return m_holder; } private: volatile dword m_lock { 0 }; + dword m_level { 0 }; + Process* m_holder { nullptr }; }; class Locker { public: - ALWAYS_INLINE explicit Locker(SpinLock& l, const char* func) : m_lock(l), m_func(func) { lock(); } + ALWAYS_INLINE explicit Locker(SpinLock& l) : m_lock(l) { lock(); } ALWAYS_INLINE ~Locker() { unlock(); } - ALWAYS_INLINE void unlock() { m_lock.unlock(m_func); } - ALWAYS_INLINE void lock() { m_lock.lock(m_func); } + ALWAYS_INLINE void unlock() { m_lock.unlock(); } + ALWAYS_INLINE void lock() { m_lock.lock(); } private: SpinLock& m_lock; - const char* m_func { nullptr }; }; -#define LOCKER(lock) Locker locker(lock, __FUNCTION__) +inline void SpinLock::lock() +{ + for (;;) { + if (CAS(&m_lock, 1, 0) == 0) { + if (!m_holder || m_holder == current) { + m_holder = current; + ++m_level; + memory_barrier(); + m_lock = 0; + return; + } + m_lock = 0; + } + sched_yield(); + } +} + +inline void SpinLock::unlock() +{ + for (;;) { + if (CAS(&m_lock, 1, 0) == 0) { + ASSERT(m_holder == current); + ASSERT(m_level); + --m_level; + if (m_level) { + memory_barrier(); + m_lock = 0; + return; + } + m_holder = nullptr; + memory_barrier(); + m_lock = 0; + return; + } + sched_yield(); + } +} + +#define LOCKER(lock) Locker locker(lock) } using AK::SpinLock; using AK::Locker; - diff --git a/Widgets/GUIEventDevice.cpp b/Kernel/GUIEventDevice.cpp index 20ba6c917b..20ba6c917b 100644 --- a/Widgets/GUIEventDevice.cpp +++ b/Kernel/GUIEventDevice.cpp diff --git a/Widgets/GUIEventDevice.h b/Kernel/GUIEventDevice.h index e98b208f05..e98b208f05 100644 --- a/Widgets/GUIEventDevice.h +++ b/Kernel/GUIEventDevice.h diff --git a/Kernel/Makefile b/Kernel/Makefile index 149cffa46c..580a921618 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -30,7 +30,7 @@ KERNEL_OBJS = \ ELFLoader.o \ KSyms.o \ PS2MouseDevice.o \ - WindowServer.o + GUIEventDevice.o VFS_OBJS = \ ../VirtualFileSystem/DiskDevice.o \ @@ -46,21 +46,20 @@ VFS_OBJS = \ ../VirtualFileSystem/FileDescriptor.o \ ../VirtualFileSystem/SyntheticFileSystem.o -WIDGETS_OBJS = \ - ../Widgets/Window.o \ - ../Widgets/Painter.o \ - ../Widgets/WindowManager.o \ - ../Widgets/FrameBuffer.o \ - ../Widgets/GraphicsBitmap.o \ - ../Widgets/Object.o \ +WINDOWSERVER_OBJS = \ ../Widgets/Rect.o \ - ../Widgets/Widget.o \ + ../Widgets/Painter.o \ ../Widgets/Font.o \ ../Widgets/Color.o \ ../Widgets/CharacterBitmap.o \ - ../Widgets/EventLoop.o \ - ../Widgets/AbstractScreen.o \ - ../Widgets/GUIEventDevice.o \ + ../Widgets/GraphicsBitmap.o \ + ../WindowServer/WSEventReceiver.o \ + ../WindowServer/WSEventLoop.o \ + ../WindowServer/WSWindow.o \ + ../WindowServer/WSWindowManager.o \ + ../WindowServer/WSFrameBuffer.o \ + ../WindowServer/WSScreen.o \ + ../WindowServer/main.o AK_OBJS = \ ../AK/String.o \ @@ -68,7 +67,7 @@ AK_OBJS = \ ../AK/StringBuilder.o \ ../AK/FileSystemPath.o -OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WIDGETS_OBJS) +OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WINDOWSERVER_OBJS) NASM = nasm KERNEL = kernel diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 8b7bd457ac..eee7fc70a7 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -18,7 +18,7 @@ #include "Scheduler.h" #include "FIFO.h" #include "KSyms.h" -#include <Widgets/Window.h> +#include <WindowServer/WSWindow.h> #include "MasterPTY.h" //#define DEBUG_IO diff --git a/Kernel/Process.h b/Kernel/Process.h index 4e96a5328c..e79b37fa81 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -19,8 +19,7 @@ class PageDirectory; class Region; class VMObject; class Zone; -class Window; -class Widget; +class WSWindow; #define COOL_GLOBALS #ifdef COOL_GLOBALS @@ -47,7 +46,7 @@ struct DisplayInfo { class Process : public InlineLinkedListNode<Process> { friend class InlineLinkedListNode<Process>; - friend class WindowManager; // FIXME: Make a better API for allocate_region(). + friend class WSWindowManager; // FIXME: Make a better API for allocate_region(). friend class GraphicsBitmap; // FIXME: Make a better API for allocate_region(). public: static Process* create_kernel_process(String&& name, void (*entry)()); @@ -353,7 +352,7 @@ private: RetainPtr<Region> m_display_framebuffer_region; - HashMap<int, OwnPtr<Window>> m_windows; + HashMap<int, OwnPtr<WSWindow>> m_windows; Vector<GUI_Event> m_gui_events; SpinLock m_gui_events_lock; diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index 6801a9e86b..ff3ff76fc7 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -1,25 +1,22 @@ #include "Process.h" #include "MemoryManager.h" #include <LibC/errno_numbers.h> -#include <Widgets/AbstractScreen.h> -#include <Widgets/FrameBuffer.h> -#include <Widgets/EventLoop.h> #include <Widgets/Font.h> -#include <Widgets/Button.h> -#include <Widgets/Label.h> -#include <Widgets/Widget.h> -#include <Widgets/Window.h> -#include <Widgets/WindowManager.h> +#include <WindowServer/WSScreen.h> +#include <WindowServer/WSFrameBuffer.h> +#include <WindowServer/WSEventLoop.h> +#include <WindowServer/WSWindow.h> +#include <WindowServer/WSWindowManager.h> void Process::initialize_gui_statics() { Font::initialize(); - FrameBuffer::initialize(); - EventLoop::initialize(); - WindowManager::initialize(); - AbstractScreen::initialize(); + WSFrameBuffer::initialize(); + WSEventLoop::initialize(); + WSWindowManager::initialize(); + WSScreen::initialize(); - new EventLoop; + new WSEventLoop; } int Process::make_window_id() @@ -36,7 +33,7 @@ int Process::make_window_id() static void wait_for_gui_server() { // FIXME: Time out after a while and return an error. - while (!EventLoop::main().running()) + while (!WSEventLoop::the().running()) sleep(10); } @@ -53,13 +50,13 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params) if (rect.is_empty()) return -EINVAL; - ProcessPagingScope scope(EventLoop::main().server_process()); + ProcessPagingScope scope(WSEventLoop::the().server_process()); int window_id = make_window_id(); if (!window_id) return -ENOMEM; - auto window = make<Window>(*this, window_id); + auto window = make<WSWindow>(*this, window_id); if (!window) return -ENOMEM; @@ -113,7 +110,6 @@ int Process::gui$invalidate_window(int window_id) auto& window = *(*it).value; // FIXME: This should queue up a message that the window server process can read. // Poking into its data structures is not good. - InterruptDisabler disabler; - WindowManager::the().invalidate(window); + WSEventLoop::the().post_event(&window, make<WSEvent>(WSEvent::WM_Invalidate)); return 0; } diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 7bd8ee4d91..f8f546db1c 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -133,7 +133,7 @@ bool Scheduler::pick_next() for (auto* process = g_processes->head(); process; process = process->next()) { //if (process->state() == Process::BlockedWait || process->state() == Process::BlockedSleep) // continue; - dbgprintf("% 12s %s(%u) @ %w:%x\n", toString(process->state()), process->name().characters(), process->pid(), process->tss().cs, process->tss().eip); + dbgprintf("[K%x] % 12s %s(%u) @ %w:%x\n", process, toString(process->state()), process->name().characters(), process->pid(), process->tss().cs, process->tss().eip); } #endif diff --git a/Kernel/WindowServer.cpp b/Kernel/WindowServer.cpp deleted file mode 100644 index 674562ad7f..0000000000 --- a/Kernel/WindowServer.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Process.h" -#include <Widgets/Font.h> -#include <Widgets/FrameBuffer.h> -#include <Widgets/WindowManager.h> -#include <Widgets/EventLoop.h> -#include <Widgets/Window.h> - -void WindowServer_main() -{ - auto info = current->get_display_info(); - - dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp); - - FrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height); - - WindowManager::the(); - - dbgprintf("Entering WindowServer main loop.\n"); - EventLoop::main().exec(); - - ASSERT_NOT_REACHED(); -} diff --git a/Kernel/i386.h b/Kernel/i386.h index eae96cbd5c..d48c7b481e 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -81,6 +81,7 @@ void write_gdt_entry(word selector, Descriptor&); #define cli() asm volatile("cli") #define sti() asm volatile("sti") +#define memory_barrier() asm volatile ("" ::: "memory") static inline dword cpu_flags() { diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 52a942ac8d..1a6ce48bb8 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -15,7 +15,7 @@ #include <VirtualFileSystem/RandomDevice.h> #include <VirtualFileSystem/Ext2FileSystem.h> #include <VirtualFileSystem/VirtualFileSystem.h> -#include <Widgets/GUIEventDevice.h> +#include "GUIEventDevice.h" #include "MemoryManager.h" #include "ProcFileSystem.h" #include "RTC.h" diff --git a/Widgets/FrameBuffer.cpp b/Widgets/FrameBuffer.cpp deleted file mode 100644 index dc93460a07..0000000000 --- a/Widgets/FrameBuffer.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "FrameBuffer.h" -#include "GraphicsBitmap.h" -#include <AK/Assertions.h> - -FrameBuffer* s_the; - -void FrameBuffer::initialize() -{ - s_the = nullptr; -} - -FrameBuffer& FrameBuffer::the() -{ - ASSERT(s_the); - return *s_the; -} - -FrameBuffer::FrameBuffer(unsigned width, unsigned height) - : AbstractScreen(width, height) -{ - ASSERT(!s_the); - s_the = this; -} - -FrameBuffer::FrameBuffer(RGBA32* data, unsigned width, unsigned height) - : AbstractScreen(width, height) - , m_data(data) -{ - ASSERT(!s_the); - s_the = this; -} - - -FrameBuffer::~FrameBuffer() -{ -} - -void FrameBuffer::show() -{ -} - -RGBA32* FrameBuffer::scanline(int y) -{ - unsigned pitch = sizeof(RGBA32) * width(); - return reinterpret_cast<RGBA32*>(((byte*)m_data) + (y * pitch)); -} diff --git a/Widgets/FrameBuffer.h b/Widgets/FrameBuffer.h deleted file mode 100644 index c0758f19a6..0000000000 --- a/Widgets/FrameBuffer.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "AbstractScreen.h" -#include "Color.h" - -class GraphicsBitmap; - -class FrameBuffer final : public AbstractScreen { -public: - FrameBuffer(unsigned width, unsigned height); - FrameBuffer(RGBA32*, unsigned width, unsigned height); - virtual ~FrameBuffer() override; - - void show(); - - static FrameBuffer& the(); - - RGBA32* scanline(int y); - - static void initialize(); - -private: - RGBA32* m_data { nullptr }; -}; - diff --git a/Widgets/GraphicsBitmap.cpp b/Widgets/GraphicsBitmap.cpp index 6fc98447f9..3dbc47cf47 100644 --- a/Widgets/GraphicsBitmap.cpp +++ b/Widgets/GraphicsBitmap.cpp @@ -1,10 +1,10 @@ #include "GraphicsBitmap.h" -#include "EventLoop.h" #include <AK/kmalloc.h> #ifdef KERNEL -#include "Process.h" -#include "MemoryManager.h" +#include <Kernel/Process.h> +#include <Kernel/MemoryManager.h> +#include <WindowServer/WSEventLoop.h> #endif #ifdef KERNEL @@ -24,7 +24,7 @@ GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size) m_client_region->commit(process); { - auto& server = EventLoop::main().server_process(); + auto& server = WSEventLoop::the().server_process(); ProcessInspectionHandle composer_handle(server); m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (shared)", true, true); } @@ -50,7 +50,7 @@ GraphicsBitmap::~GraphicsBitmap() if (m_client_region) m_client_process->deallocate_region(*m_client_region); if (m_server_region) - EventLoop::main().server_process().deallocate_region(*m_server_region); + WSEventLoop::the().server_process().deallocate_region(*m_server_region); #endif m_data = nullptr; } diff --git a/Widgets/Window.h b/Widgets/Window.h index 3da05c3c97..1bbe354eb1 100644 --- a/Widgets/Window.h +++ b/Widgets/Window.h @@ -28,7 +28,6 @@ public: void set_rect_without_repaint(const Rect& rect) { m_rect = rect; } Point position() const { return m_rect.location(); } - void set_position(const Point& position) { set_rect({ position.x(), position.y(), width(), height() }); } void set_position_without_repaint(const Point& position) { set_rect_without_repaint({ position.x(), position.y(), width(), height() }); } virtual void event(Event&) override; diff --git a/WindowServer/.gitignore b/WindowServer/.gitignore new file mode 100644 index 0000000000..5761abcfdf --- /dev/null +++ b/WindowServer/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/WindowServer/WSEvent.h b/WindowServer/WSEvent.h new file mode 100644 index 0000000000..778dbd29ee --- /dev/null +++ b/WindowServer/WSEvent.h @@ -0,0 +1,151 @@ +#pragma once + +#include <Widgets/Point.h> +#include <Widgets/Rect.h> +#include <AK/AKString.h> +#include <AK/Types.h> + +static const char* WSEvent_names[] = { + "Invalid", + "Show", + "Hide", + "Paint", + "MouseMove", + "MouseDown", + "MouseUp", + "KeyDown", + "KeyUp", + "Timer", + "WM_Compose", + "WM_Invalidate", +}; + +class WSEvent { +public: + enum Type { + Invalid = 0, + Show, + Hide, + Paint, + MouseMove, + MouseDown, + MouseUp, + KeyDown, + KeyUp, + Timer, + WM_Compose, + WM_Invalidate, + }; + + WSEvent() { } + explicit WSEvent(Type type) : m_type(type) { } + virtual ~WSEvent() { } + + Type type() const { return m_type; } + + const char* name() const { return WSEvent_names[(unsigned)m_type]; } + + bool isMouseEvent() const { return m_type == MouseMove || m_type == MouseDown || m_type == MouseUp; } + bool isKeyEvent() const { return m_type == KeyUp || m_type == KeyDown; } + bool isPaintEvent() const { return m_type == Paint; } + +private: + Type m_type { Invalid }; +}; + +class PaintEvent final : public WSEvent { +public: + explicit PaintEvent(const Rect& rect = Rect()) + : WSEvent(WSEvent::Paint) + , m_rect(rect) + { + } + + const Rect& rect() const { return m_rect; } +private: + friend class WSWindowManager; + Rect m_rect; +}; + +class ShowEvent final : public WSEvent { +public: + ShowEvent() + : WSEvent(WSEvent::Show) + { + } +}; + +class HideEvent final : public WSEvent { +public: + HideEvent() + : WSEvent(WSEvent::Hide) + { + } +}; + +enum class MouseButton : byte { + None = 0, + Left, + Middle, + Right, +}; + +enum KeyboardKey { + Invalid, + LeftArrow, + RightArrow, + UpArrow, + DownArrow, + Backspace, + Return, +}; + +class KeyEvent final : public WSEvent { +public: + KeyEvent(Type type, int key) + : WSEvent(type) + , m_key(key) + { + } + + int key() const { return m_key; } + bool ctrl() const { return m_ctrl; } + bool alt() const { return m_alt; } + bool shift() const { return m_shift; } + String text() const { return m_text; } + +private: + friend class WSEventLoop; + friend class WSScreen; + int m_key { 0 }; + bool m_ctrl { false }; + bool m_alt { false }; + bool m_shift { false }; + String m_text; +}; + +class MouseEvent final : public WSEvent { +public: + MouseEvent(Type type, int x, int y, MouseButton button = MouseButton::None) + : WSEvent(type) + , m_position(x, y) + , m_button(button) + { + } + + Point position() const { return m_position; } + int x() const { return m_position.x(); } + int y() const { return m_position.y(); } + MouseButton button() const { return m_button; } + +private: + Point m_position; + MouseButton m_button { MouseButton::None }; +}; + +class TimerEvent final : public WSEvent { +public: + TimerEvent() : WSEvent(WSEvent::Timer) { } + ~TimerEvent() { } +}; + diff --git a/WindowServer/WSEventLoop.cpp b/WindowServer/WSEventLoop.cpp new file mode 100644 index 0000000000..a6769a3510 --- /dev/null +++ b/WindowServer/WSEventLoop.cpp @@ -0,0 +1,98 @@ +#include "WSEventLoop.h" +#include "WSEvent.h" +#include "WSEventReceiver.h" +#include "WSWindowManager.h" +#include "WSScreen.h" +#include "PS2MouseDevice.h" +#include "Scheduler.h" + +//#define WSEVENTLOOP_DEBUG + +static WSEventLoop* s_the; + +void WSEventLoop::initialize() +{ + s_the = nullptr; +} + +WSEventLoop::WSEventLoop() +{ + if (!s_the) + s_the = this; +} + +WSEventLoop::~WSEventLoop() +{ +} + +WSEventLoop& WSEventLoop::the() +{ + ASSERT(s_the); + return *s_the; +} + +int WSEventLoop::exec() +{ + m_server_process = current; + m_running = true; + for (;;) { + if (m_queued_events.is_empty()) + waitForEvent(); + Vector<QueuedEvent> events; + { + LOCKER(m_lock); + events = move(m_queued_events); + } + + for (auto& queued_event : events) { + auto* receiver = queued_event.receiver; + auto& event = *queued_event.event; +#ifdef WSEVENTLOOP_DEBUG + dbgprintf("WSEventLoop: receiver{%p} event %u (%s)\n", receiver, (unsigned)event.type(), event.name()); +#endif + if (!receiver) { + dbgprintf("WSEvent type %u with no receiver :(\n", event.type()); + ASSERT_NOT_REACHED(); + return 1; + } else { + receiver->event(event); + } + } + } +} + +void WSEventLoop::post_event(WSEventReceiver* receiver, OwnPtr<WSEvent>&& event) +{ + //ASSERT_INTERRUPTS_ENABLED(); + LOCKER(m_lock); +#ifdef WSEVENTLOOP_DEBUG + dbgprintf("WSEventLoop::post_event: {%u} << receiver=%p, event=%p\n", m_queued_events.size(), receiver, event.ptr()); +#endif + m_queued_events.append({ receiver, move(event) }); +} + +void WSEventLoop::waitForEvent() +{ + auto& mouse = PS2MouseDevice::the(); + auto& screen = WSScreen::the(); + bool prev_left_button = screen.left_mouse_button_pressed(); + bool prev_right_button = screen.right_mouse_button_pressed(); + int dx = 0; + int dy = 0; + while (mouse.can_read(*m_server_process)) { + signed_byte data[3]; + ssize_t nread = mouse.read(*m_server_process, (byte*)data, 3); + ASSERT(nread == 3); + bool left_button = data[0] & 1; + bool right_button = data[0] & 2; + dx += data[1]; + dy += -data[2]; + if (left_button != prev_left_button || right_button != prev_right_button || !mouse.can_read(*m_server_process)) { + prev_left_button = left_button; + prev_right_button = right_button; + screen.on_receive_mouse_data(dx, dy, left_button, right_button); + dx = 0; + dy = 0; + } + } +} diff --git a/WindowServer/WSEventLoop.h b/WindowServer/WSEventLoop.h new file mode 100644 index 0000000000..d461a6b52a --- /dev/null +++ b/WindowServer/WSEventLoop.h @@ -0,0 +1,40 @@ +#pragma once + +#include "WSEvent.h" +#include <AK/Lock.h> +#include <AK/OwnPtr.h> +#include <AK/Vector.h> + +class WSEventReceiver; +class Process; + +class WSEventLoop { +public: + WSEventLoop(); + ~WSEventLoop(); + + int exec(); + + void post_event(WSEventReceiver* receiver, OwnPtr<WSEvent>&&); + + static WSEventLoop& the(); + + static void initialize(); + + bool running() const { return m_running; } + Process& server_process() { return *m_server_process; } + +private: + void waitForEvent(); + + SpinLock m_lock; + + struct QueuedEvent { + WSEventReceiver* receiver { nullptr }; + OwnPtr<WSEvent> event; + }; + Vector<QueuedEvent> m_queued_events; + + Process* m_server_process { nullptr }; + bool m_running { false }; +}; diff --git a/WindowServer/WSEventReceiver.cpp b/WindowServer/WSEventReceiver.cpp new file mode 100644 index 0000000000..74e31e8906 --- /dev/null +++ b/WindowServer/WSEventReceiver.cpp @@ -0,0 +1,10 @@ +#include "WSEventReceiver.h" +#include <AK/Assertions.h> + +WSEventReceiver::WSEventReceiver() +{ +} + +WSEventReceiver::~WSEventReceiver() +{ +} diff --git a/WindowServer/WSEventReceiver.h b/WindowServer/WSEventReceiver.h new file mode 100644 index 0000000000..1b81da7c2a --- /dev/null +++ b/WindowServer/WSEventReceiver.h @@ -0,0 +1,13 @@ +#pragma once + +#include <AK/Weakable.h> + +class WSEvent; + +class WSEventReceiver : public Weakable<WSEventReceiver> { +public: + WSEventReceiver(); + virtual ~WSEventReceiver(); + + virtual void event(WSEvent&) = 0; +}; diff --git a/WindowServer/WSFrameBuffer.cpp b/WindowServer/WSFrameBuffer.cpp new file mode 100644 index 0000000000..54ca0dc633 --- /dev/null +++ b/WindowServer/WSFrameBuffer.cpp @@ -0,0 +1,46 @@ +#include "WSFrameBuffer.h" +#include <Widgets/GraphicsBitmap.h> +#include <AK/Assertions.h> + +WSFrameBuffer* s_the; + +void WSFrameBuffer::initialize() +{ + s_the = nullptr; +} + +WSFrameBuffer& WSFrameBuffer::the() +{ + ASSERT(s_the); + return *s_the; +} + +WSFrameBuffer::WSFrameBuffer(unsigned width, unsigned height) + : WSScreen(width, height) +{ + ASSERT(!s_the); + s_the = this; +} + +WSFrameBuffer::WSFrameBuffer(RGBA32* data, unsigned width, unsigned height) + : WSScreen(width, height) + , m_data(data) +{ + ASSERT(!s_the); + s_the = this; +} + + +WSFrameBuffer::~WSFrameBuffer() +{ +} + +void WSFrameBuffer::show() +{ +} + +RGBA32* WSFrameBuffer::scanline(int y) +{ + unsigned pitch = sizeof(RGBA32) * width(); + return reinterpret_cast<RGBA32*>(((byte*)m_data) + (y * pitch)); +} diff --git a/WindowServer/WSFrameBuffer.h b/WindowServer/WSFrameBuffer.h new file mode 100644 index 0000000000..8239fdfd9a --- /dev/null +++ b/WindowServer/WSFrameBuffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include "WSScreen.h" +#include <Widgets/Color.h> + +class GraphicsBitmap; + +class WSFrameBuffer final : public WSScreen { +public: + WSFrameBuffer(unsigned width, unsigned height); + WSFrameBuffer(RGBA32*, unsigned width, unsigned height); + virtual ~WSFrameBuffer() override; + + void show(); + + static WSFrameBuffer& the(); + + RGBA32* scanline(int y); + + static void initialize(); + +private: + RGBA32* m_data { nullptr }; +}; + diff --git a/Widgets/AbstractScreen.cpp b/WindowServer/WSScreen.cpp index 10993e6363..2276ff6f5d 100644 --- a/Widgets/AbstractScreen.cpp +++ b/WindowServer/WSScreen.cpp @@ -1,26 +1,24 @@ -#include "AbstractScreen.h" -#include "EventLoop.h" -#include "Event.h" -#include "Widget.h" -#include "WindowManager.h" +#include "WSScreen.h" +#include "WSEventLoop.h" +#include "WSEvent.h" +#include "WSWindowManager.h" #include <AK/Assertions.h> -static AbstractScreen* s_the; +static WSScreen* s_the; -void AbstractScreen::initialize() +void WSScreen::initialize() { s_the = nullptr; } -AbstractScreen& AbstractScreen::the() +WSScreen& WSScreen::the() { ASSERT(s_the); return *s_the; } -AbstractScreen::AbstractScreen(unsigned width, unsigned height) - : Object(nullptr) - , m_width(width) +WSScreen::WSScreen(unsigned width, unsigned height) + : m_width(width) , m_height(height) { ASSERT(!s_the); @@ -31,11 +29,11 @@ AbstractScreen::AbstractScreen(unsigned width, unsigned height) Keyboard::the().set_client(this); } -AbstractScreen::~AbstractScreen() +WSScreen::~WSScreen() { } -void AbstractScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button) +void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button) { auto prev_location = m_cursor_location; m_cursor_location.moveBy(dx, dy); @@ -45,28 +43,28 @@ void AbstractScreen::on_receive_mouse_data(int dx, int dy, bool left_button, boo if (m_cursor_location.y() >= height()) m_cursor_location.setY(height() - 1); if (m_cursor_location != prev_location) { - auto event = make<MouseEvent>(Event::MouseMove, m_cursor_location.x(), m_cursor_location.y()); - EventLoop::main().postEvent(&WindowManager::the(), move(event)); + auto event = make<MouseEvent>(WSEvent::MouseMove, m_cursor_location.x(), m_cursor_location.y()); + WSEventLoop::the().post_event(&WSWindowManager::the(), move(event)); } bool prev_left_button = m_left_mouse_button_pressed; bool prev_right_button = m_right_mouse_button_pressed; m_left_mouse_button_pressed = left_button; m_right_mouse_button_pressed = right_button; if (prev_left_button != left_button) { - auto event = make<MouseEvent>(left_button ? Event::MouseDown : Event::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Left); - EventLoop::main().postEvent(&WindowManager::the(), move(event)); + auto event = make<MouseEvent>(left_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Left); + WSEventLoop::the().post_event(&WSWindowManager::the(), move(event)); } if (prev_right_button != right_button) { - auto event = make<MouseEvent>(right_button ? Event::MouseDown : Event::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Right); - EventLoop::main().postEvent(&WindowManager::the(), move(event)); + auto event = make<MouseEvent>(right_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Right); + WSEventLoop::the().post_event(&WSWindowManager::the(), move(event)); } if (m_cursor_location != prev_location || prev_left_button != left_button) - WindowManager::the().draw_cursor(); + WSWindowManager::the().draw_cursor(); } -void AbstractScreen::on_key_pressed(Keyboard::Key key) +void WSScreen::on_key_pressed(Keyboard::Key key) { - auto event = make<KeyEvent>(Event::KeyDown, 0); + auto event = make<KeyEvent>(WSEvent::KeyDown, 0); int key_code = 0; switch (key.character) { @@ -115,5 +113,5 @@ void AbstractScreen::on_key_pressed(Keyboard::Key key) event->m_ctrl = key.ctrl(); event->m_alt = key.alt(); - EventLoop::main().postEvent(&WindowManager::the(), move(event)); + WSEventLoop::the().post_event(&WSWindowManager::the(), move(event)); } diff --git a/Widgets/AbstractScreen.h b/WindowServer/WSScreen.h index 444b1efcb3..0967bfcbb1 100644 --- a/Widgets/AbstractScreen.h +++ b/WindowServer/WSScreen.h @@ -1,19 +1,17 @@ #pragma once -#include "Object.h" -#include "Rect.h" -#include "Size.h" -#include "Keyboard.h" -#include "PS2MouseDevice.h" +#include <Widgets/Rect.h> +#include <Widgets/Size.h> +#include <Kernel/Keyboard.h> -class AbstractScreen : public Object, public KeyboardClient { +class WSScreen : public KeyboardClient { public: - virtual ~AbstractScreen(); + virtual ~WSScreen(); int width() const { return m_width; } int height() const { return m_height; } - static AbstractScreen& the(); + static WSScreen& the(); Size size() const { return { width(), height() }; } Rect rect() const { return { 0, 0, width(), height() }; } @@ -27,7 +25,7 @@ public: void on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button); protected: - AbstractScreen(unsigned width, unsigned height); + WSScreen(unsigned width, unsigned height); private: // ^KeyboardClient diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp new file mode 100644 index 0000000000..72755d0ace --- /dev/null +++ b/WindowServer/WSWindow.cpp @@ -0,0 +1,89 @@ +#include "WSWindow.h" +#include "WSWindowManager.h" +#include "WSEvent.h" +#include "WSEventLoop.h" +#include "Process.h" + +WSWindow::WSWindow(Process& process, int window_id) + : m_process(process) + , m_window_id(window_id) +{ + WSWindowManager::the().addWindow(*this); +} + +WSWindow::~WSWindow() +{ + WSWindowManager::the().removeWindow(*this); +} + +void WSWindow::set_title(String&& title) +{ + if (m_title == title) + return; + + m_title = move(title); + WSWindowManager::the().notifyTitleChanged(*this); +} + +void WSWindow::set_rect(const Rect& rect) +{ + if (m_rect == rect) + return; + auto oldRect = m_rect; + m_rect = rect; + m_backing = GraphicsBitmap::create(m_process, m_rect.size()); + WSWindowManager::the().notifyRectChanged(*this, oldRect, m_rect); +} + +// FIXME: Just use the same types. +static GUI_MouseButton to_api(MouseButton button) +{ + switch (button) { + case MouseButton::None: return GUI_MouseButton::NoButton; + case MouseButton::Left: return GUI_MouseButton::Left; + case MouseButton::Right: return GUI_MouseButton::Right; + case MouseButton::Middle: return GUI_MouseButton::Middle; + } +} + +void WSWindow::event(WSEvent& event) +{ + GUI_Event gui_event; + gui_event.window_id = window_id(); + + switch (event.type()) { + case WSEvent::Paint: + gui_event.type = GUI_Event::Type::Paint; + gui_event.paint.rect = static_cast<PaintEvent&>(event).rect(); + break; + case WSEvent::MouseMove: + gui_event.type = GUI_Event::Type::MouseMove; + gui_event.mouse.position = static_cast<MouseEvent&>(event).position(); + break; + case WSEvent::MouseDown: + gui_event.type = GUI_Event::Type::MouseDown; + gui_event.mouse.position = static_cast<MouseEvent&>(event).position(); + gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button()); + break; + case WSEvent::MouseUp: + gui_event.type = GUI_Event::Type::MouseUp; + gui_event.mouse.position = static_cast<MouseEvent&>(event).position(); + gui_event.mouse.button = to_api(static_cast<MouseEvent&>(event).button()); + break; + case WSEvent::KeyDown: + gui_event.type = GUI_Event::Type::KeyDown; + gui_event.key.character = static_cast<KeyEvent&>(event).text()[0]; + break; + case WSEvent::WM_Invalidate: + WSWindowManager::the().invalidate(*this); + return; + } + + if (gui_event.type == GUI_Event::Type::Invalid) + return; + + { + LOCKER(m_process.gui_events_lock()); + m_process.gui_events().append(move(gui_event)); + } +} diff --git a/WindowServer/WSWindow.h b/WindowServer/WSWindow.h new file mode 100644 index 0000000000..1e2b54fb2b --- /dev/null +++ b/WindowServer/WSWindow.h @@ -0,0 +1,55 @@ +#pragma once + +#include <Widgets/Rect.h> +#include <Widgets/GraphicsBitmap.h> +#include <AK/AKString.h> +#include <AK/InlineLinkedList.h> +#include "WSEventReceiver.h" + +class Process; + +class WSWindow final : public WSEventReceiver, public InlineLinkedListNode<WSWindow> { +public: + WSWindow(Process&, int window_id); + virtual ~WSWindow() override; + + 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(); } + + const Rect& rect() const { return m_rect; } + 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(const Point& position) { set_rect({ position.x(), position.y(), width(), height() }); } + void set_position_without_repaint(const Point& position) { set_rect_without_repaint({ position.x(), position.y(), width(), height() }); } + + virtual void event(WSEvent&) override; + + bool is_being_dragged() const { return m_is_being_dragged; } + void set_is_being_dragged(bool b) { m_is_being_dragged = b; } + + GraphicsBitmap* backing() { return m_backing.ptr(); } + + // For InlineLinkedList. + // FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that. + WSWindow* m_next { nullptr }; + WSWindow* m_prev { nullptr }; + +private: + String m_title; + Rect m_rect; + bool m_is_being_dragged { false }; + + RetainPtr<GraphicsBitmap> m_backing; + Process& m_process; + int m_window_id { -1 }; +}; + diff --git a/Widgets/WindowManager.cpp b/WindowServer/WSWindowManager.cpp index 2b77912277..710eefea55 100644 --- a/Widgets/WindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -1,12 +1,13 @@ -#include "WindowManager.h" -#include "Painter.h" -#include "Widget.h" -#include "Window.h" -#include "AbstractScreen.h" -#include "EventLoop.h" -#include "FrameBuffer.h" +#include "WSWindowManager.h" +#include "WSWindow.h" +#include "WSScreen.h" +#include "WSEventLoop.h" +#include "WSFrameBuffer.h" #include "Process.h" #include "MemoryManager.h" +#include <Widgets/Painter.h> +#include <Widgets/CharacterBitmap.h> +#include <AK/StdLibExtras.h> //#define DEBUG_FLUSH_YELLOW @@ -50,16 +51,16 @@ static inline Rect outerRectForWindow(const Rect& window) return rect; } -static WindowManager* s_the_window_manager; +static WSWindowManager* s_the_window_manager; -WindowManager& WindowManager::the() +WSWindowManager& WSWindowManager::the() { if (!s_the_window_manager) - s_the_window_manager = new WindowManager; + s_the_window_manager = new WSWindowManager; return *s_the_window_manager; } -void WindowManager::initialize() +void WSWindowManager::initialize() { s_the_window_manager = nullptr; } @@ -104,8 +105,8 @@ static const char* cursor_bitmap_outer_ascii = { " ## " }; -WindowManager::WindowManager() - : m_framebuffer(FrameBuffer::the()) +WSWindowManager::WSWindowManager() + : m_framebuffer(WSFrameBuffer::the()) , m_screen_rect(m_framebuffer.rect()) { auto size = m_screen_rect.size(); @@ -129,11 +130,11 @@ WindowManager::WindowManager() compose(); } -WindowManager::~WindowManager() +WSWindowManager::~WSWindowManager() { } -void WindowManager::paintWindowFrame(Window& window) +void WSWindowManager::paintWindowFrame(WSWindow& window) { //printf("[WM] paintWindowFrame {%p}, rect: %d,%d %dx%d\n", &window, window.rect().x(), window.rect().y(), window.rect().width(), window.rect().height()); @@ -159,7 +160,7 @@ void WindowManager::paintWindowFrame(Window& window) m_back_painter->draw_text(titleBarTitleRect, window.title(), Painter::TextAlignment::CenterLeft, titleColor); } -void WindowManager::addWindow(Window& window) +void WSWindowManager::addWindow(WSWindow& window) { m_windows.set(&window); m_windows_in_order.append(&window); @@ -167,18 +168,13 @@ void WindowManager::addWindow(Window& window) setActiveWindow(&window); } -void WindowManager::move_to_front(Window& window) +void WSWindowManager::move_to_front(WSWindow& window) { m_windows_in_order.remove(&window); m_windows_in_order.append(&window); } -void WindowManager::did_paint(Window& window) -{ - invalidate(window); -} - -void WindowManager::removeWindow(Window& window) +void WSWindowManager::removeWindow(WSWindow& window) { if (!m_windows.contains(&window)) return; @@ -190,22 +186,24 @@ void WindowManager::removeWindow(Window& window) setActiveWindow(*m_windows.begin()); } -void WindowManager::notifyTitleChanged(Window& window) +void WSWindowManager::notifyTitleChanged(WSWindow& window) { - printf("[WM] Window{%p} title set to '%s'\n", &window, window.title().characters()); + printf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); } -void WindowManager::notifyRectChanged(Window& window, const Rect& old_rect, const Rect& new_rect) +void WSWindowManager::notifyRectChanged(WSWindow& window, const Rect& old_rect, const Rect& new_rect) { - printf("[WM] Window %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()); + 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(outerRectForWindow(old_rect)); invalidate(outerRectForWindow(new_rect)); } -void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event) +void WSWindowManager::handleTitleBarMouseEvent(WSWindow& window, MouseEvent& event) { - if (event.type() == Event::MouseDown && event.button() == MouseButton::Left) { - printf("[WM] Begin dragging Window{%p}\n", &window); + if (event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left) { + printf("[WM] Begin dragging WSWindow{%p}\n", &window); m_dragWindow = window.makeWeakPtr();; m_dragOrigin = event.position(); m_dragWindowOrigin = window.position(); @@ -215,11 +213,11 @@ void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event) } } -void WindowManager::processMouseEvent(MouseEvent& event) +void WSWindowManager::processMouseEvent(MouseEvent& event) { - if (event.type() == Event::MouseUp && event.button() == MouseButton::Left) { + if (event.type() == WSEvent::MouseUp && event.button() == MouseButton::Left) { if (m_dragWindow) { - printf("[WM] Finish dragging Window{%p}\n", m_dragWindow.ptr()); + printf("[WM] Finish dragging WSWindow{%p}\n", m_dragWindow.ptr()); invalidate(m_dragStartRect); invalidate(*m_dragWindow); m_dragWindow->set_is_being_dragged(false); @@ -229,7 +227,7 @@ void WindowManager::processMouseEvent(MouseEvent& event) } } - if (event.type() == Event::MouseMove) { + if (event.type() == WSEvent::MouseMove) { if (m_dragWindow) { auto old_window_rect = m_dragWindow->rect(); Point pos = m_dragWindowOrigin; @@ -244,7 +242,7 @@ void WindowManager::processMouseEvent(MouseEvent& event) for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { if (titleBarRectForWindow(window->rect()).contains(event.position())) { - if (event.type() == Event::MouseDown) { + if (event.type() == WSEvent::MouseDown) { move_to_front(*window); setActiveWindow(window); } @@ -253,7 +251,7 @@ void WindowManager::processMouseEvent(MouseEvent& event) } if (window->rect().contains(event.position())) { - if (event.type() == Event::MouseDown) { + if (event.type() == WSEvent::MouseDown) { move_to_front(*window); setActiveWindow(window); } @@ -265,7 +263,7 @@ void WindowManager::processMouseEvent(MouseEvent& event) } } -void WindowManager::compose() +void WSWindowManager::compose() { auto invalidated_rects = move(m_invalidated_rects); printf("[WM] compose #%u (%u rects)\n", ++m_recompose_count, invalidated_rects.size()); @@ -297,8 +295,10 @@ void WindowManager::compose() draw_cursor(); } -void WindowManager::draw_cursor() +void WSWindowManager::draw_cursor() { + ASSERT_INTERRUPTS_ENABLED(); + LOCKER(m_lock); auto cursor_location = m_framebuffer.cursor_location(); Rect cursor_rect { cursor_location.x(), cursor_location.y(), (int)m_cursor_bitmap_inner->width(), (int)m_cursor_bitmap_inner->height() }; flush(m_last_cursor_rect.united(cursor_rect)); @@ -311,8 +311,10 @@ void WindowManager::draw_cursor() m_last_cursor_rect = cursor_rect; } -void WindowManager::event(Event& event) +void WSWindowManager::event(WSEvent& event) { + ASSERT_INTERRUPTS_ENABLED(); + LOCKER(m_lock); if (event.isMouseEvent()) return processMouseEvent(static_cast<MouseEvent&>(event)); @@ -320,46 +322,35 @@ void WindowManager::event(Event& event) // FIXME: This is a good place to hook key events globally. :) if (m_activeWindow) return m_activeWindow->event(event); - return Object::event(event); + return; } - if (event.type() == Event::WM_Compose) { + if (event.type() == WSEvent::WM_Compose) { m_pending_compose_event = false; compose(); return; } - - return Object::event(event); } -void WindowManager::setActiveWindow(Window* window) +void WSWindowManager::setActiveWindow(WSWindow* window) { if (window == m_activeWindow.ptr()) return; - if (auto* previously_active_window = m_activeWindow.ptr()) { + if (auto* previously_active_window = m_activeWindow.ptr()) invalidate(*previously_active_window); - EventLoop::main().postEvent(previously_active_window, make<Event>(Event::WindowBecameInactive)); - } m_activeWindow = window->makeWeakPtr(); - if (m_activeWindow) { + if (m_activeWindow) invalidate(*m_activeWindow); - EventLoop::main().postEvent(m_activeWindow.ptr(), make<Event>(Event::WindowBecameActive)); - } -} - -bool WindowManager::isVisible(Window& window) const -{ - return m_windows.contains(&window); } -void WindowManager::invalidate() +void WSWindowManager::invalidate() { m_invalidated_rects.clear_with_capacity(); m_invalidated_rects.append(m_screen_rect); } -void WindowManager::invalidate(const Rect& a_rect) +void WSWindowManager::invalidate(const Rect& a_rect) { auto rect = Rect::intersection(a_rect, m_screen_rect); if (rect.is_empty()) @@ -379,17 +370,20 @@ void WindowManager::invalidate(const Rect& a_rect) m_invalidated_rects.append(rect); if (!m_pending_compose_event) { - EventLoop::main().postEvent(this, make<Event>(Event::WM_Compose)); + ASSERT_INTERRUPTS_ENABLED(); + WSEventLoop::the().post_event(this, make<WSEvent>(WSEvent::WM_Compose)); m_pending_compose_event = true; } } -void WindowManager::invalidate(const Window& window) +void WSWindowManager::invalidate(const WSWindow& window) { + ASSERT_INTERRUPTS_ENABLED(); + LOCKER(m_lock); invalidate(outerRectForWindow(window.rect())); } -void WindowManager::flush(const Rect& a_rect) +void WSWindowManager::flush(const Rect& a_rect) { auto rect = Rect::intersection(a_rect, m_screen_rect); diff --git a/Widgets/WindowManager.h b/WindowServer/WSWindowManager.h index a5277861f4..b6bf211ac2 100644 --- a/Widgets/WindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -1,61 +1,58 @@ #pragma once -#include "Object.h" -#include "Rect.h" -#include "Color.h" -#include "Painter.h" +#include <Widgets/Rect.h> +#include <Widgets/Color.h> +#include <Widgets/Painter.h> #include <AK/HashTable.h> #include <AK/InlineLinkedList.h> #include <AK/WeakPtr.h> +#include <AK/Lock.h> +#include "WSEventReceiver.h" -class FrameBuffer; +class WSFrameBuffer; class MouseEvent; class PaintEvent; -class Widget; -class Window; +class WSWindow; class CharacterBitmap; class GraphicsBitmap; -class WindowManager : public Object { +class WSWindowManager : public WSEventReceiver { public: - static WindowManager& the(); - void addWindow(Window&); - void removeWindow(Window&); + static WSWindowManager& the(); + void addWindow(WSWindow&); + void removeWindow(WSWindow&); - void notifyTitleChanged(Window&); - void notifyRectChanged(Window&, const Rect& oldRect, const Rect& newRect); + void notifyTitleChanged(WSWindow&); + void notifyRectChanged(WSWindow&, const Rect& oldRect, const Rect& newRect); - Window* activeWindow() { return m_activeWindow.ptr(); } - void setActiveWindow(Window*); + WSWindow* activeWindow() { return m_activeWindow.ptr(); } - bool isVisible(Window&) const; - - void did_paint(Window&); - - void move_to_front(Window&); + void move_to_front(WSWindow&); static void initialize(); void draw_cursor(); - void invalidate(const Window&); + void invalidate(const WSWindow&); void invalidate(const Rect&); void invalidate(); void flush(const Rect&); private: - WindowManager(); - virtual ~WindowManager() override; + WSWindowManager(); + virtual ~WSWindowManager() override; void processMouseEvent(MouseEvent&); - void handleTitleBarMouseEvent(Window&, MouseEvent&); + void handleTitleBarMouseEvent(WSWindow&, MouseEvent&); + + void setActiveWindow(WSWindow*); - virtual void event(Event&) override; + virtual void event(WSEvent&) override; void compose(); - void paintWindowFrame(Window&); + void paintWindowFrame(WSWindow&); - FrameBuffer& m_framebuffer; + WSFrameBuffer& m_framebuffer; Rect m_screen_rect; Color m_activeWindowBorderColor; @@ -64,12 +61,12 @@ private: Color m_inactiveWindowBorderColor; Color m_inactiveWindowTitleColor; - HashTable<Window*> m_windows; - InlineLinkedList<Window> m_windows_in_order; + HashTable<WSWindow*> m_windows; + InlineLinkedList<WSWindow> m_windows_in_order; - WeakPtr<Window> m_activeWindow; + WeakPtr<WSWindow> m_activeWindow; - WeakPtr<Window> m_dragWindow; + WeakPtr<WSWindow> m_dragWindow; Point m_dragOrigin; Point m_dragWindowOrigin; @@ -93,4 +90,6 @@ private: OwnPtr<Painter> m_back_painter; OwnPtr<Painter> m_front_painter; + + mutable SpinLock m_lock; }; diff --git a/WindowServer/main.cpp b/WindowServer/main.cpp new file mode 100644 index 0000000000..827f8291e4 --- /dev/null +++ b/WindowServer/main.cpp @@ -0,0 +1,25 @@ +#include "Process.h" +#include <Widgets/Font.h> +#include <WindowServer/WSFrameBuffer.h> +#include <WindowServer/WSWindowManager.h> +#include <WindowServer/WSEventLoop.h> +#include <WindowServer/WSWindow.h> + +// NOTE: This actually runs as a kernel process. +// I'd like to change this eventually. + +void WindowServer_main() +{ + auto info = current->get_display_info(); + + dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp); + + WSFrameBuffer framebuffer((dword*)info.framebuffer, info.width, info.height); + + WSWindowManager::the(); + + dbgprintf("Entering WindowServer main loop.\n"); + WSEventLoop::the().exec(); + + ASSERT_NOT_REACHED(); +} |