mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:07:34 +00:00
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:
parent
4132f645ee
commit
de184d0999
20 changed files with 170 additions and 320 deletions
|
@ -10,7 +10,6 @@ SHAREDGRAPHICS_OBJS = \
|
||||||
../../SharedGraphics/PNGLoader.o
|
../../SharedGraphics/PNGLoader.o
|
||||||
|
|
||||||
WINDOWSERVER_OBJS = \
|
WINDOWSERVER_OBJS = \
|
||||||
WSMessageReceiver.o \
|
|
||||||
WSMessageLoop.o \
|
WSMessageLoop.o \
|
||||||
WSWindow.o \
|
WSWindow.o \
|
||||||
WSWindowManager.o \
|
WSWindowManager.o \
|
||||||
|
@ -35,7 +34,7 @@ WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings -Wimplicit-fal
|
||||||
FLAVOR_FLAGS = -fno-exceptions -fno-rtti
|
FLAVOR_FLAGS = -fno-exceptions -fno-rtti
|
||||||
OPTIMIZATION_FLAGS = -Os
|
OPTIMIZATION_FLAGS = -Os
|
||||||
INCLUDE_FLAGS = -I.. -I../.. -I. -I../../LibC
|
INCLUDE_FLAGS = -I.. -I../.. -I. -I../../LibC
|
||||||
LDFLAGS = -L../../LibC
|
LDFLAGS = -L../../LibC -L../../LibCore
|
||||||
|
|
||||||
DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
|
DEFINES = -DSERENITY -DSANITIZE_PTRS -DUSERLAND
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ AR = i686-pc-serenity-ar
|
||||||
all: $(APP)
|
all: $(APP)
|
||||||
|
|
||||||
$(APP): $(OBJS)
|
$(APP): $(OBJS)
|
||||||
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc
|
$(LD) -o $(APP) $(LDFLAGS) $(OBJS) -lc -lcore
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
|
@ -93,9 +93,9 @@ void WSClientConnection::notify_about_new_screen_rect(const Rect& rect)
|
||||||
post_message(message);
|
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));
|
on_request(static_cast<const WSAPIClientRequest&>(message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
#include <WindowServer/WSMessageReceiver.h>
|
#include <LibCore/CObject.h>
|
||||||
#include <WindowServer/WSMessage.h>
|
#include <WindowServer/WSMessage.h>
|
||||||
|
|
||||||
class WSWindow;
|
class WSWindow;
|
||||||
|
@ -13,7 +13,7 @@ class WSMenu;
|
||||||
class WSMenuBar;
|
class WSMenuBar;
|
||||||
struct WSAPI_ServerMessage;
|
struct WSAPI_ServerMessage;
|
||||||
|
|
||||||
class WSClientConnection final : public WSMessageReceiver {
|
class WSClientConnection final : public CObject {
|
||||||
public:
|
public:
|
||||||
explicit WSClientConnection(int fd);
|
explicit WSClientConnection(int fd);
|
||||||
virtual ~WSClientConnection() override;
|
virtual ~WSClientConnection() override;
|
||||||
|
@ -40,7 +40,7 @@ public:
|
||||||
void post_paint_request(const WSWindow&, const Rect&);
|
void post_paint_request(const WSWindow&, const Rect&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void on_message(const WSMessage&) override;
|
virtual void event(CEvent&) override;
|
||||||
|
|
||||||
void on_request(const WSAPIClientRequest&);
|
void on_request(const WSAPIClientRequest&);
|
||||||
void handle_request(const WSAPICreateMenubarRequest&);
|
void handle_request(const WSAPICreateMenubarRequest&);
|
||||||
|
|
|
@ -16,10 +16,6 @@ WSClipboard::~WSClipboard()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSClipboard::on_message(const WSMessage&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const byte* WSClipboard::data() const
|
const byte* WSClipboard::data() const
|
||||||
{
|
{
|
||||||
if (!m_shared_buffer)
|
if (!m_shared_buffer)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <WindowServer/WSMessageReceiver.h>
|
|
||||||
#include <SharedBuffer.h>
|
#include <SharedBuffer.h>
|
||||||
|
|
||||||
class WSClipboard final : public WSMessageReceiver {
|
class WSClipboard {
|
||||||
public:
|
public:
|
||||||
static WSClipboard& the();
|
static WSClipboard& the();
|
||||||
virtual ~WSClipboard() override;
|
~WSClipboard();
|
||||||
|
|
||||||
bool has_data() const
|
bool has_data() const
|
||||||
{
|
{
|
||||||
|
@ -22,7 +21,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WSClipboard();
|
WSClipboard();
|
||||||
virtual void on_message(const WSMessage&) override;
|
|
||||||
|
|
||||||
RetainPtr<SharedBuffer> m_shared_buffer;
|
RetainPtr<SharedBuffer> m_shared_buffer;
|
||||||
int m_contents_size { 0 };
|
int m_contents_size { 0 };
|
||||||
|
|
|
@ -110,7 +110,7 @@ void WSMenu::draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSMenu::on_message(const WSMessage& message)
|
void WSMenu::event(CEvent& message)
|
||||||
{
|
{
|
||||||
ASSERT(menu_window());
|
ASSERT(menu_window());
|
||||||
if (message.type() == WSMessage::MouseMove) {
|
if (message.type() == WSMessage::MouseMove) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <SharedGraphics/Rect.h>
|
#include <SharedGraphics/Rect.h>
|
||||||
#include <WindowServer/WSMenuItem.h>
|
#include <WindowServer/WSMenuItem.h>
|
||||||
#include <WindowServer/WSMessageReceiver.h>
|
#include <LibCore/CObject.h>
|
||||||
|
|
||||||
class WSClientConnection;
|
class WSClientConnection;
|
||||||
class WSMenuBar;
|
class WSMenuBar;
|
||||||
|
@ -13,7 +13,7 @@ class WSMessage;
|
||||||
class WSWindow;
|
class WSWindow;
|
||||||
class Font;
|
class Font;
|
||||||
|
|
||||||
class WSMenu final : public WSMessageReceiver {
|
class WSMenu final : public CObject {
|
||||||
public:
|
public:
|
||||||
WSMenu(WSClientConnection*, int menu_id, String&& name);
|
WSMenu(WSClientConnection*, int menu_id, String&& name);
|
||||||
virtual ~WSMenu() override;
|
virtual ~WSMenu() override;
|
||||||
|
@ -77,7 +77,7 @@ public:
|
||||||
void popup(const Point&);
|
void popup(const Point&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void on_message(const WSMessage&) override;
|
virtual void event(CEvent&) override;
|
||||||
|
|
||||||
int padding_between_text_and_shortcut() const { return 50; }
|
int padding_between_text_and_shortcut() const { return 50; }
|
||||||
void did_activate(WSMenuItem&);
|
void did_activate(WSMenuItem&);
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
#include <Kernel/KeyCode.h>
|
#include <Kernel/KeyCode.h>
|
||||||
#include <WindowServer/WSCursor.h>
|
#include <WindowServer/WSCursor.h>
|
||||||
#include <WindowServer/WSWindowType.h>
|
#include <WindowServer/WSWindowType.h>
|
||||||
|
#include <LibCore/CEvent.h>
|
||||||
|
|
||||||
class WSMessage {
|
class WSMessage : public CEvent {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
enum Type {
|
||||||
Invalid = 0,
|
Invalid = 2000,
|
||||||
WM_DeferredCompose,
|
WM_DeferredCompose,
|
||||||
WM_ClientDisconnected,
|
WM_ClientDisconnected,
|
||||||
MouseMove,
|
MouseMove,
|
||||||
|
@ -64,17 +65,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
WSMessage() { }
|
WSMessage() { }
|
||||||
explicit WSMessage(Type type) : m_type(type) { }
|
explicit WSMessage(Type type) : CEvent(type) { }
|
||||||
virtual ~WSMessage() { }
|
virtual ~WSMessage() { }
|
||||||
|
|
||||||
Type type() const { return m_type; }
|
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_client_request() const { return m_type > __Begin_API_Client_Requests && m_type < __End_API_Client_Requests; }
|
bool is_key_event() const { return type() == KeyUp || type() == KeyDown; }
|
||||||
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 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class WSClientDisconnectedNotification : public WSMessage {
|
class WSClientDisconnectedNotification : public WSMessage {
|
||||||
|
@ -663,7 +659,7 @@ public:
|
||||||
unsigned buttons() const { return m_buttons; }
|
unsigned buttons() const { return m_buttons; }
|
||||||
unsigned modifiers() const { return m_modifiers; }
|
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:
|
private:
|
||||||
Point m_position;
|
Point m_position;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <WindowServer/WSMessageLoop.h>
|
#include <WindowServer/WSMessageLoop.h>
|
||||||
#include <WindowServer/WSMessage.h>
|
#include <WindowServer/WSMessage.h>
|
||||||
#include <WindowServer/WSMessageReceiver.h>
|
#include <LibCore/CObject.h>
|
||||||
#include <WindowServer/WSWindowManager.h>
|
#include <WindowServer/WSWindowManager.h>
|
||||||
#include <WindowServer/WSScreen.h>
|
#include <WindowServer/WSScreen.h>
|
||||||
#include <WindowServer/WSClientConnection.h>
|
#include <WindowServer/WSClientConnection.h>
|
||||||
|
@ -8,36 +8,18 @@
|
||||||
#include <WindowServer/WSCursor.h>
|
#include <WindowServer/WSCursor.h>
|
||||||
#include <Kernel/KeyCode.h>
|
#include <Kernel/KeyCode.h>
|
||||||
#include <Kernel/MousePacket.h>
|
#include <Kernel/MousePacket.h>
|
||||||
#include <LibC/sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <LibC/sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <LibC/sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <LibC/time.h>
|
#include <time.h>
|
||||||
#include <LibC/unistd.h>
|
#include <unistd.h>
|
||||||
#include <LibC/fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <LibC/stdio.h>
|
#include <stdio.h>
|
||||||
#include <LibC/errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
//#define WSMESSAGELOOP_DEBUG
|
//#define WSMESSAGELOOP_DEBUG
|
||||||
|
|
||||||
static WSMessageLoop* s_the;
|
|
||||||
|
|
||||||
WSMessageLoop::WSMessageLoop()
|
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_keyboard_fd = open("/dev/keyboard", O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||||
m_mouse_fd = open("/dev/psaux", 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_keyboard_fd >= 0);
|
||||||
ASSERT(m_mouse_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;
|
return static_cast<WSMessageLoop&>(CEventLoop::current());
|
||||||
gettimeofday(&now, nullptr);
|
|
||||||
next_fire_time = {
|
|
||||||
now.tv_sec + (interval / 1000),
|
|
||||||
now.tv_usec + (interval % 1000) * 1000
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WSMessageLoop::start_timer(int interval, Function<void()>&& callback)
|
void WSMessageLoop::drain_server()
|
||||||
{
|
{
|
||||||
auto timer = make<Timer>();
|
sockaddr_un address;
|
||||||
int timer_id = m_next_timer_id++;
|
socklen_t address_size = sizeof(address);
|
||||||
timer->timer_id = timer_id;
|
int client_fd = accept(m_server_fd, (sockaddr*)&address, &address_size);
|
||||||
timer->callback = move(callback);
|
if (client_fd < 0) {
|
||||||
timer->interval = interval;
|
dbgprintf("WindowServer: accept() failed: %s\n", strerror(errno));
|
||||||
timer->reload();
|
} else {
|
||||||
m_timers.set(timer_id, move(timer));
|
new WSClientConnection(client_fd);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
void WSMessageLoop::drain_mouse()
|
||||||
|
@ -246,7 +107,7 @@ void WSMessageLoop::notify_client_disconnected(int client_id)
|
||||||
auto* client = WSClientConnection::from_client_id(client_id);
|
auto* client = WSClientConnection::from_client_id(client_id);
|
||||||
if (!client)
|
if (!client)
|
||||||
return;
|
return;
|
||||||
post_message(*client, make<WSClientDisconnectedNotification>(client_id));
|
post_event(*client, make<WSClientDisconnectedNotification>(client_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static WSWindowType from_api(WSAPI_WindowType api_type)
|
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);
|
client.set_client_pid(message.greeting.client_pid);
|
||||||
break;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::CreateMenubar:
|
case WSAPI_ClientMessage::Type::CreateMenubar:
|
||||||
post_message(client, make<WSAPICreateMenubarRequest>(client_id));
|
post_event(client, make<WSAPICreateMenubarRequest>(client_id));
|
||||||
break;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::DestroyMenubar:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetApplicationMenubar:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::AddMenuToMenubar:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::CreateMenu:
|
case WSAPI_ClientMessage::Type::CreateMenu:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::PopupMenu:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::DismissMenu:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWindowIcon:
|
case WSAPI_ClientMessage::Type::SetWindowIcon:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::DestroyMenu:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::AddMenuItem:
|
case WSAPI_ClientMessage::Type::AddMenuItem:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
||||||
ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::UpdateMenuItem:
|
case WSAPI_ClientMessage::Type::UpdateMenuItem:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
||||||
ASSERT(message.menu.shortcut_text_length < (ssize_t)sizeof(message.menu.shortcut_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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::AddMenuSeparator:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::CreateWindow:
|
case WSAPI_ClientMessage::Type::CreateWindow:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::DestroyWindow:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWindowTitle:
|
case WSAPI_ClientMessage::Type::SetWindowTitle:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::GetWindowTitle:
|
case WSAPI_ClientMessage::Type::GetWindowTitle:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWindowRect:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::GetWindowRect:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetClipboardContents:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::GetClipboardContents:
|
case WSAPI_ClientMessage::Type::GetClipboardContents:
|
||||||
post_message(client, make<WSAPIGetClipboardContentsRequest>(client_id));
|
post_event(client, make<WSAPIGetClipboardContentsRequest>(client_id));
|
||||||
break;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::InvalidateRect:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::DidFinishPainting:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::GetWindowBackingStore:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWindowBackingStore:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetGlobalCursorTracking:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWallpaper:
|
case WSAPI_ClientMessage::Type::SetWallpaper:
|
||||||
ASSERT(message.text_length < (ssize_t)sizeof(message.text));
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::GetWallpaper:
|
case WSAPI_ClientMessage::Type::GetWallpaper:
|
||||||
post_message(client, make<WSAPIGetWallpaperRequest>(client_id));
|
post_event(client, make<WSAPIGetWallpaperRequest>(client_id));
|
||||||
break;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::SetWindowOverrideCursor:
|
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;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::WM_SetActiveWindow:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -6,57 +6,32 @@
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
#include <LibCore/CEventLoop.h>
|
||||||
|
|
||||||
class WSMessageReceiver;
|
class CObject;
|
||||||
struct WSAPI_ClientMessage;
|
struct WSAPI_ClientMessage;
|
||||||
struct WSAPI_ServerMessage;
|
struct WSAPI_ServerMessage;
|
||||||
|
|
||||||
class WSMessageLoop {
|
class WSMessageLoop : public CEventLoop {
|
||||||
public:
|
public:
|
||||||
WSMessageLoop();
|
WSMessageLoop();
|
||||||
~WSMessageLoop();
|
virtual ~WSMessageLoop() override;
|
||||||
|
|
||||||
int exec();
|
|
||||||
|
|
||||||
void post_message(WSMessageReceiver& receiver, OwnPtr<WSMessage>&&);
|
|
||||||
|
|
||||||
static WSMessageLoop& the();
|
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 on_receive_from_client(int client_id, const WSAPI_ClientMessage&);
|
||||||
|
|
||||||
void notify_client_disconnected(int client_id);
|
void notify_client_disconnected(int client_id);
|
||||||
|
|
||||||
private:
|
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_mouse();
|
||||||
void drain_keyboard();
|
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_keyboard_fd { -1 };
|
||||||
int m_mouse_fd { -1 };
|
int m_mouse_fd { -1 };
|
||||||
int m_server_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;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
#include "WSMessageReceiver.h"
|
|
||||||
|
|
||||||
WSMessageReceiver::WSMessageReceiver()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
WSMessageReceiver::~WSMessageReceiver()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -70,14 +70,14 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, unsigned buttons)
|
||||||
if (!(changed_buttons & (unsigned)button))
|
if (!(changed_buttons & (unsigned)button))
|
||||||
return;
|
return;
|
||||||
auto message = make<WSMouseEvent>(buttons & (unsigned)button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, button, m_modifiers);
|
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::Left);
|
||||||
post_mousedown_or_mouseup_if_needed(MouseButton::Right);
|
post_mousedown_or_mouseup_if_needed(MouseButton::Right);
|
||||||
post_mousedown_or_mouseup_if_needed(MouseButton::Middle);
|
post_mousedown_or_mouseup_if_needed(MouseButton::Middle);
|
||||||
if (m_cursor_location != prev_location) {
|
if (m_cursor_location != prev_location) {
|
||||||
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons, MouseButton::None, m_modifiers);
|
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.)
|
// 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)
|
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();
|
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());
|
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)
|
void WSScreen::set_y_offset(int offset)
|
||||||
|
|
|
@ -18,7 +18,7 @@ static GraphicsBitmap& default_window_icon()
|
||||||
return *s_icon;
|
return *s_icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type)
|
WSWindow::WSWindow(CObject& internal_owner, WSWindowType type)
|
||||||
: m_internal_owner(&internal_owner)
|
: m_internal_owner(&internal_owner)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_icon(default_window_icon())
|
, m_icon(default_window_icon())
|
||||||
|
@ -130,10 +130,10 @@ void WSWindow::set_minimized(bool minimized)
|
||||||
WSWindowManager::the().notify_minimization_state_changed(*this);
|
WSWindowManager::the().notify_minimization_state_changed(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindow::on_message(const WSMessage& message)
|
void WSWindow::event(CEvent& message)
|
||||||
{
|
{
|
||||||
if (m_internal_owner)
|
if (m_internal_owner)
|
||||||
return m_internal_owner->on_message(message);
|
return m_internal_owner->event(message);
|
||||||
|
|
||||||
if (is_blocked_by_modal_window())
|
if (is_blocked_by_modal_window())
|
||||||
return;
|
return;
|
||||||
|
@ -141,7 +141,7 @@ void WSWindow::on_message(const WSMessage& message)
|
||||||
WSAPI_ServerMessage server_message;
|
WSAPI_ServerMessage server_message;
|
||||||
server_message.window_id = window_id();
|
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));
|
return handle_mouse_event(static_cast<const WSMouseEvent&>(message));
|
||||||
|
|
||||||
switch (message.type()) {
|
switch (message.type()) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <SharedGraphics/GraphicsBitmap.h>
|
#include <SharedGraphics/GraphicsBitmap.h>
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <AK/InlineLinkedList.h>
|
#include <AK/InlineLinkedList.h>
|
||||||
#include "WSMessageReceiver.h"
|
#include <LibCore/CObject.h>
|
||||||
#include <WindowServer/WSWindowType.h>
|
#include <WindowServer/WSWindowType.h>
|
||||||
#include <WindowServer/WSWindowFrame.h>
|
#include <WindowServer/WSWindowFrame.h>
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ class WSCursor;
|
||||||
class WSMenu;
|
class WSMenu;
|
||||||
class WSMouseEvent;
|
class WSMouseEvent;
|
||||||
|
|
||||||
class WSWindow final : public WSMessageReceiver, public InlineLinkedListNode<WSWindow> {
|
class WSWindow final : public CObject, public InlineLinkedListNode<WSWindow> {
|
||||||
public:
|
public:
|
||||||
WSWindow(WSClientConnection&, WSWindowType, int window_id, bool modal);
|
WSWindow(WSClientConnection&, WSWindowType, int window_id, bool modal);
|
||||||
WSWindow(WSMessageReceiver&, WSWindowType);
|
WSWindow(CObject&, WSWindowType);
|
||||||
virtual ~WSWindow() override;
|
virtual ~WSWindow() override;
|
||||||
|
|
||||||
Color background_color() const { return m_background_color; }
|
Color background_color() const { return m_background_color; }
|
||||||
|
@ -84,7 +84,7 @@ public:
|
||||||
|
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
|
||||||
virtual void on_message(const WSMessage&) override;
|
virtual void event(CEvent&) override;
|
||||||
|
|
||||||
GraphicsBitmap* backing_store() { return m_backing_store.ptr(); }
|
GraphicsBitmap* backing_store() { return m_backing_store.ptr(); }
|
||||||
void set_backing_store(RetainPtr<GraphicsBitmap>&& backing_store)
|
void set_backing_store(RetainPtr<GraphicsBitmap>&& backing_store)
|
||||||
|
@ -133,7 +133,7 @@ private:
|
||||||
void handle_mouse_event(const WSMouseEvent&);
|
void handle_mouse_event(const WSMouseEvent&);
|
||||||
|
|
||||||
WSClientConnection* m_client { nullptr };
|
WSClientConnection* m_client { nullptr };
|
||||||
WSMessageReceiver* m_internal_owner { nullptr };
|
CObject* m_internal_owner { nullptr };
|
||||||
String m_title;
|
String m_title;
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
WSWindowType m_type { WSWindowType::Normal };
|
WSWindowType m_type { WSWindowType::Normal };
|
||||||
|
|
|
@ -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();
|
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_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] {
|
m_buttons.append(make<WSButton>(*this, *s_minimize_button_bitmap, [this] {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <SharedGraphics/PNGLoader.h>
|
#include <SharedGraphics/PNGLoader.h>
|
||||||
#include <WindowServer/WSCursor.h>
|
#include <WindowServer/WSCursor.h>
|
||||||
#include <WindowServer/WSButton.h>
|
#include <WindowServer/WSButton.h>
|
||||||
|
#include <LibCore/CTimer.h>
|
||||||
|
|
||||||
//#define DEBUG_COUNTERS
|
//#define DEBUG_COUNTERS
|
||||||
//#define RESIZE_DEBUG
|
//#define RESIZE_DEBUG
|
||||||
|
@ -141,7 +142,8 @@ WSWindowManager::WSWindowManager()
|
||||||
// NOTE: This ensures that the system menu has the correct dimensions.
|
// NOTE: This ensures that the system menu has the correct dimensions.
|
||||||
set_current_menubar(nullptr);
|
set_current_menubar(nullptr);
|
||||||
|
|
||||||
WSMessageLoop::the().start_timer(300, [this] {
|
auto* timer = new CTimer;
|
||||||
|
timer->on_timeout = [this] {
|
||||||
static time_t last_update_time;
|
static time_t last_update_time;
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
if (now != last_update_time || m_cpu_monitor.is_dirty()) {
|
if (now != last_update_time || m_cpu_monitor.is_dirty()) {
|
||||||
|
@ -149,7 +151,8 @@ WSWindowManager::WSWindowManager()
|
||||||
last_update_time = now;
|
last_update_time = now;
|
||||||
m_cpu_monitor.set_dirty(false);
|
m_cpu_monitor.set_dirty(false);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
timer->start(300);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
compose();
|
compose();
|
||||||
|
@ -309,7 +312,7 @@ void WSWindowManager::remove_window(WSWindow& window)
|
||||||
|
|
||||||
for_each_window_listening_to_wm_events([&window] (WSWindow& listener) {
|
for_each_window_listening_to_wm_events([&window] (WSWindow& listener) {
|
||||||
if (window.client())
|
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;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -317,7 +320,7 @@ void WSWindowManager::remove_window(WSWindow& window)
|
||||||
void WSWindowManager::tell_wm_listener_about_window(WSWindow& listener, WSWindow& window)
|
void WSWindowManager::tell_wm_listener_about_window(WSWindow& listener, WSWindow& window)
|
||||||
{
|
{
|
||||||
if (window.client())
|
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)
|
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
|
#ifdef RESIZE_DEBUG
|
||||||
printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
|
printf("[WM] Finish resizing WSWindow{%p}\n", m_resize_window.ptr());
|
||||||
#endif
|
#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);
|
invalidate(*m_resize_window);
|
||||||
m_resize_window = nullptr;
|
m_resize_window = nullptr;
|
||||||
m_resizing_mouse_button = MouseButton::None;
|
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());
|
new_rect.to_string().characters());
|
||||||
#endif
|
#endif
|
||||||
m_resize_window->set_rect(new_rect);
|
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;
|
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_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.
|
ASSERT(!window->is_minimized()); // Maybe this should also be supported? Idk.
|
||||||
windows_who_received_mouse_event_due_to_cursor_tracking.set(window);
|
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())) {
|
if (menubar_rect().contains(event.position())) {
|
||||||
|
@ -618,7 +622,8 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
|
||||||
close_current_menu();
|
close_current_menu();
|
||||||
} else {
|
} else {
|
||||||
event_window = &window;
|
event_window = &window;
|
||||||
window.on_message(event.translated(-window.position()));
|
auto translated_event = event.translated(-window.position());
|
||||||
|
window.event(translated_event);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -650,8 +655,10 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*&
|
||||||
if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown)
|
if (window.type() == WSWindowType::Normal && event.type() == WSMessage::MouseDown)
|
||||||
move_to_front_and_make_active(window);
|
move_to_front_and_make_active(window);
|
||||||
event_window = &window;
|
event_window = &window;
|
||||||
if (!window.global_cursor_tracking() && !windows_who_received_mouse_event_due_to_cursor_tracking.contains(&window))
|
if (!window.global_cursor_tracking() && !windows_who_received_mouse_event_due_to_cursor_tracking.contains(&window)) {
|
||||||
window.on_message(event.translated(-window.position()));
|
auto translated_event = event.translated(-window.position());
|
||||||
|
window.event(translated_event);
|
||||||
|
}
|
||||||
return IterationDecision::Abort;
|
return IterationDecision::Abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,16 +919,16 @@ void WSWindowManager::draw_cursor()
|
||||||
m_last_cursor_rect = cursor_rect;
|
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;
|
WSWindow* event_window = nullptr;
|
||||||
process_mouse_event(static_cast<const WSMouseEvent&>(message), event_window);
|
process_mouse_event(static_cast<const WSMouseEvent&>(message), event_window);
|
||||||
set_hovered_window(event_window);
|
set_hovered_window(event_window);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.is_key_event()) {
|
if (static_cast<WSMessage&>(message).is_key_event()) {
|
||||||
auto& key_event = static_cast<const WSKeyEvent&>(message);
|
auto& key_event = static_cast<const WSKeyEvent&>(message);
|
||||||
m_keyboard_modifiers = key_event.modifiers();
|
m_keyboard_modifiers = key_event.modifiers();
|
||||||
|
|
||||||
|
@ -932,7 +939,7 @@ void WSWindowManager::on_message(const WSMessage& message)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_active_window)
|
if (m_active_window)
|
||||||
return m_active_window->on_message(message);
|
return m_active_window->event(message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,12 +976,12 @@ void WSWindowManager::set_active_window(WSWindow* window)
|
||||||
|
|
||||||
auto* previously_active_window = m_active_window.ptr();
|
auto* previously_active_window = m_active_window.ptr();
|
||||||
if (previously_active_window) {
|
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);
|
invalidate(*previously_active_window);
|
||||||
}
|
}
|
||||||
m_active_window = window->make_weak_ptr();
|
m_active_window = window->make_weak_ptr();
|
||||||
if (m_active_window) {
|
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);
|
invalidate(*m_active_window);
|
||||||
|
|
||||||
auto* client = window->client();
|
auto* client = window->client();
|
||||||
|
@ -992,12 +999,12 @@ void WSWindowManager::set_hovered_window(WSWindow* window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_hovered_window)
|
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;
|
m_hovered_window = window ? window->make_weak_ptr() : nullptr;
|
||||||
|
|
||||||
if (m_hovered_window)
|
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()
|
void WSWindowManager::invalidate()
|
||||||
|
@ -1021,7 +1028,7 @@ void WSWindowManager::invalidate(const Rect& a_rect, bool should_schedule_compos
|
||||||
m_dirty_rects.add(rect);
|
m_dirty_rects.add(rect);
|
||||||
|
|
||||||
if (should_schedule_compose_event && !m_pending_compose_event) {
|
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;
|
m_pending_compose_event = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include <AK/InlineLinkedList.h>
|
#include <AK/InlineLinkedList.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include "WSMessageReceiver.h"
|
|
||||||
#include "WSMenuBar.h"
|
#include "WSMenuBar.h"
|
||||||
#include <WindowServer/WSWindowSwitcher.h>
|
#include <WindowServer/WSWindowSwitcher.h>
|
||||||
#include <WindowServer/WSWindowType.h>
|
#include <WindowServer/WSWindowType.h>
|
||||||
|
@ -30,7 +29,7 @@ class WSButton;
|
||||||
|
|
||||||
enum class ResizeDirection { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft };
|
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 WSWindowFrame;
|
||||||
friend class WSWindowSwitcher;
|
friend class WSWindowSwitcher;
|
||||||
public:
|
public:
|
||||||
|
@ -132,7 +131,7 @@ private:
|
||||||
template<typename Callback> void for_each_window(Callback);
|
template<typename Callback> void for_each_window(Callback);
|
||||||
template<typename Callback> void for_each_active_menubar_menu(Callback);
|
template<typename Callback> void for_each_active_menubar_menu(Callback);
|
||||||
void close_current_menu();
|
void close_current_menu();
|
||||||
virtual void on_message(const WSMessage&) override;
|
virtual void event(CEvent&) override;
|
||||||
void compose();
|
void compose();
|
||||||
void paint_window_frame(const WSWindow&);
|
void paint_window_frame(const WSWindow&);
|
||||||
void flip_buffers();
|
void flip_buffers();
|
||||||
|
|
|
@ -115,7 +115,3 @@ void WSWindowSwitcher::refresh()
|
||||||
m_switcher_window->set_rect(m_rect);
|
m_switcher_window->set_rect(m_rect);
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSWindowSwitcher::on_message(const WSMessage&)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
#include <SharedGraphics/Rect.h>
|
#include <SharedGraphics/Rect.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <WindowServer/WSMessageReceiver.h>
|
#include <LibCore/CObject.h>
|
||||||
|
|
||||||
class Painter;
|
class Painter;
|
||||||
class WSKeyEvent;
|
class WSKeyEvent;
|
||||||
class WSWindow;
|
class WSWindow;
|
||||||
|
|
||||||
class WSWindowSwitcher : public WSMessageReceiver {
|
class WSWindowSwitcher : public CObject {
|
||||||
public:
|
public:
|
||||||
WSWindowSwitcher();
|
WSWindowSwitcher();
|
||||||
virtual ~WSWindowSwitcher() override;
|
virtual ~WSWindowSwitcher() override;
|
||||||
|
@ -33,8 +33,6 @@ public:
|
||||||
WSWindow* switcher_window() { return m_switcher_window.ptr(); }
|
WSWindow* switcher_window() { return m_switcher_window.ptr(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void on_message(const WSMessage&) override;
|
|
||||||
|
|
||||||
OwnPtr<WSWindow> m_switcher_window;
|
OwnPtr<WSWindow> m_switcher_window;
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
bool m_visible { false };
|
bool m_visible { false };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue