From: Alon Levy Date: Sat, 9 Jun 2012 14:23:37 +0000 (+0300) Subject: map-to-output: implement reflections and rotations X-Git-Url: https://diplodocus.org/git/xorg-xinput/commitdiff_plain/9071787a1d22b256c5871897f9421ba6ea2f4f76?ds=sidebyside;hp=-c map-to-output: implement reflections and rotations Uses the rotation & translation currently set according to RandR. Signed-off-by: Alon Levy Signed-off-by: Peter Hutterer --- 9071787a1d22b256c5871897f9421ba6ea2f4f76 diff --git a/src/transform.c b/src/transform.c index f80a592..d85b071 100644 --- a/src/transform.c +++ b/src/transform.c @@ -106,11 +106,31 @@ apply_matrix(Display *dpy, int deviceid, Matrix *m) return EXIT_SUCCESS; } +static void +matrix_s4(Matrix *m, float x02, float x12, float d1, float d2, int main_diag) +{ + matrix_set(m, 0, 2, x02); + matrix_set(m, 1, 2, x12); + + if (main_diag) { + matrix_set(m, 0, 0, d1); + matrix_set(m, 1, 1, d2); + } else { + matrix_set(m, 0, 0, 0); + matrix_set(m, 1, 1, 0); + matrix_set(m, 0, 1, d1); + matrix_set(m, 1, 0, d2); + } +} + +#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y) + static void set_transformation_matrix(Display *dpy, Matrix *m, int offset_x, int offset_y, - int screen_width, int screen_height) + int screen_width, int screen_height, + int rotation) { - /* offset */ + /* total display size */ int width = DisplayWidth(dpy, DefaultScreen(dpy)); int height = DisplayHeight(dpy, DefaultScreen(dpy)); @@ -124,11 +144,49 @@ set_transformation_matrix(Display *dpy, Matrix *m, int offset_x, int offset_y, matrix_set_unity(m); - matrix_set(m, 0, 2, x); - matrix_set(m, 1, 2, y); - - matrix_set(m, 0, 0, w); - matrix_set(m, 1, 1, h); + /* + * There are 16 cases: + * Rotation X Reflection + * Rotation: 0 | 90 | 180 | 270 + * Reflection: None | X | Y | XY + * + * They are spelled out instead of doing matrix multiplication to avoid + * any floating point errors. + */ + switch (rotation) { + case RR_Rotate_0: + case RR_Rotate_180 | RR_Reflect_All: + matrix_s4(m, x, y, w, h, 1); + break; + case RR_Reflect_X|RR_Rotate_0: + case RR_Reflect_Y|RR_Rotate_180: + matrix_s4(m, x + w, y, -w, h, 1); + break; + case RR_Reflect_Y|RR_Rotate_0: + case RR_Reflect_X|RR_Rotate_180: + matrix_s4(m, x, y + h, w, -h, 1); + break; + case RR_Rotate_90: + case RR_Rotate_270 | RR_Reflect_All: /* left limited - correct in working zone. */ + matrix_s4(m, x + w, y, -w, h, 0); + break; + case RR_Rotate_270: + case RR_Rotate_90 | RR_Reflect_All: /* left limited - correct in working zone. */ + matrix_s4(m, x, y + h, w, -h, 0); + break; + case RR_Rotate_90 | RR_Reflect_X: /* left limited - correct in working zone. */ + case RR_Rotate_270 | RR_Reflect_Y: /* left limited - correct in working zone. */ + matrix_s4(m, x, y, w, h, 0); + break; + case RR_Rotate_90 | RR_Reflect_Y: /* right limited - correct in working zone. */ + case RR_Rotate_270 | RR_Reflect_X: /* right limited - correct in working zone. */ + matrix_s4(m, x + w, y + h, -w, -h, 0); + break; + case RR_Rotate_180: + case RR_Reflect_All|RR_Rotate_0: + matrix_s4(m, x + w, y + h, -w, -h, 1); + break; + } #if DEBUG matrix_print(m); @@ -186,7 +244,8 @@ map_output_xrandr(Display *dpy, int deviceid, const char *output_name) matrix_set_unity(&m); crtc_info = XRRGetCrtcInfo (dpy, res, output_info->crtc); set_transformation_matrix(dpy, &m, crtc_info->x, crtc_info->y, - crtc_info->width, crtc_info->height); + crtc_info->width, crtc_info->height, + crtc_info->rotation); rc = apply_matrix(dpy, deviceid, &m); XRRFreeCrtcInfo(crtc_info); XRRFreeOutputInfo(output_info); @@ -242,7 +301,8 @@ map_output_xinerama(Display *dpy, int deviceid, const char *output_name) matrix_set_unity(&m); set_transformation_matrix(dpy, &m, screens[head].x_org, screens[head].y_org, - screens[head].width, screens[head].height); + screens[head].width, screens[head].height, + RR_Rotate_0); rc = apply_matrix(dpy, deviceid, &m); out: