diff --git a/backend/drm/drm.c b/backend/drm/drm.c index c040d0798..3426cb276 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -540,6 +540,30 @@ bool drm_connector_supports_vrr(struct wlr_drm_connector *conn) { return true; } +static int32_t drm_connector_get_suggested_x(struct wlr_drm_connector *conn) { + struct wlr_drm_backend *drm = conn->backend; + + uint64_t suggested_x; + if (conn->props.suggested_x == 0 || + !get_drm_prop(drm->fd, conn->id, conn->props.suggested_x, &suggested_x)) { + return -1; + } + + return suggested_x; +} + +static int32_t drm_connector_get_suggested_y(struct wlr_drm_connector *conn) { + struct wlr_drm_backend *drm = conn->backend; + + uint64_t suggested_y; + if (conn->props.suggested_y == 0 || + !get_drm_prop(drm->fd, conn->id, conn->props.suggested_y, &suggested_y)) { + return -1; + } + + return suggested_y; +} + static bool drm_connector_commit(struct wlr_output *output) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); struct wlr_drm_backend *drm = conn->backend; @@ -1315,6 +1339,25 @@ static bool update_modes(drmModeConnector *drm_conn, return changes_made; } +static bool update_suggested_position(struct wlr_drm_connector *wlr_conn) { + int32_t suggested_x = drm_connector_get_suggested_x(wlr_conn); + int32_t suggested_y = drm_connector_get_suggested_y(wlr_conn); + + bool position_changed = false; + + if (suggested_x != wlr_conn->output.suggested_x) { + position_changed = true; + wlr_conn->output.suggested_x = suggested_x; + } + + if (suggested_y != wlr_conn->output.suggested_y) { + position_changed = true; + wlr_conn->output.suggested_y = suggested_y; + } + + return position_changed; +} + void scan_drm_connectors(struct wlr_drm_backend *drm) { /* * This GPU is not really a modesetting device. @@ -1423,6 +1466,10 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { if (update_modes(drm_conn, wlr_conn)) { wlr_output_update_available_modes(&wlr_conn->output); } + + if (update_suggested_position(wlr_conn)) { + wlr_output_update_suggested_position(&wlr_conn->output); + } } if (wlr_conn->state == WLR_DRM_CONN_DISCONNECTED && @@ -1458,6 +1505,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) { wlr_output_set_description(output, description); update_modes(drm_conn, wlr_conn); + update_suggested_position(wlr_conn); wlr_conn->possible_crtcs = get_possible_crtcs(drm->fd, res, drm_conn); if (wlr_conn->possible_crtcs == 0) { diff --git a/backend/drm/properties.c b/backend/drm/properties.c index de51a3dea..d9dbf06bc 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -25,6 +25,8 @@ static const struct prop_info connector_info[] = { { "PATH", INDEX(path) }, { "link-status", INDEX(link_status) }, { "vrr_capable", INDEX(vrr_capable) }, + { "suggested X", INDEX(suggested_x) }, + { "suggested Y", INDEX(suggested_y) }, #undef INDEX }; diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index c2027c4f3..29df1b4b2 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -17,6 +17,8 @@ union wlr_drm_connector_props { uint32_t link_status; // not guaranteed to exist uint32_t path; uint32_t vrr_capable; // not guaranteed to exist + uint32_t suggested_x; + uint32_t suggested_y; // atomic-modesetting only diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 696c2c77f..f3aefc381 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -116,6 +116,13 @@ void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width, * to notify compositors about the change. */ void wlr_output_update_available_modes(struct wlr_output *output); +/** + * Update the output suggested position. + * + * The backend must call this function when the suggested position is updated + * to notify compositors about the change. + */ +void wlr_output_update_suggested_position (struct wlr_output *output); /** * Update the current output status. * diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 1d819aee5..057c479d3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -128,6 +128,7 @@ struct wlr_output { char model[16]; char serial[16]; int32_t phys_width, phys_height; // mm + int32_t suggested_x, suggested_y; // Note: some backends may have zero modes struct wl_list modes; // wlr_output_mode::link @@ -171,6 +172,7 @@ struct wlr_output { struct wl_signal enable; struct wl_signal mode; struct wl_signal available_modes; + struct wl_signal suggested_position; struct wl_signal scale; struct wl_signal transform; struct wl_signal description; diff --git a/types/wlr_output.c b/types/wlr_output.c index d200ac8ac..dbbc7d164 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -263,6 +263,10 @@ void wlr_output_update_available_modes(struct wlr_output *output) { wlr_signal_emit_safe(&output->events.available_modes, output); } +void wlr_output_update_suggested_position (struct wlr_output *output) { + wlr_signal_emit_safe(&output->events.suggested_position, output); +} + void wlr_output_set_transform(struct wlr_output *output, enum wl_output_transform transform) { if (output->transform == transform) { @@ -381,6 +385,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.enable); wl_signal_init(&output->events.mode); wl_signal_init(&output->events.available_modes); + wl_signal_init(&output->events.suggested_position); wl_signal_init(&output->events.scale); wl_signal_init(&output->events.transform); wl_signal_init(&output->events.description);