mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
Merge branch 'release/1.9.x'
This commit is contained in:
commit
24ec0d6c46
@ -157,6 +157,10 @@ AuthDialog(const string &cert_filename, const string &cert_dir) :
|
||||
_stack = NULL;
|
||||
_verify_result = -1;
|
||||
|
||||
// Center the window on the screen.
|
||||
position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
|
||||
set_modal();
|
||||
|
||||
read_cert_file(cert_filename);
|
||||
get_friendly_name();
|
||||
verify_cert();
|
||||
@ -583,6 +587,10 @@ ViewCertDialog(AuthDialog *auth_dialog, X509 *cert) :
|
||||
_auth_dialog(auth_dialog),
|
||||
_cert(cert)
|
||||
{
|
||||
// Center the window on the screen.
|
||||
position((Fl::w() - w()) / 2, (Fl::h() - h()) / 2);
|
||||
set_modal();
|
||||
|
||||
layout();
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#ifdef HAVE_X11
|
||||
#ifdef HAVE_X11
|
||||
// This header file is designed to help work around some of the
|
||||
// namespace spamming that X11 causes, by renaming the symbols that
|
||||
// X11 declares that are known to conflict with other library names
|
||||
@ -30,14 +30,21 @@
|
||||
#ifdef CPPPARSER
|
||||
// A simple hack so interrogate can get all of the necessary
|
||||
// typenames.
|
||||
typedef int X11_Display;
|
||||
typedef int X11_Window;
|
||||
typedef int X11_Cursor;
|
||||
typedef int XErrorEvent;
|
||||
typedef int XVisualInfo;
|
||||
typedef int Atom;
|
||||
typedef int XIM;
|
||||
typedef int XIC;
|
||||
typedef struct _XDisplay X11_Display;
|
||||
typedef unsigned int XID;
|
||||
typedef unsigned int Atom;
|
||||
typedef unsigned int Cardinal;
|
||||
typedef XID Colormap;
|
||||
typedef XID X11_Window;
|
||||
typedef XID X11_Cursor;
|
||||
typedef struct _XIM *XIM;
|
||||
typedef struct _XIC *XIC;
|
||||
struct XErrorEvent;
|
||||
struct XVisualInfo;
|
||||
#define Bool int
|
||||
#define Status int
|
||||
#define True 1
|
||||
#define False 0
|
||||
#else
|
||||
|
||||
#include "pre_x11_include.h"
|
||||
@ -45,6 +52,7 @@ typedef int XIC;
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
|
||||
#ifdef HAVE_XRANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
@ -207,6 +207,20 @@ get_y_size() const {
|
||||
return _size.get_y();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_fb_size
|
||||
// Access: Published
|
||||
// Description: Returns the internal size of the window or buffer.
|
||||
// This is almost always the same as get_size(),
|
||||
// except when a pixel_zoom is in effect--see
|
||||
// set_pixel_zoom().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LVecBase2i GraphicsOutput::
|
||||
get_fb_size() const {
|
||||
return LVecBase2i(max(int(_size.get_x() * get_pixel_factor()), 1),
|
||||
max(int(_size.get_y() * get_pixel_factor()), 1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_fb_x_size
|
||||
// Access: Published
|
||||
@ -233,6 +247,23 @@ get_fb_y_size() const {
|
||||
return max(int(_size.get_y() * get_pixel_factor()), 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_sbs_left_size
|
||||
// Access: Published
|
||||
// Description: If side-by-side stereo is enabled, this returns the
|
||||
// pixel size of the left eye, based on scaling
|
||||
// get_size() by get_sbs_left_dimensions(). If
|
||||
// side-by-side stereo is not enabled, this returns the
|
||||
// same as get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LVecBase2i GraphicsOutput::
|
||||
get_sbs_left_size() const {
|
||||
PN_stdfloat left_w = _sbs_left_dimensions[1] - _sbs_left_dimensions[0];
|
||||
PN_stdfloat left_h = _sbs_left_dimensions[3] - _sbs_left_dimensions[2];
|
||||
return LVecBase2i(max(int(_size.get_x() * left_w), 1),
|
||||
max(int(_size.get_y() * left_h), 1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_sbs_left_x_size
|
||||
// Access: Published
|
||||
@ -263,6 +294,23 @@ get_sbs_left_y_size() const {
|
||||
return max(int(_size.get_y() * left_h), 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_sbs_right_size
|
||||
// Access: Published
|
||||
// Description: If side-by-side stereo is enabled, this returns the
|
||||
// pixel size of the right eye, based on scaling
|
||||
// get_size() by get_sbs_right_dimensions(). If
|
||||
// side-by-side stereo is not enabled, this returns the
|
||||
// same as get_size().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LVecBase2i GraphicsOutput::
|
||||
get_sbs_right_size() const {
|
||||
PN_stdfloat right_w = _sbs_right_dimensions[1] - _sbs_right_dimensions[0];
|
||||
PN_stdfloat right_h = _sbs_right_dimensions[3] - _sbs_right_dimensions[2];
|
||||
return LVecBase2i(max(int(_size.get_x() * right_w), 1),
|
||||
max(int(_size.get_y() * right_h), 1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsOutput::get_sbs_right_x_size
|
||||
// Access: Published
|
||||
|
@ -135,10 +135,13 @@ PUBLISHED:
|
||||
INLINE const LVecBase2i &get_size() const;
|
||||
INLINE int get_x_size() const;
|
||||
INLINE int get_y_size() const;
|
||||
INLINE LVecBase2i get_fb_size() const;
|
||||
INLINE int get_fb_x_size() const;
|
||||
INLINE int get_fb_y_size() const;
|
||||
INLINE LVecBase2i get_sbs_left_size() const;
|
||||
INLINE int get_sbs_left_x_size() const;
|
||||
INLINE int get_sbs_left_y_size() const;
|
||||
INLINE LVecBase2i get_sbs_right_size() const;
|
||||
INLINE int get_sbs_right_x_size() const;
|
||||
INLINE int get_sbs_right_y_size() const;
|
||||
INLINE bool has_size() const;
|
||||
|
@ -736,24 +736,10 @@ set_properties_now(WindowProperties &properties) {
|
||||
// Fullscreen property specified, but unchanged.
|
||||
properties.clear_fullscreen();
|
||||
}
|
||||
if (properties.has_mouse_mode() ) {
|
||||
|
||||
if (properties.get_mouse_mode() == _properties.get_mouse_mode()) {
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
else {
|
||||
if(properties.get_mouse_mode() == WindowProperties::M_absolute) {
|
||||
_properties.set_mouse_mode(WindowProperties::M_absolute);
|
||||
mouse_mode_absolute();
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
else
|
||||
{
|
||||
_properties.set_mouse_mode(WindowProperties::M_relative);
|
||||
mouse_mode_relative();
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
}
|
||||
if (properties.has_mouse_mode() &&
|
||||
properties.get_mouse_mode() == _properties.get_mouse_mode()) {
|
||||
// Mouse mode specified, but unchanged.
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -798,19 +798,30 @@ clear_z_order() {
|
||||
// Function: WindowProperties::set_mouse_mode
|
||||
// Access: Published
|
||||
// Description: Specifies the mode in which the window is to operate
|
||||
// its mouse pointer. The default is M_absolute, which
|
||||
// is the normal mode in which a mouse pointer operates;
|
||||
// but you can also set M_relative, which is
|
||||
// particularly useful for FPS-style mouse movements
|
||||
// where you have hidden the mouse pointer and are are
|
||||
// more interested in how fast the mouse is moving,
|
||||
// rather than precisely where the pointer is hovering.
|
||||
// its mouse pointer.
|
||||
//
|
||||
// M_absolute: the normal mode in which a mouse pointer
|
||||
// operates, where the mouse can move outside the window
|
||||
// and the mouse coordinates are relative to its
|
||||
// position in the window.
|
||||
//
|
||||
// M_relative (OSX or Unix/X11 only): a mode where only
|
||||
// relative movements are reported; particularly useful
|
||||
// for FPS-style mouse movements where you have hidden
|
||||
// the mouse pointer and are are more interested in how
|
||||
// fast the mouse is moving, rather than precisely where
|
||||
// the pointer is hovering.
|
||||
//
|
||||
// This has no effect on Windows. On Unix/X11, this
|
||||
// requires the Xxf86dga extension to be available.
|
||||
//
|
||||
// M_confined: this mode reports absolute mouse
|
||||
// positions, but confines the mouse pointer to
|
||||
// the window boundary. It can portably replace
|
||||
// M_relative for an FPS, but you need to periodically
|
||||
// move the pointer to the center of the window
|
||||
// and track movement deltas.
|
||||
//
|
||||
// This has no effect on Windows, which does not
|
||||
// have this concept; but is important to do on OSX
|
||||
// and Unix/X11 to properly enable a smooth FPS-style
|
||||
// mouselook mode. On Unix/X11, this requires the
|
||||
// Xxf86dga extension to be available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void WindowProperties::
|
||||
set_mouse_mode(MouseMode mode) {
|
||||
|
@ -400,6 +400,8 @@ operator << (ostream &out, WindowProperties::MouseMode mode) {
|
||||
return out << "absolute";
|
||||
case WindowProperties::M_relative:
|
||||
return out << "relative";
|
||||
case WindowProperties::M_confined:
|
||||
return out << "confined";
|
||||
}
|
||||
return out << "**invalid WindowProperties::MouseMode(" << (int)mode << ")**";
|
||||
}
|
||||
@ -413,6 +415,8 @@ operator >> (istream &in, WindowProperties::MouseMode &mode) {
|
||||
mode = WindowProperties::M_absolute;
|
||||
} else if (word == "relative") {
|
||||
mode = WindowProperties::M_relative;
|
||||
} else if (word == "confined") {
|
||||
mode = WindowProperties::M_confined;
|
||||
} else {
|
||||
display_cat.warning()
|
||||
<< "Unknown mouse mode: " << word << "\n";
|
||||
|
@ -40,6 +40,7 @@ PUBLISHED:
|
||||
enum MouseMode {
|
||||
M_absolute,
|
||||
M_relative,
|
||||
M_confined,
|
||||
};
|
||||
|
||||
WindowProperties();
|
||||
|
@ -6979,16 +6979,20 @@ query_gl_version() {
|
||||
_gl_shadlang_ver_major = 1;
|
||||
_gl_shadlang_ver_minor = 1;
|
||||
const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
if (verstr == NULL || sscanf(verstr, "%d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) {
|
||||
GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
|
||||
if (verstr == NULL ||
|
||||
sscanf(verstr, "%d.%d", &_gl_shadlang_ver_major,
|
||||
&_gl_shadlang_ver_minor) != 2) {
|
||||
GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
|
||||
}
|
||||
}
|
||||
#elif defined(OPENGLES_2)
|
||||
_gl_shadlang_ver_major = 1;
|
||||
_gl_shadlang_ver_minor = 0;
|
||||
const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
if (verstr == NULL || sscanf(verstr, "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) {
|
||||
GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
|
||||
if (verstr == NULL ||
|
||||
sscanf(verstr, "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major,
|
||||
&_gl_shadlang_ver_minor) != 2) {
|
||||
GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ ConfigVariableBool vertices_float64
|
||||
"slower."));
|
||||
|
||||
ConfigVariableInt vertex_column_alignment
|
||||
("vertex-column-alignment", 1,
|
||||
("vertex-column-alignment", 4,
|
||||
PRC_DESC("This specifies the default byte alignment for each column of "
|
||||
"data within a GeomVertexData when it is assembled using the default "
|
||||
"interfaces. Normally, you should not change this config variable "
|
||||
|
@ -56,12 +56,14 @@ PUBLISHED:
|
||||
|
||||
INLINE_MATHUTIL bool extend_by(const BoundingVolume *vol);
|
||||
|
||||
public:
|
||||
// It might be nice to make these template member functions so we
|
||||
// could have true STL-style first/last iterators, but that's
|
||||
// impossible for virtual functions.
|
||||
bool around(const BoundingVolume **first,
|
||||
const BoundingVolume **last);
|
||||
|
||||
PUBLISHED:
|
||||
// The contains() functions return the union of one or more of these
|
||||
// bits.
|
||||
enum IntersectionFlags {
|
||||
|
@ -36,6 +36,7 @@ PUBLISHED:
|
||||
INLINE_MATHUTIL bool extend_by(const GeometricBoundingVolume *vol);
|
||||
INLINE_MATHUTIL bool extend_by(const LPoint3 &point);
|
||||
|
||||
public:
|
||||
// It might be nice to make these template member functions so we
|
||||
// could have true STL-style first/last iterators, but that's
|
||||
// impossible for virtual functions.
|
||||
@ -43,6 +44,7 @@ PUBLISHED:
|
||||
const GeometricBoundingVolume **last);
|
||||
INLINE_MATHUTIL bool around(const LPoint3 *first, const LPoint3 *last);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE_MATHUTIL int contains(const GeometricBoundingVolume *vol) const;
|
||||
INLINE_MATHUTIL int contains(const LPoint3 &point) const;
|
||||
INLINE_MATHUTIL int contains(const LPoint3 &a, const LPoint3 &b) const;
|
||||
|
@ -35,6 +35,8 @@ WinGraphicsWindow *WinGraphicsWindow::_creating_window = NULL;
|
||||
WinGraphicsWindow *WinGraphicsWindow::_cursor_window = NULL;
|
||||
bool WinGraphicsWindow::_cursor_hidden = false;
|
||||
|
||||
RECT WinGraphicsWindow::_mouse_unconfined_cliprect;
|
||||
|
||||
// These are used to save the previous state of the fancy Win2000
|
||||
// effects that interfere with rendering when the mouse wanders into a
|
||||
// window's client area.
|
||||
@ -359,6 +361,48 @@ set_properties_now(WindowProperties &properties) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.has_mouse_mode()) {
|
||||
if (properties.get_mouse_mode() != _properties.get_mouse_mode()) {
|
||||
switch (properties.get_mouse_mode()) {
|
||||
case WindowProperties::M_absolute:
|
||||
case WindowProperties::M_relative: // not implemented, treat as absolute
|
||||
|
||||
if (_properties.get_mouse_mode() == WindowProperties::M_confined) {
|
||||
ClipCursor(NULL);
|
||||
windisplay_cat.info() << "Unconfining cursor from window\n";
|
||||
}
|
||||
_properties.set_mouse_mode(WindowProperties::M_absolute);
|
||||
break;
|
||||
|
||||
case WindowProperties::M_confined:
|
||||
{
|
||||
RECT clip;
|
||||
|
||||
if (!GetWindowRect(_hWnd, &clip)) {
|
||||
windisplay_cat.warning()
|
||||
<< "GetWindowRect() failed in set_properties_now. Cannot confine cursor.\n";
|
||||
} else {
|
||||
windisplay_cat.info()
|
||||
<< "ClipCursor() to " << clip.left << "," << clip.top << " to "
|
||||
<< clip.right << "," << clip.bottom << endl;
|
||||
|
||||
GetClipCursor(&_mouse_unconfined_cliprect);
|
||||
if (!ClipCursor(&clip)) {
|
||||
windisplay_cat.warning()
|
||||
<< "ClipCursor() failed in set_properties_now. Ignoring.\n";
|
||||
} else {
|
||||
_properties.set_mouse_mode(WindowProperties::M_confined);
|
||||
windisplay_cat.info() << "Confining cursor to window\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -214,6 +214,9 @@ private:
|
||||
static BOOL _saved_cursor_shadow;
|
||||
static BOOL _saved_mouse_vanish;
|
||||
|
||||
// The mouse constraints before applying mouse mode M_confined.
|
||||
static RECT _mouse_unconfined_cliprect;
|
||||
|
||||
// Since the Panda API requests icons and cursors by filename, we
|
||||
// need a table mapping filenames to handles, so we can avoid
|
||||
// re-reading the file each time we change icons.
|
||||
|
@ -140,6 +140,7 @@ x11GraphicsPipe(const string &display) {
|
||||
|
||||
// Get some X atom numbers.
|
||||
_wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
|
||||
_net_wm_pid = XInternAtom(_display, "_NET_WM_PID", false);
|
||||
_net_wm_window_type = XInternAtom(_display, "_NET_WM_WINDOW_TYPE", false);
|
||||
_net_wm_window_type_splash = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_SPLASH", false);
|
||||
_net_wm_window_type_fullscreen = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_FULLSCREEN", false);
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
public:
|
||||
// Atom specifications.
|
||||
Atom _wm_delete_window;
|
||||
Atom _net_wm_pid;
|
||||
Atom _net_wm_window_type;
|
||||
Atom _net_wm_window_type_splash;
|
||||
Atom _net_wm_window_type_fullscreen;
|
||||
|
@ -105,15 +105,6 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
||||
_awaiting_configure = false;
|
||||
_dga_mouse_enabled = false;
|
||||
_wm_delete_window = x11_pipe->_wm_delete_window;
|
||||
_net_wm_window_type = x11_pipe->_net_wm_window_type;
|
||||
_net_wm_window_type_splash = x11_pipe->_net_wm_window_type_splash;
|
||||
_net_wm_window_type_fullscreen = x11_pipe->_net_wm_window_type_fullscreen;
|
||||
_net_wm_state = x11_pipe->_net_wm_state;
|
||||
_net_wm_state_fullscreen = x11_pipe->_net_wm_state_fullscreen;
|
||||
_net_wm_state_above = x11_pipe->_net_wm_state_above;
|
||||
_net_wm_state_below = x11_pipe->_net_wm_state_below;
|
||||
_net_wm_state_add = x11_pipe->_net_wm_state_add;
|
||||
_net_wm_state_remove = x11_pipe->_net_wm_state_remove;
|
||||
|
||||
GraphicsWindowInputDevice device =
|
||||
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
|
||||
@ -175,7 +166,6 @@ move_pointer(int device, int x, int y) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: x11GraphicsWindow::begin_frame
|
||||
// Access: Public, Virtual
|
||||
@ -711,6 +701,88 @@ set_properties_now(WindowProperties &properties) {
|
||||
properties.clear_foreground();
|
||||
}
|
||||
|
||||
if (properties.has_mouse_mode()) {
|
||||
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);
|
||||
_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)) {
|
||||
|
||||
X11_Cursor cursor = None;
|
||||
if (_properties.get_cursor_hidden()) {
|
||||
x11GraphicsPipe *x11_pipe;
|
||||
DCAST_INTO_V(x11_pipe, _pipe);
|
||||
cursor = x11_pipe->get_hidden_cursor();
|
||||
}
|
||||
|
||||
if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
|
||||
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);
|
||||
|
||||
_properties.set_mouse_mode(WindowProperties::M_relative);
|
||||
properties.clear_mouse_mode();
|
||||
_dga_mouse_enabled = true;
|
||||
|
||||
// Get the real mouse position, so we can add/subtract
|
||||
// our relative coordinates later.
|
||||
XEvent event;
|
||||
XQueryPointer(_display, _xwindow, &event.xbutton.root,
|
||||
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
|
||||
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
|
||||
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
|
||||
}
|
||||
} else {
|
||||
x11display_cat.info() << "XF86DGA extension not available\n";
|
||||
_dga_mouse_enabled = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case WindowProperties::M_confined:
|
||||
{
|
||||
#ifdef HAVE_XF86DGA
|
||||
if (_dga_mouse_enabled) {
|
||||
XF86DGADirectVideo(_display, _screen, 0);
|
||||
_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();
|
||||
}
|
||||
|
||||
if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
|
||||
GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
|
||||
x11display_cat.error() << "Failed to grab pointer!\n";
|
||||
} else {
|
||||
_properties.set_mouse_mode(WindowProperties::M_confined);
|
||||
properties.clear_mouse_mode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_wm_properties(wm_properties, true);
|
||||
}
|
||||
|
||||
@ -721,14 +793,7 @@ set_properties_now(WindowProperties &properties) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void x11GraphicsWindow::
|
||||
mouse_mode_absolute() {
|
||||
#ifdef HAVE_XF86DGA
|
||||
if (!_dga_mouse_enabled) return;
|
||||
|
||||
XUngrabPointer(_display, CurrentTime);
|
||||
x11display_cat.info() << "Disabling relative mouse using XF86DGA extension\n";
|
||||
XF86DGADirectVideo(_display, _screen, 0);
|
||||
_dga_mouse_enabled = false;
|
||||
#endif
|
||||
// unused: remove in 1.10!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -738,42 +803,7 @@ mouse_mode_absolute() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void x11GraphicsWindow::
|
||||
mouse_mode_relative() {
|
||||
#ifdef HAVE_XF86DGA
|
||||
if (_dga_mouse_enabled) return;
|
||||
|
||||
int major_ver, minor_ver;
|
||||
if (XF86DGAQueryVersion(_display, &major_ver, &minor_ver)) {
|
||||
|
||||
X11_Cursor cursor = None;
|
||||
if (_properties.get_cursor_hidden()) {
|
||||
x11GraphicsPipe *x11_pipe;
|
||||
DCAST_INTO_V(x11_pipe, _pipe);
|
||||
cursor = x11_pipe->get_hidden_cursor();
|
||||
}
|
||||
|
||||
if (XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync,
|
||||
GrabModeAsync, _xwindow, cursor, CurrentTime) != GrabSuccess) {
|
||||
x11display_cat.error() << "Failed to grab pointer!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
x11display_cat.info() << "Enabling relative mouse using XF86DGA extension\n";
|
||||
XF86DGADirectVideo(_display, _screen, XF86DGADirectMouse);
|
||||
|
||||
_dga_mouse_enabled = true;
|
||||
} else {
|
||||
x11display_cat.info() << "XF86DGA extension not available\n";
|
||||
_dga_mouse_enabled = false;
|
||||
}
|
||||
|
||||
// Get the real mouse position, so we can add/subtract
|
||||
// our relative coordinates later.
|
||||
XEvent event;
|
||||
XQueryPointer(_display, _xwindow, &event.xbutton.root,
|
||||
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
|
||||
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
|
||||
_input_devices[0].set_pointer_in_window(event.xbutton.x, event.xbutton.y);
|
||||
#endif
|
||||
// unused: remove in 1.10!
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -997,6 +1027,9 @@ open_window() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void x11GraphicsWindow::
|
||||
set_wm_properties(const WindowProperties &properties, bool already_mapped) {
|
||||
x11GraphicsPipe *x11_pipe;
|
||||
DCAST_INTO_V(x11_pipe, _pipe);
|
||||
|
||||
// Name the window if there is a name
|
||||
XTextProperty window_name;
|
||||
XTextProperty *window_name_p = (XTextProperty *)NULL;
|
||||
@ -1077,15 +1110,15 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
|
||||
if (properties.get_fullscreen()) {
|
||||
// For a "fullscreen" request, we pass this through, hoping the
|
||||
// window manager will support EWMH.
|
||||
type_data[next_type_data++] = _net_wm_window_type_fullscreen;
|
||||
type_data[next_type_data++] = x11_pipe->_net_wm_window_type_fullscreen;
|
||||
|
||||
// We also request it as a state.
|
||||
state_data[next_state_data++] = _net_wm_state_fullscreen;
|
||||
state_data[next_state_data++] = x11_pipe->_net_wm_state_fullscreen;
|
||||
// Don't ask me why this has to be 1/0 and not _net_wm_state_add.
|
||||
// It doesn't seem to work otherwise.
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, 1);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 1);
|
||||
} else {
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, 0);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_fullscreen, 0);
|
||||
}
|
||||
|
||||
// If we asked for a window without a border, there's no excellent
|
||||
@ -1112,26 +1145,32 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
|
||||
}
|
||||
|
||||
if (properties.get_undecorated() && !properties.get_fullscreen()) {
|
||||
type_data[next_type_data++] = _net_wm_window_type_splash;
|
||||
type_data[next_type_data++] = x11_pipe->_net_wm_window_type_splash;
|
||||
}
|
||||
|
||||
if (properties.has_z_order()) {
|
||||
switch (properties.get_z_order()) {
|
||||
case WindowProperties::Z_bottom:
|
||||
state_data[next_state_data++] = _net_wm_state_below;
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_add);
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
|
||||
state_data[next_state_data++] = x11_pipe->_net_wm_state_below;
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
|
||||
x11_pipe->_net_wm_state_add);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
|
||||
x11_pipe->_net_wm_state_remove);
|
||||
break;
|
||||
|
||||
case WindowProperties::Z_normal:
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
|
||||
x11_pipe->_net_wm_state_remove);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
|
||||
x11_pipe->_net_wm_state_remove);
|
||||
break;
|
||||
|
||||
case WindowProperties::Z_top:
|
||||
state_data[next_state_data++] = _net_wm_state_above;
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove);
|
||||
set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_add);
|
||||
state_data[next_state_data++] = x11_pipe->_net_wm_state_above;
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_below,
|
||||
x11_pipe->_net_wm_state_remove);
|
||||
set_data[next_set_data++] = SetAction(x11_pipe->_net_wm_state_above,
|
||||
x11_pipe->_net_wm_state_add);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1140,12 +1179,18 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
|
||||
nassertv(next_state_data < max_state_data);
|
||||
nassertv(next_set_data < max_set_data);
|
||||
|
||||
XChangeProperty(_display, _xwindow, _net_wm_window_type,
|
||||
// Add the process ID as a convenience for other applications.
|
||||
Cardinal pid = getpid();
|
||||
XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_pid,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char *)&pid, 1);
|
||||
|
||||
XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_window_type,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char *)type_data, next_type_data);
|
||||
|
||||
// Request the state properties all at once.
|
||||
XChangeProperty(_display, _xwindow, _net_wm_state,
|
||||
XChangeProperty(_display, _xwindow, x11_pipe->_net_wm_state,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char *)state_data, next_state_data);
|
||||
|
||||
@ -1164,7 +1209,7 @@ set_wm_properties(const WindowProperties &properties, bool already_mapped) {
|
||||
event.send_event = True;
|
||||
event.display = _display;
|
||||
event.window = _xwindow;
|
||||
event.message_type = _net_wm_state;
|
||||
event.message_type = x11_pipe->_net_wm_state;
|
||||
event.format = 32;
|
||||
event.data.l[0] = set_data[i]._action;
|
||||
event.data.l[1] = set_data[i]._state;
|
||||
|
@ -100,15 +100,6 @@ protected:
|
||||
bool _awaiting_configure;
|
||||
bool _dga_mouse_enabled;
|
||||
Atom _wm_delete_window;
|
||||
Atom _net_wm_window_type;
|
||||
Atom _net_wm_window_type_splash;
|
||||
Atom _net_wm_window_type_fullscreen;
|
||||
Atom _net_wm_state;
|
||||
Atom _net_wm_state_fullscreen;
|
||||
Atom _net_wm_state_above;
|
||||
Atom _net_wm_state_below;
|
||||
Atom _net_wm_state_add;
|
||||
Atom _net_wm_state_remove;
|
||||
|
||||
struct MouseDeviceInfo {
|
||||
int _fd;
|
||||
|
172
samples/mouse-modes/main.py
Normal file
172
samples/mouse-modes/main.py
Normal file
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Demonstrate different mouse modes
|
||||
'''
|
||||
|
||||
# from panda3d.core import loadPrcFileData
|
||||
#
|
||||
# loadPrcFileData("", "notify-level-x11display debug")
|
||||
# loadPrcFileData("", "notify-level-windisplay debug")
|
||||
#
|
||||
# loadPrcFileData("", "load-display p3tinydisplay")
|
||||
|
||||
from panda3d.core import WindowProperties, TextNode
|
||||
from direct.task.TaskManagerGlobal import taskMgr
|
||||
from direct.gui.OnscreenText import OnscreenText
|
||||
from direct.task import Task
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
|
||||
import sys
|
||||
|
||||
class App(ShowBase):
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
self.base = self
|
||||
self.setup()
|
||||
|
||||
def genLabelText(self, text, i):
|
||||
text = OnscreenText(text = text, pos = (-1.3, .5-.05*i), fg=(0,1,0,1),
|
||||
align = TextNode.ALeft, scale = .05)
|
||||
return text
|
||||
|
||||
|
||||
def setup(self):
|
||||
# Disable the camera trackball controls.
|
||||
self.disableMouse()
|
||||
|
||||
self.mouseMagnitude = 144
|
||||
|
||||
self.rotateX, self.rotateY = 0, 0
|
||||
|
||||
self.genLabelText("[0] Absolute mode, [1] Relative mode, [2] Confined mode", 0)
|
||||
|
||||
self.base.accept('0', lambda: self.setMouseMode(WindowProperties.M_absolute))
|
||||
self.base.accept('1', lambda: self.setMouseMode(WindowProperties.M_relative))
|
||||
self.base.accept('2', lambda: self.setMouseMode(WindowProperties.M_confined))
|
||||
|
||||
self.genLabelText("[C] Manually re-center mouse on each tick", 1)
|
||||
self.base.accept('C', lambda: self.toggleRecenter())
|
||||
self.base.accept('c', lambda: self.toggleRecenter())
|
||||
|
||||
self.genLabelText("[S] Show mouse", 2)
|
||||
self.base.accept('S', lambda: self.toggleMouse())
|
||||
self.base.accept('s', lambda: self.toggleMouse())
|
||||
|
||||
self.base.accept('escape', sys.exit, [0])
|
||||
|
||||
self.mouseText = self.genLabelText("", 5)
|
||||
self.deltaText = self.genLabelText("", 6)
|
||||
self.positionText = self.genLabelText("", 8)
|
||||
|
||||
self.lastMouseX, self.lastMouseY = None, None
|
||||
|
||||
self.hideMouse = False
|
||||
|
||||
self.setMouseMode(WindowProperties.M_absolute)
|
||||
self.manualRecenterMouse = True
|
||||
|
||||
# make a box to move with the mouse
|
||||
self.model = self.loader.loadModel("box.egg")
|
||||
self.model.reparentTo(self.render)
|
||||
|
||||
self.cam.setPos(0, -5, 0)
|
||||
self.cam.lookAt(0, 0, 0)
|
||||
|
||||
self.mouseTask = taskMgr.add(self.mouseTask, "Mouse Task")
|
||||
|
||||
def setMouseMode(self, mode):
|
||||
print "Changing mode to",mode
|
||||
|
||||
self.mouseMode = mode
|
||||
|
||||
wp = WindowProperties()
|
||||
wp.setMouseMode(mode)
|
||||
self.base.win.requestProperties(wp)
|
||||
|
||||
# these changes may require a tick to apply
|
||||
self.base.taskMgr.doMethodLater(0, self.resolveMouse, "Resolve mouse setting")
|
||||
|
||||
def resolveMouse(self, t):
|
||||
wp = self.base.win.getProperties()
|
||||
|
||||
actualMode = wp.getMouseMode()
|
||||
if self.mouseMode != actualMode:
|
||||
print "ACTUAL MOUSE MODE:", actualMode
|
||||
|
||||
self.mouseMode = actualMode
|
||||
|
||||
self.rotateX, self.rotateY = -.5, -.5
|
||||
self.lastMouseX, self.lastMouseY = None, None
|
||||
self.recenterMouse()
|
||||
|
||||
def recenterMouse(self):
|
||||
self.base.win.movePointer(0,
|
||||
int(self.base.win.getProperties().getXSize() / 2),
|
||||
int(self.base.win.getProperties().getYSize() / 2))
|
||||
|
||||
|
||||
def toggleRecenter(self):
|
||||
print "Toggling re-center behavior"
|
||||
self.manualRecenterMouse = not self.manualRecenterMouse
|
||||
|
||||
def toggleMouse(self):
|
||||
print "Toggling mouse visibility"
|
||||
|
||||
self.hideMouse = not self.hideMouse
|
||||
|
||||
wp = WindowProperties()
|
||||
wp.setCursorHidden(self.hideMouse)
|
||||
self.base.win.requestProperties(wp)
|
||||
|
||||
def mouseTask(self, task):
|
||||
mw = self.base.mouseWatcherNode
|
||||
|
||||
hasMouse = mw.hasMouse()
|
||||
if hasMouse:
|
||||
# get the window manager's idea of the mouse position
|
||||
x, y = mw.getMouseX(), mw.getMouseY()
|
||||
|
||||
if self.lastMouseX is not None:
|
||||
# get the delta
|
||||
if self.manualRecenterMouse:
|
||||
# when recentering, the position IS the delta
|
||||
# since the center is reported as 0, 0
|
||||
dx, dy = x, y
|
||||
else:
|
||||
dx, dy = x - self.lastMouseX, y - self.lastMouseY
|
||||
else:
|
||||
# no data to compare with yet
|
||||
dx, dy = 0, 0
|
||||
|
||||
self.lastMouseX, self.lastMouseY = x, y
|
||||
|
||||
else:
|
||||
x, y, dx, dy = 0, 0, 0, 0
|
||||
|
||||
if self.manualRecenterMouse:
|
||||
# move mouse back to center
|
||||
self.recenterMouse()
|
||||
|
||||
# scale position and delta to pixels for user
|
||||
w, h = self.win.getSize()
|
||||
|
||||
self.mouseText.setText("Mode: {0}, Recenter: {1} | Mouse: {2}, {3} | hasMouse: {4}".format(
|
||||
self.mouseMode, self.manualRecenterMouse,
|
||||
int(x*w), int(y*h),
|
||||
hasMouse))
|
||||
self.deltaText.setText("Delta: {0}, {1}".format(
|
||||
int(dx*w), int(dy*h)))
|
||||
|
||||
# rotate box by delta
|
||||
self.rotateX += dx * 10
|
||||
self.rotateY += dy * 10
|
||||
|
||||
self.positionText.setText("Model rotation: {0}, {1}".format(
|
||||
int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.))
|
||||
|
||||
self.model.setH(self.rotateX)
|
||||
self.model.setP(self.rotateY)
|
||||
return Task.cont
|
||||
|
||||
app = App()
|
||||
app.run()
|
Loading…
x
Reference in New Issue
Block a user