diff --git a/Backends/System/Linux/Sources/kinc/backend/wayland/system.c.h b/Backends/System/Linux/Sources/kinc/backend/wayland/system.c.h index 1498cfd64..2fb161af6 100644 --- a/Backends/System/Linux/Sources/kinc/backend/wayland/system.c.h +++ b/Backends/System/Linux/Sources/kinc/backend/wayland/system.c.h @@ -1,3 +1,5 @@ +#include "kinc/math/core.h" +#include "wayland-generated/wayland-fractional-scale.h" #include "wayland.h" #include @@ -280,7 +282,7 @@ void wl_pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_ case KINC_WL_DECORATION_FOCUS_BOTTOM: if (x < 10) cursor_name = "sw-resize"; - else if (x > window->width + 10) + else if (x > window->surface_width + 10) cursor_name = "se-resize"; else cursor_name = "s-resize"; @@ -942,7 +944,7 @@ static const struct zwp_tablet_seat_v2_listener zwp_tablet_seat_v2_listener = { static void wl_registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { if (strcmp(interface, wl_compositor_interface.name) == 0) { - wl_ctx.compositor = wl_registry_bind(wl_ctx.registry, name, &wl_compositor_interface, 4); + wl_ctx.compositor = wl_registry_bind(wl_ctx.registry, name, &wl_compositor_interface, kinc_mini(version, 6)); } else if (strcmp(interface, wl_shm_interface.name) == 0) { wl_ctx.shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); @@ -1012,6 +1014,8 @@ static void wl_registry_handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zwp_relative_pointer_manager_v1_interface.name) == 0) { wl_ctx.relative_pointer_manager = wl_registry_bind(registry, name, &zwp_relative_pointer_manager_v1_interface, 1); + } else if(strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { + wl_ctx.fractional_scale_manager = wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1); } } diff --git a/Backends/System/Linux/Sources/kinc/backend/wayland/wayland.h b/Backends/System/Linux/Sources/kinc/backend/wayland/wayland.h index 83498c086..b8bead14f 100644 --- a/Backends/System/Linux/Sources/kinc/backend/wayland/wayland.h +++ b/Backends/System/Linux/Sources/kinc/backend/wayland/wayland.h @@ -93,6 +93,7 @@ struct kinc_wl_procs { extern struct kinc_wl_procs wl; #include +#include #include #include #include @@ -150,25 +151,25 @@ enum kinc_wl_decoration_focus { #define KINC_WL_DECORATION_TOP_X 0 #define KINC_WL_DECORATION_TOP_Y -(KINC_WL_DECORATION_TOP_HEIGHT) -#define KINC_WL_DECORATION_TOP_WIDTH window->width +#define KINC_WL_DECORATION_TOP_WIDTH window->surface_width #define KINC_WL_DECORATION_TOP_HEIGHT KINC_WL_DECORATION_WIDTH * 3 #define KINC_WL_DECORATION_LEFT_X -10 #define KINC_WL_DECORATION_LEFT_Y -(KINC_WL_DECORATION_TOP_HEIGHT) #define KINC_WL_DECORATION_LEFT_WIDTH KINC_WL_DECORATION_WIDTH -#define KINC_WL_DECORATION_LEFT_HEIGHT window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT +#define KINC_WL_DECORATION_LEFT_HEIGHT window->surface_height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT -#define KINC_WL_DECORATION_RIGHT_X window->width +#define KINC_WL_DECORATION_RIGHT_X window->surface_width #define KINC_WL_DECORATION_RIGHT_Y -(KINC_WL_DECORATION_TOP_HEIGHT) #define KINC_WL_DECORATION_RIGHT_WIDTH 10 -#define KINC_WL_DECORATION_RIGHT_HEIGHT window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT +#define KINC_WL_DECORATION_RIGHT_HEIGHT window->surface_height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT #define KINC_WL_DECORATION_BOTTOM_X 0 -#define KINC_WL_DECORATION_BOTTOM_Y window->height -#define KINC_WL_DECORATION_BOTTOM_WIDTH window->width +#define KINC_WL_DECORATION_BOTTOM_Y window->surface_height +#define KINC_WL_DECORATION_BOTTOM_WIDTH window->surface_width #define KINC_WL_DECORATION_BOTTOM_HEIGHT KINC_WL_DECORATION_WIDTH -#define KINC_WL_DECORATION_CLOSE_X window->width - 10 +#define KINC_WL_DECORATION_CLOSE_X window->surface_width - 10 #define KINC_WL_DECORATION_CLOSE_Y -20 #define KINC_WL_DECORATION_CLOSE_WIDTH 9 #define KINC_WL_DECORATION_CLOSE_HEIGHT 9 @@ -176,13 +177,21 @@ enum kinc_wl_decoration_focus { struct kinc_wl_window { int display_index; int window_id; - int width; - int height; + int surface_width; + int surface_height; + + int buffer_width; + int buffer_height; + kinc_window_mode_t mode; struct wl_surface *surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *toplevel; struct zxdg_toplevel_decoration_v1 *xdg_decoration; + struct wp_fractional_scale_v1 *fractional_scale; + struct wp_viewport *viewport; + + uint32_t preferred_scale; bool configured; @@ -347,6 +356,7 @@ struct wayland_context { struct zwp_tablet_manager_v2 *tablet_manager; struct zwp_pointer_constraints_v1 *pointer_constraints; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; + struct wp_fractional_scale_manager_v1 *fractional_scale_manager; struct wl_cursor_theme *cursor_theme; int cursor_size; int num_windows; diff --git a/Backends/System/Linux/Sources/kinc/backend/wayland/window.c.h b/Backends/System/Linux/Sources/kinc/backend/wayland/window.c.h index f63ec099a..3f6998051 100644 --- a/Backends/System/Linux/Sources/kinc/backend/wayland/window.c.h +++ b/Backends/System/Linux/Sources/kinc/backend/wayland/window.c.h @@ -2,6 +2,7 @@ #include #include +#include // for all that shared memory stuff later on #include @@ -27,17 +28,17 @@ void kinc_wayland_destroy_decoration(struct kinc_wl_decoration *); void kinc_wayland_resize_decoration(struct kinc_wl_decoration *, int x, int y, int width, int height); static void xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) { struct kinc_wl_window *window = data; - if ((width <= 0 || height <= 0) || (width == window->width + (KINC_WL_DECORATION_WIDTH * 2) && - height == window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT)) { - return; - } - if (window->decorations.server_side) { - window->width = width; - window->height = height; - } - else { - window->width = width - (KINC_WL_DECORATION_WIDTH * 2); - window->height = height - KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT; + if(width > 0 && height > 0) { + if (window->decorations.server_side) { + window->surface_width = width; + window->surface_height = height; + } + else { + window->surface_width = width - (KINC_WL_DECORATION_WIDTH * 2); + window->surface_height = height - KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT; + } + window->buffer_width = window->surface_width * window->preferred_scale / 120; + window->buffer_height = window->surface_height * window->preferred_scale / 120; } enum xdg_toplevel_state *state; @@ -54,30 +55,41 @@ static void xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *tople break; } } - kinc_internal_resize(window->window_id, window->width, window->height); - kinc_internal_call_resize_callback(window->window_id, window->width, window->height); - if (window->decorations.server_side) { - xdg_surface_set_window_geometry(window->xdg_surface, 0, 0, window->width, window->height); - } - else { - xdg_surface_set_window_geometry(window->xdg_surface, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_TOP_Y, - window->width + (KINC_WL_DECORATION_WIDTH * 2), - window->height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT); - } + + if (window->surface_width > 0 && window->surface_height > 0) { + if (window->decorations.server_side) { + xdg_surface_set_window_geometry(window->xdg_surface, 0, 0, window->surface_width, window->surface_height); + } + else { + xdg_surface_set_window_geometry(window->xdg_surface, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_TOP_Y, + window->surface_width + (KINC_WL_DECORATION_WIDTH * 2), + window->surface_height + KINC_WL_DECORATION_TOP_HEIGHT + KINC_WL_DECORATION_BOTTOM_HEIGHT); + } + if (window->viewport) { + wp_viewport_set_source(window->viewport, 0, 0, wl_fixed_from_int(window->buffer_width), wl_fixed_from_int(window->buffer_height)); + wp_viewport_set_destination(window->viewport, window->surface_width, window->surface_height); + } + else { + wl_surface_set_buffer_scale(window->surface, window->preferred_scale / 120); + } + + kinc_internal_resize(window->window_id, window->buffer_width, window->buffer_height); + kinc_internal_call_resize_callback(window->window_id, window->buffer_width, window->buffer_height); #ifdef KINC_EGL - wl_egl_window_resize(window->egl_window, window->width, window->height, 0, 0); + wl_egl_window_resize(window->egl_window, window->buffer_width, window->buffer_height, 0, 0); #endif - kinc_wayland_resize_decoration(&window->decorations.top, KINC_WL_DECORATION_TOP_X, KINC_WL_DECORATION_TOP_Y, KINC_WL_DECORATION_TOP_WIDTH, - KINC_WL_DECORATION_TOP_HEIGHT); - kinc_wayland_resize_decoration(&window->decorations.left, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_LEFT_Y, KINC_WL_DECORATION_LEFT_WIDTH, - KINC_WL_DECORATION_LEFT_HEIGHT); - kinc_wayland_resize_decoration(&window->decorations.right, KINC_WL_DECORATION_RIGHT_X, KINC_WL_DECORATION_RIGHT_Y, KINC_WL_DECORATION_RIGHT_WIDTH, - KINC_WL_DECORATION_RIGHT_HEIGHT); - kinc_wayland_resize_decoration(&window->decorations.bottom, KINC_WL_DECORATION_BOTTOM_X, KINC_WL_DECORATION_BOTTOM_Y, KINC_WL_DECORATION_BOTTOM_WIDTH, - KINC_WL_DECORATION_BOTTOM_HEIGHT); - kinc_wayland_resize_decoration(&window->decorations.close, KINC_WL_DECORATION_CLOSE_X, KINC_WL_DECORATION_CLOSE_Y, KINC_WL_DECORATION_CLOSE_WIDTH, - KINC_WL_DECORATION_CLOSE_HEIGHT); + kinc_wayland_resize_decoration(&window->decorations.top, KINC_WL_DECORATION_TOP_X, KINC_WL_DECORATION_TOP_Y, KINC_WL_DECORATION_TOP_WIDTH, + KINC_WL_DECORATION_TOP_HEIGHT); + kinc_wayland_resize_decoration(&window->decorations.left, KINC_WL_DECORATION_LEFT_X, KINC_WL_DECORATION_LEFT_Y, KINC_WL_DECORATION_LEFT_WIDTH, + KINC_WL_DECORATION_LEFT_HEIGHT); + kinc_wayland_resize_decoration(&window->decorations.right, KINC_WL_DECORATION_RIGHT_X, KINC_WL_DECORATION_RIGHT_Y, KINC_WL_DECORATION_RIGHT_WIDTH, + KINC_WL_DECORATION_RIGHT_HEIGHT); + kinc_wayland_resize_decoration(&window->decorations.bottom, KINC_WL_DECORATION_BOTTOM_X, KINC_WL_DECORATION_BOTTOM_Y, KINC_WL_DECORATION_BOTTOM_WIDTH, + KINC_WL_DECORATION_BOTTOM_HEIGHT); + kinc_wayland_resize_decoration(&window->decorations.close, KINC_WL_DECORATION_CLOSE_X, KINC_WL_DECORATION_CLOSE_Y, KINC_WL_DECORATION_CLOSE_WIDTH, + KINC_WL_DECORATION_CLOSE_HEIGHT); + } } void kinc_wayland_window_destroy(int window_index); @@ -301,9 +313,23 @@ void wl_surface_handle_enter(void *data, struct wl_surface *wl_surface, struct w void wl_surface_handle_leave(void *data, struct wl_surface *wl_surface, struct wl_output *output) {} +static void wl_surface_handle_preferred_buffer_scale(void *data, struct wl_surface *wl_surface, int32_t scale) { + struct kinc_wl_window *window = wl_surface_get_user_data(wl_surface); + if (!wl_ctx.fractional_scale_manager) { + window->preferred_scale = scale * 120; + } +} +static void wl_surface_handle_preferred_buffer_transform(void *data, struct wl_surface *wl_surface, uint32_t transform) {} + static const struct wl_surface_listener wl_surface_listener = { wl_surface_handle_enter, wl_surface_handle_leave, +#ifdef WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION + wl_surface_handle_preferred_buffer_scale, +#endif +#ifdef WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION + wl_surface_handle_preferred_buffer_transform, +#endif }; static const struct xdg_surface_listener xdg_surface_listener = { @@ -319,6 +345,15 @@ static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration xdg_toplevel_decoration_configure, }; +static void wp_fractional_scale_v1_handle_preferred_scale(void *data, struct wp_fractional_scale_v1 *fractional_scale, uint32_t scale) { + struct kinc_wl_window *window = data; + window->preferred_scale = scale; +} + +static const struct wp_fractional_scale_v1_listener wp_fractional_scale_v1_listener = { + wp_fractional_scale_v1_handle_preferred_scale, +}; + void kinc_wayland_window_set_title(int window_index, const char *title); void kinc_wayland_window_change_mode(int window_index, kinc_window_mode_t mode); @@ -331,26 +366,36 @@ int kinc_wayland_window_create(kinc_window_options_t *win, kinc_framebuffer_opti } } if (window_index == -1) { - kinc_log(KINC_LOG_LEVEL_ERROR, "Too much windows (maximum is %i)", MAXIMUM_WINDOWS); + kinc_log(KINC_LOG_LEVEL_ERROR, "Too many windows (maximum is %i)", MAXIMUM_WINDOWS); exit(1); } struct kinc_wl_window *window = &wl_ctx.windows[window_index]; window->window_id = window_index; - window->width = win->width; - window->height = win->height; - window->mode = KINC_WINDOW_MODE_WINDOW; + window->mode = -1; + window->preferred_scale = 120; window->surface = wl_compositor_create_surface(wl_ctx.compositor); wl_surface_set_user_data(window->surface, window); wl_surface_add_listener(window->surface, &wl_surface_listener, NULL); + if (wl_ctx.viewporter) { + window->viewport = wp_viewporter_get_viewport(wl_ctx.viewporter, window->surface); + } + + if (wl_ctx.fractional_scale_manager) { + if (!window->viewport) { + kinc_log(KINC_LOG_LEVEL_ERROR, "missing wp_viewport wayland extension"); + exit(1); + } + window->fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale(wl_ctx.fractional_scale_manager, window->surface); + wp_fractional_scale_v1_add_listener(window->fractional_scale, &wp_fractional_scale_v1_listener, window); + } + window->xdg_surface = xdg_wm_base_get_xdg_surface(wl_ctx.xdg_wm_base, window->surface); xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, window); window->toplevel = xdg_surface_get_toplevel(window->xdg_surface); xdg_toplevel_add_listener(window->toplevel, &xdg_toplevel_listener, window); - kinc_wayland_window_set_title(window_index, win->title); - if (wl_ctx.decoration_manager) { window->xdg_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(wl_ctx.decoration_manager, window->toplevel); #ifdef KINC_WAYLAND_FORCE_CSD @@ -360,20 +405,36 @@ int kinc_wayland_window_create(kinc_window_options_t *win, kinc_framebuffer_opti } else { window->decorations.server_side = false; - kinc_wayland_create_decorations(window); } -#ifdef KINC_EGL - window->egl_window = wl_egl_window_create(window->surface, window->width, window->height); -#endif wl_surface_commit(window->surface); - kinc_wayland_window_change_mode(window_index, win->mode); wl_ctx.num_windows++; while (!window->configured) { wl_display_roundtrip(wl_ctx.display); } + kinc_wayland_window_set_title(window_index, win->title); + kinc_wayland_window_change_mode(window_index, win->mode); + window->surface_width = (win->width * 120) / window->preferred_scale; + window->surface_height = (win->height * 120) / window->preferred_scale; + window->buffer_width = win->width; + window->buffer_height = win->height; + if (window->viewport) { + wp_viewport_set_source(window->viewport, 0, 0, wl_fixed_from_int(window->buffer_width), wl_fixed_from_int(window->buffer_height)); + wp_viewport_set_destination(window->viewport, window->surface_width, window->surface_height); + } else { + wl_surface_set_buffer_scale(window->surface, window->preferred_scale / 120); + } + xdg_surface_set_window_geometry(window->xdg_surface, 0, 0, window->surface_width, window->surface_height); + if(!window->decorations.server_side) { + kinc_wayland_create_decorations(window); + } + +#ifdef KINC_EGL + window->egl_window = wl_egl_window_create(window->surface, window->buffer_width, window->buffer_height); +#endif + wl_surface_commit(window->surface); return window_index; } @@ -413,11 +474,11 @@ void kinc_wayland_window_move(int window_index, int x, int y) { } int kinc_wayland_window_width(int window_index) { - return wl_ctx.windows[window_index].width; + return wl_ctx.windows[window_index].buffer_width; } int kinc_wayland_window_height(int window_index) { - return wl_ctx.windows[window_index].height; + return wl_ctx.windows[window_index].buffer_height; } void kinc_wayland_window_resize(int window_index, int width, int height) { diff --git a/kfile.js b/kfile.js index 4a5339ae6..ca3b65313 100644 --- a/kfile.js +++ b/kfile.js @@ -436,6 +436,7 @@ else if (platform === Platform.Linux || platform === Platform.FreeBSD) { wl_protocol('unstable/tablet/tablet-unstable-v2.xml', 'wayland-tablet'); wl_protocol('unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', 'wayland-pointer-constraint'); wl_protocol('unstable/relative-pointer/relative-pointer-unstable-v1.xml', 'wayland-relative-pointer'); + wl_protocol('staging/fractional-scale/fractional-scale-v1.xml', 'wayland-fractional-scale'); if (good_wayland) { let cfile = '#include "wayland-protocol.c.h"\n';