diff --git a/backend/wayland/output.c b/backend/wayland/output.c index c4301617..f6182dcd 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -28,6 +28,15 @@ static struct wl_callback_listener frame_listener = { .done = surface_frame_callback }; +static bool wlr_wl_output_set_custom_mode(struct wlr_output *_output, + int32_t width, int32_t height, int32_t refresh) { + struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; + wl_egl_window_resize(output->egl_window, width, height, 0, 0); + wlr_output_update_size(&output->wlr_output, width, height); + wl_signal_emit(&output->wlr_output.events.resolution, output); + return true; +} + static void wlr_wl_output_make_current(struct wlr_output *_output) { struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; if (!eglMakeCurrent(output->backend->egl.display, @@ -185,6 +194,7 @@ bool wlr_wl_output_move_cursor(struct wlr_output *_output, int x, int y) { } static struct wlr_output_impl output_impl = { + .set_custom_mode = wlr_wl_output_set_custom_mode, .transform = wlr_wl_output_transform, .destroy = wlr_wl_output_destroy, .make_current = wlr_wl_output_make_current, diff --git a/backend/x11/backend.c b/backend/x11/backend.c index b798daf6..5fb54ffd 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -267,8 +267,8 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) { snprintf(output->wlr_output.name, sizeof(output->wlr_output.name), "X11-1"); output->win = xcb_generate_id(x11->xcb_conn); - xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win, x11->screen->root, - 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, + xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win, + x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values); output->surf = wlr_egl_create_surface(&x11->egl, &output->win); @@ -329,6 +329,17 @@ static struct wlr_backend_impl backend_impl = { .get_egl = wlr_x11_backend_get_egl, }; +static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width, + int32_t height, int32_t refresh) { + struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; + struct wlr_x11_backend *x11 = output->x11; + + const uint32_t values[] = { width, height }; + xcb_configure_window(x11->xcb_conn, output->win, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + return true; +} + static void output_transform(struct wlr_output *wlr_output, enum wl_output_transform transform) { struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; output->wlr_output.transform = transform; @@ -362,6 +373,7 @@ static void output_swap_buffers(struct wlr_output *wlr_output) { } static struct wlr_output_impl output_impl = { + .set_custom_mode = output_set_custom_mode, .transform = output_transform, .destroy = output_destroy, .make_current = output_make_current, diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index b4f39d35..dc2a867b 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -9,6 +9,8 @@ struct wlr_output_impl { void (*enable)(struct wlr_output *output, bool enable); bool (*set_mode)(struct wlr_output *output, struct wlr_output_mode *mode); + bool (*set_custom_mode)(struct wlr_output *output, int32_t width, + int32_t height, int32_t refresh); void (*transform)(struct wlr_output *output, enum wl_output_transform transform); bool (*set_cursor)(struct wlr_output *output, const uint8_t *buf, diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 895536e1..7f681ab7 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -83,6 +83,8 @@ struct wlr_surface; void wlr_output_enable(struct wlr_output *output, bool enable); bool wlr_output_set_mode(struct wlr_output *output, struct wlr_output_mode *mode); +bool wlr_output_set_custom_mode(struct wlr_output *output, int32_t width, + int32_t height, int32_t refresh); void wlr_output_transform(struct wlr_output *output, enum wl_output_transform transform); void wlr_output_set_position(struct wlr_output *output, int32_t lx, int32_t ly); diff --git a/rootston/output.c b/rootston/output.c index cf2ffdc3..b2d6554d 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -263,8 +263,15 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { static void set_mode(struct wlr_output *output, struct roots_output_config *oc) { - struct wlr_output_mode *mode, *best = NULL; int mhz = (int)(oc->mode.refresh_rate * 1000); + + if (wl_list_empty(&output->modes)) { + // Output has no mode, try setting a custom one + wlr_output_set_custom_mode(output, oc->mode.width, oc->mode.height, mhz); + return; + } + + struct wlr_output_mode *mode, *best = NULL; wl_list_for_each(mode, &output->modes, link) { if (mode->width == oc->mode.width && mode->height == oc->mode.height) { if (mode->refresh == mhz) { diff --git a/types/wlr_output.c b/types/wlr_output.c index f4ae7aaa..adade238 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -164,6 +164,23 @@ bool wlr_output_set_mode(struct wlr_output *output, return result; } +bool wlr_output_set_custom_mode(struct wlr_output *output, int32_t width, + int32_t height, int32_t refresh) { + if (!output->impl || !output->impl->set_custom_mode) { + return false; + } + bool result = output->impl->set_custom_mode(output, width, height, refresh); + if (result) { + wlr_output_update_matrix(output); + + struct wl_resource *resource; + wl_resource_for_each(resource, &output->wl_resources) { + wlr_output_send_current_mode_to_resource(resource); + } + } + return result; +} + void wlr_output_update_size(struct wlr_output *output, int32_t width, int32_t height) { if (output->width == width && output->height == height) {