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);
{
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;
};
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;
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);
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;
#include "libds/output.h"
#include "xdg-shell-client-protocol.h"
+#include "output.h"
#include "backend.h"
const struct ds_output_interface wl_output_iface;
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)
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)
.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;
+}
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,
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,
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)
{
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)
{
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;
+}
--- /dev/null
+#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