2011-04-19 19:46:05 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
2006-12-21 20:19:14 +08:00
|
|
|
*
|
2011-04-19 19:46:05 +08:00
|
|
|
* This library is open source and may be redistributed and/or modified under
|
|
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
2006-12-21 20:19:14 +08:00
|
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
|
|
* included with this distribution, and on the openscenegraph.org website.
|
2011-04-19 19:46:05 +08:00
|
|
|
*
|
2006-12-21 20:19:14 +08:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2011-04-19 19:46:05 +08:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2006-12-21 20:19:14 +08:00
|
|
|
* OpenSceneGraph Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Note, elements of GraphicsWindowX11 have used Prodcer/RenderSurface_X11.cpp as both
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
* a guide to use of X11/GLX and copying directly in the case of setBorder().
|
|
|
|
* These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004 Don Burns.
|
2006-12-21 20:19:14 +08:00
|
|
|
*/
|
|
|
|
|
2010-12-12 18:00:57 +08:00
|
|
|
// TODO:
|
|
|
|
// implement http://www.opengl.org/registry/specs/OML/glx_swap_method.txt
|
|
|
|
|
2007-04-10 19:03:37 +08:00
|
|
|
#include <osgViewer/api/X11/GraphicsWindowX11>
|
2007-06-20 01:12:05 +08:00
|
|
|
#include <osgViewer/api/X11/PixelBufferX11>
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2007-07-06 21:08:51 +08:00
|
|
|
#include <osg/DeleteHandler>
|
|
|
|
|
2006-12-21 20:24:20 +08:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
|
|
#include <X11/Xmd.h>
|
|
|
|
#include <X11/keysym.h>
|
2013-02-04 21:28:05 +08:00
|
|
|
#include <X11/XKBlib.h>
|
2006-12-21 20:24:20 +08:00
|
|
|
#include <X11/cursorfont.h>
|
|
|
|
|
2007-04-25 17:32:12 +08:00
|
|
|
#include <X11/Xmd.h> /* For CARD16 */
|
2006-12-21 20:24:20 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
|
|
|
#include <X11/extensions/Xrandr.h>
|
|
|
|
#endif
|
|
|
|
|
2007-04-14 16:31:40 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
using namespace osgViewer;
|
|
|
|
|
2009-11-06 18:31:03 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
|
|
|
bool checkEGLError(const char* str)
|
|
|
|
{
|
|
|
|
EGLint err = eglGetError();
|
|
|
|
if (err != EGL_SUCCESS)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_WARN<<"Warning: "<<str<<" EGL error "<<std::hex<<err<<std::dec<<std::endl;
|
2009-11-06 18:31:03 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_WARN<<"EGL reports no errors: "<<str<<std::endl;
|
2009-11-06 18:31:03 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-01-02 02:20:10 +08:00
|
|
|
class X11KeyboardMap
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
X11KeyboardMap()
|
|
|
|
{
|
2009-06-02 16:56:32 +08:00
|
|
|
#if 0
|
|
|
|
_extendKeymap[8 ] = osgGA::GUIEventAdapter::KEY_BackSpace;
|
|
|
|
_extendKeymap[127 ] = osgGA::GUIEventAdapter::KEY_Delete;
|
|
|
|
_extendKeymap[27 ] = osgGA::GUIEventAdapter::KEY_Escape;
|
|
|
|
// _extendKeymap[13 ] = osgGA::GUIEventAdapter::KEY_Enter;
|
|
|
|
#endif
|
|
|
|
_extendedKeymap[XK_Escape ] = osgGA::GUIEventAdapter::KEY_Escape;
|
|
|
|
_extendedKeymap[XK_F1 ] = osgGA::GUIEventAdapter::KEY_F1;
|
|
|
|
_extendedKeymap[XK_F2 ] = osgGA::GUIEventAdapter::KEY_F2;
|
|
|
|
_extendedKeymap[XK_F3 ] = osgGA::GUIEventAdapter::KEY_F3;
|
|
|
|
_extendedKeymap[XK_F4 ] = osgGA::GUIEventAdapter::KEY_F4;
|
|
|
|
_extendedKeymap[XK_F5 ] = osgGA::GUIEventAdapter::KEY_F5;
|
|
|
|
_extendedKeymap[XK_F6 ] = osgGA::GUIEventAdapter::KEY_F6;
|
|
|
|
_extendedKeymap[XK_F7 ] = osgGA::GUIEventAdapter::KEY_F7;
|
|
|
|
_extendedKeymap[XK_F8 ] = osgGA::GUIEventAdapter::KEY_F8;
|
|
|
|
_extendedKeymap[XK_F9 ] = osgGA::GUIEventAdapter::KEY_F9;
|
|
|
|
_extendedKeymap[XK_F10 ] = osgGA::GUIEventAdapter::KEY_F10;
|
|
|
|
_extendedKeymap[XK_F11 ] = osgGA::GUIEventAdapter::KEY_F11;
|
|
|
|
_extendedKeymap[XK_F12 ] = osgGA::GUIEventAdapter::KEY_F12;
|
|
|
|
_extendedKeymap[XK_quoteleft ] = '`';
|
|
|
|
_extendedKeymap[XK_minus ] = '-';
|
|
|
|
_extendedKeymap[XK_equal ] = '=';
|
|
|
|
_extendedKeymap[XK_BackSpace ] = osgGA::GUIEventAdapter::KEY_BackSpace;
|
|
|
|
_extendedKeymap[XK_Tab ] = osgGA::GUIEventAdapter::KEY_Tab;
|
2009-08-21 00:05:06 +08:00
|
|
|
_extendedKeymap[XK_bracketleft ] = '[';
|
|
|
|
_extendedKeymap[XK_bracketright ] = ']';
|
2009-06-02 16:56:32 +08:00
|
|
|
_extendedKeymap[XK_backslash ] = '\\';
|
|
|
|
_extendedKeymap[XK_Caps_Lock ] = osgGA::GUIEventAdapter::KEY_Caps_Lock;
|
|
|
|
_extendedKeymap[XK_semicolon ] = ';';
|
|
|
|
_extendedKeymap[XK_apostrophe ] = '\'';
|
|
|
|
_extendedKeymap[XK_Return ] = osgGA::GUIEventAdapter::KEY_Return;
|
|
|
|
_extendedKeymap[XK_comma ] = ',';
|
|
|
|
_extendedKeymap[XK_period ] = '.';
|
|
|
|
_extendedKeymap[XK_slash ] = '/';
|
|
|
|
_extendedKeymap[XK_space ] = ' ';
|
|
|
|
_extendedKeymap[XK_Shift_L ] = osgGA::GUIEventAdapter::KEY_Shift_L;
|
|
|
|
_extendedKeymap[XK_Shift_R ] = osgGA::GUIEventAdapter::KEY_Shift_R;
|
|
|
|
_extendedKeymap[XK_Control_L ] = osgGA::GUIEventAdapter::KEY_Control_L;
|
|
|
|
_extendedKeymap[XK_Control_R ] = osgGA::GUIEventAdapter::KEY_Control_R;
|
|
|
|
_extendedKeymap[XK_Meta_L ] = osgGA::GUIEventAdapter::KEY_Meta_L;
|
|
|
|
_extendedKeymap[XK_Meta_R ] = osgGA::GUIEventAdapter::KEY_Meta_R;
|
|
|
|
_extendedKeymap[XK_Alt_L ] = osgGA::GUIEventAdapter::KEY_Alt_L;
|
|
|
|
_extendedKeymap[XK_Alt_R ] = osgGA::GUIEventAdapter::KEY_Alt_R;
|
|
|
|
_extendedKeymap[XK_Super_L ] = osgGA::GUIEventAdapter::KEY_Super_L;
|
|
|
|
_extendedKeymap[XK_Super_R ] = osgGA::GUIEventAdapter::KEY_Super_R;
|
|
|
|
_extendedKeymap[XK_Hyper_L ] = osgGA::GUIEventAdapter::KEY_Hyper_L;
|
|
|
|
_extendedKeymap[XK_Hyper_R ] = osgGA::GUIEventAdapter::KEY_Hyper_R;
|
|
|
|
_extendedKeymap[XK_Menu ] = osgGA::GUIEventAdapter::KEY_Menu;
|
|
|
|
_extendedKeymap[XK_Print ] = osgGA::GUIEventAdapter::KEY_Print;
|
|
|
|
_extendedKeymap[XK_Scroll_Lock ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock;
|
|
|
|
_extendedKeymap[XK_Pause ] = osgGA::GUIEventAdapter::KEY_Pause;
|
|
|
|
_extendedKeymap[XK_Home ] = osgGA::GUIEventAdapter::KEY_Home;
|
|
|
|
_extendedKeymap[XK_Page_Up ] = osgGA::GUIEventAdapter::KEY_Page_Up;
|
|
|
|
_extendedKeymap[XK_End ] = osgGA::GUIEventAdapter::KEY_End;
|
|
|
|
_extendedKeymap[XK_Page_Down ] = osgGA::GUIEventAdapter::KEY_Page_Down;
|
|
|
|
_extendedKeymap[XK_Delete ] = osgGA::GUIEventAdapter::KEY_Delete;
|
|
|
|
_extendedKeymap[XK_Insert ] = osgGA::GUIEventAdapter::KEY_Insert;
|
|
|
|
_extendedKeymap[XK_Left ] = osgGA::GUIEventAdapter::KEY_Left;
|
|
|
|
_extendedKeymap[XK_Up ] = osgGA::GUIEventAdapter::KEY_Up;
|
|
|
|
_extendedKeymap[XK_Right ] = osgGA::GUIEventAdapter::KEY_Right;
|
|
|
|
_extendedKeymap[XK_Down ] = osgGA::GUIEventAdapter::KEY_Down;
|
|
|
|
_extendedKeymap[XK_Num_Lock ] = osgGA::GUIEventAdapter::KEY_Num_Lock;
|
|
|
|
_extendedKeymap[XK_KP_Divide ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
|
|
|
|
_extendedKeymap[XK_KP_Multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
|
|
|
|
_extendedKeymap[XK_KP_Subtract ] = osgGA::GUIEventAdapter::KEY_KP_Subtract;
|
|
|
|
_extendedKeymap[XK_KP_Add ] = osgGA::GUIEventAdapter::KEY_KP_Add;
|
|
|
|
_extendedKeymap[XK_KP_Home ] = osgGA::GUIEventAdapter::KEY_KP_Home;
|
|
|
|
_extendedKeymap[XK_KP_Up ] = osgGA::GUIEventAdapter::KEY_KP_Up;
|
|
|
|
_extendedKeymap[XK_KP_Page_Up ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
|
|
|
|
_extendedKeymap[XK_KP_Left ] = osgGA::GUIEventAdapter::KEY_KP_Left;
|
|
|
|
_extendedKeymap[XK_KP_Begin ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
|
|
|
|
_extendedKeymap[XK_KP_Right ] = osgGA::GUIEventAdapter::KEY_KP_Right;
|
|
|
|
_extendedKeymap[XK_KP_End ] = osgGA::GUIEventAdapter::KEY_KP_End;
|
|
|
|
_extendedKeymap[XK_KP_Down ] = osgGA::GUIEventAdapter::KEY_KP_Down;
|
|
|
|
_extendedKeymap[XK_KP_Page_Down ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
|
|
|
|
_extendedKeymap[XK_KP_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
|
|
|
|
_extendedKeymap[XK_KP_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
|
|
|
|
_extendedKeymap[XK_KP_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter;
|
|
|
|
|
|
|
|
_standardKeymap[XK_1 ] = '1';
|
|
|
|
_standardKeymap[XK_2 ] = '2';
|
|
|
|
_standardKeymap[XK_3 ] = '3';
|
|
|
|
_standardKeymap[XK_4 ] = '4';
|
|
|
|
_standardKeymap[XK_5 ] = '5';
|
|
|
|
_standardKeymap[XK_6 ] = '6';
|
|
|
|
_standardKeymap[XK_7 ] = '7';
|
|
|
|
_standardKeymap[XK_8 ] = '8';
|
|
|
|
_standardKeymap[XK_9 ] = '9';
|
|
|
|
_standardKeymap[XK_0 ] = '0';
|
|
|
|
_standardKeymap[XK_A ] = 'A';
|
|
|
|
_standardKeymap[XK_B ] = 'B';
|
|
|
|
_standardKeymap[XK_C ] = 'C';
|
|
|
|
_standardKeymap[XK_D ] = 'D';
|
|
|
|
_standardKeymap[XK_E ] = 'E';
|
|
|
|
_standardKeymap[XK_F ] = 'F';
|
|
|
|
_standardKeymap[XK_G ] = 'G';
|
|
|
|
_standardKeymap[XK_H ] = 'H';
|
|
|
|
_standardKeymap[XK_I ] = 'I';
|
|
|
|
_standardKeymap[XK_J ] = 'J';
|
|
|
|
_standardKeymap[XK_K ] = 'K';
|
|
|
|
_standardKeymap[XK_L ] = 'L';
|
|
|
|
_standardKeymap[XK_M ] = 'M';
|
|
|
|
_standardKeymap[XK_N ] = 'N';
|
|
|
|
_standardKeymap[XK_O ] = 'O';
|
|
|
|
_standardKeymap[XK_P ] = 'P';
|
|
|
|
_standardKeymap[XK_Q ] = 'Q';
|
|
|
|
_standardKeymap[XK_R ] = 'R';
|
|
|
|
_standardKeymap[XK_S ] = 'S';
|
|
|
|
_standardKeymap[XK_T ] = 'T';
|
|
|
|
_standardKeymap[XK_U ] = 'U';
|
|
|
|
_standardKeymap[XK_V ] = 'V';
|
|
|
|
_standardKeymap[XK_W ] = 'W';
|
|
|
|
_standardKeymap[XK_X ] = 'X';
|
|
|
|
_standardKeymap[XK_Y ] = 'Y';
|
|
|
|
_standardKeymap[XK_Z ] = 'Z';
|
|
|
|
_standardKeymap[XK_a ] = 'a';
|
|
|
|
_standardKeymap[XK_b ] = 'b';
|
|
|
|
_standardKeymap[XK_c ] = 'c';
|
|
|
|
_standardKeymap[XK_d ] = 'd';
|
|
|
|
_standardKeymap[XK_e ] = 'e';
|
|
|
|
_standardKeymap[XK_f ] = 'f';
|
|
|
|
_standardKeymap[XK_g ] = 'g';
|
|
|
|
_standardKeymap[XK_h ] = 'h';
|
|
|
|
_standardKeymap[XK_i ] = 'i';
|
|
|
|
_standardKeymap[XK_j ] = 'j';
|
|
|
|
_standardKeymap[XK_k ] = 'k';
|
|
|
|
_standardKeymap[XK_l ] = 'l';
|
|
|
|
_standardKeymap[XK_m ] = 'm';
|
|
|
|
_standardKeymap[XK_n ] = 'n';
|
|
|
|
_standardKeymap[XK_o ] = 'o';
|
|
|
|
_standardKeymap[XK_p ] = 'p';
|
|
|
|
_standardKeymap[XK_q ] = 'q';
|
|
|
|
_standardKeymap[XK_r ] = 'r';
|
|
|
|
_standardKeymap[XK_s ] = 's';
|
|
|
|
_standardKeymap[XK_t ] = 't';
|
|
|
|
_standardKeymap[XK_u ] = 'u';
|
|
|
|
_standardKeymap[XK_v ] = 'v';
|
|
|
|
_standardKeymap[XK_w ] = 'w';
|
|
|
|
_standardKeymap[XK_x ] = 'x';
|
|
|
|
_standardKeymap[XK_y ] = 'y';
|
|
|
|
_standardKeymap[XK_z ] = 'z';
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
~X11KeyboardMap() {}
|
|
|
|
|
|
|
|
int remapKey(int key)
|
|
|
|
{
|
2009-06-02 16:56:32 +08:00
|
|
|
KeyMap::iterator itr = _extendedKeymap.find(key);
|
|
|
|
if (itr != _extendedKeymap.end()) return itr->second;
|
|
|
|
|
|
|
|
itr = _standardKeymap.find(key);
|
|
|
|
if (itr != _standardKeymap.end()) return itr->second;
|
|
|
|
|
|
|
|
return key;
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
2009-06-02 16:56:32 +08:00
|
|
|
|
|
|
|
bool remapExtendedKey(int& key)
|
|
|
|
{
|
|
|
|
KeyMap::iterator itr = _extendedKeymap.find(key);
|
|
|
|
if (itr != _extendedKeymap.end())
|
|
|
|
{
|
|
|
|
key = itr->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else return false;
|
|
|
|
}
|
|
|
|
|
2007-01-02 02:20:10 +08:00
|
|
|
protected:
|
|
|
|
|
|
|
|
typedef std::map<int, int> KeyMap;
|
2009-06-02 16:56:32 +08:00
|
|
|
KeyMap _extendedKeymap;
|
|
|
|
KeyMap _standardKeymap;
|
2007-01-02 02:20:10 +08:00
|
|
|
};
|
|
|
|
|
2009-06-02 16:56:32 +08:00
|
|
|
static bool remapExtendedX11Key(int& key)
|
2007-01-02 02:20:10 +08:00
|
|
|
{
|
|
|
|
static X11KeyboardMap s_x11KeyboardMap;
|
2009-06-02 16:56:32 +08:00
|
|
|
return s_x11KeyboardMap.remapExtendedKey(key);
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
// Functions to handle key maps of type char[32] as contained in
|
|
|
|
// an XKeymapEvent or returned by XQueryKeymap().
|
|
|
|
static inline bool keyMapGetKey(const char* map, unsigned int key)
|
|
|
|
{
|
|
|
|
return (map[(key & 0xff) / 8] & (1 << (key & 7))) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void keyMapSetKey(char* map, unsigned int key)
|
|
|
|
{
|
|
|
|
map[(key & 0xff) / 8] |= (1 << (key & 7));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void keyMapClearKey(char* map, unsigned int key)
|
|
|
|
{
|
|
|
|
map[(key & 0xff) / 8] &= ~(1 << (key & 7));
|
|
|
|
}
|
|
|
|
|
2007-01-04 00:06:12 +08:00
|
|
|
GraphicsWindowX11::~GraphicsWindowX11()
|
|
|
|
{
|
|
|
|
close(true);
|
|
|
|
}
|
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* GraphicsWindowX11::getDisplayToUse() const
|
|
|
|
{
|
|
|
|
if (_threadOfLastMakeCurrent==0)
|
|
|
|
{
|
|
|
|
return _display;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
|
|
|
if (OpenThreads::Thread::CurrentThread()==_threadOfLastMakeCurrent)
|
2007-04-13 21:22:52 +08:00
|
|
|
{
|
|
|
|
return _display;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
else
|
2007-04-13 21:22:52 +08:00
|
|
|
{
|
|
|
|
return _eventDisplay;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
bool GraphicsWindowX11::createVisualInfo()
|
|
|
|
{
|
2010-04-30 18:52:24 +08:00
|
|
|
if (_visualInfo)
|
|
|
|
{
|
|
|
|
#ifdef OSG_USE_EGL
|
|
|
|
delete _visualInfo;
|
|
|
|
#else
|
|
|
|
XFree(_visualInfo);
|
|
|
|
#endif
|
|
|
|
_visualInfo = 0;
|
|
|
|
}
|
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if( _window != 0 )
|
|
|
|
{
|
|
|
|
XWindowAttributes watt;
|
|
|
|
XGetWindowAttributes( _display, _window, &watt );
|
|
|
|
XVisualInfo temp;
|
|
|
|
temp.visualid = XVisualIDFromVisual(watt.visual);
|
|
|
|
int n;
|
|
|
|
_visualInfo = XGetVisualInfo( _display, VisualIDMask, &temp, &n );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
|
|
|
|
|
|
|
_visualInfo = new XVisualInfo;
|
|
|
|
int depth = DefaultDepth( _display, _traits->screenNum );
|
|
|
|
if (XMatchVisualInfo( _display, _traits->screenNum, depth, TrueColor, _visualInfo )==0)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::createVisualInfo() failed."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2006-12-23 05:53:44 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
typedef std::vector<int> Attributes;
|
|
|
|
Attributes attributes;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
attributes.push_back(GLX_USE_GL);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
attributes.push_back(GLX_RGBA);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (_traits->doubleBuffer) attributes.push_back(GLX_DOUBLEBUFFER);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (_traits->quadBufferStereo) attributes.push_back(GLX_STEREO);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
attributes.push_back(GLX_RED_SIZE); attributes.push_back(_traits->red);
|
|
|
|
attributes.push_back(GLX_GREEN_SIZE); attributes.push_back(_traits->green);
|
|
|
|
attributes.push_back(GLX_BLUE_SIZE); attributes.push_back(_traits->blue);
|
|
|
|
attributes.push_back(GLX_DEPTH_SIZE); attributes.push_back(_traits->depth);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (_traits->alpha) { attributes.push_back(GLX_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (_traits->stencil) { attributes.push_back(GLX_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#if defined(GLX_SAMPLE_BUFFERS) && defined (GLX_SAMPLES)
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
if (_traits->sampleBuffers) { attributes.push_back(GLX_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
|
2011-07-28 20:07:22 +08:00
|
|
|
if (_traits->samples) { attributes.push_back(GLX_SAMPLES); attributes.push_back(_traits->samples); }
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#endif
|
2007-09-26 17:50:32 +08:00
|
|
|
// TODO
|
|
|
|
// GLX_AUX_BUFFERS
|
|
|
|
// GLX_ACCUM_RED_SIZE
|
|
|
|
// GLX_ACCUM_GREEN_SIZE
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
attributes.push_back(None);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
_visualInfo = glXChooseVisual( _display, _traits->screenNum, &(attributes.front()) );
|
2009-10-30 23:17:38 +08:00
|
|
|
#endif
|
2007-09-26 17:50:32 +08:00
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
return _visualInfo != 0;
|
|
|
|
}
|
2011-06-20 17:22:57 +08:00
|
|
|
|
|
|
|
bool GraphicsWindowX11::checkAndSendEventFullScreenIfNeeded(Display* display, int x, int y, int width, int height, bool windowDecoration)
|
|
|
|
{
|
|
|
|
osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
|
|
|
|
if (wsi == NULL)
|
|
|
|
{
|
|
|
|
OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int screenWidth;
|
|
|
|
unsigned int screenHeight;
|
|
|
|
|
|
|
|
wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
|
|
|
|
bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !windowDecoration;
|
|
|
|
|
2012-01-26 21:08:19 +08:00
|
|
|
if (isFullScreen) {
|
|
|
|
resized(x, y, width, height);
|
|
|
|
getEventQueue()->windowResize(x, y, width, height, getEventQueue()->getTime());
|
|
|
|
}
|
|
|
|
|
2011-06-20 17:22:57 +08:00
|
|
|
Atom netWMStateAtom = XInternAtom(display, "_NET_WM_STATE", True);
|
|
|
|
Atom netWMStateFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True);
|
|
|
|
|
|
|
|
if (netWMStateAtom != None && netWMStateFullscreenAtom != None)
|
|
|
|
{
|
|
|
|
XEvent xev;
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
|
|
xev.xclient.serial = 0;
|
|
|
|
xev.xclient.send_event = True;
|
|
|
|
xev.xclient.window = _window;
|
|
|
|
xev.xclient.message_type = netWMStateAtom;
|
|
|
|
xev.xclient.format = 32;
|
|
|
|
xev.xclient.data.l[0] = isFullScreen ? 1 : 0;
|
|
|
|
xev.xclient.data.l[1] = netWMStateFullscreenAtom;
|
|
|
|
xev.xclient.data.l[2] = 0;
|
|
|
|
|
|
|
|
XSendEvent(display, RootWindow(display, DefaultScreen(display)),
|
|
|
|
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-06-24 05:55:35 +08:00
|
|
|
#define MWM_HINTS_FUNCTIONS (1L << 0)
|
|
|
|
#define MWM_HINTS_DECORATIONS (1L << 1)
|
|
|
|
#define MWM_HINTS_INPUT_MODE (1L << 2)
|
|
|
|
#define MWM_HINTS_STATUS (1L << 3)
|
|
|
|
|
|
|
|
#define MWM_DECOR_ALL (1L<<0)
|
|
|
|
#define MWM_DECOR_BORDER (1L<<1)
|
|
|
|
#define MWM_DECOR_RESIZEH (1L<<2)
|
|
|
|
#define MWM_DECOR_TITLE (1L<<3)
|
|
|
|
#define MWM_DECOR_MENU (1L<<4)
|
|
|
|
#define MWM_DECOR_MINIMIZE (1L<<5)
|
|
|
|
#define MWM_DECOR_MAXIMIZE (1L<<6)
|
|
|
|
|
|
|
|
#define MWM_FUNC_ALL (1L<<0)
|
|
|
|
#define MWM_FUNC_RESIZE (1L<<1)
|
|
|
|
#define MWM_FUNC_MOVE (1L<<2)
|
|
|
|
#define MWM_FUNC_MINIMIZE (1L<<3)
|
|
|
|
#define MWM_FUNC_MAXIMIZE (1L<<4)
|
|
|
|
#define MWM_FUNC_CLOSE (1L<<5)
|
|
|
|
|
2007-06-11 03:53:18 +08:00
|
|
|
bool GraphicsWindowX11::setWindowDecorationImplementation(bool flag)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* display = getDisplayToUse();
|
2007-12-07 01:28:29 +08:00
|
|
|
|
|
|
|
XMapWindow(display, _window );
|
|
|
|
|
|
|
|
checkAndSendEventFullScreenIfNeeded(display, _traits->x, _traits->y, _traits->width, _traits->height, flag);
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
unsigned long functions;
|
|
|
|
unsigned long decorations;
|
|
|
|
long inputMode;
|
|
|
|
unsigned long status;
|
|
|
|
} wmHints;
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
Atom atom;
|
2007-12-07 01:28:29 +08:00
|
|
|
bool result = false;
|
2007-02-09 21:51:28 +08:00
|
|
|
if( (atom = XInternAtom( display, "_MOTIF_WM_HINTS", 0 )) != None )
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2011-06-20 17:22:57 +08:00
|
|
|
if (flag)
|
2007-06-24 05:55:35 +08:00
|
|
|
{
|
2011-06-20 17:22:57 +08:00
|
|
|
wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
|
|
|
|
wmHints.functions = MWM_FUNC_ALL;
|
|
|
|
wmHints.decorations = MWM_DECOR_ALL;
|
|
|
|
wmHints.inputMode = 0;
|
|
|
|
wmHints.status = 0;
|
|
|
|
|
|
|
|
// if traits says not resize we want to set the functions to exlude MWM_FUNC_RESIZE,
|
|
|
|
// but this bitmask needs to be set if the MWM_FUNC_ALL bit is already set in order to toggle it off.
|
|
|
|
if (_traits.valid() && !_traits->supportsResize) wmHints.functions = wmHints.functions | MWM_FUNC_RESIZE;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-06-24 05:55:35 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-06-20 17:22:57 +08:00
|
|
|
wmHints.flags = MWM_HINTS_DECORATIONS;
|
|
|
|
wmHints.functions = 0;
|
|
|
|
wmHints.decorations = 0;
|
|
|
|
wmHints.inputMode = 0;
|
|
|
|
wmHints.status = 0;
|
2007-06-24 05:55:35 +08:00
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-06-24 05:55:35 +08:00
|
|
|
XChangeProperty( display, _window, atom, atom, 32, PropModeReplace, (unsigned char *)&wmHints, 5 );
|
2007-12-07 01:28:29 +08:00
|
|
|
result = true;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else
|
2007-06-11 03:53:18 +08:00
|
|
|
{
|
2011-06-20 17:22:57 +08:00
|
|
|
OSG_NOTICE<<"Error: GraphicsWindowX11::setWindowDecorationImplementation(" << flag << ") - couldn't change decorations." << std::endl;
|
2007-12-07 01:28:29 +08:00
|
|
|
result = false;
|
2007-06-11 03:53:18 +08:00
|
|
|
}
|
|
|
|
|
2007-12-07 01:28:29 +08:00
|
|
|
XFlush(display);
|
|
|
|
XSync(display,0);
|
|
|
|
// add usleep here to give window manager a chance to handle the request, if
|
|
|
|
// we don't add this sleep then any X11 calls right afterwards can produce
|
|
|
|
// X11 errors.
|
|
|
|
usleep(100000);
|
|
|
|
return result;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2007-06-11 03:53:18 +08:00
|
|
|
bool GraphicsWindowX11::setWindowRectangleImplementation(int x, int y, int width, int height)
|
2007-04-13 21:22:52 +08:00
|
|
|
{
|
2007-10-01 19:02:02 +08:00
|
|
|
if (!_initialized) return false;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* display = getDisplayToUse();
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2011-06-20 17:22:57 +08:00
|
|
|
checkAndSendEventFullScreenIfNeeded(display, x, y, width, height, _traits->windowDecoration);
|
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
XMoveResizeWindow(display, _window, x, y, width, height);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
XFlush(display);
|
|
|
|
XSync(display, 0);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-04-13 22:54:22 +08:00
|
|
|
// add usleep here to give window manager a chance to handle the request, if
|
|
|
|
// we don't add this sleep then any X11 calls right afterwards can produce
|
|
|
|
// X11 errors.
|
|
|
|
usleep(100000);
|
2007-12-07 01:28:29 +08:00
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-06-11 03:53:18 +08:00
|
|
|
return true;
|
2007-04-13 21:22:52 +08:00
|
|
|
}
|
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
void GraphicsWindowX11::setWindowName(const std::string& name)
|
|
|
|
{
|
2007-10-01 19:02:02 +08:00
|
|
|
if( _window == 0) return;
|
2007-09-26 17:50:32 +08:00
|
|
|
|
|
|
|
// char *slist[] = { name.c_str(), 0L };
|
|
|
|
// XTextProperty xtp;
|
|
|
|
|
|
|
|
// XStringListToTextProperty( slist, 1, &xtp );
|
|
|
|
|
|
|
|
Display* display = getDisplayToUse();
|
|
|
|
if( !display ) return;
|
|
|
|
|
|
|
|
// XSetWMName( display, _window, &xtp );
|
|
|
|
XStoreName( display, _window, name.c_str() );
|
|
|
|
XSetIconName( display, _window, name.c_str() );
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
XFlush(display);
|
2007-09-26 17:50:32 +08:00
|
|
|
XSync(display,0);
|
2007-10-01 19:02:02 +08:00
|
|
|
|
|
|
|
_traits->windowName = name;
|
2007-09-26 17:50:32 +08:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:43:28 +08:00
|
|
|
void GraphicsWindowX11::setCursor(MouseCursor mouseCursor)
|
2007-01-02 20:50:57 +08:00
|
|
|
{
|
2007-06-02 03:43:28 +08:00
|
|
|
Cursor newCursor = getOrCreateCursor(mouseCursor);
|
|
|
|
if (newCursor == _currentCursor) return;
|
|
|
|
|
|
|
|
_currentCursor = newCursor;
|
|
|
|
if (!_window) return;
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* display = getDisplayToUse();
|
2007-06-02 03:43:28 +08:00
|
|
|
if (!display) return;
|
|
|
|
XDefineCursor( display, _window, _currentCursor );
|
|
|
|
XFlush(display);
|
|
|
|
XSync(display, 0);
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2007-06-02 03:43:28 +08:00
|
|
|
_traits->useCursor = (_currentCursor != getOrCreateCursor(NoCursor));
|
|
|
|
}
|
|
|
|
|
|
|
|
Cursor GraphicsWindowX11::getOrCreateCursor(MouseCursor mouseCursor)
|
|
|
|
{
|
|
|
|
std::map<MouseCursor,Cursor>::iterator i = _mouseCursorMap.find(mouseCursor);
|
|
|
|
if (i != _mouseCursorMap.end()) return i->second;
|
2007-01-02 20:50:57 +08:00
|
|
|
|
2007-06-02 03:43:28 +08:00
|
|
|
Display* display = getDisplayToUse();
|
|
|
|
if (!display) return None;
|
|
|
|
|
|
|
|
switch (mouseCursor) {
|
|
|
|
case NoCursor:
|
2007-01-02 20:50:57 +08:00
|
|
|
{
|
2007-06-02 03:43:28 +08:00
|
|
|
// create an empty mouse cursor, note that it is safe to destroy the Pixmap just past cursor creation
|
|
|
|
// since the resource in the x server is reference counted.
|
|
|
|
char buff[2] = {0,0};
|
|
|
|
XColor ncol = {0,0,0,0,DoRed|DoGreen|DoBlue,0};
|
|
|
|
Pixmap pixmap = XCreateBitmapFromData( display, _parent, buff, 1, 1);
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreatePixmapCursor( display, pixmap, pixmap, &ncol, &ncol, 0, 0 );
|
|
|
|
XFreePixmap(display, pixmap);
|
|
|
|
// Important to have the pixmap and the buffer still available when the request is sent to the server ...
|
2007-02-09 21:51:28 +08:00
|
|
|
XFlush(display);
|
2007-06-02 03:43:28 +08:00
|
|
|
XSync(display, 0);
|
|
|
|
break;
|
2007-01-02 20:50:57 +08:00
|
|
|
}
|
2007-06-02 03:43:28 +08:00
|
|
|
case RightArrowCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_ptr );
|
|
|
|
break;
|
|
|
|
case LeftArrowCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_arrow );
|
|
|
|
break;
|
|
|
|
case InfoCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
|
|
|
|
break;
|
|
|
|
case DestroyCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_pirate );
|
|
|
|
break;
|
|
|
|
case HelpCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_question_arrow );
|
|
|
|
break;
|
|
|
|
case CycleCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_exchange );
|
|
|
|
break;
|
|
|
|
case SprayCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_spraycan );
|
|
|
|
break;
|
|
|
|
case WaitCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_watch );
|
|
|
|
break;
|
|
|
|
case TextCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_xterm );
|
|
|
|
break;
|
|
|
|
case CrosshairCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_crosshair );
|
|
|
|
break;
|
|
|
|
case UpDownCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_v_double_arrow );
|
|
|
|
break;
|
|
|
|
case LeftRightCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_sb_h_double_arrow );
|
|
|
|
break;
|
|
|
|
case TopSideCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_side );
|
|
|
|
break;
|
|
|
|
case BottomSideCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_side );
|
|
|
|
break;
|
|
|
|
case LeftSideCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_left_side );
|
|
|
|
break;
|
|
|
|
case RightSideCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_right_side );
|
|
|
|
break;
|
|
|
|
case TopLeftCorner:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_left_corner );
|
|
|
|
break;
|
|
|
|
case TopRightCorner:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_top_right_corner );
|
|
|
|
break;
|
|
|
|
case BottomRightCorner:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_right_corner );
|
|
|
|
break;
|
|
|
|
case BottomLeftCorner:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_bottom_left_corner );
|
|
|
|
break;
|
2009-04-22 19:22:08 +08:00
|
|
|
case HandCursor:
|
|
|
|
_mouseCursorMap[mouseCursor] = XCreateFontCursor( display, XC_hand1 );
|
|
|
|
break;
|
2007-06-02 03:43:28 +08:00
|
|
|
|
|
|
|
case InheritCursor:
|
|
|
|
default:
|
|
|
|
_mouseCursorMap[mouseCursor] = None;
|
|
|
|
break;
|
|
|
|
};
|
|
|
|
return _mouseCursorMap[mouseCursor];
|
2007-01-02 20:50:57 +08:00
|
|
|
}
|
|
|
|
|
2007-03-27 00:28:26 +08:00
|
|
|
void GraphicsWindowX11::init()
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2006-12-25 00:40:19 +08:00
|
|
|
if (_initialized) return;
|
|
|
|
|
|
|
|
if (!_traits)
|
|
|
|
{
|
|
|
|
_valid = false;
|
|
|
|
return;
|
|
|
|
}
|
2007-09-26 17:50:32 +08:00
|
|
|
|
2008-06-03 01:34:47 +08:00
|
|
|
// getEventQueue()->setCurrentEventState(osgGA::GUIEventAdapter::getAccumulatedEventState().get());
|
2007-09-26 17:50:32 +08:00
|
|
|
|
|
|
|
WindowData* inheritedWindowData = dynamic_cast<WindowData*>(_traits->inheritedWindowData.get());
|
|
|
|
Window windowHandle = inheritedWindowData ? inheritedWindowData->_window : 0;
|
|
|
|
|
|
|
|
_ownsWindow = windowHandle == 0;
|
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
_display = XOpenDisplay(_traits->displayName().c_str());
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
if (!_display)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Error: Unable to open display \"" << XDisplayName(_traits->displayName().c_str()) << "\"."<<std::endl;
|
2006-12-25 00:40:19 +08:00
|
|
|
_valid = false;
|
|
|
|
return;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2009-11-01 17:04:41 +08:00
|
|
|
_eglDisplay = eglGetDisplay((EGLNativeDisplayType)_display);
|
2007-09-26 17:50:32 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
EGLint eglMajorVersion, eglMinorVersion;
|
2009-11-01 17:04:41 +08:00
|
|
|
if (!eglInitialize(_eglDisplay, &eglMajorVersion, &eglMinorVersion))
|
2009-10-30 23:17:38 +08:00
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() failed."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
|
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
_valid = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - eglInitialize() succeded eglMajorVersion="<<eglMajorVersion<<" iMinorVersion="<<eglMinorVersion<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
|
|
|
|
#else
|
|
|
|
// Query for GLX extension
|
|
|
|
int errorBase, eventBase;
|
|
|
|
if( glXQueryExtension( _display, &errorBase, &eventBase) == False )
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Error: " << XDisplayName(_traits->displayName().c_str()) <<" has no GLX extension." << std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
|
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
_valid = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"GLX extension, errorBase="<<errorBase<<" eventBase="<<eventBase<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
if (!createVisualInfo())
|
|
|
|
{
|
2011-04-19 19:46:05 +08:00
|
|
|
_traits->red /= 2;
|
|
|
|
_traits->green /= 2;
|
|
|
|
_traits->blue /= 2;
|
|
|
|
_traits->alpha /= 2;
|
|
|
|
_traits->depth /= 2;
|
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"Relaxing traits"<<std::endl;
|
2007-01-29 01:32:41 +08:00
|
|
|
|
|
|
|
if (!createVisualInfo())
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Error: Not able to create requested visual." << std::endl;
|
2007-01-29 01:32:41 +08:00
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
_valid = false;
|
|
|
|
return;
|
2011-04-19 19:46:05 +08:00
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
2007-09-26 17:50:32 +08:00
|
|
|
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
// get any shared GLX contexts
|
2012-09-06 05:03:41 +08:00
|
|
|
GraphicsHandleX11* graphicsHandleX11 = dynamic_cast<GraphicsHandleX11*>(_traits->sharedContext.get());
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
Context sharedContext = graphicsHandleX11 ? graphicsHandleX11->getContext() : 0;
|
2009-10-30 23:17:38 +08:00
|
|
|
|
|
|
|
#ifdef OSG_USE_EGL
|
|
|
|
|
|
|
|
_valid = _ownsWindow ? createWindow() : setWindow(windowHandle);
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
if (!_valid)
|
2009-10-30 23:17:38 +08:00
|
|
|
{
|
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
return;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - window created ="<<_valid<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
|
2011-07-28 20:07:22 +08:00
|
|
|
eglBindAPI(EGL_OPENGL_ES_API);
|
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
EGLConfig eglConfig = 0;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-11-06 18:38:22 +08:00
|
|
|
#if defined(OSG_GLES2_AVAILABLE)
|
|
|
|
#define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES2_BIT
|
2009-10-30 23:17:38 +08:00
|
|
|
#else
|
2009-11-06 18:38:22 +08:00
|
|
|
#define OSG_EGL_OPENGL_TARGET_BIT EGL_OPENGL_ES_BIT
|
2009-10-30 23:17:38 +08:00
|
|
|
#endif
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2011-07-28 20:07:22 +08:00
|
|
|
typedef std::vector<EGLint> Attributes;
|
|
|
|
Attributes attributes;
|
|
|
|
|
|
|
|
attributes.push_back(EGL_RED_SIZE); attributes.push_back(_traits->red);
|
|
|
|
attributes.push_back(EGL_GREEN_SIZE); attributes.push_back(_traits->green);
|
|
|
|
attributes.push_back(EGL_BLUE_SIZE); attributes.push_back(_traits->blue);
|
|
|
|
attributes.push_back(EGL_DEPTH_SIZE); attributes.push_back(_traits->depth);
|
|
|
|
|
|
|
|
if (_traits->alpha) { attributes.push_back(EGL_ALPHA_SIZE); attributes.push_back(_traits->alpha); }
|
|
|
|
if (_traits->stencil) { attributes.push_back(EGL_STENCIL_SIZE); attributes.push_back(_traits->stencil); }
|
|
|
|
|
|
|
|
if (_traits->sampleBuffers) { attributes.push_back(EGL_SAMPLE_BUFFERS); attributes.push_back(_traits->sampleBuffers); }
|
|
|
|
if (_traits->samples) { attributes.push_back(EGL_SAMPLES); attributes.push_back(_traits->samples); }
|
|
|
|
|
|
|
|
attributes.push_back(EGL_RENDERABLE_TYPE); attributes.push_back(OSG_EGL_OPENGL_TARGET_BIT);
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2011-07-28 20:07:22 +08:00
|
|
|
attributes.push_back(EGL_NONE);
|
|
|
|
attributes.push_back(EGL_NONE);
|
2009-10-30 23:17:38 +08:00
|
|
|
|
|
|
|
int numConfigs;
|
2011-07-28 20:07:22 +08:00
|
|
|
if (!eglChooseConfig(_eglDisplay, &(attributes.front()), &eglConfig, 1, &numConfigs) || (numConfigs != 1))
|
2009-10-30 23:17:38 +08:00
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - eglChooseConfig() failed."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
XCloseDisplay( _display );
|
|
|
|
_valid = false;
|
|
|
|
_display = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-11-06 18:31:03 +08:00
|
|
|
|
2009-11-01 17:04:41 +08:00
|
|
|
_eglSurface = eglCreateWindowSurface(_eglDisplay, eglConfig, (EGLNativeWindowType)_window, NULL);
|
|
|
|
if (_eglSurface == EGL_NO_SURFACE)
|
2009-10-30 23:17:38 +08:00
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateWindowSurface(..) failed."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
XCloseDisplay( _display );
|
|
|
|
_valid = false;
|
|
|
|
_display = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(OSG_GLES1_AVAILABLE)
|
|
|
|
EGLint* contextAttribs = 0;
|
|
|
|
#else
|
2009-11-06 18:38:22 +08:00
|
|
|
EGLint contextAttribs[] = {
|
|
|
|
EGL_CONTEXT_CLIENT_VERSION,
|
|
|
|
2,
|
|
|
|
EGL_NONE
|
|
|
|
};
|
2009-10-30 23:17:38 +08:00
|
|
|
#endif
|
|
|
|
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
_context = eglCreateContext(_eglDisplay, eglConfig, sharedContext, contextAttribs);
|
2009-10-30 23:17:38 +08:00
|
|
|
if (_context == EGL_NO_CONTEXT)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::init() - eglCreateContext(..) failed."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
XCloseDisplay( _display );
|
|
|
|
_valid = false;
|
|
|
|
_display = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_initialized = true;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-11-06 18:31:03 +08:00
|
|
|
checkEGLError("after eglCreateContext()");
|
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#else
|
2011-04-19 19:46:05 +08:00
|
|
|
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
_context = glXCreateContext( _display, _visualInfo, sharedContext, True );
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
if (!_context)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Error: Unable to create OpenGL graphics context."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
_valid = false;
|
|
|
|
return;
|
|
|
|
}
|
2007-09-26 17:50:32 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
_initialized = _ownsWindow ? createWindow() : setWindow(windowHandle);
|
|
|
|
_valid = _initialized;
|
2007-09-26 17:50:32 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#endif
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (_valid == false)
|
|
|
|
{
|
2011-05-30 17:26:24 +08:00
|
|
|
if (_display)
|
|
|
|
{
|
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_eventDisplay)
|
|
|
|
{
|
|
|
|
XCloseDisplay( _eventDisplay );
|
|
|
|
_eventDisplay = 0;
|
|
|
|
}
|
2007-09-26 17:50:32 +08:00
|
|
|
}
|
2009-11-06 18:31:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphicsWindowX11::createWindow()
|
|
|
|
{
|
|
|
|
unsigned int screen = _traits->screenNum;
|
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
_eventDisplay = XOpenDisplay(_traits->displayName().c_str());
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
_parent = RootWindow( _display, screen );
|
|
|
|
|
|
|
|
XWindowAttributes watt;
|
|
|
|
XGetWindowAttributes( _display, _parent, &watt );
|
|
|
|
// unsigned int parentWindowHeight = watt.height;
|
|
|
|
|
|
|
|
XSetWindowAttributes swatt;
|
|
|
|
swatt.colormap = XCreateColormap( _display, _parent, _visualInfo->visual, AllocNone);
|
|
|
|
//swatt.colormap = DefaultColormap( _dpy, 10 );
|
|
|
|
swatt.background_pixel = 0;
|
|
|
|
swatt.border_pixel = 0;
|
|
|
|
swatt.event_mask = 0;
|
|
|
|
unsigned long mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
|
|
|
|
|
2008-06-22 01:50:58 +08:00
|
|
|
if (_traits->overrideRedirect)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
|
|
|
swatt.override_redirect = true;
|
|
|
|
mask |= CWOverrideRedirect;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"Setting override redirect"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2011-06-20 17:22:57 +08:00
|
|
|
|
|
|
|
osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface();
|
|
|
|
if (wsi == NULL) {
|
|
|
|
OSG_NOTICE << "Error, no WindowSystemInterface available, cannot toggle window fullscreen." << std::endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = _traits->x;
|
|
|
|
int y = _traits->y;
|
|
|
|
int width = _traits->width;
|
|
|
|
int height = _traits->height;
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int screenWidth;
|
|
|
|
unsigned int screenHeight;
|
|
|
|
wsi->getScreenResolution(*_traits, screenWidth, screenHeight);
|
|
|
|
|
2011-06-20 19:25:52 +08:00
|
|
|
bool doFullSceenWorkAround = false;
|
2011-06-20 17:22:57 +08:00
|
|
|
bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight && !_traits->windowDecoration;
|
2011-06-20 17:28:39 +08:00
|
|
|
if (isFullScreen && !_traits->overrideRedirect)
|
2011-06-20 17:22:57 +08:00
|
|
|
{
|
|
|
|
// follows is hack to get around problems with toggling off full screen with modern X11 window
|
|
|
|
// managers that try to be too clever when toggling off full screen and ignore the window size
|
|
|
|
// calls made by the OSG when the initial window size is full screen.
|
|
|
|
|
|
|
|
Atom netWMStateAtom = XInternAtom(_display, "_NET_WM_STATE", True);
|
|
|
|
Atom netWMStateFullscreenAtom = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", True);
|
|
|
|
|
|
|
|
// we have a modern X11 server so assume we need the do the full screen hack.
|
|
|
|
if (netWMStateAtom != None && netWMStateFullscreenAtom != None)
|
|
|
|
{
|
|
|
|
// artifically reduce the initial window size so that the windowing
|
|
|
|
// system has a size to go back to when toggling off full screen,
|
|
|
|
// we don't have to worry about the window being initially smaller as the
|
|
|
|
// setWindowDecoration(..) implementation with enable full screen for us
|
|
|
|
x = width/4;
|
|
|
|
y = height/4;
|
|
|
|
width /= 2;
|
|
|
|
height /= 2;
|
2011-06-20 19:25:52 +08:00
|
|
|
|
|
|
|
doFullSceenWorkAround = true;
|
2011-06-20 17:22:57 +08:00
|
|
|
}
|
|
|
|
}
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
_window = XCreateWindow( _display, _parent,
|
2011-06-20 17:22:57 +08:00
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width, height, 0,
|
2006-12-21 20:19:14 +08:00
|
|
|
_visualInfo->depth, InputOutput,
|
2011-04-19 19:46:05 +08:00
|
|
|
_visualInfo->visual, mask, &swatt );
|
2008-08-16 01:32:26 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
if (!_window)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Error: Unable to create Window."<<std::endl;
|
2009-10-30 23:17:38 +08:00
|
|
|
_context = 0;
|
2007-09-26 17:50:32 +08:00
|
|
|
return false;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2009-11-20 19:25:49 +08:00
|
|
|
// Give window a class so that user preferences can be saved in the resource database.
|
|
|
|
XClassHint clH;
|
|
|
|
clH.res_name = (char *)"OSG";
|
|
|
|
clH.res_class = (char *)"osgViewer";
|
|
|
|
XSetClassHint( _display, _window, &clH);
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
// This positions the window at _windowX, _windowY
|
|
|
|
XSizeHints sh;
|
|
|
|
sh.flags = 0;
|
|
|
|
sh.flags |= USSize;
|
|
|
|
sh.flags &= 0x7;
|
|
|
|
sh.flags |= USPosition;
|
|
|
|
sh.flags &= 0xB;
|
2006-12-23 05:53:44 +08:00
|
|
|
sh.x = _traits->x;
|
|
|
|
sh.y = _traits->y;
|
|
|
|
sh.width = _traits->width;
|
|
|
|
sh.height = _traits->height;
|
|
|
|
XSetStandardProperties( _display, _window, _traits->windowName.c_str(), _traits->windowName.c_str(), None, 0, 0, &sh);
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
setWindowDecoration(_traits->windowDecoration);
|
2007-04-13 21:22:52 +08:00
|
|
|
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2007-01-18 05:11:57 +08:00
|
|
|
useCursor(_traits->useCursor);
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
_deleteWindow = XInternAtom (_display, "WM_DELETE_WINDOW", False);
|
2011-04-19 19:46:05 +08:00
|
|
|
XSetWMProtocols(_display, _window, &_deleteWindow, 1);
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
XFlush( _display );
|
|
|
|
XSync( _display, 0 );
|
|
|
|
|
|
|
|
// now update the window dimensions to account for any size changes made by the window manager,
|
|
|
|
XGetWindowAttributes( _display, _window, &watt );
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-11-24 18:16:03 +08:00
|
|
|
if (_traits->x != watt.x || _traits->y != watt.y
|
|
|
|
||_traits->width != watt.width || _traits->height != watt.height)
|
2007-01-02 02:20:10 +08:00
|
|
|
{
|
2011-06-20 19:25:52 +08:00
|
|
|
|
|
|
|
if (doFullSceenWorkAround)
|
|
|
|
{
|
|
|
|
OSG_INFO<<"Full Screen failed, resizing manually"<<std::endl;
|
|
|
|
XMoveResizeWindow(_display, _window, _traits->x, _traits->y, _traits->width, _traits->height);
|
|
|
|
|
|
|
|
XFlush(_display);
|
|
|
|
XSync(_display, 0);
|
|
|
|
|
|
|
|
XGetWindowAttributes( _display, _window, &watt );
|
|
|
|
}
|
|
|
|
|
2008-11-24 18:16:03 +08:00
|
|
|
resized( watt.x, watt.y, watt.width, watt.height );
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
//OSG_NOTICE<<"After sync apply.x = "<<watt.x<<" watt.y="<<watt.y<<" width="<<watt.width<<" height="<<watt.height<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
XSelectInput( _eventDisplay, _window, ExposureMask | StructureNotifyMask |
|
2007-02-09 21:51:28 +08:00
|
|
|
KeyPressMask | KeyReleaseMask |
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
2008-03-14 00:12:46 +08:00
|
|
|
KeymapStateMask | FocusChangeMask | EnterWindowMask );
|
2007-02-09 21:51:28 +08:00
|
|
|
|
|
|
|
XFlush( _eventDisplay );
|
|
|
|
XSync( _eventDisplay, 0 );
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
rescanModifierMapping();
|
2007-01-04 07:00:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphicsWindowX11::setWindow(Window window)
|
|
|
|
{
|
|
|
|
if (_initialized)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "GraphicsWindowX11::setWindow() - Window already created; it cannot be changed";
|
2007-09-26 17:50:32 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
if (window==0)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "GraphicsWindowX11::setWindow() - Invalid window handle passed ";
|
2007-09-26 17:50:32 +08:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
_window = window;
|
|
|
|
if (_window==0)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "GraphicsWindowX11::setWindow() - Unable to retrieve native window handle";
|
2007-09-26 17:50:32 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
XWindowAttributes watt;
|
|
|
|
XGetWindowAttributes( _display, _window, &watt );
|
|
|
|
_traits->x = watt.x;
|
|
|
|
_traits->y = watt.y;
|
|
|
|
_traits->width = watt.width;
|
|
|
|
_traits->height = watt.height;
|
|
|
|
|
|
|
|
_parent = DefaultRootWindow( _display );
|
|
|
|
|
|
|
|
//_traits->supportsResize = false;
|
|
|
|
_traits->windowDecoration = false;
|
2007-10-01 19:02:02 +08:00
|
|
|
|
|
|
|
if (_traits->windowName.size()) setWindowName(_traits->windowName);
|
|
|
|
|
2007-09-26 17:50:32 +08:00
|
|
|
_eventDisplay = XOpenDisplay(_traits->displayName().c_str());
|
|
|
|
|
|
|
|
XFlush( _eventDisplay );
|
|
|
|
XSync( _eventDisplay, 0 );
|
|
|
|
|
|
|
|
return true;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphicsWindowX11::realizeImplementation()
|
|
|
|
{
|
2006-12-23 01:46:21 +08:00
|
|
|
if (_realized)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl;
|
2006-12-23 01:46:21 +08:00
|
|
|
return true;
|
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
if (!_initialized) init();
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
if (!_initialized) return false;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
XMapWindow( _display, _window );
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-27 01:38:47 +08:00
|
|
|
// Window temp = _window;
|
|
|
|
// XSetWMColormapWindows( _display, _window, &temp, 1);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
_realized = true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-01-09 03:29:59 +08:00
|
|
|
bool GraphicsWindowX11::makeCurrentImplementation()
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-01-04 00:06:12 +08:00
|
|
|
if (!_realized)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do makeCurrent."<<std::endl;
|
2007-01-09 03:29:59 +08:00
|
|
|
return false;
|
2007-01-04 00:06:12 +08:00
|
|
|
}
|
2006-12-25 00:40:19 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
2009-11-01 17:04:41 +08:00
|
|
|
bool result = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _context)==EGL_TRUE;
|
2009-11-06 18:31:03 +08:00
|
|
|
checkEGLError("after eglMakeCurrent()");
|
2009-10-30 23:17:38 +08:00
|
|
|
return result;
|
|
|
|
#else
|
|
|
|
return glXMakeCurrent( _display, _window, _context )==True;
|
|
|
|
#endif
|
2007-01-09 03:29:59 +08:00
|
|
|
}
|
2007-01-04 00:06:12 +08:00
|
|
|
|
2007-01-09 03:29:59 +08:00
|
|
|
bool GraphicsWindowX11::releaseContextImplementation()
|
|
|
|
{
|
|
|
|
if (!_realized)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Warning: GraphicsWindow not realized, cannot do release context."<<std::endl;
|
2007-01-09 03:29:59 +08:00
|
|
|
return false;
|
2007-01-04 00:06:12 +08:00
|
|
|
}
|
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
bool result = eglMakeCurrent( _eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT )==EGL_TRUE;
|
2009-11-06 18:31:03 +08:00
|
|
|
checkEGLError("after eglMakeCurrent() release");
|
From Colin MacDonald, "In my application I have a custom graphics context class, derived from
osg::GraphicsContext, in order to give good integration with the
application's GUI toolkit. This works really well.
However, I need to share OpenGL texture resources with the standard
osgViewer GraphicsContext implementations, in particular the
PixelBuffers. This is essential for my application to conserve graphics
memory on low-end hardware. Currently the standard osg implementations
will not share resources with another derived osg::GraphicsContext,
other than the pre-defined osgViewer classes e.g. PixelBufferX11 is
hardcoded to only share resources with GraphicsWindowX11 and
PixelBufferX11 objects, and no other osg::GraphicsContext object.
To address this in the cleanest way I could think of, I have moved the
OpenGL handle variables for each platform into a small utility class,
e.g. GraphicsHandleX11 for unix. Then GraphicsWindowX11, PixelBufferX11
and any other derived osg::GraphicsContext class can inherit from
GraphicsHandleX11 to share OpenGL resources.
I have updated the X11, Win32 and Carbon implementations to use this.
The changes are minor. I haven't touched the Cocoa implmentation as
I'm not familiar with it at all and couldn't test it - it will work
unchanged.
Without this I had some horrible hacks in my application, this greatly
simplifies things for me. It also simplifies the osgViewer
implementations slightly. Perhaps it may help with other users'
desires to share resources with external graphics contexts, as was
discussed on the user list recently."
Notes from Robert Osfield, adapted Colin's submission to work with the new EGL related changes.
2009-11-22 00:41:02 +08:00
|
|
|
return result;
|
2009-10-30 23:17:38 +08:00
|
|
|
#else
|
|
|
|
return glXMakeCurrent( _display, None, NULL )==True;
|
|
|
|
#endif
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GraphicsWindowX11::closeImplementation()
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"Closing GraphicsWindowX11"<<std::endl;
|
2007-01-04 00:06:12 +08:00
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
if (_eventDisplay)
|
2006-12-25 00:40:19 +08:00
|
|
|
{
|
2007-02-09 21:51:28 +08:00
|
|
|
XCloseDisplay( _eventDisplay );
|
|
|
|
_eventDisplay = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_display)
|
|
|
|
{
|
2009-10-30 23:17:38 +08:00
|
|
|
if (_context)
|
2007-02-09 21:51:28 +08:00
|
|
|
{
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
2009-11-01 17:04:41 +08:00
|
|
|
eglDestroyContext( _eglDisplay, _context );
|
2009-10-30 23:17:38 +08:00
|
|
|
#else
|
|
|
|
glXDestroyContext( _display, _context );
|
|
|
|
#endif
|
2007-02-09 21:51:28 +08:00
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-10-01 19:02:02 +08:00
|
|
|
if (_window && _ownsWindow)
|
2007-02-09 21:51:28 +08:00
|
|
|
{
|
|
|
|
XDestroyWindow(_display, _window);
|
|
|
|
}
|
2006-12-25 00:40:19 +08:00
|
|
|
|
|
|
|
XFlush( _display );
|
|
|
|
XSync( _display,0 );
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
_window = 0;
|
|
|
|
_parent = 0;
|
2009-10-30 23:17:38 +08:00
|
|
|
_context = 0;
|
2006-12-25 00:40:19 +08:00
|
|
|
|
2007-02-08 19:30:57 +08:00
|
|
|
if (_visualInfo)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
|
|
|
delete _visualInfo;
|
2011-04-19 19:46:05 +08:00
|
|
|
#else
|
2009-10-30 23:17:38 +08:00
|
|
|
XFree(_visualInfo);
|
|
|
|
#endif
|
2006-12-21 20:19:14 +08:00
|
|
|
_visualInfo = 0;
|
|
|
|
}
|
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2007-02-08 19:30:57 +08:00
|
|
|
if (_display)
|
|
|
|
{
|
|
|
|
XCloseDisplay( _display );
|
|
|
|
_display = 0;
|
|
|
|
}
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
_initialized = false;
|
|
|
|
_realized = false;
|
2007-01-04 19:49:15 +08:00
|
|
|
_valid = false;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::swapBuffersImplementation()
|
|
|
|
{
|
2006-12-25 00:40:19 +08:00
|
|
|
if (!_realized) return;
|
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
|
2006-12-23 01:46:21 +08:00
|
|
|
|
2009-10-30 23:17:38 +08:00
|
|
|
#ifdef OSG_USE_EGL
|
2009-11-01 17:04:41 +08:00
|
|
|
eglSwapBuffers( _eglDisplay, _eglSurface );
|
2009-11-06 18:31:03 +08:00
|
|
|
checkEGLError("after eglSwapBuffers()");
|
2009-10-30 23:17:38 +08:00
|
|
|
#else
|
2010-04-22 01:16:13 +08:00
|
|
|
#if 0
|
|
|
|
if (_traits.valid() && _traits->vsync) {
|
|
|
|
|
|
|
|
unsigned int counter;
|
|
|
|
glXGetVideoSyncSGI(&counter);
|
|
|
|
glXWaitVideoSyncSGI(1, 0, &counter);
|
|
|
|
}
|
|
|
|
#endif
|
2009-10-30 23:17:38 +08:00
|
|
|
glXSwapBuffers( _display, _window );
|
|
|
|
#endif
|
2011-05-28 00:04:18 +08:00
|
|
|
|
|
|
|
|
|
|
|
while( XPending(_display) )
|
|
|
|
{
|
|
|
|
XEvent ev;
|
|
|
|
XNextEvent( _display, &ev );
|
|
|
|
|
|
|
|
switch( ev.type )
|
|
|
|
{
|
|
|
|
case ClientMessage:
|
|
|
|
{
|
|
|
|
if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
|
|
|
|
{
|
|
|
|
OSG_INFO<<"DeleteWindow event received"<<std::endl;
|
|
|
|
getEventQueue()->closeWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::checkEvents()
|
|
|
|
{
|
2006-12-25 00:40:19 +08:00
|
|
|
if (!_realized) return;
|
|
|
|
|
2007-04-16 04:53:09 +08:00
|
|
|
Display* display = _eventDisplay;
|
2007-02-09 21:51:28 +08:00
|
|
|
|
2007-01-05 21:01:08 +08:00
|
|
|
double baseTime = _timeOfLastCheckEvents;
|
|
|
|
double eventTime = baseTime;
|
|
|
|
double resizeTime = eventTime;
|
|
|
|
_timeOfLastCheckEvents = getEventQueue()->getTime();
|
2011-11-04 20:47:24 +08:00
|
|
|
if (baseTime>_timeOfLastCheckEvents) baseTime = _timeOfLastCheckEvents;
|
2012-03-22 01:36:20 +08:00
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"GraphicsWindowX11::checkEvents() : getEventQueue()->getCurrentEventState()->getGraphicsContext()="<<getEventQueue()->getCurrentEventState()->getGraphicsContext()<<std::endl;
|
2007-01-05 21:01:08 +08:00
|
|
|
|
2007-01-02 02:20:10 +08:00
|
|
|
int windowX = _traits->x;
|
|
|
|
int windowY = _traits->y;
|
|
|
|
int windowWidth = _traits->width;
|
|
|
|
int windowHeight = _traits->height;
|
|
|
|
|
2007-01-05 21:01:08 +08:00
|
|
|
Time firstEventTime = 0;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"Check events"<<std::endl;
|
2007-02-09 21:51:28 +08:00
|
|
|
while( XPending(display) )
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
|
|
|
XEvent ev;
|
2007-02-09 21:51:28 +08:00
|
|
|
XNextEvent( display, &ev );
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
switch( ev.type )
|
|
|
|
{
|
2007-01-04 07:00:05 +08:00
|
|
|
case ClientMessage:
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"ClientMessage event received"<<std::endl;
|
2007-01-04 19:49:15 +08:00
|
|
|
if (static_cast<Atom>(ev.xclient.data.l[0]) == _deleteWindow)
|
2007-01-04 07:00:05 +08:00
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"DeleteWindow event received"<<std::endl;
|
2007-09-26 17:50:32 +08:00
|
|
|
// FIXME only do if _ownsWindow ?
|
2007-01-09 03:29:59 +08:00
|
|
|
getEventQueue()->closeWindow(eventTime);
|
2007-01-04 07:00:05 +08:00
|
|
|
}
|
2011-05-03 18:14:34 +08:00
|
|
|
break;
|
2007-01-04 07:00:05 +08:00
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
case Expose :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"Expose x="<<ev.xexpose.x<<" y="<<ev.xexpose.y<<" width="<<ev.xexpose.width<<", height="<<ev.xexpose.height<<std::endl;
|
2011-04-19 20:01:38 +08:00
|
|
|
requestRedraw();
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GravityNotify :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"GravityNotify event received"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ReparentNotify:
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"ReparentNotify event received"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DestroyNotify :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"DestroyNotify event received"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
_realized = false;
|
2007-01-04 19:49:15 +08:00
|
|
|
_valid = false;
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case ConfigureNotify :
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"ConfigureNotify x="<<ev.xconfigure.x<<" y="<<ev.xconfigure.y<<" width="<<ev.xconfigure.width<<", height="<<ev.xconfigure.height<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
if (windowX != ev.xconfigure.x ||
|
2012-01-26 01:35:17 +08:00
|
|
|
windowY != ev.xconfigure.y ||
|
2007-01-02 02:20:10 +08:00
|
|
|
windowWidth != ev.xconfigure.width ||
|
|
|
|
windowHeight != ev.xconfigure.height)
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
resizeTime = eventTime;
|
|
|
|
|
2007-01-02 02:20:10 +08:00
|
|
|
windowX = ev.xconfigure.x;
|
|
|
|
windowY = ev.xconfigure.y;
|
|
|
|
windowWidth = ev.xconfigure.width;
|
|
|
|
windowHeight = ev.xconfigure.height;
|
|
|
|
}
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case MapNotify :
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"MapNotify"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
XWindowAttributes watt;
|
|
|
|
do
|
2007-02-09 21:51:28 +08:00
|
|
|
XGetWindowAttributes(display, _window, &watt );
|
2006-12-21 20:19:14 +08:00
|
|
|
while( watt.map_state != IsViewable );
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
|
2007-01-02 02:20:10 +08:00
|
|
|
|
|
|
|
if (windowWidth != watt.width || windowHeight != watt.height)
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
resizeTime = eventTime;
|
|
|
|
|
2007-01-02 02:20:10 +08:00
|
|
|
windowWidth = watt.width;
|
|
|
|
windowHeight = watt.height;
|
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
case FocusIn :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"FocusIn event received"<<std::endl;
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
flushKeyEvents();
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case UnmapNotify :
|
|
|
|
case FocusOut :
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"FocusOut/UnmapNotify event received"<<std::endl;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
if (ev.type == FocusOut && ev.xfocus.mode != NotifyNormal) break;
|
|
|
|
|
|
|
|
char modMap[32];
|
|
|
|
getModifierMap(modMap);
|
|
|
|
|
|
|
|
// release normal (non-modifier) keys
|
|
|
|
for (unsigned int key = 8; key < 256; key++)
|
|
|
|
{
|
|
|
|
bool isModifier = keyMapGetKey(modMap, key);
|
|
|
|
if (!isModifier) forceKey(key, eventTime, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// release modifier keys
|
|
|
|
for (unsigned int key = 8; key < 256; key++)
|
|
|
|
{
|
|
|
|
bool isModifier = keyMapGetKey(modMap, key);
|
|
|
|
if (isModifier) forceKey(key, eventTime, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-03-14 00:12:46 +08:00
|
|
|
case EnterNotify :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"EnterNotify event received"<<std::endl;
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
_modifierState = ev.xcrossing.state;
|
|
|
|
syncLocks();
|
2008-03-14 00:12:46 +08:00
|
|
|
break;
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
case KeymapNotify :
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"KeymapNotify event received"<<std::endl;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
|
|
|
|
// KeymapNotify is guaranteed to directly follow either a FocusIn or
|
|
|
|
// an EnterNotify event. We are only interested in the FocusIn case.
|
|
|
|
if (_lastEventType != FocusIn) break;
|
|
|
|
|
|
|
|
char modMap[32];
|
|
|
|
getModifierMap(modMap);
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
syncLocks();
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
char keyMap[32];
|
|
|
|
XQueryKeymap(_eventDisplay, keyMap);
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
// release normal (non-modifier) keys
|
|
|
|
for (unsigned int key = 8; key < 256; key++)
|
|
|
|
{
|
|
|
|
bool isModifier = keyMapGetKey(modMap, key);
|
|
|
|
if (isModifier) continue;
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
bool isPressed = keyMapGetKey(keyMap, key);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
if (!isPressed) forceKey(key, eventTime, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// press/release modifier keys
|
|
|
|
for (unsigned int key = 8; key < 256; key++)
|
|
|
|
{
|
|
|
|
bool isModifier = keyMapGetKey(modMap, key);
|
|
|
|
if (!isModifier) continue;
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
bool isPressed = keyMapGetKey(keyMap, key);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
forceKey(key, eventTime, isPressed);
|
|
|
|
}
|
|
|
|
|
|
|
|
// press normal keys
|
|
|
|
for (unsigned int key = 8; key < 256; key++)
|
|
|
|
{
|
|
|
|
bool isModifier = keyMapGetKey(modMap, key);
|
|
|
|
if (isModifier) continue;
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
bool isPressed = keyMapGetKey(keyMap, key);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
if (isPressed) forceKey(key, eventTime, true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
case MappingNotify :
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"MappingNotify event received"<<std::endl;
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
if (ev.xmapping.request == MappingModifier) rescanModifierMapping();
|
|
|
|
break;
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
case MotionNotify :
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
|
|
|
Time relativeTime = ev.xmotion.time - firstEventTime;
|
|
|
|
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
int wx, wy;
|
|
|
|
Window win = 0L;
|
|
|
|
if( ev.xmotion.same_screen )
|
|
|
|
{
|
|
|
|
wx = ev.xmotion.x;
|
|
|
|
wy = ev.xmotion.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// the mouse in on another screen so need to compute the
|
|
|
|
// coordinates of the mouse position relative to an absolute position
|
|
|
|
// then take away the position of the original window/screen to get
|
|
|
|
// the coordinates relative to the original position.
|
|
|
|
Window root;
|
|
|
|
int rx, ry;
|
|
|
|
unsigned int buttons;
|
|
|
|
|
|
|
|
int screenOrigin_x = 0;
|
|
|
|
int screenOrigin_y = 0;
|
|
|
|
int i;
|
2007-02-09 21:51:28 +08:00
|
|
|
for(i= 0; i < ScreenCount(display); i++ )
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-02-09 21:51:28 +08:00
|
|
|
if( XQueryPointer( display, RootWindow(display, i),
|
2006-12-21 20:19:14 +08:00
|
|
|
&root, &win, &rx, &ry, &wx, &wy, &buttons) )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
screenOrigin_x += DisplayWidth(display, i);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2006-12-23 05:53:44 +08:00
|
|
|
for(i= 0; i < static_cast<int>(_traits->screenNum); i++ )
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-02-09 21:51:28 +08:00
|
|
|
screenOrigin_x -= DisplayWidth(display, i);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int dest_x_return, dest_y_return;
|
|
|
|
Window child_return;
|
2007-02-09 21:51:28 +08:00
|
|
|
XTranslateCoordinates(display, _window, _parent, 0, 0, &dest_x_return, &dest_y_return, &child_return);
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
wx += (screenOrigin_x - dest_x_return);
|
|
|
|
wy += (screenOrigin_y - dest_y_return);
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
float mx = wx;
|
|
|
|
float my = wy;
|
|
|
|
transformMouseXY(mx, my);
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseMotion(mx, my, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_NOTICE<<"MotionNotify wx="<<wx<<" wy="<<wy<<" mx="<<mx<<" my="<<my<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case ButtonPress :
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
|
|
|
Time relativeTime = ev.xmotion.time - firstEventTime;
|
|
|
|
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
if( ev.xbutton.button == Button4 )
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else if( ev.xbutton.button == Button5)
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float mx = ev.xbutton.x;
|
|
|
|
float my = ev.xmotion.y;
|
|
|
|
transformMouseXY(mx, my);
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseButtonPress(mx, my, ev.xbutton.button, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case ButtonRelease :
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
|
|
|
Time relativeTime = ev.xmotion.time - firstEventTime;
|
|
|
|
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
if( ev.xbutton.button == Button4 )
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_UP, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else if( ev.xbutton.button == Button5)
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float mx = ev.xbutton.x;
|
|
|
|
float my = ev.xmotion.y;
|
|
|
|
transformMouseXY(mx, my);
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->mouseButtonRelease(mx, my, ev.xbutton.button, eventTime);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case KeyPress:
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
|
|
|
Time relativeTime = ev.xmotion.time - firstEventTime;
|
|
|
|
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
|
|
|
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
_modifierState = ev.xkey.state;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
keyMapSetKey(_keyMap, ev.xkey.keycode);
|
2006-12-21 20:19:14 +08:00
|
|
|
int keySymbol = 0;
|
2011-01-28 00:23:48 +08:00
|
|
|
int unmodifiedKeySymbol = 0;
|
|
|
|
adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol);
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2011-01-28 00:23:48 +08:00
|
|
|
getEventQueue()->keyPress(keySymbol, eventTime, unmodifiedKeySymbol);
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
case KeyRelease:
|
|
|
|
{
|
2007-01-05 21:01:08 +08:00
|
|
|
if (firstEventTime==0) firstEventTime = ev.xmotion.time;
|
|
|
|
Time relativeTime = ev.xmotion.time - firstEventTime;
|
|
|
|
eventTime = baseTime + static_cast<double>(relativeTime)*0.001;
|
2011-04-19 19:46:05 +08:00
|
|
|
#if 1
|
2007-08-05 22:59:17 +08:00
|
|
|
// Check for following KeyPress events and see if
|
|
|
|
// the pair are the result of auto-repeat. If so, drop
|
|
|
|
// this one on the floor, to be consistent with
|
2011-04-19 19:46:05 +08:00
|
|
|
// Windows and Mac ports. The idea comes from libSDL sources.
|
2007-08-05 22:59:17 +08:00
|
|
|
XEvent nextev;
|
|
|
|
if (XPending(display))
|
|
|
|
{
|
|
|
|
XPeekEvent(display, &nextev);
|
|
|
|
if ((nextev.type == KeyPress)
|
|
|
|
&& (nextev.xkey.keycode == ev.xkey.keycode)
|
|
|
|
&& (nextev.xmotion.time - ev.xmotion.time < 2))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-03-14 00:12:46 +08:00
|
|
|
#endif
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
_modifierState = ev.xkey.state;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
keyMapClearKey(_keyMap, ev.xkey.keycode);
|
2006-12-21 20:19:14 +08:00
|
|
|
int keySymbol = 0;
|
2011-01-28 00:23:48 +08:00
|
|
|
int unmodifiedKeySymbol = 0;
|
|
|
|
adaptKey(ev.xkey, keySymbol, unmodifiedKeySymbol);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2011-01-28 00:23:48 +08:00
|
|
|
getEventQueue()->keyRelease(keySymbol, eventTime, unmodifiedKeySymbol);
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
default:
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Other event "<<ev.type<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
break;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
_lastEventType = ev.type;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
2007-01-02 02:20:10 +08:00
|
|
|
|
2011-04-19 20:01:38 +08:00
|
|
|
// send window resize event if window position or size was changed
|
2011-04-19 19:46:05 +08:00
|
|
|
if (windowX != _traits->x ||
|
2007-01-02 02:20:10 +08:00
|
|
|
windowY != _traits->y ||
|
|
|
|
windowWidth != _traits->width ||
|
|
|
|
windowHeight != _traits->height)
|
|
|
|
{
|
2011-04-19 19:46:05 +08:00
|
|
|
resized(windowX, windowY, windowWidth, windowHeight);
|
2007-01-05 21:01:08 +08:00
|
|
|
getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime);
|
2011-04-19 20:01:38 +08:00
|
|
|
|
|
|
|
// request window repaint if window size was changed
|
|
|
|
if (windowWidth != _traits->width ||
|
|
|
|
windowHeight != _traits->height)
|
|
|
|
{
|
|
|
|
requestRedraw();
|
|
|
|
}
|
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::grabFocus()
|
|
|
|
{
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* display = getDisplayToUse();
|
|
|
|
|
|
|
|
XSetInputFocus( display, _window, RevertToNone, CurrentTime );
|
2011-04-19 19:46:05 +08:00
|
|
|
XFlush(display);
|
2007-04-13 21:22:52 +08:00
|
|
|
XSync(display,0);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::grabFocusIfPointerInWindow()
|
|
|
|
{
|
|
|
|
Window win, root;
|
|
|
|
int wx, wy, rx, ry;
|
|
|
|
unsigned int buttons;
|
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
Display* display = getDisplayToUse();
|
|
|
|
|
|
|
|
if( XQueryPointer( display, _window,
|
2006-12-21 20:19:14 +08:00
|
|
|
&root, &win, &rx, &ry, &wx, &wy, &buttons))
|
|
|
|
{
|
2007-02-09 21:51:28 +08:00
|
|
|
#if 0
|
|
|
|
if (wx>=0 && wx<_traits->width &&
|
|
|
|
wy>=0 && wy<_traits->height)
|
|
|
|
{
|
|
|
|
grabFocus();
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
#else
|
2006-12-21 20:19:14 +08:00
|
|
|
grabFocus();
|
2007-02-09 21:51:28 +08:00
|
|
|
#endif
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::transformMouseXY(float& x, float& y)
|
|
|
|
{
|
|
|
|
if (getEventQueue()->getUseFixedMouseInputRange())
|
|
|
|
{
|
|
|
|
osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
|
2006-12-23 05:53:44 +08:00
|
|
|
x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width);
|
|
|
|
y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-28 00:23:48 +08:00
|
|
|
void GraphicsWindowX11::adaptKey(XKeyEvent& keyevent, int& keySymbol, int& unmodifiedKeySymbol)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2009-06-02 16:56:32 +08:00
|
|
|
unsigned char buffer_return[32];
|
|
|
|
int bytes_buffer = 32;
|
|
|
|
KeySym keysym_return;
|
2009-05-26 00:34:26 +08:00
|
|
|
|
2009-06-02 16:56:32 +08:00
|
|
|
int numChars = XLookupString(&keyevent, reinterpret_cast<char*>(buffer_return), bytes_buffer, &keysym_return, NULL);
|
|
|
|
keySymbol = keysym_return;
|
|
|
|
if (!remapExtendedX11Key(keySymbol) && (numChars==1))
|
|
|
|
{
|
|
|
|
keySymbol = buffer_return[0];
|
|
|
|
}
|
2011-01-28 00:23:48 +08:00
|
|
|
|
2013-02-04 21:28:05 +08:00
|
|
|
unmodifiedKeySymbol = XkbKeycodeToKeysym(keyevent.display, keyevent.keycode, 0, 0);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Function to inject artificial key presses/releases.
|
|
|
|
void GraphicsWindowX11::forceKey(int key, double time, bool state)
|
|
|
|
{
|
|
|
|
if (!(state ^ keyMapGetKey(_keyMap, key))) return; // already pressed/released
|
|
|
|
|
|
|
|
XKeyEvent event;
|
|
|
|
event.serial = 0;
|
|
|
|
event.send_event = True;
|
|
|
|
event.display = _eventDisplay;
|
|
|
|
event.window = _window;
|
|
|
|
event.subwindow = 0;
|
2008-02-26 01:30:30 +08:00
|
|
|
event.time = 0;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
event.x = 0;
|
|
|
|
event.y = 0;
|
|
|
|
event.x_root = 0;
|
|
|
|
event.y_root = 0;
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
event.state = getModifierMask() | (_modifierState & (LockMask | _numLockMask));
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
event.keycode = key;
|
|
|
|
event.same_screen = True;
|
|
|
|
|
|
|
|
int keySymbol = 0;
|
2011-01-28 00:23:48 +08:00
|
|
|
int unmodifiedKeySymbol = 0;
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
if (state)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
event.type = KeyPress;
|
2011-01-28 00:23:48 +08:00
|
|
|
adaptKey(event, keySymbol, unmodifiedKeySymbol);
|
|
|
|
getEventQueue()->keyPress(keySymbol, time, unmodifiedKeySymbol);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
keyMapSetKey(_keyMap, key);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
else
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
event.type = KeyRelease;
|
2011-01-28 00:23:48 +08:00
|
|
|
adaptKey(event, keySymbol, unmodifiedKeySymbol);
|
|
|
|
getEventQueue()->keyRelease(keySymbol, time, unmodifiedKeySymbol);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
keyMapClearKey(_keyMap, key);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
}
|
2006-12-21 20:19:14 +08:00
|
|
|
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
void GraphicsWindowX11::syncLocks()
|
2008-03-14 23:13:08 +08:00
|
|
|
{
|
|
|
|
unsigned int mask = getEventQueue()->getCurrentEventState()->getModKeyMask();
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
|
|
|
|
if (_modifierState & LockMask)
|
2008-03-14 23:13:08 +08:00
|
|
|
mask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
|
|
|
|
else
|
|
|
|
mask &= ~osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK;
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
|
|
|
|
if (_modifierState & _numLockMask)
|
|
|
|
mask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
|
|
|
|
else
|
|
|
|
mask &= ~osgGA::GUIEventAdapter::MODKEY_NUM_LOCK;
|
|
|
|
|
2008-03-14 23:13:08 +08:00
|
|
|
getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
|
|
|
|
}
|
|
|
|
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
void GraphicsWindowX11::rescanModifierMapping()
|
|
|
|
{
|
|
|
|
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
|
|
|
|
KeyCode *m = mkm->modifiermap;
|
|
|
|
KeyCode numlock = XKeysymToKeycode(_eventDisplay, XK_Num_Lock);
|
|
|
|
_numLockMask = 0;
|
|
|
|
for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
|
|
|
|
{
|
|
|
|
if (*m == numlock)
|
|
|
|
{
|
|
|
|
_numLockMask = 1 << (i / mkm->max_keypermod);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-28 22:15:36 +08:00
|
|
|
XFree(mkm->modifiermap);
|
|
|
|
XFree(mkm);
|
From Melchoir Franz, "osgViewer toggled the NumLock state correctly when pressing the NumLock
key, but it didn't pick up the initial state. So, if NumLock was on for
the OS at startup (LED on), it was still off for OSG. And the first
keypress turned the LED off, and NumLock on for OSG. The attached fix
picks up the state on every FocusIn, just like it was done in the last
commits for CapsLock. The difference is, that the NumLock mask isn't
standardized (e.g. 0x10 for Linux, and 0x80 for AIX), so we have to do
a reverse lookup (::rescanModifierMapping()).
Note that I could not reproduce the problem on my system, but someone
else confirmed it twice on his, and the patch fixed it for him.
Changed files:
./include/osgViewer/api/X11/GraphicsWindowX11
./src/osgViewer/GraphicsWindowX11.cpp
"
2008-03-20 05:05:38 +08:00
|
|
|
}
|
|
|
|
|
From Melchior Franz, "In KDE I switch desktops with Super-Tab, and occasionally I
get an excess Tab key report when switching back to an OSG
application (usually FlightGear :-). Although KDE has consumed
the Tab, it's sometimes still in the XKeymapEvent's key_vector,
and followed by a Tab KeyRelease event.
Avoid this artifact by
- asking for a "fresh" keymap (via XQueryKeymap()), rather than
using the unreliable(?) XKeymapEvent's key_vector, and by
- flushing all key events on focus-in (to avoid the KeyRelease)
After Super-press, Tab-press, Super-release, Tab-release (note
the wrong release order!) I still get an extra Tab event. But
this is not surprising and not exactly wrong either. Also it's
hard to avoid, as we can't see what happened to the keyboard
before we regained focus.
Files changed:
src/osgViewer/GraphicsWindowX11.cpp
include/osgViewer/api/X11/GraphicsWindowX11"
2008-05-09 00:45:59 +08:00
|
|
|
void GraphicsWindowX11::flushKeyEvents()
|
|
|
|
{
|
|
|
|
XEvent e;
|
|
|
|
while (XCheckMaskEvent(_eventDisplay, KeyPressMask|KeyReleaseMask, &e))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
// Returns char[32] keymap with bits for every modifier key set.
|
|
|
|
void GraphicsWindowX11::getModifierMap(char* keymap) const
|
|
|
|
{
|
|
|
|
memset(keymap, 0, 32);
|
|
|
|
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
|
|
|
|
KeyCode *m = mkm->modifiermap;
|
|
|
|
for (int i = 0; i < mkm->max_keypermod * 8; i++, m++)
|
2007-01-02 02:20:10 +08:00
|
|
|
{
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
if (*m) keyMapSetKey(keymap, *m);
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
2009-05-28 22:15:36 +08:00
|
|
|
XFree(mkm->modifiermap);
|
|
|
|
XFree(mkm);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int GraphicsWindowX11::getModifierMask() const
|
|
|
|
{
|
|
|
|
int mask = 0;
|
|
|
|
XModifierKeymap *mkm = XGetModifierMapping(_eventDisplay);
|
|
|
|
for (int i = 0; i < mkm->max_keypermod * 8; i++)
|
2007-01-02 02:20:10 +08:00
|
|
|
{
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
unsigned int key = mkm->modifiermap[i];
|
|
|
|
if (key && keyMapGetKey(_keyMap, key))
|
|
|
|
{
|
|
|
|
mask |= 1 << (i / mkm->max_keypermod);
|
|
|
|
}
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
2009-05-28 22:15:36 +08:00
|
|
|
XFree(mkm->modifiermap);
|
|
|
|
XFree(mkm);
|
From Franz Melchior, "When switching virtual desktops or minimizing a window, keys
remain in pressed state after revealing, even if they are no
longer pressed on the keyboard. This can have bad effects,
especially if the stuck keys are modifier keys. One has to
press and release the stuck keys again to reset the wrong state.
The fix keeps track of all key presses and releases. On FocusOut
and UnmapNotify it releases all keys that are in pressed state,
and on KeymapNotify (following a FocusIn), it sets the currently
pressed keys again. To avoid confusion in the OSG-using application
normal keys are always reported released /before/ and pressed
/after/ modifier keys.
As current key states are returned as char[32] keymap by
XQueryKeymap and XKeymapEvent, this format is also used to
recognize modifier keys and for maintaining the current
internal key state. Functions to set/clear/query bits in
such a keymap are added.
The patch was extensively tested with osgkeyboard and
FlightGear under KDE and fvwm2. It was not tested on a
Xinerama setup or with multiple windows, but as _eventDisplay
is used throughout, there should be no problems. The patch also
makes the following changes:
- removes old and obsolete handling of modifier keys in ::adaptKey().
This wasn't only unused, but also wrong (and for that reason commented
out in revision 7066). The modifier states are actually handled
in ./src/osgGA/EventQueue.cpp (EventQueue::keyPress/keyRelease).
- fixes some spelling"
2008-02-26 00:50:28 +08:00
|
|
|
return mask;
|
2007-01-02 02:20:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphicsWindowX11::requestWarpPointer(float x,float y)
|
|
|
|
{
|
2010-06-18 22:53:58 +08:00
|
|
|
if (!_realized)
|
|
|
|
{
|
|
|
|
OSG_INFO<<"GraphicsWindowX11::requestWarpPointer() - Window not realized; cannot warp pointer, screenNum="<< _traits->screenNum<<std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-10-01 17:41:05 +08:00
|
|
|
Display* display = _eventDisplay; // getDisplayToUse();
|
2007-04-13 21:22:52 +08:00
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
XWarpPointer( display,
|
2007-01-02 02:20:10 +08:00
|
|
|
None,
|
2011-04-19 19:46:05 +08:00
|
|
|
_window,
|
2007-01-02 02:20:10 +08:00
|
|
|
0, 0, 0, 0,
|
|
|
|
static_cast<int>(x), static_cast<int>(y) );
|
|
|
|
|
2007-04-13 21:22:52 +08:00
|
|
|
XFlush(display);
|
|
|
|
XSync(display, 0);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-01-02 04:01:45 +08:00
|
|
|
getEventQueue()->mouseWarped(x,y);
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
extern "C"
|
2007-04-14 16:31:40 +08:00
|
|
|
{
|
|
|
|
|
2008-04-04 02:06:09 +08:00
|
|
|
typedef int (*X11ErrorHandler)(Display*, XErrorEvent*);
|
|
|
|
|
2007-01-04 00:06:12 +08:00
|
|
|
int X11ErrorHandling(Display* display, XErrorEvent* event)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE<<"Got an X11ErrorHandling call display="<<display<<" event="<<event<<std::endl;
|
2007-02-08 19:26:04 +08:00
|
|
|
|
|
|
|
char buffer[256];
|
|
|
|
XGetErrorText( display, event->error_code, buffer, 256);
|
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << buffer << std::endl;
|
|
|
|
OSG_NOTICE << "Major opcode: " << (int)event->request_code << std::endl;
|
|
|
|
OSG_NOTICE << "Minor opcode: " << (int)event->minor_code << std::endl;
|
|
|
|
OSG_NOTICE << "Error code: " << (int)event->error_code << std::endl;
|
|
|
|
OSG_NOTICE << "Request serial: " << event->serial << std::endl;
|
|
|
|
OSG_NOTICE << "Current serial: " << NextRequest( display ) - 1 << std::endl;
|
2007-02-08 19:26:04 +08:00
|
|
|
|
|
|
|
switch( event->error_code )
|
|
|
|
{
|
|
|
|
case BadValue:
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << " Value: " << event->resourceid << std::endl;
|
2007-02-08 19:26:04 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case BadAtom:
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << " AtomID: " << event->resourceid << std::endl;
|
2007-02-08 19:26:04 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << " ResourceID: " << event->resourceid << std::endl;
|
2007-02-08 19:26:04 +08:00
|
|
|
break;
|
|
|
|
}
|
2007-01-04 19:49:15 +08:00
|
|
|
return 0;
|
2007-01-04 00:06:12 +08:00
|
|
|
}
|
|
|
|
|
2007-04-14 16:31:40 +08:00
|
|
|
}
|
2007-01-04 00:06:12 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
class X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-12-21 21:32:13 +08:00
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
|
|
|
// TODO: Investigate whether or not Robert thinks we should store/restore the original
|
|
|
|
// resolution in the destructor; I'm not sure the other ones do this, and it may be the
|
|
|
|
// responsibility of the user.
|
2008-12-16 23:08:04 +08:00
|
|
|
bool _setScreen(const osg::GraphicsContext::ScreenIdentifier& si, unsigned int width, unsigned int height, unsigned int colorDepth, double rate) {
|
|
|
|
if (colorDepth>0)
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "X11WindowingSystemInterface::_setScreen() is not fully implemented (missing depth)."<<std::endl;
|
2008-12-16 23:08:04 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
Display* display = XOpenDisplay(si.displayName().c_str());
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
if(display)
|
|
|
|
{
|
|
|
|
XRRScreenConfiguration* sc = XRRGetScreenInfo(display, RootWindow(display, si.screenNum));
|
|
|
|
|
|
|
|
if(!sc)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Unable to create XRRScreenConfiguration on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
|
2007-12-21 21:32:13 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int numScreens = 0;
|
|
|
|
int numRates = 0;
|
|
|
|
Rotation currentRot = 0;
|
|
|
|
bool okay = false;
|
|
|
|
|
|
|
|
XRRConfigRotations(sc, ¤tRot);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
// If the width or height are zero, use our defaults.
|
|
|
|
if(!width || !height)
|
|
|
|
{
|
|
|
|
getScreenResolution(si, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this somehow fails, okay will still be false, no iteration will take place below,
|
|
|
|
// and the sc pointer will still be freed later on.
|
|
|
|
XRRScreenSize* ss = XRRConfigSizes(sc, &numScreens);
|
|
|
|
|
|
|
|
for(int i = 0; i < numScreens; i++)
|
|
|
|
{
|
|
|
|
if(ss[i].width == static_cast<int>(width) && ss[i].height == static_cast<int>(height))
|
|
|
|
{
|
|
|
|
short* rates = XRRConfigRates(sc, i, &numRates);
|
|
|
|
bool rateFound = false;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
// Search for our rate in the list of acceptable rates given to us by Xrandr.
|
|
|
|
// If it's not found, rateFound will still be false and the call will never
|
|
|
|
// be made to XRRSetScreenConfigAndRate since the rate will be invalid.
|
|
|
|
for(int r = 0; r < numRates; r++)
|
|
|
|
{
|
|
|
|
if(rates[r] == static_cast<short>(rate))
|
|
|
|
{
|
|
|
|
rateFound = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rate > 0.0f && !rateFound)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Unable to find valid refresh rate " << rate << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
|
2007-12-21 21:32:13 +08:00
|
|
|
}
|
|
|
|
else if(XRRSetScreenConfigAndRate(display, sc, DefaultRootWindow(display), i, currentRot, static_cast<short>(rate), CurrentTime) != RRSetConfigSuccess)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Unable to set resolution to " << width << "x" << height << " on display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
|
2007-12-21 21:32:13 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
okay = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
XRRFreeScreenConfigInfo(sc);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
return okay;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
|
2007-12-21 21:32:13 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2006-12-21 20:19:14 +08:00
|
|
|
|
2008-04-04 02:06:09 +08:00
|
|
|
protected:
|
|
|
|
bool _errorHandlerSet;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-04-04 02:06:09 +08:00
|
|
|
|
2007-12-21 21:32:13 +08:00
|
|
|
public:
|
2006-12-21 20:19:14 +08:00
|
|
|
X11WindowingSystemInterface()
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"X11WindowingSystemInterface()"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Install an X11 error handler, if the application has not already done so.
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-04-04 02:06:09 +08:00
|
|
|
// Set default handler, and get pointer to current handler.
|
|
|
|
X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-04-04 02:06:09 +08:00
|
|
|
// Set our handler, and get pointer to default handler.
|
|
|
|
X11ErrorHandler defHandler = XSetErrorHandler(X11ErrorHandling);
|
|
|
|
|
|
|
|
if ( currentHandler == defHandler )
|
|
|
|
{
|
|
|
|
// No application error handler, use ours.
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_INFO<<"Set osgViewer X11 error handler"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
_errorHandlerSet = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Application error handler exists, leave it set.
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_INFO<<"Existing application X11 error handler set"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
_errorHandlerSet = 0;
|
|
|
|
XSetErrorHandler(currentHandler);
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2007-02-09 21:51:28 +08:00
|
|
|
#if 0
|
2006-12-23 01:46:21 +08:00
|
|
|
if (XInitThreads() == 0)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Error: XInitThreads() failed. Aborting." << std::endl;
|
2006-12-23 01:46:21 +08:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
|
2006-12-23 01:46:21 +08:00
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
#endif
|
2008-12-16 23:08:04 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
|
|
|
|
|
2007-01-04 00:06:12 +08:00
|
|
|
~X11WindowingSystemInterface()
|
|
|
|
{
|
2007-07-06 21:08:51 +08:00
|
|
|
if (osg::Referenced::getDeleteHandler())
|
|
|
|
{
|
|
|
|
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
|
|
|
|
osg::Referenced::getDeleteHandler()->flushAll();
|
|
|
|
}
|
|
|
|
|
2010-05-28 23:56:43 +08:00
|
|
|
//OSG_NOTICE<<"~X11WindowingSystemInterface()"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
|
|
|
|
// Unset our X11 error handler, providing the application has not replaced it.
|
|
|
|
|
|
|
|
if ( _errorHandlerSet )
|
|
|
|
{
|
|
|
|
X11ErrorHandler currentHandler = XSetErrorHandler(NULL);
|
2008-04-11 18:31:49 +08:00
|
|
|
if ( currentHandler == X11ErrorHandling )
|
2008-04-04 02:06:09 +08:00
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_INFO<<"osgViewer X11 error handler removed"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Not our error handler, leave it set.
|
2010-05-28 23:56:43 +08:00
|
|
|
// OSG_INFO<<"Application X11 error handler left"<<std::endl;
|
2008-04-04 02:06:09 +08:00
|
|
|
XSetErrorHandler(currentHandler);
|
|
|
|
}
|
|
|
|
}
|
2007-01-04 00:06:12 +08:00
|
|
|
}
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
Display* display = XOpenDisplay(si.displayName().c_str());
|
2006-12-21 20:19:14 +08:00
|
|
|
if(display)
|
|
|
|
{
|
2011-04-19 19:46:05 +08:00
|
|
|
unsigned int numScreens = ScreenCount(display);
|
2006-12-21 20:19:14 +08:00
|
|
|
XCloseDisplay(display);
|
|
|
|
|
|
|
|
return numScreens;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "A Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\""<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
bool supportsRandr(Display* display) const
|
|
|
|
{
|
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
|
|
|
int event_basep;
|
|
|
|
int error_basep;
|
|
|
|
bool supports_randr = XRRQueryExtension( display, &event_basep, &error_basep );
|
|
|
|
if( supports_randr )
|
|
|
|
{
|
|
|
|
int major, minor;
|
|
|
|
XRRQueryVersion( display, &major, &minor );
|
|
|
|
return ( major > 1 || ( major == 1 && minor >= 2 ) );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettings & resolution )
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2006-12-25 00:40:19 +08:00
|
|
|
Display* display = XOpenDisplay(si.displayName().c_str());
|
2006-12-21 20:19:14 +08:00
|
|
|
if(display)
|
|
|
|
{
|
2008-12-16 23:08:04 +08:00
|
|
|
resolution.width = DisplayWidth(display, si.screenNum);
|
|
|
|
resolution.height = DisplayHeight(display, si.screenNum);
|
|
|
|
resolution.colorDepth = DefaultDepth(display, si.screenNum);
|
2011-02-04 18:27:05 +08:00
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
resolution.refreshRate = 0; // Missing call. Need a X11 expert.
|
2011-02-04 18:27:05 +08:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
|
|
|
if (supportsRandr(display))
|
|
|
|
{
|
|
|
|
|
|
|
|
XRRScreenConfiguration* screenConfig = XRRGetScreenInfo ( display, RootWindow(display, si.screenNum) );
|
|
|
|
|
|
|
|
resolution.refreshRate = XRRConfigCurrentRate ( screenConfig );
|
|
|
|
|
|
|
|
XRRFreeScreenConfigInfo( screenConfig );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
XCloseDisplay(display);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "Unable to open display \"" << XDisplayName(si.displayName().c_str()) << "\"."<<std::endl;
|
2008-12-16 23:08:04 +08:00
|
|
|
resolution.width = 0;
|
|
|
|
resolution.height = 0;
|
|
|
|
resolution.colorDepth = 0;
|
|
|
|
resolution.refreshRate = 0;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, const osg::GraphicsContext::ScreenSettings & resolution )
|
2007-12-21 21:32:13 +08:00
|
|
|
{
|
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
2008-12-16 23:08:04 +08:00
|
|
|
_setScreen(si, resolution.width, resolution.height, resolution.colorDepth, resolution.refreshRate);
|
2007-12-21 21:32:13 +08:00
|
|
|
#else
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "You must build osgViewer with Xrandr 1.2 or higher for setScreenSettings support!" << std::endl;
|
2007-12-21 21:32:13 +08:00
|
|
|
#endif
|
2008-12-16 23:08:04 +08:00
|
|
|
return false;
|
2007-12-21 21:32:13 +08:00
|
|
|
}
|
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& si, osg::GraphicsContext::ScreenSettingsList & resolutionList)
|
2007-12-21 21:32:13 +08:00
|
|
|
{
|
2008-12-16 23:08:04 +08:00
|
|
|
resolutionList.clear();
|
|
|
|
|
|
|
|
Display* display = XOpenDisplay(si.displayName().c_str());
|
|
|
|
if(display)
|
|
|
|
{
|
2007-12-21 21:32:13 +08:00
|
|
|
#ifdef OSGVIEWER_USE_XRANDR
|
2008-12-16 23:08:04 +08:00
|
|
|
int defaultDepth = DefaultDepth(display, si.screenNum);
|
|
|
|
|
|
|
|
if (supportsRandr(display))
|
|
|
|
{
|
|
|
|
int nsizes = 0;
|
|
|
|
XRRScreenSize * screenSizes = XRRSizes(display, si.screenNum, &nsizes);
|
|
|
|
if (screenSizes && nsizes>0)
|
|
|
|
{
|
|
|
|
for(int i=0; i<nsizes; ++i)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"Screen size "<<screenSizes[i].width<<" "<<screenSizes[i].height<<" "<<screenSizes[i].mwidth<<" "<<screenSizes[i].mheight<<std::endl;
|
2008-12-16 23:08:04 +08:00
|
|
|
|
|
|
|
int nrates;
|
|
|
|
short * rates = XRRRates (display, si.screenNum, i, &nrates);
|
|
|
|
if (rates && nrates>0)
|
|
|
|
{
|
|
|
|
for(int j=0; j<nrates; ++j)
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<" rates "<<rates[j]<<std::endl;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-12-16 23:08:04 +08:00
|
|
|
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
|
|
|
|
screenSizes[i].width,
|
|
|
|
screenSizes[i].height,
|
|
|
|
double(rates[j]),
|
|
|
|
defaultDepth));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resolutionList.push_back(osg::GraphicsContext::ScreenSettings(
|
|
|
|
screenSizes[i].width,
|
|
|
|
screenSizes[i].height,
|
|
|
|
0.0,
|
|
|
|
defaultDepth));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-19 19:46:05 +08:00
|
|
|
#endif
|
2008-12-16 23:08:04 +08:00
|
|
|
XCloseDisplay(display);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resolutionList.empty())
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_NOTICE << "X11WindowingSystemInterface::enumerateScreenSettings() not supported." << std::endl;
|
2008-12-16 23:08:04 +08:00
|
|
|
}
|
2007-12-21 21:32:13 +08:00
|
|
|
}
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
|
|
|
|
{
|
2006-12-23 05:53:44 +08:00
|
|
|
if (traits->pbuffer)
|
2006-12-21 20:19:14 +08:00
|
|
|
{
|
2007-06-20 01:12:05 +08:00
|
|
|
#if 1
|
|
|
|
osg::ref_ptr<osgViewer::PixelBufferX11> pbuffer = new PixelBufferX11(traits);
|
2006-12-25 00:40:19 +08:00
|
|
|
if (pbuffer->valid()) return pbuffer.release();
|
|
|
|
else return 0;
|
2007-06-20 01:12:05 +08:00
|
|
|
#else
|
|
|
|
osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
|
|
|
|
if (window->valid()) return window.release();
|
|
|
|
else return 0;
|
|
|
|
#endif
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-12-25 00:40:19 +08:00
|
|
|
osg::ref_ptr<osgViewer::GraphicsWindowX11> window = new GraphicsWindowX11(traits);
|
|
|
|
if (window->valid()) return window.release();
|
|
|
|
else return 0;
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RegisterWindowingSystemInterfaceProxy
|
|
|
|
{
|
|
|
|
RegisterWindowingSystemInterfaceProxy()
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"RegisterWindowingSystemInterfaceProxy()"<<std::endl;
|
2006-12-21 20:19:14 +08:00
|
|
|
osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
|
|
|
|
}
|
|
|
|
|
|
|
|
~RegisterWindowingSystemInterfaceProxy()
|
|
|
|
{
|
2010-05-28 23:56:43 +08:00
|
|
|
OSG_INFO<<"~RegisterWindowingSystemInterfaceProxy()"<<std::endl;
|
2007-07-06 21:08:51 +08:00
|
|
|
|
|
|
|
if (osg::Referenced::getDeleteHandler())
|
|
|
|
{
|
|
|
|
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
|
|
|
|
osg::Referenced::getDeleteHandler()->flushAll();
|
|
|
|
}
|
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
osg::GraphicsContext::setWindowingSystemInterface(0);
|
2007-07-06 21:08:51 +08:00
|
|
|
|
2006-12-21 20:19:14 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
|
2007-05-25 23:26:13 +08:00
|
|
|
|
|
|
|
// declare C entry point for static compilation.
|
2007-06-11 03:53:18 +08:00
|
|
|
extern "C" void graphicswindow_X11(void)
|
|
|
|
{
|
|
|
|
osg::GraphicsContext::setWindowingSystemInterface(new X11WindowingSystemInterface);
|
|
|
|
}
|
2008-08-16 01:32:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
void GraphicsWindowX11::raiseWindow()
|
|
|
|
{
|
|
|
|
Display* display = getDisplayToUse();
|
|
|
|
XWindowAttributes winAttrib;
|
|
|
|
|
|
|
|
Window root_return, parent_return, *children;
|
|
|
|
unsigned int nchildren, i=0;
|
|
|
|
XTextProperty windowName;
|
|
|
|
bool xraise = false;
|
2011-04-19 19:46:05 +08:00
|
|
|
|
2008-08-16 01:32:26 +08:00
|
|
|
|
|
|
|
XQueryTree(display, _parent, &root_return, &parent_return, &children, &nchildren);
|
|
|
|
while (!xraise && i<nchildren)
|
|
|
|
{
|
|
|
|
XGetWMName(display,children[i++],&windowName);
|
|
|
|
if ((windowName.nitems != 0) && (strcmp(_traits->windowName.c_str(),(const char *)windowName.value) == 0)) xraise = true;
|
|
|
|
}
|
|
|
|
if (xraise) XRaiseWindow(display,_window);
|
2011-04-19 19:46:05 +08:00
|
|
|
else
|
2008-08-16 01:32:26 +08:00
|
|
|
{
|
|
|
|
XGetWindowAttributes(display, _window, &winAttrib);
|
|
|
|
XReparentWindow(display, _window, _parent, winAttrib.x, winAttrib.y);
|
|
|
|
}
|
|
|
|
XFree(children);
|
|
|
|
|
2011-04-19 19:46:05 +08:00
|
|
|
XFlush(display);
|
2008-08-16 01:32:26 +08:00
|
|
|
XSync(display,0);
|
|
|
|
}
|