Compare commits
10 Commits
df2aa925cb
...
16d57d0194
| Author | SHA1 | Date | |
|---|---|---|---|
| 16d57d0194 | |||
| f1a0738d13 | |||
| b81ff29e00 | |||
| 0dc88d09bf | |||
| 97e82afd4d | |||
| d787afb7e3 | |||
| f6a87f064f | |||
| 7fe5b0174f | |||
| 6450fd9a2f | |||
| 2ddd67dede |
@@ -374,6 +374,9 @@ void invalidate_window(WINDOW wid, int32_t x, int32_t y, int32_t w, int32_t h)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
if (wid == g_root.windowId)
|
||||||
|
return;
|
||||||
|
|
||||||
auto& object = *g_objects[wid];
|
auto& object = *g_objects[wid];
|
||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
|
||||||
@@ -506,17 +509,26 @@ transitient_for_done:
|
|||||||
|
|
||||||
static BAN::ErrorOr<void> map_window(Client& client_info, WINDOW wid)
|
static BAN::ErrorOr<void> map_window(Client& client_info, WINDOW wid)
|
||||||
{
|
{
|
||||||
|
static const CARD32 WM_CLASS = g_atoms_name_to_id["WM_CLASS"_sv];
|
||||||
|
|
||||||
auto& object = *g_objects[wid];
|
auto& object = *g_objects[wid];
|
||||||
ASSERT(object.type == Object::Type::Window);
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
|
||||||
auto& window = object.object.get<Object::Window>();
|
auto& window = object.object.get<Object::Window>();
|
||||||
if (window.mapped)
|
if (window.mapped)
|
||||||
return {};
|
return {};
|
||||||
|
window.mapped = true;
|
||||||
|
|
||||||
if (window.parent == g_root.windowId)
|
if (window.parent == g_root.windowId)
|
||||||
{
|
{
|
||||||
ASSERT(!window.platform_window);
|
ASSERT(!window.platform_window);
|
||||||
|
|
||||||
|
// NOTE: This is not perfect but seems to work.
|
||||||
|
// This is used to not display "dummy" event windows
|
||||||
|
// that should not be visible.
|
||||||
|
if (!window.properties.contains(WM_CLASS))
|
||||||
|
return {};
|
||||||
|
|
||||||
auto info = get_plaform_window_info(window);
|
auto info = get_plaform_window_info(window);
|
||||||
window.platform_window = TRY(g_platform_ops.create_window(
|
window.platform_window = TRY(g_platform_ops.create_window(
|
||||||
info.transient_for,
|
info.transient_for,
|
||||||
@@ -529,8 +541,6 @@ static BAN::ErrorOr<void> map_window(Client& client_info, WINDOW wid)
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
window.mapped = true;
|
|
||||||
|
|
||||||
for (auto& pixel : window.pixels)
|
for (auto& pixel : window.pixels)
|
||||||
pixel = window.background;
|
pixel = window.background;
|
||||||
invalidate_window(wid, 0, 0, window.width, window.height);
|
invalidate_window(wid, 0, 0, window.width, window.height);
|
||||||
@@ -715,7 +725,7 @@ static PlatformWindow* get_platform_window(const Object::Window& window)
|
|||||||
{
|
{
|
||||||
if (window.platform_window)
|
if (window.platform_window)
|
||||||
return const_cast<PlatformWindow*>(window.platform_window.ptr());
|
return const_cast<PlatformWindow*>(window.platform_window.ptr());
|
||||||
if (window.parent == g_root.windowId)
|
if (window.parent == None)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto& object = *g_objects[window.parent];
|
auto& object = *g_objects[window.parent];
|
||||||
@@ -728,30 +738,28 @@ void update_cursor(WINDOW wid, int32_t x, int32_t y)
|
|||||||
if (g_platform_ops.set_cursor == nullptr)
|
if (g_platform_ops.set_cursor == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto child_wid = find_child_window(wid, x, y);
|
wid = find_child_window(wid, x, y);
|
||||||
if (child_wid == None)
|
if (wid == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CURSOR cursor = None;
|
const CURSOR cid = [&wid]() -> CURSOR {
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
const auto& window = g_objects[wid]->object.get<Object::Window>();
|
||||||
|
if (window.cursor != None || window.parent == None)
|
||||||
|
return window.cursor;
|
||||||
|
wid = window.parent;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
if (child_wid != None)
|
static CURSOR active_cid = None;
|
||||||
{
|
if (cid == active_cid)
|
||||||
auto& object = *g_objects[child_wid];
|
|
||||||
ASSERT(object.type == Object::Type::Window);
|
|
||||||
cursor = object.object.get<Object::Window>().cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURSOR active_cursor = None;
|
|
||||||
if (cursor == active_cursor)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& object = *g_objects[wid];
|
const auto& window = g_objects[wid]->object.get<Object::Window>();
|
||||||
ASSERT(object.type == Object::Type::Window);
|
g_platform_ops.set_cursor(get_platform_window(window), get_cursor_safe(cid));
|
||||||
auto& window = object.object.get<Object::Window>();
|
|
||||||
|
|
||||||
g_platform_ops.set_cursor(get_platform_window(window), get_cursor_safe(cursor));
|
active_cid = cid;
|
||||||
|
|
||||||
active_cursor = window.cursor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_root_client_message(const xEvent& event)
|
static void on_root_client_message(const xEvent& event)
|
||||||
@@ -1010,9 +1018,11 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cursor_id.has_value())
|
if (cursor_id.has_value())
|
||||||
|
{
|
||||||
window.cursor = cursor_id.value();
|
window.cursor = cursor_id.value();
|
||||||
if (window.hovered)
|
if (window.hovered)
|
||||||
update_cursor(request.window, window.cursor_x, window.cursor_y);
|
update_cursor(request.window, window.cursor_x, window.cursor_y);
|
||||||
|
}
|
||||||
|
|
||||||
if (background.has_value())
|
if (background.has_value())
|
||||||
window.background = background.value();
|
window.background = background.value();
|
||||||
@@ -1932,12 +1942,15 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
|
|
||||||
const auto& window = TRY_REF(get_window(client_info, wid, opcode));
|
const auto& window = TRY_REF(get_window(client_info, wid, opcode));
|
||||||
|
|
||||||
int32_t root_x, root_y;
|
WINDOW child_wid { None };
|
||||||
int32_t event_x, event_y;
|
for (auto wid_ : window.children)
|
||||||
root_x = event_x = window.cursor_x;
|
{
|
||||||
root_y = event_y = window.cursor_y;
|
const auto& child_window = g_objects[wid_]->object.get<Object::Window>();
|
||||||
|
if (!child_window.hovered)
|
||||||
const auto child_wid = find_child_window(wid, event_x, event_y);
|
continue;
|
||||||
|
child_wid = wid_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
xQueryPointerReply reply {
|
xQueryPointerReply reply {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
@@ -1945,11 +1958,11 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
.sequenceNumber = client_info.sequence,
|
.sequenceNumber = client_info.sequence,
|
||||||
.length = 0,
|
.length = 0,
|
||||||
.root = g_root.windowId,
|
.root = g_root.windowId,
|
||||||
.child = static_cast<CARD32>(child_wid == wid ? None : child_wid),
|
.child = static_cast<CARD32>(child_wid),
|
||||||
.rootX = static_cast<INT16>(root_x),
|
.rootX = static_cast<INT16>(window.cursor_x), // FIXME
|
||||||
.rootY = static_cast<INT16>(root_y),
|
.rootY = static_cast<INT16>(window.cursor_y), // FIXME
|
||||||
.winX = static_cast<INT16>(event_x),
|
.winX = static_cast<INT16>(window.cursor_x),
|
||||||
.winY = static_cast<INT16>(event_y),
|
.winY = static_cast<INT16>(window.cursor_y),
|
||||||
.mask = static_cast<KeyButMask>(g_keymask | g_butmask),
|
.mask = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||||
};
|
};
|
||||||
TRY(encode(client_info.output_buffer, reply));
|
TRY(encode(client_info.output_buffer, reply));
|
||||||
@@ -2052,8 +2065,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
.depth = request.depth,
|
.depth = request.depth,
|
||||||
.width = request.width,
|
.width = request.width,
|
||||||
.height = request.height,
|
.height = request.height,
|
||||||
.data = data.span(),
|
.data = BAN::move(data),
|
||||||
.owned_data = BAN::move(data),
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
));
|
));
|
||||||
@@ -2697,7 +2709,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
|||||||
{
|
{
|
||||||
auto request = decode<xQueryBestSizeReq>(packet).value();
|
auto request = decode<xQueryBestSizeReq>(packet).value();
|
||||||
|
|
||||||
dprintln("FreeCursor");
|
dprintln("QueryBestSize");
|
||||||
dprintln(" class: {}", request.c_class);
|
dprintln(" class: {}", request.c_class);
|
||||||
dprintln(" drawable: {}", request.drawable);
|
dprintln(" drawable: {}", request.drawable);
|
||||||
dprintln(" width: {}", request.width);
|
dprintln(" width: {}", request.width);
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ struct Object
|
|||||||
CARD8 depth;
|
CARD8 depth;
|
||||||
CARD32 width;
|
CARD32 width;
|
||||||
CARD32 height;
|
CARD32 height;
|
||||||
BAN::ByteSpan data;
|
BAN::Vector<uint8_t> data;
|
||||||
BAN::Vector<uint8_t> owned_data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsContext
|
struct GraphicsContext
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Definitions.h"
|
#include "Definitions.h"
|
||||||
#include "Keymap.h"
|
#include "Keymap.h"
|
||||||
#include "Platform.h"
|
|
||||||
#include "SafeGetters.h"
|
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
@@ -451,14 +449,26 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
|||||||
MUST(window.send_event(event, EnterWindowMask));
|
MUST(window.send_event(event, EnterWindowMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto set_last_entry_hovered = [](const BAN::Vector<WINDOW>& path, bool value) {
|
for (const auto wid : old_child_path)
|
||||||
if (path.empty())
|
g_objects[wid]->object.get<Object::Window>().hovered = false;
|
||||||
return;
|
for (const auto wid : new_child_path)
|
||||||
g_objects[path.back()]->object.get<Object::Window>().hovered = value;
|
g_objects[wid]->object.get<Object::Window>().hovered = true;
|
||||||
};
|
}
|
||||||
|
|
||||||
set_last_entry_hovered(old_child_path, false);
|
static WINDOW s_current_top_level_window = None;
|
||||||
set_last_entry_hovered(new_child_path, true);
|
|
||||||
|
void on_window_leave_event(WINDOW wid)
|
||||||
|
{
|
||||||
|
if (s_current_top_level_window != wid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& object = *g_objects[wid];
|
||||||
|
ASSERT(object.type == Object::Type::Window);
|
||||||
|
auto& window = object.object.get<Object::Window>();
|
||||||
|
|
||||||
|
send_enter_and_leave_events(wid, window.cursor_x, window.cursor_y, wid, -1, -1);
|
||||||
|
|
||||||
|
s_current_top_level_window = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
||||||
@@ -469,21 +479,17 @@ void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y)
|
|||||||
|
|
||||||
update_cursor(wid, x, y);
|
update_cursor(wid, x, y);
|
||||||
|
|
||||||
|
if (auto it = g_objects.find(s_current_top_level_window); it == g_objects.end())
|
||||||
|
send_enter_and_leave_events(wid, -1, -1, wid, x, y);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
static WINDOW old_wid = g_root.windowId;
|
|
||||||
|
|
||||||
auto it = g_objects.find(old_wid);
|
|
||||||
if (it == g_objects.end())
|
|
||||||
it = g_objects.find(g_root.windowId);
|
|
||||||
|
|
||||||
ASSERT(it->value->type == Object::Type::Window);
|
ASSERT(it->value->type == Object::Type::Window);
|
||||||
auto& old_window = it->value->object.get<Object::Window>();
|
auto& old_window = it->value->object.get<Object::Window>();
|
||||||
|
send_enter_and_leave_events(s_current_top_level_window, old_window.cursor_x, old_window.cursor_y, wid, x, y);
|
||||||
send_enter_and_leave_events(old_wid, old_window.cursor_x, old_window.cursor_y, wid, x, y);
|
|
||||||
|
|
||||||
old_wid = wid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_current_top_level_window = wid;
|
||||||
|
|
||||||
update_cursor_position_recursive(wid, x, y);
|
update_cursor_position_recursive(wid, x, y);
|
||||||
|
|
||||||
// TODO: optimize with PointerMotionHint
|
// TODO: optimize with PointerMotionHint
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ void on_window_close_event(WINDOW wid);
|
|||||||
void on_window_resize_event(WINDOW wid, uint32_t width, uint32_t height);
|
void on_window_resize_event(WINDOW wid, uint32_t width, uint32_t height);
|
||||||
void on_window_focus_event(WINDOW wid, bool focused);
|
void on_window_focus_event(WINDOW wid, bool focused);
|
||||||
void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen);
|
void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen);
|
||||||
|
void on_window_leave_event(WINDOW wid);
|
||||||
|
|
||||||
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y);
|
void on_mouse_move_event(WINDOW wid, int32_t x, int32_t y);
|
||||||
void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed);
|
void on_mouse_button_event(WINDOW wid, uint8_t xbutton, bool pressed);
|
||||||
|
|||||||
@@ -7,42 +7,13 @@
|
|||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/extensions/shmproto.h>
|
#include <X11/extensions/shmproto.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static BYTE s_shm_event_base;
|
static BYTE s_shm_event_base;
|
||||||
static BYTE s_shm_error_base;
|
static BYTE s_shm_error_base;
|
||||||
static BYTE s_shm_major_opcode;
|
static BYTE s_shm_major_opcode;
|
||||||
|
|
||||||
static bool is_local_socket(int socket)
|
|
||||||
{
|
|
||||||
sockaddr_storage addr;
|
|
||||||
socklen_t addr_len = sizeof(addr);
|
|
||||||
if (getpeername(socket, reinterpret_cast<sockaddr*>(&addr), &addr_len) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (addr.ss_family)
|
|
||||||
{
|
|
||||||
case AF_UNIX:
|
|
||||||
return true;
|
|
||||||
case AF_INET:
|
|
||||||
{
|
|
||||||
const auto* addr_in = reinterpret_cast<const sockaddr_in*>(&addr);
|
|
||||||
const auto ipv4 = ntohl(addr_in->sin_addr.s_addr);
|
|
||||||
return (ipv4 & IN_CLASSA_NET) == IN_LOOPBACKNET;
|
|
||||||
}
|
|
||||||
case AF_INET6:
|
|
||||||
{
|
|
||||||
const auto* addr_in6 = reinterpret_cast<const sockaddr_in6*>(&addr);
|
|
||||||
return IN6_IS_ADDR_LOOPBACK(&addr_in6->sin6_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BAN::ErrorOr<void*> get_shmseg(Client& client_info, CARD32 shmseg, BYTE op_major, BYTE op_minor)
|
static BAN::ErrorOr<void*> get_shmseg(Client& client_info, CARD32 shmseg, BYTE op_major, BYTE op_minor)
|
||||||
{
|
{
|
||||||
auto it = g_objects.find(shmseg);
|
auto it = g_objects.find(shmseg);
|
||||||
@@ -74,11 +45,11 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
{
|
{
|
||||||
case X_ShmQueryVersion:
|
case X_ShmQueryVersion:
|
||||||
{
|
{
|
||||||
dwarnln("ShmQueryVersion");
|
dprintln("ShmQueryVersion");
|
||||||
|
|
||||||
xShmQueryVersionReply reply {
|
xShmQueryVersionReply reply {
|
||||||
.type = X_Reply,
|
.type = X_Reply,
|
||||||
.sharedPixmaps = is_local_socket(client_info.fd),
|
.sharedPixmaps = false,
|
||||||
.sequenceNumber = client_info.sequence,
|
.sequenceNumber = client_info.sequence,
|
||||||
.length = 0,
|
.length = 0,
|
||||||
.majorVersion = 1,
|
.majorVersion = 1,
|
||||||
@@ -95,7 +66,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
{
|
{
|
||||||
auto request = decode<xShmAttachReq>(packet).value();
|
auto request = decode<xShmAttachReq>(packet).value();
|
||||||
|
|
||||||
dwarnln("ShmAttach");
|
dprintln("ShmAttach");
|
||||||
dprintln(" shmseg: {}", request.shmseg);
|
dprintln(" shmseg: {}", request.shmseg);
|
||||||
dprintln(" shmid: {}", request.shmid);
|
dprintln(" shmid: {}", request.shmid);
|
||||||
dprintln(" readOnly: {}", request.readOnly);
|
dprintln(" readOnly: {}", request.readOnly);
|
||||||
@@ -144,7 +115,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
{
|
{
|
||||||
auto request = decode<xShmDetachReq>(packet).value();
|
auto request = decode<xShmDetachReq>(packet).value();
|
||||||
|
|
||||||
dwarnln("ShmDetach");
|
dprintln("ShmDetach");
|
||||||
dprintln(" shmseg: {}", request.shmseg);
|
dprintln(" shmseg: {}", request.shmseg);
|
||||||
|
|
||||||
void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
|
void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
|
||||||
@@ -159,7 +130,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
{
|
{
|
||||||
auto request = decode<xShmPutImageReq>(packet).value();
|
auto request = decode<xShmPutImageReq>(packet).value();
|
||||||
|
|
||||||
dwarnln("ShmPutImage");
|
dprintln("ShmPutImage");
|
||||||
dprintln(" drawable: {}", request.drawable);
|
dprintln(" drawable: {}", request.drawable);
|
||||||
dprintln(" gc: {}", request.gc);
|
dprintln(" gc: {}", request.gc);
|
||||||
dprintln(" totalWidth: {}", request.totalWidth);
|
dprintln(" totalWidth: {}", request.totalWidth);
|
||||||
@@ -223,7 +194,7 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
{
|
{
|
||||||
auto request = decode<xShmGetImageReq>(packet).value();
|
auto request = decode<xShmGetImageReq>(packet).value();
|
||||||
|
|
||||||
dwarnln("ShmGetImage");
|
dprintln("ShmGetImage");
|
||||||
dprintln(" drawable: {}", request.drawable);
|
dprintln(" drawable: {}", request.drawable);
|
||||||
dprintln(" x: {}", request.x);
|
dprintln(" x: {}", request.x);
|
||||||
dprintln(" y: {}", request.y);
|
dprintln(" y: {}", request.y);
|
||||||
@@ -265,44 +236,6 @@ static BAN::ErrorOr<void> extension_shm(Client& client_info, BAN::ConstByteSpan
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case X_ShmCreatePixmap:
|
|
||||||
{
|
|
||||||
auto request = decode<xShmCreatePixmapReq>(packet).value();
|
|
||||||
|
|
||||||
dwarnln("ShmCreatePixmap");
|
|
||||||
dprintln(" depth: {}", request.depth);
|
|
||||||
dprintln(" pid: {}", request.pid);
|
|
||||||
dprintln(" drawable: {}", request.drawable);
|
|
||||||
dprintln(" width: {}", request.width);
|
|
||||||
dprintln(" height: {}", request.height);
|
|
||||||
dprintln(" shmseg: {}", request.shmseg);
|
|
||||||
dprintln(" offset: {}", request.offset);
|
|
||||||
|
|
||||||
uint8_t bpp = 0;
|
|
||||||
for (auto format : g_formats)
|
|
||||||
if (format.depth == request.depth)
|
|
||||||
bpp = format.bitsPerPixel;
|
|
||||||
ASSERT(bpp == 32);
|
|
||||||
|
|
||||||
void* shm_segment = TRY(get_shmseg(client_info, request.shmseg, op_major, op_minor));
|
|
||||||
|
|
||||||
TRY(client_info.objects.insert(request.pid));
|
|
||||||
TRY(g_objects.insert(
|
|
||||||
request.pid,
|
|
||||||
TRY(BAN::UniqPtr<Object>::create(Object {
|
|
||||||
.type = Object::Type::Pixmap,
|
|
||||||
.object = Object::Pixmap {
|
|
||||||
.depth = request.depth,
|
|
||||||
.width = request.width,
|
|
||||||
.height = request.height,
|
|
||||||
.data = BAN::ByteSpan(static_cast<uint8_t*>(shm_segment) + request.offset, request.width * request.height * 4),
|
|
||||||
.owned_data = {},
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
dwarnln("unsupported shm minor opcode {}", packet[1]);
|
dwarnln("unsupported shm minor opcode {}", packet[1]);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -60,8 +60,33 @@ void put_image(const PutImageInfo& info)
|
|||||||
}
|
}
|
||||||
case ZPixmap:
|
case ZPixmap:
|
||||||
{
|
{
|
||||||
|
bool needs_clipping = true;
|
||||||
|
|
||||||
|
if (info.gc.clip_mask == None)
|
||||||
|
{
|
||||||
|
needs_clipping = false;
|
||||||
|
}
|
||||||
|
else if (info.gc.clip_mask == UINT32_MAX)
|
||||||
|
{
|
||||||
|
const uint32_t clip_min_x = min_x - info.gc.clip_origin_x;
|
||||||
|
const uint32_t clip_min_y = min_y - info.gc.clip_origin_y;
|
||||||
|
|
||||||
|
const uint32_t clip_max_x = max_x - info.gc.clip_origin_x;
|
||||||
|
const uint32_t clip_max_y = max_y - info.gc.clip_origin_y;
|
||||||
|
|
||||||
|
for (const auto& rect : info.gc.clip_rects)
|
||||||
|
{
|
||||||
|
if (clip_min_x < rect.x || clip_max_x > rect.x + rect.width)
|
||||||
|
continue;
|
||||||
|
if (clip_min_y < rect.y || clip_max_y > rect.y + rect.height)
|
||||||
|
continue;
|
||||||
|
needs_clipping = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(info.left_pad == 0);
|
ASSERT(info.left_pad == 0);
|
||||||
if (in_bpp == 32 && info.gc.clip_mask == None)
|
if (in_bpp == 32 && !needs_clipping)
|
||||||
{
|
{
|
||||||
const auto bytes_per_row = (max_x - min_x) * 4;
|
const auto bytes_per_row = (max_x - min_x) * 4;
|
||||||
for (int32_t y = min_y; y < max_y; y++)
|
for (int32_t y = min_y; y < max_y; y++)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl2_create_window(PlatformWin
|
|||||||
window->width = width;
|
window->width = width;
|
||||||
window->height = height;
|
window->height = height;
|
||||||
|
|
||||||
if (parent == nullptr || type != WindowType::Popup)
|
if (parent == nullptr)
|
||||||
x = y = SDL_WINDOWPOS_UNDEFINED;
|
x = y = SDL_WINDOWPOS_UNDEFINED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -215,6 +215,9 @@ static void sdl2_poll_events(void*)
|
|||||||
case SDL_WINDOWEVENT_RESTORED:
|
case SDL_WINDOWEVENT_RESTORED:
|
||||||
on_window_fullscreen_event(window.wid, false);
|
on_window_fullscreen_event(window.wid, false);
|
||||||
break;
|
break;
|
||||||
|
case SDL_WINDOWEVENT_LEAVE:
|
||||||
|
on_window_leave_event(window.wid);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -325,11 +328,10 @@ static void sdl2_invalidate(PlatformWindow* window, const uint32_t* src_pixels,
|
|||||||
static void sdl2_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
static void sdl2_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||||
{
|
{
|
||||||
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||||
(void)sdl_window;
|
SDL_SetWindowFullscreen(sdl_window.window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||||
(void)fullscreen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_system_cursor(SystemCursorType type)
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_system_cursor(SystemCursorType type)
|
||||||
{
|
{
|
||||||
SDL_SystemCursor sdl_type;
|
SDL_SystemCursor sdl_type;
|
||||||
switch (type)
|
switch (type)
|
||||||
@@ -385,7 +387,7 @@ BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_system_cursor(SystemCurso
|
|||||||
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(const uint32_t* pixels, uint32_t width, uint32_t height, int32_t origin_x, int32_t origin_y)
|
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(const uint32_t* pixels, uint32_t width, uint32_t height, int32_t origin_x, int32_t origin_y)
|
||||||
{
|
{
|
||||||
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
auto cursor = TRY(BAN::UniqPtr<SDLCursor>::create());
|
||||||
|
|
||||||
@@ -396,6 +398,8 @@ BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(const uint3
|
|||||||
return BAN::Error::from_errno(EFAULT);
|
return BAN::Error::from_errno(EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
origin_x = BAN::Math::clamp<int32_t>(origin_x, 0, width - 1);
|
||||||
|
origin_y = BAN::Math::clamp<int32_t>(origin_y, 0, height - 1);
|
||||||
cursor->cursor = SDL_CreateColorCursor(surface, origin_x, origin_y);
|
cursor->cursor = SDL_CreateColorCursor(surface, origin_x, origin_y);
|
||||||
|
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
@@ -409,7 +413,7 @@ BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> sdl2_create_bitmap_cursor(const uint3
|
|||||||
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
return BAN::UniqPtr<PlatformCursor>(BAN::move(cursor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdl2_set_cursor(PlatformWindow*, PlatformCursor* cursor)
|
static void sdl2_set_cursor(PlatformWindow*, PlatformCursor* cursor)
|
||||||
{
|
{
|
||||||
if (cursor == nullptr)
|
if (cursor == nullptr)
|
||||||
SDL_SetCursor(s_default_cursor);
|
SDL_SetCursor(s_default_cursor);
|
||||||
|
|||||||
@@ -290,6 +290,18 @@ int main()
|
|||||||
window.event_masks.remove(&client_info);
|
window.event_masks.remove(&client_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto it = client_info.objects.begin(); it != client_info.objects.end();)
|
||||||
|
{
|
||||||
|
auto obj_it = g_objects.find(*it);
|
||||||
|
if (obj_it == g_objects.end() || obj_it->value->type != Object::Type::Window)
|
||||||
|
it++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)destroy_window(client_info, *it);
|
||||||
|
it = client_info.objects.begin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto id : client_info.objects)
|
for (auto id : client_info.objects)
|
||||||
{
|
{
|
||||||
auto it = g_objects.find(id);
|
auto it = g_objects.find(id);
|
||||||
@@ -304,14 +316,13 @@ int main()
|
|||||||
case Object::Type::Pixmap:
|
case Object::Type::Pixmap:
|
||||||
case Object::Type::GraphicsContext:
|
case Object::Type::GraphicsContext:
|
||||||
case Object::Type::Font:
|
case Object::Type::Font:
|
||||||
case Object::Type::Window:
|
|
||||||
break;
|
break;
|
||||||
|
case Object::Type::Window:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
case Object::Type::Extension:
|
case Object::Type::Extension:
|
||||||
{
|
|
||||||
auto& extension = object.object.get<Object::Extension>();
|
auto& extension = object.object.get<Object::Extension>();
|
||||||
extension.destructor(extension);
|
extension.destructor(extension);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_objects.remove(it);
|
g_objects.remove(it);
|
||||||
|
|||||||
Reference in New Issue
Block a user