summaryrefslogtreecommitdiff
path: root/xserver/hw/xwayland/xwayland-output.c
diff options
context:
space:
mode:
Diffstat (limited to 'xserver/hw/xwayland/xwayland-output.c')
-rw-r--r--xserver/hw/xwayland/xwayland-output.c147
1 files changed, 130 insertions, 17 deletions
diff --git a/xserver/hw/xwayland/xwayland-output.c b/xserver/hw/xwayland/xwayland-output.c
index 5a0f739f3..cc68f0340 100644
--- a/xserver/hw/xwayland/xwayland-output.c
+++ b/xserver/hw/xwayland/xwayland-output.c
@@ -38,6 +38,8 @@
RR_Reflect_X | \
RR_Reflect_Y)
+static void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
+
static Rotation
wl_transform_to_xrandr(enum wl_output_transform transform)
{
@@ -93,9 +95,12 @@ output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
physical_width, physical_height);
RROutputSetSubpixelOrder(xwl_output->randr_output,
wl_subpixel_to_xrandr(subpixel));
- xwl_output->x = x;
- xwl_output->y = y;
+ /* Apply the change from wl_output only if xdg-output is not supported */
+ if (!xwl_output->xdg_output) {
+ xwl_output->x = x;
+ xwl_output->y = y;
+ }
xwl_output->rotation = wl_transform_to_xrandr(transform);
}
@@ -108,18 +113,22 @@ output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
if (!(flags & WL_OUTPUT_MODE_CURRENT))
return;
- xwl_output->width = width;
- xwl_output->height = height;
+ /* Apply the change from wl_output only if xdg-output is not supported */
+ if (!xwl_output->xdg_output) {
+ xwl_output->width = width;
+ xwl_output->height = height;
+ }
xwl_output->refresh = refresh;
}
static inline void
output_get_new_size(struct xwl_output *xwl_output,
+ Bool need_rotate,
int *height, int *width)
{
int output_width, output_height;
- if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
+ if (!need_rotate || (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180))) {
output_width = xwl_output->width;
output_height = xwl_output->height;
} else {
@@ -137,8 +146,9 @@ output_get_new_size(struct xwl_output *xwl_output,
/* Approximate some kind of mmpd (m.m. per dot) of the screen given the outputs
* associated with it.
*
- * It will either calculate the mean mmpd of all the outputs, or default to
- * 96 DPI if no reasonable value could be calculated.
+ * It either calculates the mean mmpd of all the outputs or, if no reasonable
+ * value could be calculated, defaults to the mmpd of a screen with a DPI value
+ * of DEFAULT_DPI.
*/
static double
approximate_mmpd(struct xwl_screen *xwl_screen)
@@ -199,14 +209,32 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
}
static void
-output_handle_done(void *data, struct wl_output *wl_output)
+apply_output_change(struct xwl_output *xwl_output)
{
- struct xwl_output *it, *xwl_output = data;
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+ struct xwl_output *it;
+ int mode_width, mode_height;
int width = 0, height = 0, has_this_output = 0;
RRModePtr randr_mode;
+ Bool need_rotate;
- randr_mode = xwayland_cvt(xwl_output->width, xwl_output->height,
+ /* Clear out the "done" received flags */
+ xwl_output->wl_output_done = FALSE;
+ xwl_output->xdg_output_done = FALSE;
+
+ /* xdg-output sends output size in compositor space. so already rotated */
+ need_rotate = (xwl_output->xdg_output == NULL);
+
+ /* We need to rotate back the logical size for the mode */
+ if (need_rotate || xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
+ mode_width = xwl_output->width;
+ mode_height = xwl_output->height;
+ } else {
+ mode_width = xwl_output->height;
+ mode_height = xwl_output->width;
+ }
+
+ randr_mode = xwayland_cvt(mode_width, mode_height,
xwl_output->refresh / 1000.0, 0, 0);
RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1);
RRCrtcNotify(xwl_output->randr_crtc, randr_mode,
@@ -221,14 +249,14 @@ output_handle_done(void *data, struct wl_output *wl_output)
if (it == xwl_output)
has_this_output = 1;
- output_get_new_size(it, &height, &width);
+ output_get_new_size(it, need_rotate, &height, &width);
}
if (!has_this_output) {
xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
/* we did not check this output for new screen size, do it now */
- output_get_new_size(xwl_output, &height, &width);
+ output_get_new_size(xwl_output, need_rotate, &height, &width);
--xwl_screen->expecting_event;
}
@@ -237,6 +265,19 @@ output_handle_done(void *data, struct wl_output *wl_output)
}
static void
+output_handle_done(void *data, struct wl_output *wl_output)
+{
+ struct xwl_output *xwl_output = data;
+
+ xwl_output->wl_output_done = TRUE;
+ /* Apply the changes from wl_output only if both "done" events are received,
+ * or if xdg-output is not supported.
+ */
+ if (xwl_output->xdg_output_done || !xwl_output->xdg_output)
+ apply_output_change(xwl_output);
+}
+
+static void
output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
{
}
@@ -248,6 +289,42 @@ static const struct wl_output_listener output_listener = {
output_handle_scale
};
+static void
+xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output,
+ int32_t x, int32_t y)
+{
+ struct xwl_output *xwl_output = data;
+
+ xwl_output->x = x;
+ xwl_output->y = y;
+}
+
+static void
+xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
+ int32_t width, int32_t height)
+{
+ struct xwl_output *xwl_output = data;
+
+ xwl_output->width = width;
+ xwl_output->height = height;
+}
+
+static void
+xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
+{
+ struct xwl_output *xwl_output = data;
+
+ xwl_output->xdg_output_done = TRUE;
+ if (xwl_output->wl_output_done)
+ apply_output_change(xwl_output);
+}
+
+static const struct zxdg_output_v1_listener xdg_output_listener = {
+ xdg_output_handle_logical_position,
+ xdg_output_handle_logical_size,
+ xdg_output_handle_done,
+};
+
struct xwl_output *
xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
{
@@ -255,9 +332,9 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
static int serial;
char name[256];
- xwl_output = calloc(sizeof *xwl_output, 1);
+ xwl_output = calloc(1, sizeof *xwl_output);
if (xwl_output == NULL) {
- ErrorF("create_output ENOMEM\n");
+ ErrorF("%s ENOMEM\n", __func__);
return NULL;
}
@@ -292,6 +369,15 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
+ /* We want the output to be in the list as soon as created so we can
+ * use it when binding to the xdg-output protocol...
+ */
+ xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
+ --xwl_screen->expecting_event;
+
+ if (xwl_screen->xdg_output_manager)
+ xwl_output_get_xdg_output(xwl_output);
+
return xwl_output;
err:
@@ -316,15 +402,17 @@ xwl_output_remove(struct xwl_output *xwl_output)
struct xwl_output *it;
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
int width = 0, height = 0;
+ Bool need_rotate = (xwl_output->xdg_output == NULL);
- RRCrtcDestroy(xwl_output->randr_crtc);
- RROutputDestroy(xwl_output->randr_output);
xorg_list_del(&xwl_output->link);
xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
- output_get_new_size(it, &height, &width);
+ output_get_new_size(it, need_rotate, &height, &width);
update_screen_size(xwl_output, width, height);
+ RRCrtcDestroy(xwl_output->randr_crtc);
+ RROutputDestroy(xwl_output->randr_output);
+
xwl_output_destroy(xwl_output);
}
@@ -359,3 +447,28 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
return TRUE;
}
+
+static void
+xwl_output_get_xdg_output(struct xwl_output *xwl_output)
+{
+ struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+
+ xwl_output->xdg_output =
+ zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_manager,
+ xwl_output->output);
+
+ zxdg_output_v1_add_listener(xwl_output->xdg_output,
+ &xdg_output_listener,
+ xwl_output);
+}
+
+void
+xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen)
+{
+ struct xwl_output *it;
+
+ assert(xwl_screen->xdg_output_manager);
+
+ xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
+ xwl_output_get_xdg_output(it);
+}