diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index d08b404751..15701579a6 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -1,7 +1,7 @@ /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2017 - Daniel De Matteis - * Copyright (C) 2016-2017 - Brad Parker + * Copyright (C) 2016-2019 - Brad Parker * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -15,19 +15,20 @@ * If not, see . */ +/* We are targeting XRandR 1.2 here. */ + #include #include #include #include -#include /* run pkg-config --static --libs xrandr */ -#include -#include #include "../../config.h" #ifdef HAVE_XRANDR #include +#include +#include #endif #include "../video_display_server.h" @@ -358,10 +359,95 @@ const char *x11_display_server_get_output_options(void *data) #endif } +#ifdef HAVE_XRANDR static void x11_display_server_set_screen_orientation(enum rotation rotation) { - (void)rotation; + int i, j, num_sizes = 0; + XRRScreenResources *screen; + XRRScreenConfiguration *config = XRRGetScreenInfo(g_x11_dpy, DefaultRootWindow(g_x11_dpy)); + XRRScreenSize *sizes = XRRConfigSizes(config, &num_sizes); + double dpi = (25.4 * DisplayHeight(g_x11_dpy, DefaultScreen(g_x11_dpy))) / DisplayHeightMM(g_x11_dpy, DefaultScreen(g_x11_dpy)); + + XGrabServer(g_x11_dpy); + + screen = XRRGetScreenResources(g_x11_dpy, DefaultRootWindow(g_x11_dpy)); + + for (i = 0; i < screen->noutput; i++) + { + XRROutputInfo *info = XRRGetOutputInfo(g_x11_dpy, screen, screen->outputs[i]); + + if (info->connection != RR_Connected) + { + XRRFreeOutputInfo(info); + continue; + } + + for (j = 0; j < info->ncrtc; j++) + { + XRRCrtcInfo *crtc = XRRGetCrtcInfo(g_x11_dpy, screen, screen->crtcs[j]); + Rotation new_rotation = RR_Rotate_0; + + if (crtc->width == 0 || crtc->height == 0) + { + XRRFreeCrtcInfo(crtc); + continue; + } + + switch (rotation) + { + case ORIENTATION_NORMAL: + default: + if (crtc->rotations & RR_Rotate_0) + new_rotation = RR_Rotate_0; + break; + case ORIENTATION_VERTICAL: + if (crtc->rotations & RR_Rotate_270) + new_rotation = RR_Rotate_270; + break; + case ORIENTATION_FLIPPED: + if (crtc->rotations & RR_Rotate_180) + new_rotation = RR_Rotate_180; + break; + case ORIENTATION_FLIPPED_ROTATED: + if (crtc->rotations & RR_Rotate_90) + new_rotation = RR_Rotate_90; + break; + } + + XRRSetCrtcConfig(g_x11_dpy, screen, screen->crtcs[j], CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0); + + if ((crtc->rotation & RR_Rotate_0 || crtc->rotation & RR_Rotate_180) && (rotation == ORIENTATION_VERTICAL || rotation == ORIENTATION_FLIPPED_ROTATED)) + { + unsigned width = crtc->width; + crtc->width = crtc->height; + crtc->height = width; + } + else if ((crtc->rotation & RR_Rotate_90 || crtc->rotation & RR_Rotate_270) && (rotation == ORIENTATION_NORMAL || rotation == ORIENTATION_FLIPPED)) + { + unsigned width = crtc->width; + crtc->width = crtc->height; + crtc->height = width; + } + + crtc->rotation = new_rotation; + + XRRSetScreenSize(g_x11_dpy, DefaultRootWindow(g_x11_dpy), crtc->width, crtc->height, (25.4 * crtc->width) / dpi, (25.4 * crtc->height) / dpi); + + XRRSetCrtcConfig(g_x11_dpy, screen, screen->crtcs[j], CurrentTime, crtc->x, crtc->y, crtc->mode, crtc->rotation, crtc->outputs, crtc->noutput); + + XRRFreeCrtcInfo(crtc); + } + + XRRFreeOutputInfo(info); + } + + XRRFreeScreenResources(screen); + + XUngrabServer(g_x11_dpy); + XSync(g_x11_dpy, False); + XRRFreeScreenConfigInfo(config); } +#endif const video_display_server_t dispserv_x11 = { x11_display_server_init, @@ -372,6 +458,10 @@ const video_display_server_t dispserv_x11 = { x11_display_server_set_resolution, NULL, /* get_resolution_list */ x11_display_server_get_output_options, +#ifdef HAVE_XRANDR x11_display_server_set_screen_orientation, +#else + NULL, +#endif "x11" };