ds_output: Add ds_output_set_custom_mode 84/278184/1
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 4 May 2022 06:37:27 +0000 (15:37 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 18 Jul 2022 05:58:35 +0000 (14:58 +0900)
Change-Id: Ie55a79f11a1450bae3ff6d83bb735c854459f050

include/libds/interfaces/output.h
include/libds/output.h
src/examples/tinyds.c
src/libds/backend/wayland/output.c
src/libds/backend/wayland/seat.c
src/libds/output.c
src/libds/output.h [new file with mode: 0644]

index 6fb2909..53a4e0c 100644 (file)
@@ -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;
index cae9f7f..5cf1fce 100644 (file)
@@ -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);
 
index e054e71..64612a6 100644 (file)
@@ -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;
index c57820f..7728abf 100644 (file)
@@ -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;
+}
index 6948efc..bec12ad 100644 (file)
@@ -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,
index bc286f7..d5af56e 100644 (file)
@@ -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 (file)
index 0000000..edf4560
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef DS_OUTPUT_H
+#define DS_OUTPUT_H
+
+#include <stdint.h>
+
+#include "libds/output.h"
+
+void ds_output_update_custom_mode(struct ds_output *output,
+        int32_t width, int32_t height, int32_t refresh);
+
+#endif