Add support for global window position
This allows proper TranslateCoords and event root coordinate reporting
This commit is contained in:
@@ -719,6 +719,21 @@ WINDOW find_child_window(WINDOW wid, int32_t& x, int32_t& y)
|
||||
return wid;
|
||||
}
|
||||
|
||||
xPoint get_window_position(WINDOW wid)
|
||||
{
|
||||
xPoint result { .x = 0, .y = 0 };
|
||||
|
||||
while (wid != None)
|
||||
{
|
||||
const auto& window = g_objects[wid]->object.get<Object::Window>();
|
||||
result.x += window.x;
|
||||
result.y += window.y;
|
||||
wid = window.parent;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static PlatformWindow* get_platform_window(const Object::Window& window)
|
||||
{
|
||||
if (window.platform_window)
|
||||
@@ -1239,18 +1254,21 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
}
|
||||
}
|
||||
|
||||
bool window_changed = false;
|
||||
|
||||
const int32_t min_x = BAN::Math::min(window.x, new_x);
|
||||
const int32_t min_y = BAN::Math::min(window.y, new_y);
|
||||
const int32_t max_x = BAN::Math::max(window.x + window.width, new_x + new_width);
|
||||
const int32_t max_y = BAN::Math::max(window.y + window.height, new_y + new_height);
|
||||
bool send_configure = false;
|
||||
|
||||
if (new_x != window.x || new_y != window.y)
|
||||
{
|
||||
window.x = new_x;
|
||||
window.y = new_y;
|
||||
window_changed = true;
|
||||
if (window.platform_window)
|
||||
{
|
||||
if (g_platform_ops.request_reposition)
|
||||
g_platform_ops.request_reposition(window.platform_window.ptr(), new_x, new_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.x = new_x;
|
||||
window.y = new_y;
|
||||
send_configure = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_width != window.width || new_height != window.height)
|
||||
@@ -1259,22 +1277,20 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
{
|
||||
if (g_platform_ops.request_resize)
|
||||
g_platform_ops.request_resize(window.platform_window.ptr(), new_width, new_height);
|
||||
window_changed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
window.width = new_width;
|
||||
window.height = new_height;
|
||||
|
||||
TRY(window.pixels.resize(new_width * new_height));
|
||||
for (auto& pixel : window.pixels)
|
||||
pixel = window.background;
|
||||
|
||||
window_changed = true;
|
||||
window.width = new_width;
|
||||
window.height = new_height;
|
||||
send_configure = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!window_changed)
|
||||
if (!send_configure)
|
||||
break;
|
||||
|
||||
{
|
||||
@@ -1950,6 +1966,7 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
break;
|
||||
}
|
||||
|
||||
const auto [root_x, root_y] = get_window_position(wid);
|
||||
xQueryPointerReply reply {
|
||||
.type = X_Reply,
|
||||
.sameScreen = xTrue,
|
||||
@@ -1957,8 +1974,8 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
.length = 0,
|
||||
.root = g_root.windowId,
|
||||
.child = static_cast<CARD32>(child_wid),
|
||||
.rootX = static_cast<INT16>(window.cursor_x), // FIXME
|
||||
.rootY = static_cast<INT16>(window.cursor_y), // FIXME
|
||||
.rootX = static_cast<INT16>(root_x + window.cursor_x),
|
||||
.rootY = static_cast<INT16>(root_y + window.cursor_y),
|
||||
.winX = static_cast<INT16>(window.cursor_x),
|
||||
.winY = static_cast<INT16>(window.cursor_y),
|
||||
.mask = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||
@@ -1977,14 +1994,20 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
|
||||
dprintln(" src_x: {}", request.srcX);
|
||||
dprintln(" src_y: {}", request.srcY);
|
||||
|
||||
(void)TRY_REF(get_window(client_info, request.dstWid, X_TranslateCoords));
|
||||
(void)TRY_REF(get_window(client_info, request.srcWid, X_TranslateCoords));
|
||||
|
||||
const auto [src_x, src_y] = get_window_position(request.srcWid);
|
||||
const auto [dst_x, dst_y] = get_window_position(request.dstWid);
|
||||
|
||||
xTranslateCoordsReply reply {
|
||||
.type = X_Reply,
|
||||
.sameScreen = xTrue,
|
||||
.sequenceNumber = client_info.sequence,
|
||||
.length = 0,
|
||||
.child = None,
|
||||
.dstX = request.srcX,
|
||||
.dstY = request.srcY,
|
||||
.child = None, // FIXME
|
||||
.dstX = static_cast<INT16>(src_x + request.srcX - dst_x),
|
||||
.dstY = static_cast<INT16>(src_y + request.srcY - dst_y),
|
||||
};
|
||||
TRY(encode(client_info.output_buffer, reply));
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ BAN::ErrorOr<void> destroy_window(Client& client_info, WINDOW wid);
|
||||
|
||||
WINDOW find_child_window(WINDOW wid, int32_t& x, int32_t& y);
|
||||
|
||||
xPoint get_window_position(WINDOW wid);
|
||||
|
||||
static constexpr uint32_t COLOR_INVISIBLE = 0x69000000;
|
||||
|
||||
extern CARD16 g_keymask;
|
||||
|
||||
@@ -75,21 +75,8 @@ void on_window_close_event(WINDOW wid)
|
||||
}
|
||||
}
|
||||
|
||||
void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
||||
static void send_window_configure(WINDOW wid, Object::Window& window)
|
||||
{
|
||||
auto& object = *g_objects[wid];
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
{
|
||||
window.width = new_width;
|
||||
window.height = new_height;
|
||||
|
||||
MUST(window.pixels.resize(new_width * new_height));
|
||||
for (auto& pixel : window.pixels)
|
||||
pixel = window.background;
|
||||
}
|
||||
|
||||
{
|
||||
xEvent event = { .u = {
|
||||
.configureNotify = {
|
||||
@@ -129,12 +116,42 @@ void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
||||
event.u.u.type = ConfigureNotify;
|
||||
MUST(parent_window.send_event(event, SubstructureNotifyMask));
|
||||
}
|
||||
}
|
||||
|
||||
void on_window_resize_event(WINDOW wid, uint32_t new_width, uint32_t new_height)
|
||||
{
|
||||
auto& object = *g_objects[wid];
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
{
|
||||
window.width = new_width;
|
||||
window.height = new_height;
|
||||
|
||||
MUST(window.pixels.resize(new_width * new_height));
|
||||
for (auto& pixel : window.pixels)
|
||||
pixel = window.background;
|
||||
}
|
||||
|
||||
send_window_configure(wid, window);
|
||||
|
||||
send_exposure_recursive(wid);
|
||||
|
||||
invalidate_window(wid, 0, 0, window.width, window.height);
|
||||
}
|
||||
|
||||
void on_window_move_event(WINDOW wid, int32_t x, int32_t y)
|
||||
{
|
||||
auto& object = *g_objects[wid];
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
window.x = x;
|
||||
window.y = y;
|
||||
|
||||
send_window_configure(wid, window);
|
||||
}
|
||||
|
||||
void on_window_focus_event(WINDOW wid, bool focused)
|
||||
{
|
||||
if (focused)
|
||||
@@ -219,15 +236,14 @@ void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen)
|
||||
|
||||
static void send_key_button_pointer_event(WINDOW root_wid, BYTE detail, uint32_t event_mask, BYTE event_type, KeyButMask state)
|
||||
{
|
||||
int32_t root_x, root_y;
|
||||
int32_t event_x, event_y;
|
||||
|
||||
{
|
||||
auto& object = *g_objects[root_wid];
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
root_x = event_x = window.cursor_x;
|
||||
root_y = event_y = window.cursor_y;
|
||||
event_x = window.cursor_x;
|
||||
event_y = window.cursor_y;
|
||||
}
|
||||
|
||||
const auto child_wid = find_child_window(root_wid, event_x, event_y);
|
||||
@@ -257,14 +273,15 @@ static void send_key_button_pointer_event(WINDOW root_wid, BYTE detail, uint32_t
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
const auto [root_x, root_y] = get_window_position(wid);
|
||||
xEvent event { .u = {
|
||||
.keyButtonPointer = {
|
||||
.time = static_cast<CARD32>(time(nullptr)),
|
||||
.root = g_root.windowId,
|
||||
.event = wid,
|
||||
.child = static_cast<CARD32>(child_wid == wid ? None : child_wid),
|
||||
.rootX = static_cast<INT16>(root_x),
|
||||
.rootY = static_cast<INT16>(root_y),
|
||||
.rootX = static_cast<INT16>(root_x + event_x),
|
||||
.rootY = static_cast<INT16>(root_y + event_y),
|
||||
.eventX = static_cast<INT16>(event_x),
|
||||
.eventY = static_cast<INT16>(event_y),
|
||||
.state = state,
|
||||
@@ -389,14 +406,15 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
const auto [root_x, root_y] = get_window_position(wid);
|
||||
xEvent event { .u = {
|
||||
.enterLeave = {
|
||||
.time = static_cast<CARD32>(time(nullptr)),
|
||||
.root = g_root.windowId,
|
||||
.event = wid,
|
||||
.child = first ? static_cast<WINDOW>(None) : old_child_path.back(),
|
||||
.rootX = static_cast<INT16>(old_x),
|
||||
.rootY = static_cast<INT16>(old_y),
|
||||
.rootX = static_cast<INT16>(root_x + old_x),
|
||||
.rootY = static_cast<INT16>(root_y + old_y),
|
||||
.eventX = static_cast<INT16>(old_x),
|
||||
.eventY = static_cast<INT16>(old_y),
|
||||
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||
@@ -429,14 +447,15 @@ static void send_enter_and_leave_events(WINDOW old_wid, int32_t old_x, int32_t o
|
||||
ASSERT(object.type == Object::Type::Window);
|
||||
auto& window = object.object.get<Object::Window>();
|
||||
|
||||
const auto [root_x, root_y] = get_window_position(wid);
|
||||
xEvent event { .u = {
|
||||
.enterLeave = {
|
||||
.time = static_cast<CARD32>(time(nullptr)),
|
||||
.root = g_root.windowId,
|
||||
.event = wid,
|
||||
.child = last ? static_cast<WINDOW>(None) : new_child_path.back(),
|
||||
.rootX = static_cast<INT16>(new_x),
|
||||
.rootY = static_cast<INT16>(new_y),
|
||||
.rootX = static_cast<INT16>(root_x + new_x),
|
||||
.rootY = static_cast<INT16>(root_y + new_y),
|
||||
.eventX = static_cast<INT16>(new_x),
|
||||
.eventY = static_cast<INT16>(new_y),
|
||||
.state = static_cast<KeyButMask>(g_keymask | g_butmask),
|
||||
|
||||
@@ -7,6 +7,7 @@ void unregister_event_fd(int fd);
|
||||
|
||||
void on_window_close_event(WINDOW wid);
|
||||
void on_window_resize_event(WINDOW wid, uint32_t width, uint32_t height);
|
||||
void on_window_move_event(WINDOW wid, int32_t x, int32_t y);
|
||||
void on_window_focus_event(WINDOW wid, bool focused);
|
||||
void on_window_fullscreen_event(WINDOW wid, bool is_fullscreen);
|
||||
void on_window_leave_event(WINDOW wid);
|
||||
|
||||
@@ -55,6 +55,8 @@ struct PlatformOps
|
||||
void (*invalidate)(PlatformWindow*, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
/* Request resize of a window, can be async */
|
||||
void (*request_resize)(PlatformWindow*, uint32_t width, uint32_t height);
|
||||
/* Request window repositioning */
|
||||
void (*request_reposition)(PlatformWindow*, int32_t x, int32_t y);
|
||||
/* Request new fullscreen state, can be async */
|
||||
void (*request_fullscreen)(PlatformWindow*, bool fullscreen);
|
||||
/* Create a system cursor */
|
||||
|
||||
@@ -138,7 +138,11 @@ static BAN::ErrorOr<BAN::UniqPtr<PlatformWindow>> sdl3_create_window(PlatformWin
|
||||
else
|
||||
{
|
||||
auto& sdl_parent = *static_cast<SDLWindow*>(parent);
|
||||
window->window = SDL_CreatePopupWindow(sdl_parent.window, x, y, width, height, flags | SDL_WINDOW_POPUP_MENU);
|
||||
|
||||
int parent_x, parent_y;
|
||||
SDL_GetWindowPosition(sdl_parent.window, &parent_x, &parent_y);
|
||||
|
||||
window->window = SDL_CreatePopupWindow(sdl_parent.window, x - parent_x, y - parent_y, width, height, flags | SDL_WINDOW_POPUP_MENU);
|
||||
}
|
||||
|
||||
if (window->window == nullptr)
|
||||
@@ -172,6 +176,12 @@ static void sdl3_request_resize(PlatformWindow* window, uint32_t width, uint32_t
|
||||
SDL_SetWindowSize(sdl_window.window, width, height);
|
||||
}
|
||||
|
||||
static void sdl3_request_reposition(PlatformWindow* window, int32_t x, int32_t y)
|
||||
{
|
||||
auto& sdl_window = *static_cast<SDLWindow*>(window);
|
||||
SDL_SetWindowPosition(sdl_window.window, x, y);
|
||||
}
|
||||
|
||||
static void sdl3_poll_events(void*)
|
||||
{
|
||||
uint64_t dummy;
|
||||
@@ -200,6 +210,10 @@ static void sdl3_poll_events(void*)
|
||||
on_window_resize_event(window.wid, window.width, window.height);
|
||||
}
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||
on_window_move_event(it->value->wid, event.window.data1, event.window.data2);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
if (auto it = s_window_map.find(event.motion.windowID); it != s_window_map.end())
|
||||
@@ -398,6 +412,7 @@ PlatformOps g_platform_ops = {
|
||||
.create_window = sdl3_create_window,
|
||||
.invalidate = sdl3_invalidate,
|
||||
.request_resize = sdl3_request_resize,
|
||||
.request_reposition = sdl3_request_reposition,
|
||||
.request_fullscreen = sdl3_request_fullscreen,
|
||||
.create_system_cursor = sdl3_create_system_cursor,
|
||||
.create_bitmap_cursor = sdl3_create_bitmap_cursor,
|
||||
|
||||
@@ -120,6 +120,13 @@ static void bananos_request_resize(PlatformWindow* window, uint32_t width, uint3
|
||||
banan_window.window->request_resize(width, height);
|
||||
}
|
||||
|
||||
static void bananos_request_reposition(PlatformWindow* window, int32_t x, int32_t y)
|
||||
{
|
||||
(void)window;
|
||||
(void)x;
|
||||
(void)y;
|
||||
}
|
||||
|
||||
static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||
@@ -134,6 +141,12 @@ static void bananos_invalidate(PlatformWindow* window, const uint32_t* pixels, u
|
||||
banan_window.window->invalidate(x, y, width, height);
|
||||
}
|
||||
|
||||
static void bananos_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||
{
|
||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||
banan_window.window->set_fullscreen(fullscreen);
|
||||
}
|
||||
|
||||
static BAN::ErrorOr<BAN::UniqPtr<PlatformCursor>> bananos_create_system_cursor(SystemCursorType type)
|
||||
{
|
||||
(void)type;
|
||||
@@ -169,18 +182,13 @@ static void bananos_set_cursor(PlatformWindow* window, PlatformCursor* cursor)
|
||||
}
|
||||
}
|
||||
|
||||
static void bananos_request_fullscreen(PlatformWindow* window, bool fullscreen)
|
||||
{
|
||||
auto& banan_window = *static_cast<BananWindow*>(window);
|
||||
banan_window.window->set_fullscreen(fullscreen);
|
||||
}
|
||||
|
||||
PlatformOps g_platform_ops = {
|
||||
.initialize = bananos_initialize,
|
||||
.poll_events = bananos_poll_events,
|
||||
.create_window = bananos_create_window,
|
||||
.invalidate = bananos_invalidate,
|
||||
.request_resize = bananos_request_resize,
|
||||
.request_reposition = bananos_request_reposition,
|
||||
.request_fullscreen = bananos_request_fullscreen,
|
||||
.create_system_cursor = bananos_create_system_cursor,
|
||||
.create_bitmap_cursor = bananos_create_bitmap_cursor,
|
||||
|
||||
Reference in New Issue
Block a user