mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:07:34 +00:00
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.
This commit is contained in:
parent
e655aebd70
commit
f7ca6d254d
30 changed files with 757 additions and 308 deletions
102
AK/Lock.h
102
AK/Lock.h
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
#include "Assertions.h"
|
#include "Assertions.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#ifdef SERENITY
|
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
int sched_yield();
|
int sched_yield();
|
||||||
#else
|
|
||||||
#include <sched.h>
|
class Process;
|
||||||
typedef int InterruptDisabler;
|
extern Process* current;
|
||||||
|
|
||||||
|
#ifndef KERNEL
|
||||||
|
#error This thing is kernel-only right now.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define DEBUG_LOCKS
|
//#define DEBUG_LOCKS
|
||||||
|
@ -30,70 +31,75 @@ static inline dword CAS(volatile dword* mem, dword newval, dword oldval)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Rename to YieldingLock?
|
// FIXME: Rename to YieldingLock? RecursiveLock? Maybe just Lock?
|
||||||
class SpinLock {
|
class SpinLock {
|
||||||
public:
|
public:
|
||||||
SpinLock() { }
|
SpinLock() { }
|
||||||
~SpinLock() { }
|
~SpinLock() { }
|
||||||
|
|
||||||
ALWAYS_INLINE void lock(const char* func = nullptr)
|
void lock();
|
||||||
{
|
void unlock();
|
||||||
(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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE void unlock(const char* func = nullptr)
|
const Process* holder() const { return m_holder; }
|
||||||
{
|
|
||||||
(void)func;
|
|
||||||
// barrier();
|
|
||||||
ASSERT(m_lock);
|
|
||||||
m_lock = 0;
|
|
||||||
#ifdef DEBUG_LOCKS
|
|
||||||
InterruptDisabler dis;
|
|
||||||
log_unlocked(func);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
m_lock = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile dword m_lock { 0 };
|
volatile dword m_lock { 0 };
|
||||||
|
dword m_level { 0 };
|
||||||
|
Process* m_holder { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
class Locker {
|
class Locker {
|
||||||
public:
|
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 ~Locker() { unlock(); }
|
||||||
ALWAYS_INLINE void unlock() { m_lock.unlock(m_func); }
|
ALWAYS_INLINE void unlock() { m_lock.unlock(); }
|
||||||
ALWAYS_INLINE void lock() { m_lock.lock(m_func); }
|
ALWAYS_INLINE void lock() { m_lock.lock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpinLock& m_lock;
|
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::SpinLock;
|
||||||
using AK::Locker;
|
using AK::Locker;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ KERNEL_OBJS = \
|
||||||
ELFLoader.o \
|
ELFLoader.o \
|
||||||
KSyms.o \
|
KSyms.o \
|
||||||
PS2MouseDevice.o \
|
PS2MouseDevice.o \
|
||||||
WindowServer.o
|
GUIEventDevice.o
|
||||||
|
|
||||||
VFS_OBJS = \
|
VFS_OBJS = \
|
||||||
../VirtualFileSystem/DiskDevice.o \
|
../VirtualFileSystem/DiskDevice.o \
|
||||||
|
@ -46,21 +46,20 @@ VFS_OBJS = \
|
||||||
../VirtualFileSystem/FileDescriptor.o \
|
../VirtualFileSystem/FileDescriptor.o \
|
||||||
../VirtualFileSystem/SyntheticFileSystem.o
|
../VirtualFileSystem/SyntheticFileSystem.o
|
||||||
|
|
||||||
WIDGETS_OBJS = \
|
WINDOWSERVER_OBJS = \
|
||||||
../Widgets/Window.o \
|
|
||||||
../Widgets/Painter.o \
|
|
||||||
../Widgets/WindowManager.o \
|
|
||||||
../Widgets/FrameBuffer.o \
|
|
||||||
../Widgets/GraphicsBitmap.o \
|
|
||||||
../Widgets/Object.o \
|
|
||||||
../Widgets/Rect.o \
|
../Widgets/Rect.o \
|
||||||
../Widgets/Widget.o \
|
../Widgets/Painter.o \
|
||||||
../Widgets/Font.o \
|
../Widgets/Font.o \
|
||||||
../Widgets/Color.o \
|
../Widgets/Color.o \
|
||||||
../Widgets/CharacterBitmap.o \
|
../Widgets/CharacterBitmap.o \
|
||||||
../Widgets/EventLoop.o \
|
../Widgets/GraphicsBitmap.o \
|
||||||
../Widgets/AbstractScreen.o \
|
../WindowServer/WSEventReceiver.o \
|
||||||
../Widgets/GUIEventDevice.o \
|
../WindowServer/WSEventLoop.o \
|
||||||
|
../WindowServer/WSWindow.o \
|
||||||
|
../WindowServer/WSWindowManager.o \
|
||||||
|
../WindowServer/WSFrameBuffer.o \
|
||||||
|
../WindowServer/WSScreen.o \
|
||||||
|
../WindowServer/main.o
|
||||||
|
|
||||||
AK_OBJS = \
|
AK_OBJS = \
|
||||||
../AK/String.o \
|
../AK/String.o \
|
||||||
|
@ -68,7 +67,7 @@ AK_OBJS = \
|
||||||
../AK/StringBuilder.o \
|
../AK/StringBuilder.o \
|
||||||
../AK/FileSystemPath.o
|
../AK/FileSystemPath.o
|
||||||
|
|
||||||
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WIDGETS_OBJS)
|
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WINDOWSERVER_OBJS)
|
||||||
|
|
||||||
NASM = nasm
|
NASM = nasm
|
||||||
KERNEL = kernel
|
KERNEL = kernel
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "Scheduler.h"
|
#include "Scheduler.h"
|
||||||
#include "FIFO.h"
|
#include "FIFO.h"
|
||||||
#include "KSyms.h"
|
#include "KSyms.h"
|
||||||
#include <Widgets/Window.h>
|
#include <WindowServer/WSWindow.h>
|
||||||
#include "MasterPTY.h"
|
#include "MasterPTY.h"
|
||||||
|
|
||||||
//#define DEBUG_IO
|
//#define DEBUG_IO
|
||||||
|
|
|
@ -19,8 +19,7 @@ class PageDirectory;
|
||||||
class Region;
|
class Region;
|
||||||
class VMObject;
|
class VMObject;
|
||||||
class Zone;
|
class Zone;
|
||||||
class Window;
|
class WSWindow;
|
||||||
class Widget;
|
|
||||||
|
|
||||||
#define COOL_GLOBALS
|
#define COOL_GLOBALS
|
||||||
#ifdef COOL_GLOBALS
|
#ifdef COOL_GLOBALS
|
||||||
|
@ -47,7 +46,7 @@ struct DisplayInfo {
|
||||||
|
|
||||||
class Process : public InlineLinkedListNode<Process> {
|
class Process : public InlineLinkedListNode<Process> {
|
||||||
friend class 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().
|
friend class GraphicsBitmap; // FIXME: Make a better API for allocate_region().
|
||||||
public:
|
public:
|
||||||
static Process* create_kernel_process(String&& name, void (*entry)());
|
static Process* create_kernel_process(String&& name, void (*entry)());
|
||||||
|
@ -353,7 +352,7 @@ private:
|
||||||
|
|
||||||
RetainPtr<Region> m_display_framebuffer_region;
|
RetainPtr<Region> m_display_framebuffer_region;
|
||||||
|
|
||||||
HashMap<int, OwnPtr<Window>> m_windows;
|
HashMap<int, OwnPtr<WSWindow>> m_windows;
|
||||||
|
|
||||||
Vector<GUI_Event> m_gui_events;
|
Vector<GUI_Event> m_gui_events;
|
||||||
SpinLock m_gui_events_lock;
|
SpinLock m_gui_events_lock;
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
#include <LibC/errno_numbers.h>
|
#include <LibC/errno_numbers.h>
|
||||||
#include <Widgets/AbstractScreen.h>
|
|
||||||
#include <Widgets/FrameBuffer.h>
|
|
||||||
#include <Widgets/EventLoop.h>
|
|
||||||
#include <Widgets/Font.h>
|
#include <Widgets/Font.h>
|
||||||
#include <Widgets/Button.h>
|
#include <WindowServer/WSScreen.h>
|
||||||
#include <Widgets/Label.h>
|
#include <WindowServer/WSFrameBuffer.h>
|
||||||
#include <Widgets/Widget.h>
|
#include <WindowServer/WSEventLoop.h>
|
||||||
#include <Widgets/Window.h>
|
#include <WindowServer/WSWindow.h>
|
||||||
#include <Widgets/WindowManager.h>
|
#include <WindowServer/WSWindowManager.h>
|
||||||
|
|
||||||
void Process::initialize_gui_statics()
|
void Process::initialize_gui_statics()
|
||||||
{
|
{
|
||||||
Font::initialize();
|
Font::initialize();
|
||||||
FrameBuffer::initialize();
|
WSFrameBuffer::initialize();
|
||||||
EventLoop::initialize();
|
WSEventLoop::initialize();
|
||||||
WindowManager::initialize();
|
WSWindowManager::initialize();
|
||||||
AbstractScreen::initialize();
|
WSScreen::initialize();
|
||||||
|
|
||||||
new EventLoop;
|
new WSEventLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::make_window_id()
|
int Process::make_window_id()
|
||||||
|
@ -36,7 +33,7 @@ int Process::make_window_id()
|
||||||
static void wait_for_gui_server()
|
static void wait_for_gui_server()
|
||||||
{
|
{
|
||||||
// FIXME: Time out after a while and return an error.
|
// FIXME: Time out after a while and return an error.
|
||||||
while (!EventLoop::main().running())
|
while (!WSEventLoop::the().running())
|
||||||
sleep(10);
|
sleep(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +50,13 @@ int Process::gui$create_window(const GUI_CreateWindowParameters* user_params)
|
||||||
if (rect.is_empty())
|
if (rect.is_empty())
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ProcessPagingScope scope(EventLoop::main().server_process());
|
ProcessPagingScope scope(WSEventLoop::the().server_process());
|
||||||
|
|
||||||
int window_id = make_window_id();
|
int window_id = make_window_id();
|
||||||
if (!window_id)
|
if (!window_id)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
auto window = make<Window>(*this, window_id);
|
auto window = make<WSWindow>(*this, window_id);
|
||||||
if (!window)
|
if (!window)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -113,7 +110,6 @@ int Process::gui$invalidate_window(int window_id)
|
||||||
auto& window = *(*it).value;
|
auto& window = *(*it).value;
|
||||||
// FIXME: This should queue up a message that the window server process can read.
|
// FIXME: This should queue up a message that the window server process can read.
|
||||||
// Poking into its data structures is not good.
|
// Poking into its data structures is not good.
|
||||||
InterruptDisabler disabler;
|
WSEventLoop::the().post_event(&window, make<WSEvent>(WSEvent::WM_Invalidate));
|
||||||
WindowManager::the().invalidate(window);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ bool Scheduler::pick_next()
|
||||||
for (auto* process = g_processes->head(); process; process = process->next()) {
|
for (auto* process = g_processes->head(); process; process = process->next()) {
|
||||||
//if (process->state() == Process::BlockedWait || process->state() == Process::BlockedSleep)
|
//if (process->state() == Process::BlockedWait || process->state() == Process::BlockedSleep)
|
||||||
// continue;
|
// 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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -81,6 +81,7 @@ void write_gdt_entry(word selector, Descriptor&);
|
||||||
|
|
||||||
#define cli() asm volatile("cli")
|
#define cli() asm volatile("cli")
|
||||||
#define sti() asm volatile("sti")
|
#define sti() asm volatile("sti")
|
||||||
|
#define memory_barrier() asm volatile ("" ::: "memory")
|
||||||
|
|
||||||
static inline dword cpu_flags()
|
static inline dword cpu_flags()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <VirtualFileSystem/RandomDevice.h>
|
#include <VirtualFileSystem/RandomDevice.h>
|
||||||
#include <VirtualFileSystem/Ext2FileSystem.h>
|
#include <VirtualFileSystem/Ext2FileSystem.h>
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include <Widgets/GUIEventDevice.h>
|
#include "GUIEventDevice.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
#include "ProcFileSystem.h"
|
#include "ProcFileSystem.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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 };
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "GraphicsBitmap.h"
|
#include "GraphicsBitmap.h"
|
||||||
#include "EventLoop.h"
|
|
||||||
#include <AK/kmalloc.h>
|
#include <AK/kmalloc.h>
|
||||||
|
|
||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
#include "Process.h"
|
#include <Kernel/Process.h>
|
||||||
#include "MemoryManager.h"
|
#include <Kernel/MemoryManager.h>
|
||||||
|
#include <WindowServer/WSEventLoop.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
|
@ -24,7 +24,7 @@ GraphicsBitmap::GraphicsBitmap(Process& process, const Size& size)
|
||||||
m_client_region->commit(process);
|
m_client_region->commit(process);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto& server = EventLoop::main().server_process();
|
auto& server = WSEventLoop::the().server_process();
|
||||||
ProcessInspectionHandle composer_handle(server);
|
ProcessInspectionHandle composer_handle(server);
|
||||||
m_server_region = server.allocate_region_with_vmo(LinearAddress(), size_in_bytes, move(vmo), 0, "GraphicsBitmap (shared)", true, true);
|
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)
|
if (m_client_region)
|
||||||
m_client_process->deallocate_region(*m_client_region);
|
m_client_process->deallocate_region(*m_client_region);
|
||||||
if (m_server_region)
|
if (m_server_region)
|
||||||
EventLoop::main().server_process().deallocate_region(*m_server_region);
|
WSEventLoop::the().server_process().deallocate_region(*m_server_region);
|
||||||
#endif
|
#endif
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ public:
|
||||||
void set_rect_without_repaint(const Rect& rect) { m_rect = rect; }
|
void set_rect_without_repaint(const Rect& rect) { m_rect = rect; }
|
||||||
|
|
||||||
Point position() const { return m_rect.location(); }
|
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() }); }
|
void set_position_without_repaint(const Point& position) { set_rect_without_repaint({ position.x(), position.y(), width(), height() }); }
|
||||||
|
|
||||||
virtual void event(Event&) override;
|
virtual void event(Event&) override;
|
||||||
|
|
1
WindowServer/.gitignore
vendored
Normal file
1
WindowServer/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.o
|
151
WindowServer/WSEvent.h
Normal file
151
WindowServer/WSEvent.h
Normal file
|
@ -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() { }
|
||||||
|
};
|
||||||
|
|
98
WindowServer/WSEventLoop.cpp
Normal file
98
WindowServer/WSEventLoop.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
WindowServer/WSEventLoop.h
Normal file
40
WindowServer/WSEventLoop.h
Normal file
|
@ -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 };
|
||||||
|
};
|
10
WindowServer/WSEventReceiver.cpp
Normal file
10
WindowServer/WSEventReceiver.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "WSEventReceiver.h"
|
||||||
|
#include <AK/Assertions.h>
|
||||||
|
|
||||||
|
WSEventReceiver::WSEventReceiver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WSEventReceiver::~WSEventReceiver()
|
||||||
|
{
|
||||||
|
}
|
13
WindowServer/WSEventReceiver.h
Normal file
13
WindowServer/WSEventReceiver.h
Normal file
|
@ -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;
|
||||||
|
};
|
46
WindowServer/WSFrameBuffer.cpp
Normal file
46
WindowServer/WSFrameBuffer.cpp
Normal file
|
@ -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));
|
||||||
|
}
|
25
WindowServer/WSFrameBuffer.h
Normal file
25
WindowServer/WSFrameBuffer.h
Normal file
|
@ -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 };
|
||||||
|
};
|
||||||
|
|
|
@ -1,26 +1,24 @@
|
||||||
#include "AbstractScreen.h"
|
#include "WSScreen.h"
|
||||||
#include "EventLoop.h"
|
#include "WSEventLoop.h"
|
||||||
#include "Event.h"
|
#include "WSEvent.h"
|
||||||
#include "Widget.h"
|
#include "WSWindowManager.h"
|
||||||
#include "WindowManager.h"
|
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
|
|
||||||
static AbstractScreen* s_the;
|
static WSScreen* s_the;
|
||||||
|
|
||||||
void AbstractScreen::initialize()
|
void WSScreen::initialize()
|
||||||
{
|
{
|
||||||
s_the = nullptr;
|
s_the = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractScreen& AbstractScreen::the()
|
WSScreen& WSScreen::the()
|
||||||
{
|
{
|
||||||
ASSERT(s_the);
|
ASSERT(s_the);
|
||||||
return *s_the;
|
return *s_the;
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractScreen::AbstractScreen(unsigned width, unsigned height)
|
WSScreen::WSScreen(unsigned width, unsigned height)
|
||||||
: Object(nullptr)
|
: m_width(width)
|
||||||
, m_width(width)
|
|
||||||
, m_height(height)
|
, m_height(height)
|
||||||
{
|
{
|
||||||
ASSERT(!s_the);
|
ASSERT(!s_the);
|
||||||
|
@ -31,11 +29,11 @@ AbstractScreen::AbstractScreen(unsigned width, unsigned height)
|
||||||
Keyboard::the().set_client(this);
|
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;
|
auto prev_location = m_cursor_location;
|
||||||
m_cursor_location.moveBy(dx, dy);
|
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())
|
if (m_cursor_location.y() >= height())
|
||||||
m_cursor_location.setY(height() - 1);
|
m_cursor_location.setY(height() - 1);
|
||||||
if (m_cursor_location != prev_location) {
|
if (m_cursor_location != prev_location) {
|
||||||
auto event = make<MouseEvent>(Event::MouseMove, m_cursor_location.x(), m_cursor_location.y());
|
auto event = make<MouseEvent>(WSEvent::MouseMove, m_cursor_location.x(), m_cursor_location.y());
|
||||||
EventLoop::main().postEvent(&WindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
bool prev_left_button = m_left_mouse_button_pressed;
|
bool prev_left_button = m_left_mouse_button_pressed;
|
||||||
bool prev_right_button = m_right_mouse_button_pressed;
|
bool prev_right_button = m_right_mouse_button_pressed;
|
||||||
m_left_mouse_button_pressed = left_button;
|
m_left_mouse_button_pressed = left_button;
|
||||||
m_right_mouse_button_pressed = right_button;
|
m_right_mouse_button_pressed = right_button;
|
||||||
if (prev_left_button != left_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);
|
auto event = make<MouseEvent>(left_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Left);
|
||||||
EventLoop::main().postEvent(&WindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
if (prev_right_button != right_button) {
|
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);
|
auto event = make<MouseEvent>(right_button ? WSEvent::MouseDown : WSEvent::MouseUp, m_cursor_location.x(), m_cursor_location.y(), MouseButton::Right);
|
||||||
EventLoop::main().postEvent(&WindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
||||||
if (m_cursor_location != prev_location || prev_left_button != left_button)
|
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;
|
int key_code = 0;
|
||||||
|
|
||||||
switch (key.character) {
|
switch (key.character) {
|
||||||
|
@ -115,5 +113,5 @@ void AbstractScreen::on_key_pressed(Keyboard::Key key)
|
||||||
event->m_ctrl = key.ctrl();
|
event->m_ctrl = key.ctrl();
|
||||||
event->m_alt = key.alt();
|
event->m_alt = key.alt();
|
||||||
|
|
||||||
EventLoop::main().postEvent(&WindowManager::the(), move(event));
|
WSEventLoop::the().post_event(&WSWindowManager::the(), move(event));
|
||||||
}
|
}
|
|
@ -1,19 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
#include <Widgets/Rect.h>
|
||||||
#include "Rect.h"
|
#include <Widgets/Size.h>
|
||||||
#include "Size.h"
|
#include <Kernel/Keyboard.h>
|
||||||
#include "Keyboard.h"
|
|
||||||
#include "PS2MouseDevice.h"
|
|
||||||
|
|
||||||
class AbstractScreen : public Object, public KeyboardClient {
|
class WSScreen : public KeyboardClient {
|
||||||
public:
|
public:
|
||||||
virtual ~AbstractScreen();
|
virtual ~WSScreen();
|
||||||
|
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
int height() const { return m_height; }
|
int height() const { return m_height; }
|
||||||
|
|
||||||
static AbstractScreen& the();
|
static WSScreen& the();
|
||||||
|
|
||||||
Size size() const { return { width(), height() }; }
|
Size size() const { return { width(), height() }; }
|
||||||
Rect rect() const { return { 0, 0, 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);
|
void on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractScreen(unsigned width, unsigned height);
|
WSScreen(unsigned width, unsigned height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^KeyboardClient
|
// ^KeyboardClient
|
89
WindowServer/WSWindow.cpp
Normal file
89
WindowServer/WSWindow.cpp
Normal file
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
55
WindowServer/WSWindow.h
Normal file
55
WindowServer/WSWindow.h
Normal file
|
@ -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 };
|
||||||
|
};
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#include "WindowManager.h"
|
#include "WSWindowManager.h"
|
||||||
#include "Painter.h"
|
#include "WSWindow.h"
|
||||||
#include "Widget.h"
|
#include "WSScreen.h"
|
||||||
#include "Window.h"
|
#include "WSEventLoop.h"
|
||||||
#include "AbstractScreen.h"
|
#include "WSFrameBuffer.h"
|
||||||
#include "EventLoop.h"
|
|
||||||
#include "FrameBuffer.h"
|
|
||||||
#include "Process.h"
|
#include "Process.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
#include <Widgets/Painter.h>
|
||||||
|
#include <Widgets/CharacterBitmap.h>
|
||||||
|
#include <AK/StdLibExtras.h>
|
||||||
|
|
||||||
//#define DEBUG_FLUSH_YELLOW
|
//#define DEBUG_FLUSH_YELLOW
|
||||||
|
|
||||||
|
@ -50,16 +51,16 @@ static inline Rect outerRectForWindow(const Rect& window)
|
||||||
return rect;
|
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)
|
if (!s_the_window_manager)
|
||||||
s_the_window_manager = new WindowManager;
|
s_the_window_manager = new WSWindowManager;
|
||||||
return *s_the_window_manager;
|
return *s_the_window_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::initialize()
|
void WSWindowManager::initialize()
|
||||||
{
|
{
|
||||||
s_the_window_manager = nullptr;
|
s_the_window_manager = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -104,8 +105,8 @@ static const char* cursor_bitmap_outer_ascii = {
|
||||||
" ## "
|
" ## "
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowManager::WindowManager()
|
WSWindowManager::WSWindowManager()
|
||||||
: m_framebuffer(FrameBuffer::the())
|
: m_framebuffer(WSFrameBuffer::the())
|
||||||
, m_screen_rect(m_framebuffer.rect())
|
, m_screen_rect(m_framebuffer.rect())
|
||||||
{
|
{
|
||||||
auto size = m_screen_rect.size();
|
auto size = m_screen_rect.size();
|
||||||
|
@ -129,11 +130,11 @@ WindowManager::WindowManager()
|
||||||
compose();
|
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());
|
//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);
|
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.set(&window);
|
||||||
m_windows_in_order.append(&window);
|
m_windows_in_order.append(&window);
|
||||||
|
@ -167,18 +168,13 @@ void WindowManager::addWindow(Window& window)
|
||||||
setActiveWindow(&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.remove(&window);
|
||||||
m_windows_in_order.append(&window);
|
m_windows_in_order.append(&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::did_paint(Window& window)
|
void WSWindowManager::removeWindow(WSWindow& window)
|
||||||
{
|
|
||||||
invalidate(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::removeWindow(Window& window)
|
|
||||||
{
|
{
|
||||||
if (!m_windows.contains(&window))
|
if (!m_windows.contains(&window))
|
||||||
return;
|
return;
|
||||||
|
@ -190,22 +186,24 @@ void WindowManager::removeWindow(Window& window)
|
||||||
setActiveWindow(*m_windows.begin());
|
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(old_rect));
|
||||||
invalidate(outerRectForWindow(new_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) {
|
if (event.type() == WSEvent::MouseDown && event.button() == MouseButton::Left) {
|
||||||
printf("[WM] Begin dragging Window{%p}\n", &window);
|
printf("[WM] Begin dragging WSWindow{%p}\n", &window);
|
||||||
m_dragWindow = window.makeWeakPtr();;
|
m_dragWindow = window.makeWeakPtr();;
|
||||||
m_dragOrigin = event.position();
|
m_dragOrigin = event.position();
|
||||||
m_dragWindowOrigin = window.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) {
|
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_dragStartRect);
|
||||||
invalidate(*m_dragWindow);
|
invalidate(*m_dragWindow);
|
||||||
m_dragWindow->set_is_being_dragged(false);
|
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) {
|
if (m_dragWindow) {
|
||||||
auto old_window_rect = m_dragWindow->rect();
|
auto old_window_rect = m_dragWindow->rect();
|
||||||
Point pos = m_dragWindowOrigin;
|
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()) {
|
for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) {
|
||||||
if (titleBarRectForWindow(window->rect()).contains(event.position())) {
|
if (titleBarRectForWindow(window->rect()).contains(event.position())) {
|
||||||
if (event.type() == Event::MouseDown) {
|
if (event.type() == WSEvent::MouseDown) {
|
||||||
move_to_front(*window);
|
move_to_front(*window);
|
||||||
setActiveWindow(window);
|
setActiveWindow(window);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +251,7 @@ void WindowManager::processMouseEvent(MouseEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->rect().contains(event.position())) {
|
if (window->rect().contains(event.position())) {
|
||||||
if (event.type() == Event::MouseDown) {
|
if (event.type() == WSEvent::MouseDown) {
|
||||||
move_to_front(*window);
|
move_to_front(*window);
|
||||||
setActiveWindow(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);
|
auto invalidated_rects = move(m_invalidated_rects);
|
||||||
printf("[WM] compose #%u (%u rects)\n", ++m_recompose_count, invalidated_rects.size());
|
printf("[WM] compose #%u (%u rects)\n", ++m_recompose_count, invalidated_rects.size());
|
||||||
|
@ -297,8 +295,10 @@ void WindowManager::compose()
|
||||||
draw_cursor();
|
draw_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::draw_cursor()
|
void WSWindowManager::draw_cursor()
|
||||||
{
|
{
|
||||||
|
ASSERT_INTERRUPTS_ENABLED();
|
||||||
|
LOCKER(m_lock);
|
||||||
auto cursor_location = m_framebuffer.cursor_location();
|
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() };
|
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));
|
flush(m_last_cursor_rect.united(cursor_rect));
|
||||||
|
@ -311,8 +311,10 @@ void WindowManager::draw_cursor()
|
||||||
m_last_cursor_rect = cursor_rect;
|
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())
|
if (event.isMouseEvent())
|
||||||
return processMouseEvent(static_cast<MouseEvent&>(event));
|
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. :)
|
// FIXME: This is a good place to hook key events globally. :)
|
||||||
if (m_activeWindow)
|
if (m_activeWindow)
|
||||||
return m_activeWindow->event(event);
|
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;
|
m_pending_compose_event = false;
|
||||||
compose();
|
compose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object::event(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setActiveWindow(Window* window)
|
void WSWindowManager::setActiveWindow(WSWindow* window)
|
||||||
{
|
{
|
||||||
if (window == m_activeWindow.ptr())
|
if (window == m_activeWindow.ptr())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto* previously_active_window = m_activeWindow.ptr()) {
|
if (auto* previously_active_window = m_activeWindow.ptr())
|
||||||
invalidate(*previously_active_window);
|
invalidate(*previously_active_window);
|
||||||
EventLoop::main().postEvent(previously_active_window, make<Event>(Event::WindowBecameInactive));
|
|
||||||
}
|
|
||||||
m_activeWindow = window->makeWeakPtr();
|
m_activeWindow = window->makeWeakPtr();
|
||||||
if (m_activeWindow) {
|
if (m_activeWindow)
|
||||||
invalidate(*m_activeWindow);
|
invalidate(*m_activeWindow);
|
||||||
EventLoop::main().postEvent(m_activeWindow.ptr(), make<Event>(Event::WindowBecameActive));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowManager::isVisible(Window& window) const
|
void WSWindowManager::invalidate()
|
||||||
{
|
|
||||||
return m_windows.contains(&window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowManager::invalidate()
|
|
||||||
{
|
{
|
||||||
m_invalidated_rects.clear_with_capacity();
|
m_invalidated_rects.clear_with_capacity();
|
||||||
m_invalidated_rects.append(m_screen_rect);
|
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);
|
auto rect = Rect::intersection(a_rect, m_screen_rect);
|
||||||
if (rect.is_empty())
|
if (rect.is_empty())
|
||||||
|
@ -379,17 +370,20 @@ void WindowManager::invalidate(const Rect& a_rect)
|
||||||
m_invalidated_rects.append(rect);
|
m_invalidated_rects.append(rect);
|
||||||
|
|
||||||
if (!m_pending_compose_event) {
|
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;
|
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()));
|
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);
|
auto rect = Rect::intersection(a_rect, m_screen_rect);
|
||||||
|
|
|
@ -1,61 +1,58 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
#include <Widgets/Rect.h>
|
||||||
#include "Rect.h"
|
#include <Widgets/Color.h>
|
||||||
#include "Color.h"
|
#include <Widgets/Painter.h>
|
||||||
#include "Painter.h"
|
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
#include <AK/InlineLinkedList.h>
|
#include <AK/InlineLinkedList.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
#include <AK/Lock.h>
|
||||||
|
#include "WSEventReceiver.h"
|
||||||
|
|
||||||
class FrameBuffer;
|
class WSFrameBuffer;
|
||||||
class MouseEvent;
|
class MouseEvent;
|
||||||
class PaintEvent;
|
class PaintEvent;
|
||||||
class Widget;
|
class WSWindow;
|
||||||
class Window;
|
|
||||||
class CharacterBitmap;
|
class CharacterBitmap;
|
||||||
class GraphicsBitmap;
|
class GraphicsBitmap;
|
||||||
|
|
||||||
class WindowManager : public Object {
|
class WSWindowManager : public WSEventReceiver {
|
||||||
public:
|
public:
|
||||||
static WindowManager& the();
|
static WSWindowManager& the();
|
||||||
void addWindow(Window&);
|
void addWindow(WSWindow&);
|
||||||
void removeWindow(Window&);
|
void removeWindow(WSWindow&);
|
||||||
|
|
||||||
void notifyTitleChanged(Window&);
|
void notifyTitleChanged(WSWindow&);
|
||||||
void notifyRectChanged(Window&, const Rect& oldRect, const Rect& newRect);
|
void notifyRectChanged(WSWindow&, const Rect& oldRect, const Rect& newRect);
|
||||||
|
|
||||||
Window* activeWindow() { return m_activeWindow.ptr(); }
|
WSWindow* activeWindow() { return m_activeWindow.ptr(); }
|
||||||
void setActiveWindow(Window*);
|
|
||||||
|
|
||||||
bool isVisible(Window&) const;
|
void move_to_front(WSWindow&);
|
||||||
|
|
||||||
void did_paint(Window&);
|
|
||||||
|
|
||||||
void move_to_front(Window&);
|
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
void draw_cursor();
|
void draw_cursor();
|
||||||
|
|
||||||
void invalidate(const Window&);
|
void invalidate(const WSWindow&);
|
||||||
void invalidate(const Rect&);
|
void invalidate(const Rect&);
|
||||||
void invalidate();
|
void invalidate();
|
||||||
void flush(const Rect&);
|
void flush(const Rect&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowManager();
|
WSWindowManager();
|
||||||
virtual ~WindowManager() override;
|
virtual ~WSWindowManager() override;
|
||||||
|
|
||||||
void processMouseEvent(MouseEvent&);
|
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 compose();
|
||||||
void paintWindowFrame(Window&);
|
void paintWindowFrame(WSWindow&);
|
||||||
|
|
||||||
FrameBuffer& m_framebuffer;
|
WSFrameBuffer& m_framebuffer;
|
||||||
Rect m_screen_rect;
|
Rect m_screen_rect;
|
||||||
|
|
||||||
Color m_activeWindowBorderColor;
|
Color m_activeWindowBorderColor;
|
||||||
|
@ -64,12 +61,12 @@ private:
|
||||||
Color m_inactiveWindowBorderColor;
|
Color m_inactiveWindowBorderColor;
|
||||||
Color m_inactiveWindowTitleColor;
|
Color m_inactiveWindowTitleColor;
|
||||||
|
|
||||||
HashTable<Window*> m_windows;
|
HashTable<WSWindow*> m_windows;
|
||||||
InlineLinkedList<Window> m_windows_in_order;
|
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_dragOrigin;
|
||||||
Point m_dragWindowOrigin;
|
Point m_dragWindowOrigin;
|
||||||
|
@ -93,4 +90,6 @@ private:
|
||||||
|
|
||||||
OwnPtr<Painter> m_back_painter;
|
OwnPtr<Painter> m_back_painter;
|
||||||
OwnPtr<Painter> m_front_painter;
|
OwnPtr<Painter> m_front_painter;
|
||||||
|
|
||||||
|
mutable SpinLock m_lock;
|
||||||
};
|
};
|
25
WindowServer/main.cpp
Normal file
25
WindowServer/main.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue