cdaff761f7
Fix X11 screen_init() if Xinerama is available, but not active. Still investigating why there are nonsense dpi values under Cygwin/X11, but maybe this is an X server problem. test/hello.cxx: Extended test statements - don't forget to remove before release. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8210 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
326 lines
8.4 KiB
C++
326 lines
8.4 KiB
C++
//
|
|
// "$Id$"
|
|
//
|
|
// Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK).
|
|
//
|
|
// Copyright 1998-2010 by Bill Spitzak and others.
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Library General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Library General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Library General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
// USA.
|
|
//
|
|
// Please report all bugs and problems on the following page:
|
|
//
|
|
// http://www.fltk.org/str.php
|
|
//
|
|
|
|
|
|
#include <FL/Fl.H>
|
|
#include <FL/x.H>
|
|
#include <config.h>
|
|
|
|
|
|
// Number of screens...
|
|
static int num_screens = 0;
|
|
|
|
#ifdef WIN32
|
|
# if !defined(HMONITOR_DECLARED) && (_WIN32_WINNT < 0x0500)
|
|
# define COMPILE_MULTIMON_STUBS
|
|
# include <multimon.h>
|
|
# endif // !HMONITOR_DECLARED && _WIN32_WINNT < 0x0500
|
|
|
|
// We go the much more difficult route of individually picking some multi-screen
|
|
// functions from the USER32.DLL . If these functions are not available, we
|
|
// will gracefully fall back to single monitor support.
|
|
//
|
|
// If we were to insist on the existence of "EnumDisplayMonitors" and
|
|
// "GetMonitorInfoA", it would be impossible to use FLTK on Windows 2000
|
|
// before SP2 or earlier.
|
|
|
|
// BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM)
|
|
typedef BOOL (WINAPI* fl_edm_func)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
|
|
// BOOL GetMonitorInfo(HMONITOR, LPMONITORINFO)
|
|
typedef BOOL (WINAPI* fl_gmi_func)(HMONITOR, LPMONITORINFO);
|
|
|
|
static fl_gmi_func fl_gmi = NULL; // used to get a proc pointer for GetMonitorInfoA
|
|
|
|
static RECT screens[16];
|
|
static float dpi[16][2];
|
|
|
|
static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) {
|
|
if (num_screens >= 16) return TRUE;
|
|
|
|
MONITORINFOEX mi;
|
|
mi.cbSize = sizeof(mi);
|
|
|
|
// GetMonitorInfo(mon, &mi);
|
|
// (but we use our self-aquired function pointer instead)
|
|
if (fl_gmi(mon, &mi)) {
|
|
screens[num_screens] = mi.rcWork;
|
|
|
|
// find the pixel size
|
|
if (mi.cbSize == sizeof(mi)) {
|
|
HDC screen = CreateDC(mi.szDevice, NULL, NULL, NULL);
|
|
if (screen) {
|
|
dpi[num_screens][0] = (float)GetDeviceCaps(screen, LOGPIXELSX);
|
|
dpi[num_screens][1] = (float)GetDeviceCaps(screen, LOGPIXELSY);
|
|
}
|
|
ReleaseDC(0L, screen);
|
|
}
|
|
|
|
num_screens ++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void screen_init() {
|
|
// Since not all versions of Windows include multiple monitor support,
|
|
// we do a run-time check for the required functions...
|
|
HMODULE hMod = GetModuleHandle("USER32.DLL");
|
|
|
|
if (hMod) {
|
|
// check that EnumDisplayMonitors is available
|
|
fl_edm_func fl_edm = (fl_edm_func)GetProcAddress(hMod, "EnumDisplayMonitors");
|
|
|
|
if (fl_edm) {
|
|
// We do have EnumDisplayMonitors, so lets find out how many monitors...
|
|
num_screens = GetSystemMetrics(SM_CMONITORS);
|
|
|
|
// if (num_screens > 1) {
|
|
// If there is more than 1 monitor, enumerate them...
|
|
fl_gmi = (fl_gmi_func)GetProcAddress(hMod, "GetMonitorInfoA");
|
|
|
|
if (fl_gmi) {
|
|
// We have GetMonitorInfoA, enumerate all the screens...
|
|
num_screens = 0;
|
|
// EnumDisplayMonitors(0,0,screen_cb,0);
|
|
// (but we use our self-aquired function pointer instead)
|
|
fl_edm(0, 0, screen_cb, 0);
|
|
return;
|
|
}
|
|
// }
|
|
}
|
|
}
|
|
|
|
// If we get here, assume we have 1 monitor...
|
|
num_screens = 1;
|
|
}
|
|
#elif defined(__APPLE__)
|
|
static XRectangle screens[16];
|
|
static float dpi[16];
|
|
|
|
static void screen_init() {
|
|
num_screens = Fl_X::screen_init(screens, dpi);
|
|
}
|
|
#elif HAVE_XINERAMA
|
|
# include <X11/extensions/Xinerama.h>
|
|
|
|
// Screen data...
|
|
static XineramaScreenInfo *screens;
|
|
static float dpi[16][2];
|
|
|
|
static void screen_init() {
|
|
if (!fl_display) fl_open_display();
|
|
|
|
if (XineramaIsActive(fl_display)) {
|
|
screens = XineramaQueryScreens(fl_display, &num_screens);
|
|
int i;
|
|
for (i=0; i<num_screens; i++) {
|
|
int mm = DisplayWidthMM(fl_display, i);
|
|
dpi[i][0] = mm ? screens[i].width*25.4f/mm : 0.0f;
|
|
mm = DisplayHeightMM(fl_display, fl_screen);
|
|
dpi[i][1] = mm ? screens[i].height*25.4f/mm : dpi[i][0];
|
|
}
|
|
} else { // ! XineramaIsActive()
|
|
num_screens = 1;
|
|
int mm = DisplayWidthMM(fl_display, fl_screen);
|
|
dpi[0][0] = mm ? Fl::w()*25.4f/mm : 0.0f;
|
|
mm = DisplayHeightMM(fl_display, fl_screen);
|
|
dpi[0][1] = mm ? Fl::h()*25.4f/mm : dpi[0][0];
|
|
}
|
|
}
|
|
#else
|
|
static float dpi[2];
|
|
static void screen_init() {
|
|
num_screens = 1;
|
|
if (!fl_display) fl_open_display();
|
|
int mm = DisplayWidthMM(fl_display, fl_screen);
|
|
dpi[0] = mm ? Fl::w()*25.4f/mm : 0.0f;
|
|
mm = DisplayHeightMM(fl_display, fl_screen);
|
|
dpi[1] = mm ? Fl::h()*25.4f/mm : dpi[0];
|
|
}
|
|
#endif // WIN32
|
|
|
|
|
|
/**
|
|
Gets the number of available screens.
|
|
*/
|
|
int Fl::screen_count() {
|
|
if (!num_screens) screen_init();
|
|
|
|
return num_screens;
|
|
}
|
|
|
|
/**
|
|
Gets the bounding box of a screen
|
|
that contains the specified screen position \p mx, \p my
|
|
\param[out] X,Y,W,H the corresponding screen bounding box
|
|
\param[in] mx, my the absolute screen position
|
|
*/
|
|
void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) {
|
|
if (!num_screens) screen_init();
|
|
|
|
#ifdef WIN32
|
|
if (num_screens > 1) {
|
|
int i;
|
|
|
|
for (i = 0; i < num_screens; i ++) {
|
|
if (mx >= screens[i].left && mx < screens[i].right &&
|
|
my >= screens[i].top && my < screens[i].bottom) {
|
|
X = screens[i].left;
|
|
Y = screens[i].top;
|
|
W = screens[i].right - screens[i].left;
|
|
H = screens[i].bottom - screens[i].top;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
#elif defined(__APPLE__)
|
|
if (num_screens > 1) {
|
|
int i;
|
|
|
|
for (i = 0; i < num_screens; i ++) {
|
|
if (mx >= screens[i].x &&
|
|
mx < (screens[i].x + screens[i].width) &&
|
|
my >= screens[i].y &&
|
|
my < (screens[i].y + screens[i].height)) {
|
|
X = screens[i].x;
|
|
Y = screens[i].y;
|
|
W = screens[i].width;
|
|
H = screens[i].height;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
#elif HAVE_XINERAMA
|
|
if (num_screens > 1) {
|
|
int i;
|
|
|
|
for (i = 0; i < num_screens; i ++) {
|
|
if (mx >= screens[i].x_org &&
|
|
mx < (screens[i].x_org + screens[i].width) &&
|
|
my >= screens[i].y_org &&
|
|
my < (screens[i].y_org + screens[i].height)) {
|
|
X = screens[i].x_org;
|
|
Y = screens[i].y_org;
|
|
W = screens[i].width;
|
|
H = screens[i].height;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
(void)mx;
|
|
(void)my;
|
|
#endif // WIN32
|
|
|
|
X = Fl::x();
|
|
Y = Fl::y();
|
|
W = Fl::w();
|
|
H = Fl::h();
|
|
}
|
|
|
|
/**
|
|
Gets the screen bounding rect for the given screen.
|
|
\param[out] X,Y,W,H the corresponding screen bounding box
|
|
\param[in] n the screen number (0 to Fl::screen_count() - 1)
|
|
\see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my)
|
|
*/
|
|
void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) {
|
|
if (!num_screens) screen_init();
|
|
|
|
#ifdef WIN32
|
|
if (num_screens > 1 && n >= 0 && n < num_screens) {
|
|
X = screens[n].left;
|
|
Y = screens[n].top;
|
|
W = screens[n].right - screens[n].left;
|
|
H = screens[n].bottom - screens[n].top;
|
|
return;
|
|
}
|
|
#elif defined(__APPLE__)
|
|
if (num_screens > 1 && n >= 0 && n < num_screens) {
|
|
X = screens[n].x;
|
|
Y = screens[n].y;
|
|
W = screens[n].width;
|
|
H = screens[n].height;
|
|
return;
|
|
}
|
|
#elif HAVE_XINERAMA
|
|
if (num_screens > 1 && n >= 0 && n < num_screens) {
|
|
X = screens[n].x_org;
|
|
Y = screens[n].y_org;
|
|
W = screens[n].width;
|
|
H = screens[n].height;
|
|
return;
|
|
}
|
|
#else
|
|
(void)n;
|
|
#endif // WIN32
|
|
|
|
X = Fl::x();
|
|
Y = Fl::y();
|
|
W = Fl::w();
|
|
H = Fl::h();
|
|
}
|
|
|
|
|
|
/**
|
|
Gets the screen resolution in dots-per-inch for the given screen.
|
|
\param[out] h, v horizontal and vertical resolution
|
|
\param[in] n the screen number (0 to Fl::screen_count() - 1)
|
|
\see void screen_xywh(int &x, int &y, int &w, int &h, int mx, int my)
|
|
*/
|
|
void Fl::screen_dpi(float &h, float &v, int n)
|
|
{
|
|
if (!num_screens) screen_init();
|
|
h = v = 0.0f;
|
|
|
|
#ifdef WIN32
|
|
if (n >= 0 && n < num_screens) {
|
|
h = float(dpi[n][0]);
|
|
v = float(dpi[n][1]);
|
|
}
|
|
#elif defined(__APPLE__)
|
|
if (n >= 0 && n < num_screens) {
|
|
h = v = dpi[n];
|
|
}
|
|
#elif HAVE_XINERAMA
|
|
if (n >= 0 && n < num_screens) {
|
|
h = dpi[n][0];
|
|
v = dpi[n][1];
|
|
}
|
|
#else
|
|
if (n >= 0 && n < num_screens) {
|
|
h = dpi[0];
|
|
v = dpi[1];
|
|
}
|
|
#endif // WIN32
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// End of "$Id$".
|
|
//
|