diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 7325b1c3b..1809676fe 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -43,6 +43,22 @@
#include
#include "stack-tracker.h"
#include "ui.h"
+#ifdef HAVE_WAYLAND
+#include
+#endif
+
+#ifndef HAVE_WAYLAND
+enum wl_output_transform {
+ WL_OUTPUT_TRANSFORM_NORMAL,
+ WL_OUTPUT_TRANSFORM_90,
+ WL_OUTPUT_TRANSFORM_180,
+ WL_OUTPUT_TRANSFORM_270,
+ WL_OUTPUT_TRANSFORM_FLIPPED,
+ WL_OUTPUT_TRANSFORM_FLIPPED_90,
+ WL_OUTPUT_TRANSFORM_FLIPPED_180,
+ WL_OUTPUT_TRANSFORM_FLIPPED_270
+};
+#endif
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
@@ -92,6 +108,8 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
+ enum wl_output_transform transform;
+ unsigned int all_transforms;
/* Only used to build the logical configuration
from the HW one
diff --git a/src/core/monitor.c b/src/core/monitor.c
index ba885869d..5c3abf8f4 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -43,18 +43,7 @@
#include "meta-dbus-xrandr.h"
-#ifndef HAVE_WAYLAND
-enum wl_output_transform {
- WL_OUTPUT_TRANSFORM_NORMAL,
- WL_OUTPUT_TRANSFORM_90,
- WL_OUTPUT_TRANSFORM_180,
- WL_OUTPUT_TRANSFORM_270,
- WL_OUTPUT_TRANSFORM_FLIPPED,
- WL_OUTPUT_TRANSFORM_FLIPPED_90,
- WL_OUTPUT_TRANSFORM_FLIPPED_180,
- WL_OUTPUT_TRANSFORM_FLIPPED_270
-};
-#endif
+#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef enum {
META_BACKEND_UNSPECIFIED,
@@ -176,6 +165,8 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
+ manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
@@ -185,6 +176,8 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->crtcs[1].rect.width = 0;
manager->crtcs[1].rect.height = 0;
manager->crtcs[1].current_mode = NULL;
+ manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[1].dirty = FALSE;
manager->crtcs[1].logical_monitor = NULL;
@@ -259,6 +252,76 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
}
#ifdef HAVE_RANDR
+static enum wl_output_transform
+wl_transform_from_xrandr (Rotation rotation)
+{
+ static const enum wl_output_transform y_reflected_map[4] = {
+ WL_OUTPUT_TRANSFORM_FLIPPED_180,
+ WL_OUTPUT_TRANSFORM_FLIPPED_90,
+ WL_OUTPUT_TRANSFORM_FLIPPED,
+ WL_OUTPUT_TRANSFORM_FLIPPED_270
+ };
+ enum wl_output_transform ret;
+
+ switch (rotation & 0x7F)
+ {
+ default:
+ case RR_Rotate_0:
+ ret = WL_OUTPUT_TRANSFORM_NORMAL;
+ break;
+ case RR_Rotate_90:
+ ret = WL_OUTPUT_TRANSFORM_90;
+ break;
+ case RR_Rotate_180:
+ ret = WL_OUTPUT_TRANSFORM_180;
+ break;
+ case RR_Rotate_270:
+ ret = WL_OUTPUT_TRANSFORM_270;
+ break;
+ }
+
+ if (rotation & RR_Reflect_X)
+ return ret + 4;
+ else if (rotation & RR_Reflect_Y)
+ return y_reflected_map[ret];
+ else
+ return ret;
+}
+
+#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
+
+static unsigned int
+wl_transform_from_xrandr_all (Rotation rotation)
+{
+ unsigned ret;
+
+ /* Handle the common cases first (none or all) */
+ if (rotation == 0 || rotation == RR_Rotate_0)
+ return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
+
+ /* All rotations and one reflection -> all of them by composition */
+ if ((rotation & ALL_ROTATIONS) &&
+ ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
+ return ALL_WL_TRANSFORMS;
+
+ ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
+ if (rotation & RR_Rotate_90)
+ ret |= 1 << WL_OUTPUT_TRANSFORM_90;
+ if (rotation & RR_Rotate_180)
+ ret |= 1 << WL_OUTPUT_TRANSFORM_180;
+ if (rotation & RR_Rotate_270)
+ ret |= 1 << WL_OUTPUT_TRANSFORM_270;
+ if (rotation & (RR_Rotate_0 | RR_Reflect_X))
+ ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
+ if (rotation & (RR_Rotate_90 | RR_Reflect_X))
+ ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
+ if (rotation & (RR_Rotate_180 | RR_Reflect_X))
+ ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
+ if (rotation & (RR_Rotate_270 | RR_Reflect_X))
+ ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
+
+ return ret;
+}
static void
read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
@@ -329,6 +392,8 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->dirty = FALSE;
+ meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
+ meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++)
{
@@ -546,6 +611,8 @@ read_monitor_infos_from_cogl (MetaMonitorManager *manager)
cogl_output_get_width (output),
cogl_output_get_height (output),
cogl_output_get_refresh_rate (output));
+ meta_crtc.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ meta_crtc.all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
meta_crtc.logical_monitor = NULL;
meta_crtc.dirty = FALSE;
@@ -925,7 +992,9 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
- g_variant_builder_add (&transforms, "u", 0); /* 0 = WL_OUTPUT_TRANSFORM_NORMAL */
+ for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
+ if (crtc->all_transforms & (1 << j))
+ g_variant_builder_add (&transforms, "u", j);
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */
@@ -935,7 +1004,7 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
(int)crtc->rect.width,
(int)crtc->rect.height,
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
- 0, /* 0 = WL_OUTPUT_TRANSFORM_NORMAL */
+ crtc->transform,
&transforms,
NULL /* properties */);
}
@@ -1220,6 +1289,7 @@ apply_config_dummy (MetaMonitorManager *manager,
crtc->rect.width = mode->width;
crtc->rect.height = mode->height;
crtc->current_mode = mode;
+ crtc->transform = transform;
screen_width = MAX (screen_width, x + mode->width);
screen_height = MAX (screen_height, y + mode->height);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index e6b33358a..fe01de15b 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -658,7 +658,7 @@ bind_output (struct wl_client *client,
output->subpixel_order,
output->vendor,
output->product,
- WL_OUTPUT_TRANSFORM_NORMAL);
+ output->crtc->transform);
wl_resource_post_event (resource,
WL_OUTPUT_MODE,