From 18c941bbec51fa7e899a98eaadb883dfc4f046c0 Mon Sep 17 00:00:00 2001 From: Andreas Haas Date: Thu, 9 Jun 2016 18:54:06 +0200 Subject: [PATCH] x11: Implemented dpi detection depends on XRandR. Had to dynamically load `XRRGetMonitors` as Ubuntu 12.04 doesn't have it. Also removed libudev from travis install list. --- .travis.yml | 2 +- platform/x11/detect.py | 8 +++++- platform/x11/os_x11.cpp | 58 +++++++++++++++++++++++++++++++++++++++++ platform/x11/os_x11.h | 19 ++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5f9cf48b7ec9..3c7ee5c1028d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,7 @@ addons: - libglu1-mesa-dev - libssl-dev - libxinerama-dev - - libudev-dev + - libxrandr-dev # For cross-compiling to Windows. - binutils-mingw-w64-i686 diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 2561e09b9ad66..fc6c7cde8d1f3 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -45,6 +45,11 @@ def can_build(): print("xinerama not found.. x11 disabled.") return False + x11_error=os.system("pkg-config xrandr --modversion > /dev/null ") + if (x11_error): + print("xrandr not found.. x11 disabled.") + return False + return True # X11 enabled @@ -132,6 +137,7 @@ def configure(env): env.ParseConfig('pkg-config x11 --cflags --libs') env.ParseConfig('pkg-config xinerama --cflags --libs') env.ParseConfig('pkg-config xcursor --cflags --libs') + env.ParseConfig('pkg-config xrandr --cflags --libs') if (env["openssl"]=="yes"): env.ParseConfig('pkg-config openssl --cflags --libs') @@ -179,7 +185,7 @@ def configure(env): print("PulseAudio development libraries not found, disabling driver") env.Append(CPPFLAGS=['-DX11_ENABLED','-DUNIX_ENABLED','-DGLES2_ENABLED','-DGLES_OVER_GL']) - env.Append(LIBS=['GL', 'GLU', 'pthread', 'z']) + env.Append(LIBS=['GL', 'GLU', 'pthread', 'z', 'dl']) #env.Append(CPPFLAGS=['-DMPC_FIXED_POINT']) #host compiler is default.. diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index b089436a17d85..eb576b11f4704 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -57,6 +57,7 @@ #include #include #include +#include //stupid linux.h #ifdef KEY_TAB @@ -117,6 +118,19 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi char * modifiers = XSetLocaleModifiers ("@im=none"); ERR_FAIL_COND( modifiers == NULL ); + const char* err; + xrr_get_monitors = NULL; + xrandr_handle = dlopen("libXrandr.so", RTLD_LAZY); + err = dlerror(); + if (!xrandr_handle) { + fprintf(stderr, "could not load libXrandr.so, dpi detection disabled. Error: %s\n", err); + } + else { + xrr_get_monitors = (xrr_get_monitors_t) dlsym(xrandr_handle, "XRRGetMonitors"); + if (!xrr_get_monitors) + fprintf(stderr, "could not find symbol XRRGetMonitors, dpi detection will only work on the first screen\nError: %s\n", err); + } + xim = XOpenIM (x11_display, NULL, NULL, NULL); @@ -480,6 +494,9 @@ void OS_X11::finalize() { physics_2d_server->finish(); memdelete(physics_2d_server); + if (xrandr_handle) + dlclose(xrandr_handle); + XUnmapWindow( x11_display, x11_window ); XDestroyWindow( x11_display, x11_window ); @@ -722,6 +739,47 @@ Size2 OS_X11::get_screen_size(int p_screen) const { return size; } +int OS_X11::get_screen_dpi(int p_screen) const { + + //invalid screen? + ERR_FAIL_INDEX_V(p_screen, get_screen_count(), 0); + + //Get physical monitor Dimensions through XRandR and calculate dpi + int event_base, error_base; + const Bool ext_okay = XRRQueryExtension(x11_display,&event_base, &error_base); + + Size2 sc = get_screen_size(p_screen); + if (ext_okay) { + int count = 0; + if (xrr_get_monitors) { + xrr_monitor_info *monitors = xrr_get_monitors(x11_display, x11_window, true, &count); + if (p_screen < count) { + double xdpi = sc.width / (double) monitors[p_screen].mwidth * 25.4; + double ydpi = sc.height / (double) monitors[p_screen].mheight * 25.4; + return (xdpi + ydpi) / 2; + } + } + else if (p_screen == 0) { + XRRScreenSize *sizes = XRRSizes(x11_display, 0, &count); + if (sizes) { + double xdpi = sc.width / (double) sizes[0].mwidth * 25.4; + double ydpi = sc.height / (double) sizes[0].mheight * 25.4; + return (xdpi + ydpi) / 2; + } + } + } + + int width_mm = DisplayWidthMM(x11_display, p_screen); + int height_mm = DisplayHeightMM(x11_display, p_screen); + double xdpi = (width_mm ? sc.width / (double) width_mm * 25.4 : 0); + double ydpi = (height_mm ? sc.height / (double) height_mm * 25.4 : 0); + if (xdpi || xdpi) + return (xdpi + ydpi)/(xdpi && ydpi ? 2 : 1); + + //could not get dpi + return 96; +} + Point2 OS_X11::get_window_position() const { int x,y; Window child; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 311f26d4d3d88..3a4579d818f52 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -52,6 +52,7 @@ #include #include #include +#include // Hints for X11 fullscreen typedef struct { @@ -62,6 +63,20 @@ typedef struct { unsigned long status; } Hints; +typedef struct _xrr_monitor_info { + Atom name; + Bool primary; + Bool automatic; + int noutput; + int x; + int y; + int width; + int height; + int mwidth; + int mheight; + RROutput *outputs; +} xrr_monitor_info; + #undef CursorShape /** @author Juan Linietsky @@ -162,6 +177,9 @@ class OS_X11 : public OS_Unix { //void set_wm_border(bool p_enabled); void set_wm_fullscreen(bool p_enabled); + typedef xrr_monitor_info* (*xrr_get_monitors_t)(Display *dpy, Window window, Bool get_active, int *nmonitors); + xrr_get_monitors_t xrr_get_monitors; + void *xrandr_handle; protected: @@ -219,6 +237,7 @@ class OS_X11 : public OS_Unix { virtual void set_current_screen(int p_screen); virtual Point2 get_screen_position(int p_screen=0) const; virtual Size2 get_screen_size(int p_screen=0) const; + virtual int get_screen_dpi(int p_screen=0) const; virtual Point2 get_window_position() const; virtual void set_window_position(const Point2& p_position); virtual Size2 get_window_size() const;