WindowServer: Port WindowServer to LibCore.

This was pretty straightforward thanks to the work I did separating out
LibCore from LibGUI already. :^)

- WSMessageLoop now inherits from CEventLoop.
- WSMessage now inherits from CEvent.
- WSMessageReceiver goes away.

Now there is only one event loop in Serenity. Very nice!
This commit is contained in:
Andreas Kling 2019-04-14 05:15:22 +02:00
parent 4132f645ee
commit de184d0999
Notes: sideshowbarker 2024-07-19 14:43:24 +09:00
20 changed files with 170 additions and 320 deletions

View File

@ -10,7 +10,6 @@ SHAREDGRAPHICS_OBJS = \
../../SharedGraphics/PNGLoader.o
WINDOWSERVER_OBJS = \
WSMessageReceiver.o \
WSMessageLoop.o \
WSWindow.o \
WSWindowManager.o \
@ -35,7 +34,7 @@ WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings -Wimplicit-fal
FLAVOR_FLAGS = -fno-exceptions -fno-rtti
OPTIMIZATION_FLAGS = -Os
INCLUDE_FLAGS = -I.. -I../.. -I. -I../../LibC
LDFLAGS = -L../../LibC
LDFLAGS = -L../../LibC -L../../LibCore
DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
@ -47,7 +46,7 @@ AR = i686-pc-serenity-ar
all: $(APP)
$(APP): $(OBJS)
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore
.cpp.o:
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<

View File

@ -93,9 +93,9 @@ void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
post_message(message);
}
void WSClientConnection::on_message(const WSMessage& message)
void WSClientConnection::event(CEvent& message)
{
if (message.is_client_request()) {
if (static_cast<WSMessage&>(message).is_client_request()) {
on_request(static_cast<const WSAPIClientRequest&>(message));
return;
}

View File

@ -5,7 +5,7 @@
#include <AK/WeakPtr.h>
#include <AK/Function.h>
#include <SharedGraphics/GraphicsBitmap.h>
#include <WindowServer/WSMessageReceiver.h>
#include <LibCore/CObject.h>
#include <WindowServer/WSMessage.h>
class WSWindow;
@ -13,7 +13,7 @@ class WSMenu;
class WSMenuBar;
struct WSAPI_ServerMessage;
class WSClientConnection final : public WSMessageReceiver {
class WSClientConnection final : public CObject {
public:
explicit WSClientConnection(int fd);
virtual ~WSClientConnection() override;
@ -40,7 +40,7 @@ public:
void post_paint_request(const WSWindow&, const Rect&);
private:
virtual void on_message(const WSMessage&) override;
virtual void event(CEvent&) override;
void on_request(const WSAPIClientRequest&);
void handle_request(const WSAPICreateMenubarRequest&);

View File

@ -16,10 +16,6 @@ WSClipboard::~WSClipboard()
{
}
void WSClipboard::on_message(const WSMessage&)
{
}
const byte* WSClipboard::data() const
{
if (!m_shared_buffer)

View File

@ -1,13 +1,12 @@
#pragma once
#include <AK/AKString.h>
#include <WindowServer/WSMessageReceiver.h>
#include <SharedBuffer.h>
class WSClipboard final : public WSMessageReceiver {
class WSClipboard {
public:
static WSClipboard& the();
virtual ~WSClipboard() override;
~WSClipboard();
bool has_data() const
{
@ -22,7 +21,6 @@ public:
private:
WSClipboard();
virtual void on_message(const WSMessage&) override;
RetainPtr<SharedBuffer> m_shared_buffer;
int m_contents_size { 0 };

View File

@ -110,7 +110,7 @@ void WSMenu::draw()
}
}
void WSMenu::on_message(const WSMessage& message)
void WSMenu::event(CEvent& message)
{
ASSERT(menu_window());
if (message.type() == WSMessage::MouseMove) {

View File

@ -5,7 +5,7 @@
#include <AK/WeakPtr.h>
#include <SharedGraphics/Rect.h>
#include <WindowServer/WSMenuItem.h>
#include <WindowServer/WSMessageReceiver.h>
#include <LibCore/CObject.h>
class WSClientConnection;
class WSMenuBar;
@ -13,7 +13,7 @@ class WSMessage;
class WSWindow;
class Font;
class WSMenu final : public WSMessageReceiver {
class WSMenu final : public CObject {
public:
WSMenu(WSClientConnection*, int menu_id, String&& name);
virtual ~WSMenu() override;
@ -77,7 +77,7 @@ public:
void popup(const Point&);
private:
virtual void on_message(const WSMessage&) override;
virtual void event(CEvent&) override;
int padding_between_text_and_shortcut() const { return 50; }
void did_activate(WSMenuItem&);

View File

@ -7,11 +7,12 @@
#include <Kernel/KeyCode.h>
#include <WindowServer/WSCursor.h>
#include <WindowServer/WSWindowType.h>
#include <LibCore/CEvent.h>
class WSMessage {
class WSMessage : public CEvent {
public:
enum Type {
Invalid = 0,
Invalid = 2000,
WM_DeferredCompose,
WM_ClientDisconnected,
MouseMove,
@ -64,17 +65,12 @@ public:
};
WSMessage() { }
explicit WSMessage(Type type) : m_type(type) { }
explicit WSMessage(Type type) : CEvent(type) { }
virtual ~WSMessage() { }
Type type() const { return m_type; }
bool is_client_request() const { return m_type > __Begin_API_Client_Requests && m_type < __End_API_Client_Requests; }
bool is_mouse_event() const { return m_type == MouseMove || m_type == MouseDown || m_type == MouseUp; }
bool is_key_event() const { return m_type == KeyUp || m_type == KeyDown; }
private:
Type m_type { Invalid };
bool is_client_request() const { return type() > __Begin_API_Client_Requests && type() < __End_API_Client_Requests; }
bool is_mouse_event() const { return type() == MouseMove || type() == MouseDown || type() == MouseUp; }
bool is_key_event() const { return type() == KeyUp || type() == KeyDown; }
};
class WSClientDisconnectedNotification : public WSMessage {
@ -663,7 +659,7 @@ public:
unsigned buttons() const { return m_buttons; }
unsigned modifiers() const { return m_modifiers; }
WSMouseEvent translated(const Point& delta) const { return WSMouseEvent(type(), m_position.translated(delta), m_buttons, m_button, m_modifiers); }
WSMouseEvent translated(const Point& delta) const { return WSMouseEvent((Type)type(), m_position.translated(delta), m_buttons, m_button, m_modifiers); }
private:
Point m_position;

View File

@ -1,6 +1,6 @@
#include <WindowServer/WSMessageLoop.h>
#include <WindowServer/WSMessage.h>
#include <WindowServer/WSMessageReceiver.h>
#include <LibCore/CObject.h>
#include <WindowServer/WSWindowManager.h>
#include <WindowServer/WSScreen.h>
#include <WindowServer/WSClientConnection.h>
@ -8,36 +8,18 @@
#include <WindowServer/WSCursor.h>
#include <Kernel/KeyCode.h>
#include <Kernel/MousePacket.h>
#include <LibC/sys/socket.h>
#include <LibC/sys/select.h>
#include <LibC/sys/time.h>
#include <LibC/time.h>
#include <LibC/unistd.h>
#include <LibC/fcntl.h>
#include <LibC/stdio.h>
#include <LibC/errno.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
//#define WSMESSAGELOOP_DEBUG
static WSMessageLoop* s_the;
WSMessageLoop::WSMessageLoop()
{
if (!s_the)
s_the = this;
}
WSMessageLoop::~WSMessageLoop()
{
}
WSMessageLoop& WSMessageLoop::the()
{
ASSERT(s_the);
return *s_the;
}
int WSMessageLoop::exec()
{
m_keyboard_fd = open("/dev/keyboard", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
m_mouse_fd = open("/dev/psaux", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
@ -56,148 +38,27 @@ int WSMessageLoop::exec()
ASSERT(m_keyboard_fd >= 0);
ASSERT(m_mouse_fd >= 0);
m_running = true;
for (;;) {
wait_for_message();
Vector<QueuedMessage> messages = move(m_queued_messages);
for (auto& queued_message : messages) {
auto* receiver = queued_message.receiver.ptr();
auto& message = *queued_message.message;
#ifdef WSMESSAGELOOP_DEBUG
dbgprintf("WSMessageLoop: receiver{%p} message %u\n", receiver, (unsigned)message.type());
#endif
if (receiver)
receiver->on_message(message);
}
}
}
void WSMessageLoop::post_message(WSMessageReceiver& receiver, OwnPtr<WSMessage>&& message)
WSMessageLoop::~WSMessageLoop()
{
#ifdef WSMESSAGELOOP_DEBUG
dbgprintf("WSMessageLoop::post_message: {%u} << receiver=%p, message=%p (type=%u)\n", m_queued_messages.size(), &receiver, message.ptr(), message->type());
#endif
m_queued_messages.append({ receiver.make_weak_ptr(), move(message) });
}
void WSMessageLoop::Timer::reload()
WSMessageLoop& WSMessageLoop::the()
{
struct timeval now;
gettimeofday(&now, nullptr);
next_fire_time = {
now.tv_sec + (interval / 1000),
now.tv_usec + (interval % 1000) * 1000
};
return static_cast<WSMessageLoop&>(CEventLoop::current());
}
int WSMessageLoop::start_timer(int interval, Function<void()>&& callback)
void WSMessageLoop::drain_server()
{
auto timer = make<Timer>();
int timer_id = m_next_timer_id++;
timer->timer_id = timer_id;
timer->callback = move(callback);
timer->interval = interval;
timer->reload();
m_timers.set(timer_id, move(timer));
return timer_id;
}
int WSMessageLoop::stop_timer(int timer_id)
{
auto it = m_timers.find(timer_id);
if (it == m_timers.end())
return -1;
m_timers.remove(it);
return 0;
}
void WSMessageLoop::wait_for_message()
{
fd_set rfds;
FD_ZERO(&rfds);
int max_fd = 0;
auto add_fd_to_set = [&max_fd] (int fd, auto& set) {
FD_SET(fd, &set);
if (fd > max_fd)
max_fd = fd;
};
add_fd_to_set(m_keyboard_fd, rfds);
add_fd_to_set(m_mouse_fd, rfds);
add_fd_to_set(m_server_fd, rfds);
WSClientConnection::for_each_client([&] (WSClientConnection& client) {
add_fd_to_set(client.fd(), rfds);
});
struct timeval timeout = { 0, 0 };
if (m_queued_messages.is_empty()) {
bool had_any_timer = false;
for (auto& it : m_timers) {
auto& timer = *it.value;
if (!had_any_timer) {
timeout = timer.next_fire_time;
had_any_timer = true;
continue;
}
if (timer.next_fire_time.tv_sec > timeout.tv_sec || (timer.next_fire_time.tv_sec == timeout.tv_sec && timer.next_fire_time.tv_usec > timeout.tv_usec))
timeout = timer.next_fire_time;
}
sockaddr_un address;
socklen_t address_size = sizeof(address);
int client_fd = accept(m_server_fd, (sockaddr*)&address, &address_size);
if (client_fd < 0) {
dbgprintf("WindowServer: accept() failed: %s\n", strerror(errno));
} else {
new WSClientConnection(client_fd);
}
int rc = select(max_fd + 1, &rfds, nullptr, nullptr, m_queued_messages.is_empty() && m_timers.is_empty() ? nullptr : &timeout);
if (rc < 0) {
ASSERT_NOT_REACHED();
}
struct timeval now;
gettimeofday(&now, nullptr);
for (auto& it : m_timers) {
auto& timer = *it.value;
if (now.tv_sec > timer.next_fire_time.tv_sec || (now.tv_sec == timer.next_fire_time.tv_sec && now.tv_usec > timer.next_fire_time.tv_usec)) {
timer.callback();
timer.reload();
}
}
if (FD_ISSET(m_keyboard_fd, &rfds))
drain_keyboard();
if (FD_ISSET(m_mouse_fd, &rfds))
drain_mouse();
if (FD_ISSET(m_server_fd, &rfds)) {
sockaddr_un address;
socklen_t address_size = sizeof(address);
int client_fd = accept(m_server_fd, (sockaddr*)&address, &address_size);
if (client_fd < 0) {
dbgprintf("WindowServer: accept() failed: %s\n", strerror(errno));
} else {
new WSClientConnection(client_fd);
}
}
WSClientConnection::for_each_client([&] (WSClientConnection& client) {
if (!FD_ISSET(client.fd(), &rfds))
return;
unsigned messages_received = 0;
for (;;) {
WSAPI_ClientMessage message;
// FIXME: Don't go one message at a time, that's so much context switching, oof.
ssize_t nread = read(client.fd(), &message, sizeof(WSAPI_ClientMessage));
if (nread == 0) {
if (!messages_received)
notify_client_disconnected(client.client_id());
break;
}
if (nread < 0) {
perror("read");
ASSERT_NOT_REACHED();
}
on_receive_from_client(client.client_id(), message);
++messages_received;
}
});
}
void WSMessageLoop::drain_mouse()
@ -246,7 +107,7 @@ void WSMessageLoop::notify_client_disconnected(int client_id)
auto* client = WSClientConnection::from_client_id(client_id);
if (!client)
return;
post_message(*client, make<WSClientDisconnectedNotification>(client_id));
post_event(*client, make<WSClientDisconnectedNotification>(client_id));
}
static WSWindowType from_api(WSAPI_WindowType api_type)
@ -275,103 +136,149 @@ void WSMessageLoop::on_receive_from_client(int client_id, const WSAPI_ClientMess
client.set_client_pid(message.greeting.client_pid);
break;
case WSAPI_ClientMessage::Type::CreateMenubar:
post_message(client, make<WSAPICreateMenubarRequest>(client_id));
post_event(client, make<WSAPICreateMenubarRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::DestroyMenubar:
post_message(client, make<WSAPIDestroyMenubarRequest>(client_id, message.menu.menubar_id));
post_event(client, make<WSAPIDestroyMenubarRequest>(client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::SetApplicationMenubar:
post_message(client, make<WSAPISetApplicationMenubarRequest>(client_id, message.menu.menubar_id));
post_event(client, make<WSAPISetApplicationMenubarRequest>(client_id, message.menu.menubar_id));
break;
case WSAPI_ClientMessage::Type::AddMenuToMenubar:
post_message(client, make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id));
post_event(client, make<WSAPIAddMenuToMenubarRequest>(client_id, message.menu.menubar_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateMenu:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length)));
post_event(client, make<WSAPICreateMenuRequest>(client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::PopupMenu:
post_message(client, make<WSAPIPopupMenuRequest>(client_id, message.menu.menu_id, message.menu.position));
post_event(client, make<WSAPIPopupMenuRequest>(client_id, message.menu.menu_id, message.menu.position));
break;
case WSAPI_ClientMessage::Type::DismissMenu:
post_message(client, make<WSAPIDismissMenuRequest>(client_id, message.menu.menu_id));
post_event(client, make<WSAPIDismissMenuRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::SetWindowIcon:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPISetWindowIconRequest>(client_id, message.window_id, String(message.text, message.text_length)));
post_event(client, make<WSAPISetWindowIconRequest>(client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::DestroyMenu:
post_message(client, make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id));
post_event(client, make<WSAPIDestroyMenuRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::AddMenuItem:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_text));
post_message(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled));
post_event(client, make<WSAPIAddMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled));
break;
case WSAPI_ClientMessage::Type::UpdateMenuItem:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_text));
post_message(client, make<WSAPIUpdateMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled));
post_event(client, make<WSAPIUpdateMenuItemRequest>(client_id, message.menu.menu_id, message.menu.identifier, String(message.text, message.text_length), String(message.menu.shortcut_text, message.menu.shortcut_text_length), message.menu.enabled));
break;
case WSAPI_ClientMessage::Type::AddMenuSeparator:
post_message(client, make<WSAPIAddMenuSeparatorRequest>(client_id, message.menu.menu_id));
post_event(client, make<WSAPIAddMenuSeparatorRequest>(client_id, message.menu.menu_id));
break;
case WSAPI_ClientMessage::Type::CreateWindow:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.modal, message.window.resizable, message.window.opacity, message.window.base_size, message.window.size_increment, from_api(message.window.type), Color::from_rgba(message.window.background_color)));
post_event(client, make<WSAPICreateWindowRequest>(client_id, message.window.rect, String(message.text, message.text_length), message.window.has_alpha_channel, message.window.modal, message.window.resizable, message.window.opacity, message.window.base_size, message.window.size_increment, from_api(message.window.type), Color::from_rgba(message.window.background_color)));
break;
case WSAPI_ClientMessage::Type::DestroyWindow:
post_message(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
post_event(client, make<WSAPIDestroyWindowRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowTitle:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length)));
post_event(client, make<WSAPISetWindowTitleRequest>(client_id, message.window_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWindowTitle:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPIGetWindowTitleRequest>(client_id, message.window_id));
post_event(client, make<WSAPIGetWindowTitleRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowRect:
post_message(client, make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect));
post_event(client, make<WSAPISetWindowRectRequest>(client_id, message.window_id, message.window.rect));
break;
case WSAPI_ClientMessage::Type::GetWindowRect:
post_message(client, make<WSAPIGetWindowRectRequest>(client_id, message.window_id));
post_event(client, make<WSAPIGetWindowRectRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetClipboardContents:
post_message(client, make<WSAPISetClipboardContentsRequest>(client_id, message.clipboard.shared_buffer_id, message.clipboard.contents_size));
post_event(client, make<WSAPISetClipboardContentsRequest>(client_id, message.clipboard.shared_buffer_id, message.clipboard.contents_size));
break;
case WSAPI_ClientMessage::Type::GetClipboardContents:
post_message(client, make<WSAPIGetClipboardContentsRequest>(client_id));
post_event(client, make<WSAPIGetClipboardContentsRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::InvalidateRect:
post_message(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect));
post_event(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect));
break;
case WSAPI_ClientMessage::Type::DidFinishPainting:
post_message(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect));
post_event(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect));
break;
case WSAPI_ClientMessage::Type::GetWindowBackingStore:
post_message(client, make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id));
post_event(client, make<WSAPIGetWindowBackingStoreRequest>(client_id, message.window_id));
break;
case WSAPI_ClientMessage::Type::SetWindowBackingStore:
post_message(client, make<WSAPISetWindowBackingStoreRequest>(client_id, message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
post_event(client, make<WSAPISetWindowBackingStoreRequest>(client_id, message.window_id, message.backing.shared_buffer_id, message.backing.size, message.backing.bpp, message.backing.pitch, message.backing.has_alpha_channel, message.backing.flush_immediately));
break;
case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
post_message(client, make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.window_id, message.value));
post_event(client, make<WSAPISetGlobalCursorTrackingRequest>(client_id, message.window_id, message.value));
break;
case WSAPI_ClientMessage::Type::SetWallpaper:
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
post_message(client, make<WSAPISetWallpaperRequest>(client_id, String(message.text, message.text_length)));
post_event(client, make<WSAPISetWallpaperRequest>(client_id, String(message.text, message.text_length)));
break;
case WSAPI_ClientMessage::Type::GetWallpaper:
post_message(client, make<WSAPIGetWallpaperRequest>(client_id));
post_event(client, make<WSAPIGetWallpaperRequest>(client_id));
break;
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
post_message(client, make<WSAPISetWindowOverrideCursorRequest>(client_id, message.window_id, (WSStandardCursor)message.cursor.cursor));
post_event(client, make<WSAPISetWindowOverrideCursorRequest>(client_id, message.window_id, (WSStandardCursor)message.cursor.cursor));
break;
case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
post_message(client, make<WSWMAPISetActiveWindowRequest>(client_id, message.wm.client_id, message.wm.window_id));
post_event(client, make<WSWMAPISetActiveWindowRequest>(client_id, message.wm.client_id, message.wm.window_id));
break;
default:
break;
}
}
void WSMessageLoop::add_file_descriptors_for_select(fd_set& fds, int& max_fd_added)
{
auto add_fd_to_set = [&max_fd_added] (int fd, auto& set) {
FD_SET(fd, &set);
if (fd > max_fd_added)
max_fd_added = fd;
};
add_fd_to_set(m_keyboard_fd, fds);
add_fd_to_set(m_mouse_fd, fds);
add_fd_to_set(m_server_fd, fds);
WSClientConnection::for_each_client([&] (WSClientConnection& client) {
add_fd_to_set(client.fd(), fds);
});
}
void WSMessageLoop::process_file_descriptors_after_select(const fd_set& fds)
{
if (FD_ISSET(m_server_fd, &fds))
drain_server();
if (FD_ISSET(m_keyboard_fd, &fds))
drain_keyboard();
if (FD_ISSET(m_mouse_fd, &fds))
drain_mouse();
WSClientConnection::for_each_client([&] (WSClientConnection& client) {
if (!FD_ISSET(client.fd(), &fds))
return;
unsigned messages_received = 0;
for (;;) {
WSAPI_ClientMessage message;
// FIXME: Don't go one message at a time, that's so much context switching, oof.
ssize_t nread = read(client.fd(), &message, sizeof(WSAPI_ClientMessage));
if (nread == 0) {
if (!messages_received)
notify_client_disconnected(client.client_id());
break;
}
if (nread < 0) {
perror("read");
ASSERT_NOT_REACHED();
}
on_receive_from_client(client.client_id(), message);
++messages_received;
}
});
}

View File

@ -6,57 +6,32 @@
#include <AK/Vector.h>
#include <AK/Function.h>
#include <AK/WeakPtr.h>
#include <LibCore/CEventLoop.h>
class WSMessageReceiver;
class CObject;
struct WSAPI_ClientMessage;
struct WSAPI_ServerMessage;
class WSMessageLoop {
class WSMessageLoop : public CEventLoop {
public:
WSMessageLoop();
~WSMessageLoop();
int exec();
void post_message(WSMessageReceiver& receiver, OwnPtr<WSMessage>&&);
virtual ~WSMessageLoop() override;
static WSMessageLoop& the();
bool running() const { return m_running; }
int start_timer(int ms, Function<void()>&&);
int stop_timer(int timer_id);
void on_receive_from_client(int client_id, const WSAPI_ClientMessage&);
void notify_client_disconnected(int client_id);
private:
void wait_for_message();
virtual void add_file_descriptors_for_select(fd_set&, int& max_fd_added) override;
virtual void process_file_descriptors_after_select(const fd_set&) override;
virtual void do_processing() override { }
void drain_server();
void drain_mouse();
void drain_keyboard();
struct QueuedMessage {
WeakPtr<WSMessageReceiver> receiver;
OwnPtr<WSMessage> message;
};
Vector<QueuedMessage> m_queued_messages;
bool m_running { false };
int m_keyboard_fd { -1 };
int m_mouse_fd { -1 };
int m_server_fd { -1 };
struct Timer {
void reload();
int timer_id { 0 };
int interval { 0 };
struct timeval next_fire_time { 0, 0 };
Function<void()> callback;
};
int m_next_timer_id { 1 };
HashMap<int, OwnPtr<Timer>> m_timers;
};

View File

@ -1,9 +0,0 @@
#include "WSMessageReceiver.h"
WSMessageReceiver::WSMessageReceiver()
{
}
WSMessageReceiver::~WSMessageReceiver()
{
}

View File

@ -1,13 +0,0 @@
#pragma once
#include <AK/Weakable.h>
class WSMessage;
class WSMessageReceiver : public Weakable<WSMessageReceiver> {
public:
WSMessageReceiver();
virtual ~WSMessageReceiver();
virtual void on_message(const WSMessage&) = 0;
};

View File

@ -70,14 +70,14 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, unsigned buttons)
if (!(changed_buttons & (unsigned)button))
return;
auto message = make<WSMouseEvent>(buttons & (unsigned)button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, button, m_modifiers);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
WSMessageLoop::the().post_event(WSWindowManager::the(), move(message));
};
post_mousedown_or_mouseup_if_needed(MouseButton::Left);
post_mousedown_or_mouseup_if_needed(MouseButton::Right);
post_mousedown_or_mouseup_if_needed(MouseButton::Middle);
if (m_cursor_location != prev_location) {
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons, MouseButton::None, m_modifiers);
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
WSMessageLoop::the().post_event(WSWindowManager::the(), move(message));
}
// NOTE: Invalidate the cursor if it moved, or if the left button changed state (for the cursor color inversion.)
if (m_cursor_location != prev_location || changed_buttons & (unsigned)MouseButton::Left)
@ -88,7 +88,7 @@ void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event)
{
m_modifiers = kernel_event.modifiers();
auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers());
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
WSMessageLoop::the().post_event(WSWindowManager::the(), move(message));
}
void WSScreen::set_y_offset(int offset)

View File

@ -18,7 +18,7 @@ static GraphicsBitmap& default_window_icon()
return *s_icon;
}
WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type)
WSWindow::WSWindow(CObject& internal_owner, WSWindowType type)
: m_internal_owner(&internal_owner)
, m_type(type)
, m_icon(default_window_icon())
@ -130,10 +130,10 @@ void WSWindow::set_minimized(bool minimized)
WSWindowManager::the().notify_minimization_state_changed(*this);
}
void WSWindow::on_message(const WSMessage& message)
void WSWindow::event(CEvent& message)
{
if (m_internal_owner)
return m_internal_owner->on_message(message);
return m_internal_owner->event(message);
if (is_blocked_by_modal_window())
return;
@ -141,7 +141,7 @@ void WSWindow::on_message(const WSMessage& message)
WSAPI_ServerMessage server_message;
server_message.window_id = window_id();
if (message.is_mouse_event())
if (static_cast<WSMessage&>(message).is_mouse_event())
return handle_mouse_event(static_cast<const WSMouseEvent&>(message));
switch (message.type()) {

View File

@ -4,7 +4,7 @@
#include <SharedGraphics/GraphicsBitmap.h>
#include <AK/AKString.h>
#include <AK/InlineLinkedList.h>
#include "WSMessageReceiver.h"
#include <LibCore/CObject.h>
#include <WindowServer/WSWindowType.h>
#include <WindowServer/WSWindowFrame.h>
@ -13,10 +13,10 @@ class WSCursor;
class WSMenu;
class WSMouseEvent;
class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> {
class WSWindow final : public CObject, public InlineLinkedListNode<WSWindow> {
public:
WSWindow(WSClientConnection&, WSWindowType, int window_id, bool modal);
WSWindow(WSMessageReceiver&, WSWindowType);
WSWindow(CObject&, WSWindowType);
virtual ~WSWindow() override;
Color background_color() const { return m_background_color; }
@ -84,7 +84,7 @@ public:
void invalidate();
virtual void on_message(const WSMessage&) override;
virtual void event(CEvent&) override;
GraphicsBitmap* backing_store() { return m_backing_store.ptr(); }
void set_backing_store(RetainPtr<GraphicsBitmap>&& backing_store)
@ -133,7 +133,7 @@ private:
void handle_mouse_event(const WSMouseEvent&);
WSClientConnection* m_client { nullptr };
WSMessageReceiver* m_internal_owner { nullptr };
CObject* m_internal_owner { nullptr };
String m_title;
Rect m_rect;
WSWindowType m_type { WSWindowType::Normal };

View File

@ -53,7 +53,8 @@ WSWindowFrame::WSWindowFrame(WSWindow& window)
s_minimize_button_bitmap = &CharacterBitmap::create_from_ascii(s_minimize_button_bitmap_data, s_minimize_button_bitmap_width, s_minimize_button_bitmap_height).leak_ref();
m_buttons.append(make<WSButton>(*this, *s_close_button_bitmap, [this] {
m_window.on_message(WSMessage(WSMessage::WindowCloseRequest));
WSMessage close_request(WSMessage::WindowCloseRequest);
m_window.event(close_request);
}));
m_buttons.append(make<WSButton>(*this, *s_minimize_button_bitmap, [this] {

View File

@ -18,6 +18,7 @@
#include <SharedGraphics/PNGLoader.h>
#include <WindowServer/WSCursor.h>
#include <WindowServer/WSButton.h>
#include <LibCore/CTimer.h>
//#define DEBUG_COUNTERS
//#define RESIZE_DEBUG
@ -141,7 +142,8 @@ WSWindowManager::WSWindowManager()
// NOTE: This ensures that the system menu has the correct dimensions.
set_current_menubar(nullptr);
WSMessageLoop::the().start_timer(300, [this] {
auto* timer = new CTimer;
timer->on_timeout = [this] {
static time_t last_update_time;
time_t now = time(nullptr);
if (now != last_update_time || m_cpu_monitor.is_dirty()) {
@ -149,7 +151,8 @@ WSWindowManager::WSWindowManager()
last_update_time = now;
m_cpu_monitor.set_dirty(false);
}
});
};
timer->start(300);
invalidate();
compose();
@ -309,7 +312,7 @@ void WSWindowManager::remove_window(WSWindow& window)
for_each_window_listening_to_wm_events([&window] (WSWindow& listener) {
if (window.client())
WSMessageLoop::the().post_message(listener, make<WSWMWindowRemovedEvent>(window.client()->client_id(), window.window_id()));
WSMessageLoop::the().post_event(listener, make<WSWMWindowRemovedEvent>(window.client()->client_id(), window.window_id()));
return IterationDecision::Continue;
});
}
@ -317,7 +320,7 @@ void WSWindowManager::remove_window(WSWindow& window)
void WSWindowManager::tell_wm_listener_about_window(WSWindow& listener, WSWindow& window)
{
if (window.client())
WSMessageLoop::the().post_message(listener, make<WSWMWindowStateChangedEvent>(window.client()->client_id(), window.window_id(), window.title(), window.rect(), window.is_active(), window.type(), window.is_minimized(), window.icon_path()));
WSMessageLoop::the().post_event(listener, make<WSWMWindowStateChangedEvent>(window.client()->client_id(), window.window_id(), window.title(), window.rect(), window.is_active(), window.type(), window.is_minimized(), window.icon_path()));
}
void WSWindowManager::tell_wm_listeners_window_state_changed(WSWindow& window)
@ -484,7 +487,7 @@ bool WSWindowManager::process_ongoing_window_resize(const WSMouseEvent& event, W
#ifdef RESIZE_DEBUG
printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
#endif
WSMessageLoop::the().post_message(*m_resize_window, make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect()));
WSMessageLoop::the().post_event(*m_resize_window, make<WSResizeEvent>(m_resize_window->rect(), m_resize_window->rect()));
invalidate(*m_resize_window);
m_resize_window = nullptr;
m_resizing_mouse_button = MouseButton::None;
@ -566,7 +569,7 @@ bool WSWindowManager::process_ongoing_window_resize(const WSMouseEvent& event, W
new_rect.to_string().characters());
#endif
m_resize_window->set_rect(new_rect);
WSMessageLoop::the().post_message(*m_resize_window, make<WSResizeEvent>(old_rect, new_rect));
WSMessageLoop::the().post_event(*m_resize_window, make<WSResizeEvent>(old_rect, new_rect));
return true;
}
@ -600,7 +603,8 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later.
ASSERT(!window->is_minimized()); // Maybe this should also be supported? Idk.
windows_who_received_mouse_event_due_to_cursor_tracking.set(window);
window->on_message(event.translated(-window->position()));
auto translated_event = event.translated(-window->position());
window->event(translated_event);
}
if (menubar_rect().contains(event.position())) {
@ -618,7 +622,8 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
close_current_menu();
} else {
event_window = &window;
window.on_message(event.translated(-window.position()));
auto translated_event = event.translated(-window.position());
window.event(translated_event);
}
return;
}
@ -650,8 +655,10 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown)
move_to_front_and_make_active(window);
event_window = &window;
if (!window.global_cursor_tracking() && !windows_who_received_mouse_event_due_to_cursor_tracking.contains(&window))
window.on_message(event.translated(-window.position()));
if (!window.global_cursor_tracking() && !windows_who_received_mouse_event_due_to_cursor_tracking.contains(&window)) {
auto translated_event = event.translated(-window.position());
window.event(translated_event);
}
return IterationDecision::Abort;
}
@ -912,16 +919,16 @@ void WSWindowManager::draw_cursor()
m_last_cursor_rect = cursor_rect;
}
void WSWindowManager::on_message(const WSMessage& message)
void WSWindowManager::event(CEvent& message)
{
if (message.is_mouse_event()) {
if (static_cast<WSMessage&>(message).is_mouse_event()) {
WSWindow* event_window = nullptr;
process_mouse_event(static_cast<const WSMouseEvent&>(message), event_window);
set_hovered_window(event_window);
return;
}
if (message.is_key_event()) {
if (static_cast<WSMessage&>(message).is_key_event()) {
auto& key_event = static_cast<const WSKeyEvent&>(message);
m_keyboard_modifiers = key_event.modifiers();
@ -932,7 +939,7 @@ void WSWindowManager::on_message(const WSMessage& message)
return;
}
if (m_active_window)
return m_active_window->on_message(message);
return m_active_window->event(message);
return;
}
@ -969,12 +976,12 @@ void WSWindowManager::set_active_window(WSWindow* window)
auto* previously_active_window = m_active_window.ptr();
if (previously_active_window) {
WSMessageLoop::the().post_message(*previously_active_window, make<WSMessage>(WSMessage::WindowDeactivated));
WSMessageLoop::the().post_event(*previously_active_window, make<WSMessage>(WSMessage::WindowDeactivated));
invalidate(*previously_active_window);
}
m_active_window = window->make_weak_ptr();
if (m_active_window) {
WSMessageLoop::the().post_message(*m_active_window, make<WSMessage>(WSMessage::WindowActivated));
WSMessageLoop::the().post_event(*m_active_window, make<WSMessage>(WSMessage::WindowActivated));
invalidate(*m_active_window);
auto* client = window->client();
@ -992,12 +999,12 @@ void WSWindowManager::set_hovered_window(WSWindow* window)
return;
if (m_hovered_window)
WSMessageLoop::the().post_message(*m_hovered_window, make<WSMessage>(WSMessage::WindowLeft));
WSMessageLoop::the().post_event(*m_hovered_window, make<WSMessage>(WSMessage::WindowLeft));
m_hovered_window = window ? window->make_weak_ptr() : nullptr;
if (m_hovered_window)
WSMessageLoop::the().post_message(*m_hovered_window, make<WSMessage>(WSMessage::WindowEntered));
WSMessageLoop::the().post_event(*m_hovered_window, make<WSMessage>(WSMessage::WindowEntered));
}
void WSWindowManager::invalidate()
@ -1021,7 +1028,7 @@ void WSWindowManager::invalidate(const Rect& a_rect, bool should_schedule_compos
m_dirty_rects.add(rect);
if (should_schedule_compose_event && !m_pending_compose_event) {
WSMessageLoop::the().post_message(*this, make<WSMessage>(WSMessage::WM_DeferredCompose));
WSMessageLoop::the().post_event(*this, make<WSMessage>(WSMessage::WM_DeferredCompose));
m_pending_compose_event = true;
}
}

View File

@ -8,7 +8,6 @@
#include <AK/InlineLinkedList.h>
#include <AK/WeakPtr.h>
#include <AK/HashMap.h>
#include "WSMessageReceiver.h"
#include "WSMenuBar.h"
#include <WindowServer/WSWindowSwitcher.h>
#include <WindowServer/WSWindowType.h>
@ -30,7 +29,7 @@ class WSButton;
enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft };
class WSWindowManager : public WSMessageReceiver {
class WSWindowManager : public CObject {
friend class WSWindowFrame;
friend class WSWindowSwitcher;
public:
@ -132,7 +131,7 @@ private:
template<typename Callback> void for_each_window(Callback);
template<typename Callback> void for_each_active_menubar_menu(Callback);
void close_current_menu();
virtual void on_message(const WSMessage&) override;
virtual void event(CEvent&) override;
void compose();
void paint_window_frame(const WSWindow&);
void flip_buffers();

View File

@ -115,7 +115,3 @@ void WSWindowSwitcher::refresh()
m_switcher_window->set_rect(m_rect);
draw();
}
void WSWindowSwitcher::on_message(const WSMessage&)
{
}

View File

@ -3,13 +3,13 @@
#include <SharedGraphics/Rect.h>
#include <AK/Vector.h>
#include <AK/WeakPtr.h>
#include <WindowServer/WSMessageReceiver.h>
#include <LibCore/CObject.h>
class Painter;
class WSKeyEvent;
class WSWindow;
class WSWindowSwitcher : public WSMessageReceiver {
class WSWindowSwitcher : public CObject {
public:
WSWindowSwitcher();
virtual ~WSWindowSwitcher() override;
@ -33,8 +33,6 @@ public:
WSWindow* switcher_window() { return m_switcher_window.ptr(); }
private:
virtual void on_message(const WSMessage&) override;
OwnPtr<WSWindow> m_switcher_window;
Rect m_rect;
bool m_visible { false };