Load X11 extensions dynamically; don't expect them to be there at compile time

Add x-cursor-size variable for overriding XCursor size.
This commit is contained in:
rdb 2016-12-24 22:21:18 +01:00
parent 122d9dd3ff
commit 28bb737597
9 changed files with 288 additions and 135 deletions

View File

@ -88,7 +88,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"MFC", "WX", "FLTK", # Used for web plug-in only
"ROCKET", "AWESOMIUM", # GUI libraries
"CARBON", "COCOA", # Mac OS X toolkits
"X11", "XF86DGA", "XRANDR", "XCURSOR", # Unix platform support
"X11", # Unix platform support
"PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain
"SKEL", # Example SKEL project
"PANDAFX", # Some distortion special lenses
@ -516,9 +516,6 @@ IncDirectory("ALWAYS", GetOutputDir()+"/include")
if (COMPILER == "MSVC"):
PkgDisable("X11")
PkgDisable("XRANDR")
PkgDisable("XF86DGA")
PkgDisable("XCURSOR")
PkgDisable("GLES")
PkgDisable("GLES2")
PkgDisable("EGL")
@ -843,9 +840,6 @@ if (COMPILER=="GCC"):
SmartPkgEnable("CGGL", "", ("CgGL"), "Cg/cgGL.h")
if not RUNTIME:
SmartPkgEnable("X11", "x11", "X11", ("X11", "X11/Xlib.h"))
SmartPkgEnable("XRANDR", "xrandr", "Xrandr", "X11/extensions/Xrandr.h")
SmartPkgEnable("XF86DGA", "xxf86dga", "Xxf86dga", "X11/extensions/xf86dga.h")
SmartPkgEnable("XCURSOR", "xcursor", "Xcursor", "X11/Xcursor/Xcursor.h")
if GetHost() != "darwin":
# Workaround for an issue where pkg-config does not include this path
@ -2194,9 +2188,6 @@ DTOOL_CONFIG=[
("PHAVE_STDINT_H", '1', '1'),
("HAVE_RTTI", '1', '1'),
("HAVE_X11", 'UNDEF', '1'),
("HAVE_XRANDR", 'UNDEF', '1'),
("HAVE_XF86DGA", 'UNDEF', '1'),
("HAVE_XCURSOR", 'UNDEF', '1'),
("IS_LINUX", 'UNDEF', '1'),
("IS_OSX", 'UNDEF', 'UNDEF'),
("IS_FREEBSD", 'UNDEF', 'UNDEF'),
@ -2301,9 +2292,6 @@ def WriteConfigSettings():
dtool_config["PHAVE_SYS_MALLOC_H"] = '1'
dtool_config["HAVE_OPENAL_FRAMEWORK"] = '1'
dtool_config["HAVE_X11"] = 'UNDEF' # We might have X11, but we don't need it.
dtool_config["HAVE_XRANDR"] = 'UNDEF'
dtool_config["HAVE_XF86DGA"] = 'UNDEF'
dtool_config["HAVE_XCURSOR"] = 'UNDEF'
dtool_config["HAVE_GLX"] = 'UNDEF'
dtool_config["IS_LINUX"] = 'UNDEF'
dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF'
@ -4581,7 +4569,7 @@ if (GetTarget() not in ['windows', 'darwin'] and PkgSkip("GL")==0 and PkgSkip("X
TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj')
TargetAdd('libpandagl.dll', input='p3glxdisplay_composite1.obj')
TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'NVIDIACG', 'CGGL', 'X11'])
#
# DIRECTORY: panda/src/cocoadisplay/
@ -4656,7 +4644,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI
TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj')
TargetAdd('libpandagles.dll', input='pandagles_egldisplay_composite1.obj')
TargetAdd('libpandagles.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles.dll', opts=['MODULE', 'GLES', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/egldisplay/
@ -4674,7 +4662,7 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNT
TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj')
TargetAdd('libpandagles2.dll', input='pandagles2_egldisplay_composite1.obj')
TargetAdd('libpandagles2.dll', input=COMMON_PANDA_LIBS)
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libpandagles2.dll', opts=['MODULE', 'GLES2', 'EGL', 'X11'])
#
# DIRECTORY: panda/src/ode/
@ -4970,7 +4958,7 @@ if (not RUNTIME and (GetTarget() in ('windows', 'darwin') or PkgSkip("X11")==0)
TargetAdd('libp3tinydisplay.dll', opts=['WINIMM', 'WINGDI', 'WINKERNEL', 'WINOLDNAMES', 'WINUSER', 'WINMM'])
else:
TargetAdd('libp3tinydisplay.dll', input='p3x11display_composite1.obj')
TargetAdd('libp3tinydisplay.dll', opts=['X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
TargetAdd('libp3tinydisplay.dll', opts=['X11'])
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite1.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_composite2.obj')
TargetAdd('libp3tinydisplay.dll', input='p3tinydisplay_ztriangle_1.obj')

View File

@ -49,19 +49,6 @@ struct XVisualInfo;
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif // HAVE_XRANDR
#ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#ifdef HAVE_XF86DGA
#include <X11/extensions/Xxf86dga.h>
#endif
#include "post_x11_include.h"
#endif // CPPPARSER

View File

@ -60,6 +60,11 @@ ConfigVariableInt x_wheel_right_button
"mouse button number does the system report when one scrolls "
"to the right?"));
ConfigVariableInt x_cursor_size
("x-cursor-size", -1,
PRC_DESC("This sets the cursor size when using XCursor to change the mouse "
"cursor. The default is to use the default size for the display."));
ConfigVariableString x_wm_class_name
("x-wm-class-name", "",
PRC_DESC("Specify the value to use for the res_name field of the window's "

View File

@ -32,6 +32,7 @@ extern ConfigVariableInt x_wheel_down_button;
extern ConfigVariableInt x_wheel_left_button;
extern ConfigVariableInt x_wheel_right_button;
extern ConfigVariableInt x_cursor_size;
extern ConfigVariableString x_wm_class_name;
extern ConfigVariableString x_wm_class;

View File

@ -57,6 +57,38 @@ get_hidden_cursor() {
return _hidden_cursor;
}
/**
* Returns true if relative mouse mode is supported on this display.
*/
INLINE bool x11GraphicsPipe::
supports_relative_mouse() const {
return (_XF86DGADirectVideo != NULL);
}
/**
* Enables relative mouse mode for this display. Returns false if unsupported.
*/
INLINE bool x11GraphicsPipe::
enable_relative_mouse() {
if (_XF86DGADirectVideo != NULL) {
x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n";
_XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
return true;
}
return false;
}
/**
* Disables relative mouse mode for this display.
*/
INLINE void x11GraphicsPipe::
disable_relative_mouse() {
if (_XF86DGADirectVideo != NULL) {
x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n";
_XF86DGADirectVideo(_display, _screen, 0);
}
}
/**
* Globally disables the printing of error messages that are raised by the X11
* system, for instance in order to test whether a particular X11 operation

View File

@ -17,6 +17,8 @@
#include "frameBufferProperties.h"
#include "displayInformation.h"
#include <dlfcn.h>
TypeHandle x11GraphicsPipe::_type_handle;
bool x11GraphicsPipe::_error_handlers_installed = false;
@ -31,7 +33,11 @@ LightReMutex x11GraphicsPipe::_x_mutex;
*
*/
x11GraphicsPipe::
x11GraphicsPipe(const string &display) {
x11GraphicsPipe(const string &display) :
_have_xrandr(false),
_xcursor_size(-1),
_XF86DGADirectVideo(NULL) {
string display_spec = display;
if (display_spec.empty()) {
display_spec = display_cfg;
@ -86,34 +92,116 @@ x11GraphicsPipe(const string &display) {
_display_height = DisplayHeight(_display, _screen);
_is_valid = true;
#ifdef HAVE_XRANDR
// Use Xrandr to fill in the supported resolution list.
int num_sizes, num_rates;
XRRScreenSize *xrrs;
xrrs = XRRSizes(_display, 0, &num_sizes);
_display_information->_total_display_modes = 0;
for (int i = 0; i < num_sizes; ++i) {
XRRRates(_display, 0, i, &num_rates);
_display_information->_total_display_modes += num_rates;
}
// Dynamically load the xf86dga extension.
void *xf86dga = dlopen("libXxf86dga.so.1", RTLD_NOW | RTLD_LOCAL);
if (xf86dga != NULL) {
pfn_XF86DGAQueryVersion _XF86DGAQueryVersion = (pfn_XF86DGAQueryVersion)dlsym(xf86dga, "XF86DGAQueryVersion");
_XF86DGADirectVideo = (pfn_XF86DGADirectVideo)dlsym(xf86dga, "XF86DGADirectVideo");
short *rates;
short counter = 0;
_display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes];
for (int i = 0; i < num_sizes; ++i) {
int num_rates;
rates = XRRRates(_display, 0, i, &num_rates);
for (int j = 0; j < num_rates; ++j) {
DisplayMode* dm = _display_information->_display_mode_array + counter;
dm->width = xrrs[i].width;
dm->height = xrrs[i].height;
dm->refresh_rate = rates[j];
dm->bits_per_pixel = -1;
dm->fullscreen_only = false;
++counter;
int major_ver, minor_ver;
if (_XF86DGAQueryVersion == NULL || _XF86DGADirectVideo == NULL) {
x11display_cat.warning()
<< "libXxf86dga.so.1 does not provide required functions; relative mouse mode will not work.\n";
} else if (!_XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
_XF86DGADirectVideo = NULL;
}
} else {
_XF86DGADirectVideo = NULL;
if (x11display_cat.is_debug()) {
x11display_cat.debug()
<< "cannot dlopen libXxf86dga.so.1; cursor changing will not work.\n";
}
}
// Dynamically load the XCursor extension.
void *xcursor = dlopen("libXcursor.so.1", RTLD_NOW | RTLD_LOCAL);
if (xcursor != NULL) {
pfn_XcursorGetDefaultSize _XcursorGetDefaultSize = (pfn_XcursorGetDefaultSize)dlsym(xcursor, "XcursorGetDefaultSize");
_XcursorXcFileLoadImages = (pfn_XcursorXcFileLoadImages)dlsym(xcursor, "XcursorXcFileLoadImages");
_XcursorImagesLoadCursor = (pfn_XcursorImagesLoadCursor)dlsym(xcursor, "XcursorImagesLoadCursor");
_XcursorImagesDestroy = (pfn_XcursorImagesDestroy)dlsym(xcursor, "XcursorImagesDestroy");
_XcursorImageCreate = (pfn_XcursorImageCreate)dlsym(xcursor, "XcursorImageCreate");
_XcursorImageLoadCursor = (pfn_XcursorImageLoadCursor)dlsym(xcursor, "XcursorImageLoadCursor");
_XcursorImageDestroy = (pfn_XcursorImageDestroy)dlsym(xcursor, "XcursorImageDestroy");
if (_XcursorGetDefaultSize == NULL || _XcursorXcFileLoadImages == NULL ||
_XcursorImagesLoadCursor == NULL || _XcursorImagesDestroy == NULL ||
_XcursorImageCreate == NULL || _XcursorImageLoadCursor == NULL ||
_XcursorImageDestroy == NULL) {
_xcursor_size = -1;
x11display_cat.warning()
<< "libXcursor.so.1 does not provide required functions; cursor changing will not work.\n";
} else if (x_cursor_size.get_value() >= 0) {
_xcursor_size = x_cursor_size;
} else {
_xcursor_size = _XcursorGetDefaultSize(_display);
}
} else {
_xcursor_size = -1;
if (x11display_cat.is_debug()) {
x11display_cat.debug()
<< "cannot dlopen libXcursor.so.1; cursor changing will not work.\n";
}
}
// Dynamically load the XRandr extension.
void *xrandr = dlopen("libXrandr.so.2", RTLD_NOW | RTLD_LOCAL);
if (xrandr != NULL) {
pfn_XRRQueryExtension _XRRQueryExtension = (pfn_XRRQueryExtension)dlsym(xrandr, "XRRQueryExtension");
_XRRSizes = (pfn_XRRSizes)dlsym(xrandr, "XRRSizes");
_XRRRates = (pfn_XRRRates)dlsym(xrandr, "XRRRates");
_XRRGetScreenInfo = (pfn_XRRGetScreenInfo)dlsym(xrandr, "XRRGetScreenInfo");
_XRRConfigCurrentConfiguration = (pfn_XRRConfigCurrentConfiguration)dlsym(xrandr, "XRRConfigCurrentConfiguration");
_XRRSetScreenConfig = (pfn_XRRSetScreenConfig)dlsym(xrandr, "XRRSetScreenConfig");
if (_XRRQueryExtension == NULL || _XRRSizes == NULL || _XRRRates == NULL ||
_XRRGetScreenInfo == NULL || _XRRConfigCurrentConfiguration == NULL ||
_XRRSetScreenConfig == NULL) {
_have_xrandr = false;
x11display_cat.warning()
<< "libXrandr.so.2 does not provide required functions; resolution setting will not work.\n";
} else {
int event, error;
_have_xrandr = _XRRQueryExtension(_display, &event, &error);
}
} else {
_have_xrandr = false;
if (x11display_cat.is_debug()) {
x11display_cat.debug()
<< "cannot dlopen libXrandr.so.2; resolution setting will not work.\n";
}
}
// Use Xrandr to fill in the supported resolution list.
if (_have_xrandr) {
int num_sizes, num_rates;
XRRScreenSize *xrrs;
xrrs = _XRRSizes(_display, 0, &num_sizes);
_display_information->_total_display_modes = 0;
for (int i = 0; i < num_sizes; ++i) {
_XRRRates(_display, 0, i, &num_rates);
_display_information->_total_display_modes += num_rates;
}
short *rates;
short counter = 0;
_display_information->_display_mode_array = new DisplayMode[_display_information->_total_display_modes];
for (int i = 0; i < num_sizes; ++i) {
int num_rates;
rates = _XRRRates(_display, 0, i, &num_rates);
for (int j = 0; j < num_rates; ++j) {
DisplayMode* dm = _display_information->_display_mode_array + counter;
dm->width = xrrs[i].width;
dm->height = xrrs[i].height;
dm->refresh_rate = rates[j];
dm->bits_per_pixel = -1;
dm->fullscreen_only = false;
++counter;
}
}
}
#endif
// Connect to an input method for supporting international text entry.
_im = XOpenIM(_display, NULL, NULL, NULL);

View File

@ -21,6 +21,22 @@
#include "lightReMutex.h"
#include "windowHandle.h"
#include "get_x11.h"
#include "config_x11display.h"
// Excerpt the few definitions we need for the extensions.
#define XF86DGADirectMouse 0x0004
typedef struct _XcursorFile XcursorFile;
typedef struct _XcursorImage XcursorImage;
typedef struct _XcursorImages XcursorImages;
typedef unsigned short Rotation;
typedef unsigned short SizeID;
typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
typedef struct {
int width, height;
int mwidth, mheight;
} XRRScreenSize;
class FrameBufferProperties;
@ -40,6 +56,10 @@ public:
INLINE X11_Cursor get_hidden_cursor();
INLINE bool supports_relative_mouse() const;
INLINE bool enable_relative_mouse();
INLINE void disable_relative_mouse();
static INLINE int disable_x_error_messages();
static INLINE int enable_x_error_messages();
static INLINE int get_x_error_count();
@ -61,6 +81,38 @@ public:
Atom _net_wm_state_add;
Atom _net_wm_state_remove;
// Extension functions.
typedef int (*pfn_XcursorGetDefaultSize)(X11_Display *);
typedef XcursorImages *(*pfn_XcursorXcFileLoadImages)(XcursorFile *, int);
typedef X11_Cursor (*pfn_XcursorImagesLoadCursor)(X11_Display *, const XcursorImages *);
typedef void (*pfn_XcursorImagesDestroy)(XcursorImages *);
typedef XcursorImage *(*pfn_XcursorImageCreate)(int, int);
typedef X11_Cursor (*pfn_XcursorImageLoadCursor)(X11_Display *, const XcursorImage *);
typedef void (*pfn_XcursorImageDestroy)(XcursorImage *);
int _xcursor_size;
pfn_XcursorXcFileLoadImages _XcursorXcFileLoadImages;
pfn_XcursorImagesLoadCursor _XcursorImagesLoadCursor;
pfn_XcursorImagesDestroy _XcursorImagesDestroy;
pfn_XcursorImageCreate _XcursorImageCreate;
pfn_XcursorImageLoadCursor _XcursorImageLoadCursor;
pfn_XcursorImageDestroy _XcursorImageDestroy;
typedef Bool (*pfn_XRRQueryExtension)(X11_Display *, int*, int*);
typedef XRRScreenSize *(*pfn_XRRSizes)(X11_Display*, int, int*);
typedef short *(*pfn_XRRRates)(X11_Display*, int, int, int*);
typedef XRRScreenConfiguration *(*pfn_XRRGetScreenInfo)(X11_Display*, X11_Window);
typedef SizeID (*pfn_XRRConfigCurrentConfiguration)(XRRScreenConfiguration*, Rotation*);
typedef Status (*pfn_XRRSetScreenConfig)(X11_Display*, XRRScreenConfiguration *,
Drawable, int, Rotation, Time);
bool _have_xrandr;
pfn_XRRSizes _XRRSizes;
pfn_XRRRates _XRRRates;
pfn_XRRGetScreenInfo _XRRGetScreenInfo;
pfn_XRRConfigCurrentConfiguration _XRRConfigCurrentConfiguration;
pfn_XRRSetScreenConfig _XRRSetScreenConfig;
protected:
X11_Display *_display;
int _screen;
@ -69,6 +121,10 @@ protected:
X11_Cursor _hidden_cursor;
typedef Bool (*pfn_XF86DGAQueryVersion)(X11_Display *, int*, int*);
typedef Status (*pfn_XF86DGADirectVideo)(X11_Display *, int, int);
pfn_XF86DGADirectVideo _XF86DGADirectVideo;
private:
void make_hidden_cursor();
void release_hidden_cursor();

View File

@ -38,7 +38,24 @@
#include <linux/input.h>
#endif
#ifdef HAVE_XCURSOR
struct _XcursorFile {
void *closure;
int (*read)(XcursorFile *, unsigned char *, int);
int (*write)(XcursorFile *, unsigned char *, int);
int (*seek)(XcursorFile *, long, int);
};
typedef struct _XcursorImage {
unsigned int version;
unsigned int size;
unsigned int width;
unsigned int height;
unsigned int xhot;
unsigned int yhot;
unsigned int delay;
unsigned int *pixels;
} XcursorImage;
static int xcursor_read(XcursorFile *file, unsigned char *buf, int len) {
istream* str = (istream*) file->closure;
str->read((char*) buf, len);
@ -66,7 +83,6 @@ static int xcursor_seek(XcursorFile *file, long offset, int whence) {
return str->tellg();
}
#endif
TypeHandle x11GraphicsWindow::_type_handle;
@ -92,14 +108,14 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
_xwindow = (X11_Window)NULL;
_ic = (XIC)NULL;
_visual_info = NULL;
#ifdef HAVE_XRANDR
_orig_size_id = -1;
int event, error;
_have_xrandr = XRRQueryExtension(_display, &event, &error);
#else
_have_xrandr = false;
#endif
if (x11_pipe->_have_xrandr) {
// We may still need these functions after the pipe is already destroyed,
// so we copy them into the x11GraphicsWindow.
_XRRGetScreenInfo = x11_pipe->_XRRGetScreenInfo;
_XRRSetScreenConfig = x11_pipe->_XRRSetScreenConfig;
}
_awaiting_configure = false;
_dga_mouse_enabled = false;
@ -474,10 +490,9 @@ set_properties_now(WindowProperties &properties) {
if (is_fullscreen != want_fullscreen || (is_fullscreen && properties.has_size())) {
if (want_fullscreen) {
if (_have_xrandr) {
#ifdef HAVE_XRANDR
XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root());
SizeID old_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
if (x11_pipe->_have_xrandr) {
XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root());
SizeID old_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation);
SizeID new_size_id = (SizeID) -1;
int num_sizes = 0, reqsizex, reqsizey;
if (properties.has_size()) {
@ -488,7 +503,7 @@ set_properties_now(WindowProperties &properties) {
reqsizey = _properties.get_y_size();
}
XRRScreenSize *xrrs;
xrrs = XRRSizes(_display, 0, &num_sizes);
xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes);
for (int i = 0; i < num_sizes; ++i) {
if (xrrs[i].width == reqsizex &&
xrrs[i].height == reqsizey) {
@ -502,14 +517,13 @@ set_properties_now(WindowProperties &properties) {
} else {
if (new_size_id != old_size_id) {
XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
_XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
if (_orig_size_id == (SizeID) -1) {
// Remember the original resolution so we can switch back to it.
_orig_size_id = old_size_id;
}
}
}
#endif
} else {
// If we don't have Xrandr support, we fake the fullscreen support by
// setting the window size to the desktop size.
@ -517,15 +531,13 @@ set_properties_now(WindowProperties &properties) {
x11_pipe->get_display_height());
}
} else {
#ifdef HAVE_XRANDR
// Change the resolution back to what it was. Don't remove the SizeID
// typecast!
if (_have_xrandr && _orig_size_id != (SizeID) -1) {
XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root());
XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), _orig_size_id, _orig_rotation, CurrentTime);
if (_orig_size_id != (SizeID) -1) {
XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, x11_pipe->get_root());
_XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), _orig_size_id, _orig_rotation, CurrentTime);
_orig_size_id = (SizeID) -1;
}
#endif
// Set the origin back to what it was
if (!properties.has_origin() && _properties.has_origin()) {
properties.set_origin(_properties.get_x_origin(), _properties.get_y_origin());
@ -686,23 +698,17 @@ set_properties_now(WindowProperties &properties) {
switch (properties.get_mouse_mode()) {
case WindowProperties::M_absolute:
XUngrabPointer(_display, CurrentTime);
#ifdef HAVE_XF86DGA
if (_dga_mouse_enabled) {
x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n";
XF86DGADirectVideo(_display, _screen, 0);
x11_pipe->disable_relative_mouse();
_dga_mouse_enabled = false;
}
#endif
_properties.set_mouse_mode(WindowProperties::M_absolute);
properties.clear_mouse_mode();
break;
case WindowProperties::M_relative:
#ifdef HAVE_XF86DGA
if (!_dga_mouse_enabled) {
int major_ver, minor_ver;
if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
if (x11_pipe->supports_relative_mouse()) {
X11_Cursor cursor = None;
if (_properties.get_cursor_hidden()) {
x11GraphicsPipe *x11_pipe;
@ -714,8 +720,7 @@ set_properties_now(WindowProperties &properties) {
GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
x11display_cat.error() << "Failed to grab pointer!\n";
} else {
x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n";
XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
x11_pipe->enable_relative_mouse();
_properties.set_mouse_mode(WindowProperties::M_relative);
properties.clear_mouse_mode();
@ -730,25 +735,24 @@ set_properties_now(WindowProperties &properties) {
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
}
} else {
x11display_cat.info() << "XF86DGA extension not available\n";
x11display_cat.info()
<< "XF86DGA extension not available, cannot enable relative mouse mode\n";
_dga_mouse_enabled = false;
}
}
#endif
break;
case WindowProperties::M_confined:
{
#ifdef HAVE_XF86DGA
x11GraphicsPipe *x11_pipe;
DCAST_INTO_V(x11_pipe, _pipe);
if (_dga_mouse_enabled) {
XF86DGADirectVideo(_display, _screen, 0);
x11_pipe->disable_relative_mouse();
_dga_mouse_enabled = false;
}
#endif
X11_Cursor cursor = None;
if (_properties.get_cursor_hidden()) {
x11GraphicsPipe *x11_pipe;
DCAST_INTO_V(x11_pipe, _pipe);
cursor = x11_pipe->get_hidden_cursor();
}
@ -813,10 +817,9 @@ close_window() {
XFlush(_display);
}
#ifdef HAVE_XRANDR
// Change the resolution back to what it was. Don't remove the SizeID
// typecast!
if (_have_xrandr && _orig_size_id != (SizeID) -1) {
if (_orig_size_id != (SizeID) -1) {
X11_Window root;
if (_pipe != NULL) {
x11GraphicsPipe *x11_pipe;
@ -827,11 +830,10 @@ close_window() {
// closed. Oh well, let's get the root window by ourselves.
root = RootWindow(_display, _screen);
}
XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, root);
XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime);
XRRScreenConfiguration *conf = _XRRGetScreenInfo(_display, root);
_XRRSetScreenConfig(_display, conf, root, _orig_size_id, _orig_rotation, CurrentTime);
_orig_size_id = -1;
}
#endif
GraphicsWindow::close_window();
}
@ -859,15 +861,14 @@ open_window() {
_properties.set_size(100, 100);
}
#ifdef HAVE_XRANDR
if (_properties.get_fullscreen() && _have_xrandr) {
XRRScreenConfiguration* conf = XRRGetScreenInfo(_display, x11_pipe->get_root());
if (_properties.get_fullscreen() && x11_pipe->_have_xrandr) {
XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root());
if (_orig_size_id == (SizeID) -1) {
_orig_size_id = XRRConfigCurrentConfiguration(conf, &_orig_rotation);
_orig_size_id = x11_pipe->_XRRConfigCurrentConfiguration(conf, &_orig_rotation);
}
int num_sizes, new_size_id = -1;
XRRScreenSize *xrrs;
xrrs = XRRSizes(_display, 0, &num_sizes);
xrrs = x11_pipe->_XRRSizes(_display, 0, &num_sizes);
for (int i = 0; i < num_sizes; ++i) {
if (xrrs[i].width == _properties.get_x_size() &&
xrrs[i].height == _properties.get_y_size()) {
@ -882,12 +883,11 @@ open_window() {
return false;
}
if (new_size_id != _orig_size_id) {
XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
_XRRSetScreenConfig(_display, conf, x11_pipe->get_root(), new_size_id, _orig_rotation, CurrentTime);
} else {
_orig_size_id = -1;
}
}
#endif
X11_Window parent_window = x11_pipe->get_root();
WindowHandle *window_handle = _properties.get_parent_window();
@ -2081,11 +2081,15 @@ check_event(X11_Display *display, XEvent *event, char *arg) {
*/
X11_Cursor x11GraphicsWindow::
get_cursor(const Filename &filename) {
#ifndef HAVE_XCURSOR
x11display_cat.info()
<< "XCursor support not enabled in build; cannot change mouse cursor.\n";
return None;
#else // HAVE_XCURSOR
x11GraphicsPipe *x11_pipe;
DCAST_INTO_R(x11_pipe, _pipe, None);
if (x11_pipe->_xcursor_size == -1) {
x11display_cat.info()
<< "libXcursor.so.1 not available; cannot change mouse cursor.\n";
return None;
}
// First, look for the unresolved filename in our index.
pmap<Filename, X11_Cursor>::iterator fi = _cursor_filenames.find(filename);
if (fi != _cursor_filenames.end()) {
@ -2135,10 +2139,10 @@ get_cursor(const Filename &filename) {
xcfile.write = &xcursor_write;
xcfile.seek = &xcursor_seek;
XcursorImages *images = XcursorXcFileLoadImages(&xcfile, XcursorGetDefaultSize(_display));
XcursorImages *images = x11_pipe->_XcursorXcFileLoadImages(&xcfile, x11_pipe->_xcursor_size);
if (images != NULL) {
h = XcursorImagesLoadCursor(_display, images);
XcursorImagesDestroy(images);
h = x11_pipe->_XcursorImagesLoadCursor(_display, images);
x11_pipe->_XcursorImagesDestroy(images);
}
} else if (memcmp(magic, "\0\0\1\0", 4) == 0
@ -2159,18 +2163,19 @@ get_cursor(const Filename &filename) {
_cursor_filenames[resolved] = h;
return h;
#endif // HAVE_XCURSOR
}
#ifdef HAVE_XCURSOR
/**
* Reads a Windows .ico or .cur file from the indicated stream and returns it
* as an X11 Cursor. If the file cannot be loaded, returns None.
*/
X11_Cursor x11GraphicsWindow::
read_ico(istream &ico) {
// Local structs, this is just POD, make input easier
typedef struct {
x11GraphicsPipe *x11_pipe;
DCAST_INTO_R(x11_pipe, _pipe, None);
// Local structs, this is just POD, make input easier
typedef struct {
uint16_t reserved, type, count;
} IcoHeader;
@ -2204,7 +2209,7 @@ read_ico(istream &ico) {
XcursorImage *image = NULL;
X11_Cursor ret = None;
int def_size = XcursorGetDefaultSize(_display);
int def_size = x11_pipe->_xcursor_size;
// Get our header, note that ICO = type 1 and CUR = type 2.
ico.read(reinterpret_cast<char *>(&header), sizeof(IcoHeader));
@ -2240,7 +2245,7 @@ read_ico(istream &ico) {
}
img.set_maxval(255);
image = XcursorImageCreate(img.get_x_size(), img.get_y_size());
image = x11_pipe->_XcursorImageCreate(img.get_x_size(), img.get_y_size());
xel *ptr = img.get_array();
xelval *alpha = img.get_alpha_array();
@ -2285,7 +2290,7 @@ read_ico(istream &ico) {
ico.read(andBmp, andBmpSize);
if (!ico.good()) goto cleanup;
image = XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
image = x11_pipe->_XcursorImageCreate(infoHeader.width, infoHeader.height / 2);
// Support all the formats that GIMP supports.
switch (bitsPerPixel) {
@ -2370,10 +2375,10 @@ read_ico(istream &ico) {
image->yhot = 0;
}
ret = XcursorImageLoadCursor(_display, image);
ret = x11_pipe->_XcursorImageLoadCursor(_display, image);
cleanup:
XcursorImageDestroy(image);
x11_pipe->_XcursorImageDestroy(image);
delete[] entries;
delete[] palette;
delete[] xorBmp;
@ -2381,4 +2386,3 @@ cleanup:
return ret;
}
#endif // HAVE_XCURSOR

View File

@ -20,11 +20,6 @@
#include "graphicsWindow.h"
#include "buttonHandle.h"
#ifdef HAVE_XRANDR
typedef unsigned short Rotation;
typedef unsigned short SizeID;
#endif
/**
* Interfaces to the X11 window system.
*/
@ -76,9 +71,7 @@ protected:
private:
X11_Cursor get_cursor(const Filename &filename);
#ifdef HAVE_XCURSOR
X11_Cursor read_ico(istream &ico);
#endif
protected:
X11_Display *_display;
@ -87,12 +80,8 @@ protected:
Colormap _colormap;
XIC _ic;
XVisualInfo *_visual_info;
bool _have_xrandr;
#ifdef HAVE_XRANDR
Rotation _orig_rotation;
SizeID _orig_size_id;
#endif
LVecBase2i _fixed_size;
@ -109,6 +98,9 @@ protected:
};
pvector<MouseDeviceInfo> _mouse_device_info;
x11GraphicsPipe::pfn_XRRGetScreenInfo _XRRGetScreenInfo;
x11GraphicsPipe::pfn_XRRSetScreenConfig _XRRSetScreenConfig;
public:
static TypeHandle get_class_type() {
return _type_handle;