From 6c6e5e02b50d4c1855981f6bd8df71754f71db40 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Wed, 4 May 2022 15:37:27 +0900 Subject: [PATCH 1/1] ds_output: Add ds_output_set_custom_mode Change-Id: Ie55a79f11a1450bae3ff6d83bb735c854459f050 --- include/libds/interfaces/output.h | 14 ++++++++++++ include/libds/output.h | 4 ++++ src/examples/tinyds.c | 2 ++ src/libds/backend/wayland/output.c | 19 ++++++++++++++++ src/libds/backend/wayland/seat.c | 7 ++++-- src/libds/output.c | 45 ++++++++++++++++++++++++++++++++++++-- src/libds/output.h | 11 ++++++++++ 7 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/libds/output.h diff --git a/include/libds/interfaces/output.h b/include/libds/interfaces/output.h index 6fb2909..53a4e0c 100644 --- a/include/libds/interfaces/output.h +++ b/include/libds/interfaces/output.h @@ -23,6 +23,12 @@ enum ds_output_state_field DS_OUTPUT_STATE_TRANSFORM = 1 << 5, }; +enum ds_output_state_mode_type +{ + DS_OUTPUT_STATE_MODE_FIXED, + DS_OUTPUT_STATE_MODE_CUSTOM, +}; + struct ds_output_interface { void (*destroy)(struct ds_output *output); @@ -33,7 +39,13 @@ struct ds_output_state { enum ds_output_state_field committed; struct ds_buffer *buffer; + + enum ds_output_state_mode_type mode_type; const struct ds_output_mode *mode; + struct { + int32_t width, height; + int32_t refresh; // mHz, may be zero + } custom_mode; bool enabled; }; @@ -49,6 +61,8 @@ struct ds_output struct ds_buffer *back_buffer, *front_buffer; const struct ds_output_mode *current_mode; + int32_t width, height; + int32_t refresh; // mHz, may be zero struct ds_output_state pending; struct wl_list modes; diff --git a/include/libds/output.h b/include/libds/output.h index cae9f7f..5cf1fce 100644 --- a/include/libds/output.h +++ b/include/libds/output.h @@ -40,6 +40,10 @@ ds_output_set_mode(struct ds_output *output, const struct ds_output_mode *mode); void +ds_output_set_custom_mode(struct ds_output *output, + int32_t width, int32_t height, int32_t refresh); + +void ds_output_add_destroy_listener(struct ds_output *output, struct wl_listener *listener); diff --git a/src/examples/tinyds.c b/src/examples/tinyds.c index e054e71..64612a6 100644 --- a/src/examples/tinyds.c +++ b/src/examples/tinyds.c @@ -588,6 +588,8 @@ output_init(struct tinyds_output *output, struct tinyds_server *server, output->height = height; output->drawable = true; + ds_output_set_custom_mode(ds_output, OUTPUT_WIDTH, OUTPUT_HEIGHT, 0); + output->allocator = ds_shm_allocator_create(); if (!output->allocator) return false; diff --git a/src/libds/backend/wayland/output.c b/src/libds/backend/wayland/output.c index c57820f..7728abf 100644 --- a/src/libds/backend/wayland/output.c +++ b/src/libds/backend/wayland/output.c @@ -7,6 +7,7 @@ #include "libds/output.h" #include "xdg-shell-client-protocol.h" +#include "output.h" #include "backend.h" const struct ds_output_interface wl_output_iface; @@ -14,6 +15,8 @@ static const struct xdg_surface_listener wl_output_xdg_surface_listener; static const struct xdg_toplevel_listener wl_output_xdg_toplevel_listener; static void output_update_cursor(struct ds_wl_output *output); +static bool output_set_custom_mode(struct ds_output *ds_output, + int32_t width, int32_t height, int32_t refresh); struct ds_output * ds_wl_backend_create_output(struct ds_backend *ds_backend) @@ -286,6 +289,14 @@ wl_output_iface_commit(struct ds_output *ds_output) output = wl_output_from_output(ds_output); + if (ds_output->pending.committed & DS_OUTPUT_STATE_MODE) { + if (!output_set_custom_mode(ds_output, + ds_output->pending.custom_mode.width, + ds_output->pending.custom_mode.height, + ds_output->pending.custom_mode.refresh)) + return false; + } + ds_buffer = ds_output->pending.buffer; buffer = get_or_create_wl_buffer(output->backend, ds_buffer); if (!buffer) @@ -355,3 +366,11 @@ static const struct xdg_toplevel_listener wl_output_xdg_toplevel_listener = .configure = wl_output_xdg_toplevel_handle_configure, .close = wl_output_xdg_toplevel_handle_close, }; + +static bool output_set_custom_mode(struct ds_output *ds_output, + int32_t width, int32_t height, int32_t refresh) +{ + ds_output_update_custom_mode(ds_output, width, height, 0); + + return true; +} diff --git a/src/libds/backend/wayland/seat.c b/src/libds/backend/wayland/seat.c index 6948efc..bec12ad 100644 --- a/src/libds/backend/wayland/seat.c +++ b/src/libds/backend/wayland/seat.c @@ -313,16 +313,19 @@ pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) { struct ds_wl_seat *seat = data; + struct ds_output *ds_output; if (!seat->output) return; + ds_output = &seat->output->base; + // FIXME take size size of a output into account struct ds_event_pointer_motion_absolute event = { .device = seat->pointer_dev, .time_msec = time, - .x = wl_fixed_to_double(sx) / 700, - .y = wl_fixed_to_double(sy) / 400, + .x = wl_fixed_to_double(sx) / ds_output->width, + .y = wl_fixed_to_double(sy) / ds_output->height, }; wl_signal_emit(&seat->pointer_dev->pointer->events.motion_absolute, diff --git a/src/libds/output.c b/src/libds/output.c index bc286f7..d5af56e 100644 --- a/src/libds/output.c +++ b/src/libds/output.c @@ -10,6 +10,7 @@ static void output_handle_display_destroy(struct wl_listener *listener, static void output_enable(struct ds_output *output, bool enable); static void output_state_clear(struct ds_output_state *state); static void output_state_clear_buffer(struct ds_output_state *state); +static void output_state_clear_mode(struct ds_output_state *state); WL_EXPORT void ds_output_init(struct ds_output *output, struct ds_backend *backend, @@ -100,18 +101,35 @@ ds_output_get_preferred_mode(struct ds_output *output) WL_EXPORT void ds_output_set_mode(struct ds_output *output, const struct ds_output_mode *mode) { - output->pending.mode = NULL; - output->pending.committed &= ~DS_OUTPUT_STATE_MODE; + output_state_clear_mode(&output->pending); if (output->current_mode == mode) { return; } output->pending.committed |= DS_OUTPUT_STATE_MODE; + output->pending.mode_type = DS_OUTPUT_STATE_MODE_FIXED; output->pending.mode = mode; } WL_EXPORT void +ds_output_set_custom_mode(struct ds_output *output, + int32_t width, int32_t height, int32_t refresh) +{ + output_state_clear_mode(&output->pending); + + if (output->width == width && output->height == height && + output->refresh == refresh) + return; + + output->pending.committed |= DS_OUTPUT_STATE_MODE; + output->pending.mode_type = DS_OUTPUT_STATE_MODE_CUSTOM; + output->pending.custom_mode.width = width; + output->pending.custom_mode.height = height; + output->pending.custom_mode.refresh = refresh; +} + +WL_EXPORT void ds_output_add_destroy_listener(struct ds_output *output, struct wl_listener *listener) { @@ -132,6 +150,19 @@ ds_output_add_commit_listener(struct ds_output *output, wl_signal_add(&output->events.commit, listener); } +void +ds_output_update_custom_mode(struct ds_output *output, + int32_t width, int32_t height, int32_t refresh) +{ + if (output->width == width && output->height == height && + output->refresh == refresh) + return; + + output->width = width; + output->height = height; + output->refresh = refresh; +} + static void output_handle_display_destroy(struct wl_listener *listener, void *data) { @@ -172,3 +203,13 @@ output_enable(struct ds_output *output, bool enable) output->pending.committed |= DS_OUTPUT_STATE_ENABLED; output->pending.enabled = enable; } + +static void +output_state_clear_mode(struct ds_output_state *state) +{ + if (!(state->committed & DS_OUTPUT_STATE_MODE)) + return; + + state->mode = NULL; + state->committed &= ~DS_OUTPUT_STATE_MODE; +} diff --git a/src/libds/output.h b/src/libds/output.h new file mode 100644 index 0000000..edf4560 --- /dev/null +++ b/src/libds/output.h @@ -0,0 +1,11 @@ +#ifndef DS_OUTPUT_H +#define DS_OUTPUT_H + +#include + +#include "libds/output.h" + +void ds_output_update_custom_mode(struct ds_output *output, + int32_t width, int32_t height, int32_t refresh); + +#endif -- 2.7.4