diff --git a/LibGUI/Window.cpp b/LibGUI/Window.cpp index 815c3f2..17370ef 100644 --- a/LibGUI/Window.cpp +++ b/LibGUI/Window.cpp @@ -201,11 +201,13 @@ namespace LibGUI set_attributes(attributes); } - void Window::set_cursor(uint32_t width, uint32_t height, BAN::Span pixels) + void Window::set_cursor(uint32_t width, uint32_t height, BAN::Span pixels, int32_t origin_x, int32_t origin_y) { WindowPacket::WindowSetCursor packet; packet.width = width; packet.height = height; + packet.origin_x = origin_x; + packet.origin_y = origin_y; MUST(packet.pixels.resize(pixels.size())); for (size_t i = 0; i < packet.pixels.size(); i++) packet.pixels[i] = pixels[i]; diff --git a/LibGUI/include/LibGUI/Packet.h b/LibGUI/include/LibGUI/Packet.h index 60ce044..c0e721a 100644 --- a/LibGUI/include/LibGUI/Packet.h +++ b/LibGUI/include/LibGUI/Packet.h @@ -15,6 +15,7 @@ #define FOR_EACH_4(macro, type, name, ...) macro(type, name) FOR_EACH_2(macro, __VA_ARGS__) #define FOR_EACH_6(macro, type, name, ...) macro(type, name) FOR_EACH_4(macro, __VA_ARGS__) #define FOR_EACH_8(macro, type, name, ...) macro(type, name) FOR_EACH_6(macro, __VA_ARGS__) +#define FOR_EACH_10(macro, type, name, ...) macro(type, name) FOR_EACH_8(macro, __VA_ARGS__) #define CONCATENATE_2(arg1, arg2) arg1 ## arg2 #define CONCATENATE_1(arg1, arg2) CONCATENATE_2(arg1, arg2) @@ -22,8 +23,8 @@ #define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__ __VA_OPT__(,) FOR_EACH_RSEQ_N()) #define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__) -#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N -#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define FOR_EACH_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what __VA_OPT__(,) __VA_ARGS__) #define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what __VA_OPT__(,) __VA_ARGS__) @@ -303,6 +304,8 @@ namespace LibGUI WindowSetCursor, uint32_t, width, uint32_t, height, + int32_t, origin_x, + int32_t, origin_y, BAN::Vector, pixels ); diff --git a/LibGUI/include/LibGUI/Window.h b/LibGUI/include/LibGUI/Window.h index 5d99539..1a31c4c 100644 --- a/LibGUI/include/LibGUI/Window.h +++ b/LibGUI/include/LibGUI/Window.h @@ -50,7 +50,7 @@ namespace LibGUI void set_position(int32_t x, int32_t y); void set_cursor_visible(bool visible); - void set_cursor(uint32_t width, uint32_t height, BAN::Span pixels); + void set_cursor(uint32_t width, uint32_t height, BAN::Span pixels, int32_t origin_x = 0, int32_t origin_y = 0); Attributes get_attributes() const { return m_attributes; } void set_attributes(Attributes attributes); diff --git a/WindowServer/Window.h b/WindowServer/Window.h index 00ecca9..c237ce4 100644 --- a/WindowServer/Window.h +++ b/WindowServer/Window.h @@ -16,6 +16,8 @@ public: { uint32_t width; uint32_t height; + int32_t origin_x; + int32_t origin_y; BAN::Vector pixels; }; diff --git a/WindowServer/WindowServer.cpp b/WindowServer/WindowServer.cpp index edeb97d..a04204f 100644 --- a/WindowServer/WindowServer.cpp +++ b/WindowServer/WindowServer.cpp @@ -387,6 +387,8 @@ void WindowServer::on_window_set_cursor(int fd, const LibGUI::WindowPacket::Wind Window::Cursor cursor; cursor.width = packet.width; cursor.height = packet.height; + cursor.origin_x = packet.origin_x; + cursor.origin_y = packet.origin_y; if (auto ret = cursor.pixels.resize(packet.pixels.size()); ret.is_error()) { dwarnln("failed to set cursor: {}", ret.error()); @@ -1179,12 +1181,15 @@ void WindowServer::invalidate_impl(Rectangle area) { if (const auto overlap = cursor_area().get_overlap(area); overlap.has_value()) { + const int32_t origin_x = window_cursor ? window_cursor->origin_x : 0; + const int32_t origin_y = window_cursor ? window_cursor->origin_y : 0; + for (int32_t y_off = 0; y_off < overlap->height; y_off++) { for (int32_t x_off = 0; x_off < overlap->width; x_off++) { - const int32_t rel_x = overlap->x - m_cursor.x + x_off; - const int32_t rel_y = overlap->y - m_cursor.y + y_off; + const int32_t rel_x = overlap->x - m_cursor.x + x_off + origin_x; + const int32_t rel_y = overlap->y - m_cursor.y + y_off + origin_y; const auto pixel = get_cursor_pixel(rel_x, rel_y); if (pixel.has_value()) m_framebuffer.pixels[(overlap->y + y_off) * m_framebuffer.width + (overlap->x + x_off)] = pixel.value(); @@ -1248,6 +1253,9 @@ Rectangle WindowServer::cursor_area() const int32_t width = s_default_cursor_width; int32_t height = s_default_cursor_height; + int32_t origin_x = 0; + int32_t origin_y = 0; + if (auto window = find_hovered_window()) { if (!window->get_attributes().cursor_visible) @@ -1256,10 +1264,12 @@ Rectangle WindowServer::cursor_area() const { width = window->cursor().width; height = window->cursor().height; + origin_x = window->cursor().origin_x; + origin_y = window->cursor().origin_y; } } - return { m_cursor.x, m_cursor.y, width, height }; + return { m_cursor.x - origin_x, m_cursor.y - origin_y, width, height }; } Rectangle WindowServer::resize_area(Position cursor) const