/* Copyright (C) 2007-2008 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ #include "android/utils/display.h" #include "android/utils/debug.h" #define D(...) VERBOSE_PRINT(init,__VA_ARGS__) /** HOST RESOLUTION SETTINGS ** ** return the main monitor's DPI resolution according to the host device ** beware: this is not always reliable or even obtainable. ** ** returns 0 on success, or -1 in case of error (e.g. the system returns funky values) **/ /** NOTE: the following code assumes that we exclusively use X11 on Linux, and Quartz on OS X **/ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include #include int get_monitor_resolution( int *px_dpi, int *py_dpi ) { HDC displayDC = CreateDC( "DISPLAY", NULL, NULL, NULL ); int xdpi, ydpi; if (displayDC == NULL) { D( "%s: could not get display DC\n", __FUNCTION__ ); return -1; } xdpi = GetDeviceCaps( displayDC, LOGPIXELSX ); ydpi = GetDeviceCaps( displayDC, LOGPIXELSY ); /* sanity checks */ if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) { D( "%s: bad resolution: xpi=%d ydpi=%d", __FUNCTION__, xdpi, ydpi ); return -1; } *px_dpi = xdpi; *py_dpi = ydpi; return 0; } int get_nearest_monitor_rect( int *x, int *y, int *width, int *height ) { SDL_SysWMinfo info; HMONITOR monitor; MONITORINFO monitorInfo; SDL_VERSION(&info.version); if ( !SDL_GetWMInfo(&info) ) { D( "%s: SDL_GetWMInfo() failed: %s", __FUNCTION__, SDL_GetError()); return -1; } monitor = MonitorFromWindow( info.window, MONITOR_DEFAULTTONEAREST ); monitorInfo.cbSize = sizeof(monitorInfo); GetMonitorInfo( monitor, &monitorInfo ); *x = monitorInfo.rcMonitor.left; *y = monitorInfo.rcMonitor.top; *width = monitorInfo.rcMonitor.right - *x; *height = monitorInfo.rcMonitor.bottom - *y; D("%s: found (x,y,w,h)=(%d,%d,%d,%d)", __FUNCTION__, *x, *y, *width, *height); return 0; } #elif defined __APPLE__ /* the real implementation is in display-quartz.m, but * unfortunately, the Android build system doesn't know * how to build Objective-C sources, so provide stubs * here instead. * * CONFIG_NO_COCOA is set by Makefile.android */ #ifdef CONFIG_NO_COCOA int get_monitor_resolution( int *px_dpi, int *py_dpi ) { return -1; } int get_nearest_monitor_rect( int *x, int *y, int *width, int *height ) { return -1; } #endif /* CONFIG_NO_COCOA */ #else /* Linux and others */ #include #include #include #include #define MM_PER_INCH 25.4 #define DYNLINK_FUNCTIONS \ DYNLINK_FUNC(int,XDefaultScreen,(Display*)) \ DYNLINK_FUNC(int,XDisplayWidth,(Display*,int)) \ DYNLINK_FUNC(int,XDisplayWidthMM,(Display*,int)) \ DYNLINK_FUNC(int,XDisplayHeight,(Display*,int)) \ DYNLINK_FUNC(int,XDisplayHeightMM,(Display*,int)) \ #define DYNLINK_FUNCTIONS_INIT \ x11_dynlink_init #include "dynlink.h" static int x11_lib_inited; static void* x11_lib; int x11_lib_init( void ) { if (!x11_lib_inited) { x11_lib_inited = 1; x11_lib = dlopen( "libX11.so", RTLD_NOW ); if (x11_lib == NULL) { x11_lib = dlopen( "libX11.so.6", RTLD_NOW ); } if (x11_lib == NULL) { D("%s: Could not find libX11.so on this machine", __FUNCTION__); return -1; } if (x11_dynlink_init(x11_lib) < 0) { D("%s: didn't find necessary symbols in libX11.so", __FUNCTION__); dlclose(x11_lib); x11_lib = NULL; } } return x11_lib ? 0 : -1; } int get_monitor_resolution( int *px_dpi, int *py_dpi ) { SDL_SysWMinfo info; Display* display; int screen; int width, width_mm, height, height_mm, xdpi, ydpi; SDL_VERSION(&info.version); if ( !SDL_GetWMInfo(&info) ) { D( "%s: SDL_GetWMInfo() failed: %s", __FUNCTION__, SDL_GetError()); return -1; } if (x11_lib_init() < 0) return -1; display = info.info.x11.display; screen = FF(XDefaultScreen)(display); width = FF(XDisplayWidth)(display, screen); width_mm = FF(XDisplayWidthMM)(display, screen); height = FF(XDisplayHeight)(display, screen); height_mm = FF(XDisplayHeightMM)(display, screen); if (width_mm <= 0 || height_mm <= 0) { D( "%s: bad screen dimensions: width_mm = %d, height_mm = %d", __FUNCTION__, width_mm, height_mm); return -1; } D( "%s: found screen width=%d height=%d width_mm=%d height_mm=%d", __FUNCTION__, width, height, width_mm, height_mm ); xdpi = width * MM_PER_INCH / width_mm; ydpi = height * MM_PER_INCH / height_mm; if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) { D( "%s: bad resolution: xpi=%d ydpi=%d", __FUNCTION__, xdpi, ydpi ); return -1; } *px_dpi = xdpi; *py_dpi = ydpi; return 0; } int get_nearest_monitor_rect( int *x, int *y, int *width, int *height ) { SDL_SysWMinfo info; Display* display; int screen; SDL_VERSION(&info.version); if ( !SDL_GetWMInfo(&info) ) { D( "%s: SDL_GetWMInfo() failed: %s", __FUNCTION__, SDL_GetError()); return -1; } if (x11_lib_init() < 0) return -1; display = info.info.x11.display; screen = FF(XDefaultScreen)(display); *x = 0; *y = 0; *width = FF(XDisplayWidth)(display, screen); *height = FF(XDisplayHeight)(display, screen); D("%s: found (x,y,w,h)=(%d,%d,%d,%d)", __FUNCTION__, *x, *y, *width, *height); return 0; } #endif