diff --git a/panda/src/tinydisplay/config_tinydisplay.cxx b/panda/src/tinydisplay/config_tinydisplay.cxx index f76534a445..d24b32dbd4 100644 --- a/panda/src/tinydisplay/config_tinydisplay.cxx +++ b/panda/src/tinydisplay/config_tinydisplay.cxx @@ -37,41 +37,6 @@ ConfigureFn(config_tinydisplay) { init_libtinydisplay(); } -ConfigVariableString display_cfg -("display", "", - PRC_DESC("Specify the X display string for the default display. If this " - "is not specified, $DISPLAY is used.")); - -ConfigVariableBool x_error_abort -("x-error-abort", false, - PRC_DESC("Set this true to trigger and abort (and a stack trace) on receipt " - "of an error from the X window system. This can make it easier " - "to discover where these errors are generated.")); - -ConfigVariableInt x_wheel_up_button -("x-wheel-up-button", 4, - PRC_DESC("This is the mouse button index of the wheel_up event: which " - "mouse button number does the system report when the mouse wheel " - "is rolled one notch up?")); - -ConfigVariableInt x_wheel_down_button -("x-wheel-down-button", 5, - PRC_DESC("This is the mouse button index of the wheel_down event: which " - "mouse button number does the system report when the mouse wheel " - "is rolled one notch down?")); - -ConfigVariableInt x_wheel_left_button -("x-wheel-left-button", 6, - PRC_DESC("This is the mouse button index of the wheel_left event: which " - "mouse button number does the system report when one scrolls " - "to the left?")); - -ConfigVariableInt x_wheel_right_button -("x-wheel-right-button", 7, - PRC_DESC("This is the mouse button index of the wheel_right event: which " - "mouse button number does the system report when one scrolls " - "to the right?")); - ConfigVariableBool show_resize_box ("show-resize-box", true, PRC_DESC("When this variable is true, then resizable OSX Panda windows will " diff --git a/panda/src/tinydisplay/config_tinydisplay.h b/panda/src/tinydisplay/config_tinydisplay.h index a26af12f01..1328906f08 100644 --- a/panda/src/tinydisplay/config_tinydisplay.h +++ b/panda/src/tinydisplay/config_tinydisplay.h @@ -26,13 +26,6 @@ NotifyCategoryDecl(tinydisplay, EXPCL_TINYDISPLAY, EXPTP_TINYDISPLAY); extern EXPCL_TINYDISPLAY void init_libtinydisplay(); extern "C" EXPCL_TINYDISPLAY int get_pipe_type_tinydisplay(); -extern ConfigVariableString display_cfg; -extern ConfigVariableBool x_error_abort; -extern ConfigVariableInt x_wheel_up_button; -extern ConfigVariableInt x_wheel_down_button; -extern ConfigVariableInt x_wheel_left_button; -extern ConfigVariableInt x_wheel_right_button; - extern ConfigVariableBool show_resize_box; extern ConfigVariableBool osx_disable_event_loop; extern ConfigVariableInt osx_mouse_wheel_scale; diff --git a/panda/src/tinydisplay/tinyXGraphicsPipe.I b/panda/src/tinydisplay/tinyXGraphicsPipe.I index 03b4c14977..cef3ba01be 100644 --- a/panda/src/tinydisplay/tinyXGraphicsPipe.I +++ b/panda/src/tinydisplay/tinyXGraphicsPipe.I @@ -12,61 +12,3 @@ // //////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_display -// Access: Public -// Description: Returns a pointer to the X display associated with -// the pipe: the display on which to create the windows. -//////////////////////////////////////////////////////////////////// -INLINE Display *TinyXGraphicsPipe:: -get_display() const { - return _display; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_screen -// Access: Public -// Description: Returns the X screen number associated with the pipe. -//////////////////////////////////////////////////////////////////// -INLINE int TinyXGraphicsPipe:: -get_screen() const { - return _screen; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_root -// Access: Public -// Description: Returns the handle to the root window on the pipe's -// display. -//////////////////////////////////////////////////////////////////// -INLINE Window TinyXGraphicsPipe:: -get_root() const { - return _root; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_im -// Access: Public -// Description: Returns the input method opened for the pipe, or NULL -// if the input method could not be opened for some -// reason. -//////////////////////////////////////////////////////////////////// -INLINE XIM TinyXGraphicsPipe:: -get_im() const { - return _im; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_hidden_cursor -// Access: Public -// Description: Returns an invisible Cursor suitable for assigning to -// windows that have the cursor_hidden property set. -//////////////////////////////////////////////////////////////////// -INLINE Cursor TinyXGraphicsPipe:: -get_hidden_cursor() { - if (_hidden_cursor == None) { - make_hidden_cursor(); - } - return _hidden_cursor; -} diff --git a/panda/src/tinydisplay/tinyXGraphicsPipe.cxx b/panda/src/tinydisplay/tinyXGraphicsPipe.cxx index b4d2b510b3..3786850084 100644 --- a/panda/src/tinydisplay/tinyXGraphicsPipe.cxx +++ b/panda/src/tinydisplay/tinyXGraphicsPipe.cxx @@ -24,100 +24,13 @@ TypeHandle TinyXGraphicsPipe::_type_handle; -bool TinyXGraphicsPipe::_error_handlers_installed = false; -TinyXGraphicsPipe::ErrorHandlerFunc *TinyXGraphicsPipe::_prev_error_handler; -TinyXGraphicsPipe::IOErrorHandlerFunc *TinyXGraphicsPipe::_prev_io_error_handler; - -LightReMutex TinyXGraphicsPipe::_x_mutex; - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsPipe::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// TinyXGraphicsPipe:: -TinyXGraphicsPipe(const string &display) { - string display_spec = display; - if (display_spec.empty()) { - display_spec = display_cfg; - } - if (display_spec.empty()) { - display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY"); - } - if (display_spec.empty()) { - display_spec = ":0.0"; - } - - // The X docs say we should do this to get international character - // support from the keyboard. - setlocale(LC_ALL, ""); - - // But it's important that we use the "C" locale for numeric - // formatting, since all of the internal Panda code assumes this--we - // need a decimal point to mean a decimal point. - setlocale(LC_NUMERIC, "C"); - - _is_valid = false; - _supported_types = OT_window | OT_buffer | OT_texture_buffer; - _display = NULL; - _screen = 0; - _root = (Window)NULL; - _im = (XIM)NULL; - _hidden_cursor = None; - - install_error_handlers(); - - _display = XOpenDisplay(display_spec.c_str()); - if (!_display) { - tinydisplay_cat.error() - << "Could not open display \"" << display_spec << "\".\n"; - return; - } - - if (!XSupportsLocale()) { - tinydisplay_cat.warning() - << "X does not support locale " << setlocale(LC_ALL, NULL) << "\n"; - } - XSetLocaleModifiers(""); - - _screen = DefaultScreen(_display); - _root = RootWindow(_display, _screen); - _display_width = DisplayWidth(_display, _screen); - _display_height = DisplayHeight(_display, _screen); - _is_valid = true; - - // Connect to an input method for supporting international text - // entry. - _im = XOpenIM(_display, NULL, NULL, NULL); - if (_im == (XIM)NULL) { - tinydisplay_cat.warning() - << "Couldn't open input method.\n"; - } - - // What styles does the current input method support? - /* - XIMStyles *im_supported_styles; - XGetIMValues(_im, XNQueryInputStyle, &im_supported_styles, NULL); - - for (int i = 0; i < im_supported_styles->count_styles; i++) { - XIMStyle style = im_supported_styles->supported_styles[i]; - cerr << "style " << i << ". " << hex << style << dec << "\n"; - } - - XFree(im_supported_styles); - */ - - // Get some X atom numbers. - _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false); - _net_wm_window_type = XInternAtom(_display, "_NET_WM_WINDOW_TYPE", false); - _net_wm_window_type_splash = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_SPLASH", false); - _net_wm_window_type_fullscreen = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_FULLSCREEN", false); - _net_wm_state = XInternAtom(_display, "_NET_WM_STATE", false); - _net_wm_state_fullscreen = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", false); - _net_wm_state_above = XInternAtom(_display, "_NET_WM_STATE_ABOVE", false); - _net_wm_state_below = XInternAtom(_display, "_NET_WM_STATE_BELOW", false); - _net_wm_state_add = XInternAtom(_display, "_NET_WM_STATE_ADD", false); - _net_wm_state_remove = XInternAtom(_display, "_NET_WM_STATE_REMOVE", false); +TinyXGraphicsPipe(const string &display) : x11GraphicsPipe(display) { } //////////////////////////////////////////////////////////////////// @@ -127,13 +40,6 @@ TinyXGraphicsPipe(const string &display) { //////////////////////////////////////////////////////////////////// TinyXGraphicsPipe:: ~TinyXGraphicsPipe() { - release_hidden_cursor(); - if (_im) { - XCloseIM(_im); - } - if (_display) { - XCloseDisplay(_display); - } } //////////////////////////////////////////////////////////////////// @@ -163,30 +69,6 @@ pipe_constructor() { return new TinyXGraphicsPipe; } -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::get_preferred_window_thread -// Access: Public, Virtual -// Description: Returns an indication of the thread in which this -// GraphicsPipe requires its window processing to be -// performed: typically either the app thread (e.g. X) -// or the draw thread (Windows). -//////////////////////////////////////////////////////////////////// -GraphicsPipe::PreferredWindowThread -TinyXGraphicsPipe::get_preferred_window_thread() const { - // Actually, since we're creating the graphics context in - // open_window() now, it appears we need to ensure the open_window() - // call is performed in the draw thread for now, even though X wants - // all of its calls to be single-threaded. - - // This means that all X windows may have to be handled by the same - // draw thread, which we didn't intend (though the global _x_mutex - // may allow them to be technically served by different threads, - // even though the actual X calls will be serialized). There might - // be a better way. - - return PWT_draw; -} - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsPipe::make_output // Access: Protected, Virtual @@ -242,104 +124,4 @@ make_output(const string &name, return NULL; } -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::make_hidden_cursor -// Access: Private -// Description: Called once to make an invisible Cursor for return -// from get_hidden_cursor(). -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsPipe:: -make_hidden_cursor() { - nassertv(_hidden_cursor == None); - - unsigned int x_size, y_size; - XQueryBestCursor(_display, _root, 1, 1, &x_size, &y_size); - - Pixmap empty = XCreatePixmap(_display, _root, x_size, y_size, 1); - - XColor black; - memset(&black, 0, sizeof(black)); - - _hidden_cursor = XCreatePixmapCursor(_display, empty, empty, - &black, &black, x_size, y_size); - XFreePixmap(_display, empty); -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::release_hidden_cursor -// Access: Private -// Description: Called once to release the invisible cursor created -// by make_hidden_cursor(). -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsPipe:: -release_hidden_cursor() { - if (_hidden_cursor != None) { - XFreeCursor(_display, _hidden_cursor); - _hidden_cursor = None; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::install_error_handlers -// Access: Private, Static -// Description: Installs new Xlib error handler functions if this is -// the first time this function has been called. These -// error handler functions will attempt to reduce Xlib's -// annoying tendency to shut down the client at the -// first error. Unfortunately, it is difficult to play -// nice with the client if it has already installed its -// own error handlers. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsPipe:: -install_error_handlers() { - if (_error_handlers_installed) { - return; - } - - _prev_error_handler = (ErrorHandlerFunc *)XSetErrorHandler(error_handler); - _prev_io_error_handler = (IOErrorHandlerFunc *)XSetIOErrorHandler(io_error_handler); - _error_handlers_installed = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::error_handler -// Access: Private, Static -// Description: This function is installed as the error handler for a -// non-fatal Xlib error. -//////////////////////////////////////////////////////////////////// -int TinyXGraphicsPipe:: -error_handler(Display *display, XErrorEvent *error) { - static const int msg_len = 80; - char msg[msg_len]; - XGetErrorText(display, error->error_code, msg, msg_len); - tinydisplay_cat.error() - << msg << "\n"; - - if (x_error_abort) { - abort(); - } - - // We return to allow the application to continue running, unlike - // the default X error handler which exits. - return 0; -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsPipe::io_error_handler -// Access: Private, Static -// Description: This function is installed as the error handler for a -// fatal Xlib error. -//////////////////////////////////////////////////////////////////// -int TinyXGraphicsPipe:: -io_error_handler(Display *display) { - tinydisplay_cat.fatal() - << "X fatal error on display " << (void *)display << "\n"; - - // Unfortunately, we can't continue from this function, even if we - // promise never to use X again. We're supposed to terminate - // without returning, and if we do return, the caller will exit - // anyway. Sigh. Very poor design on X's part. - return 0; -} - #endif // HAVE_X11 diff --git a/panda/src/tinydisplay/tinyXGraphicsPipe.h b/panda/src/tinydisplay/tinyXGraphicsPipe.h index 434f385df8..c05350dcfb 100644 --- a/panda/src/tinydisplay/tinyXGraphicsPipe.h +++ b/panda/src/tinydisplay/tinyXGraphicsPipe.h @@ -19,37 +19,19 @@ #ifdef HAVE_X11 -#include "graphicsWindow.h" -#include "graphicsPipe.h" +#include "x11GraphicsWindow.h" +#include "x11GraphicsPipe.h" #include "tinyGraphicsStateGuardian.h" #include "lightMutex.h" #include "lightReMutex.h" -class FrameBufferProperties; - -#ifdef CPPPARSER -// A simple hack so interrogate can parse this file. -typedef int Display; -typedef int Window; -typedef int XErrorEvent; -typedef int XVisualInfo; -typedef int Atom; -typedef int Cursor; -typedef int XIM; -typedef int XIC; -#else -#include -#include - -#endif // CPPPARSER - //////////////////////////////////////////////////////////////////// // Class : TinyXGraphicsPipe // Description : This graphics pipe represents the interface for // creating TinyPanda graphics windows on an X11-based // (e.g. Unix) client. //////////////////////////////////////////////////////////////////// -class EXPCL_TINYDISPLAY TinyXGraphicsPipe : public GraphicsPipe { +class EXPCL_TINYDISPLAY TinyXGraphicsPipe : public x11GraphicsPipe { public: TinyXGraphicsPipe(const string &display = string()); virtual ~TinyXGraphicsPipe(); @@ -57,29 +39,6 @@ public: virtual string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); - INLINE Display *get_display() const; - INLINE int get_screen() const; - INLINE Window get_root() const; - INLINE XIM get_im() const; - - INLINE Cursor get_hidden_cursor(); - -public: - virtual PreferredWindowThread get_preferred_window_thread() const; - -public: - // Atom specifications. - Atom _wm_delete_window; - Atom _net_wm_window_type; - Atom _net_wm_window_type_splash; - Atom _net_wm_window_type_fullscreen; - Atom _net_wm_state; - Atom _net_wm_state_fullscreen; - Atom _net_wm_state_above; - Atom _net_wm_state_below; - Atom _net_wm_state_add; - Atom _net_wm_state_remove; - protected: virtual PT(GraphicsOutput) make_output(const string &name, const FrameBufferProperties &fb_prop, @@ -91,40 +50,14 @@ protected: int retry, bool &precertify); -private: - void make_hidden_cursor(); - void release_hidden_cursor(); - - static void install_error_handlers(); - static int error_handler(Display *display, XErrorEvent *error); - static int io_error_handler(Display *display); - - Display *_display; - int _screen; - Window _root; - XIM _im; - - Cursor _hidden_cursor; - - typedef int ErrorHandlerFunc(Display *, XErrorEvent *); - typedef int IOErrorHandlerFunc(Display *); - static bool _error_handlers_installed; - static ErrorHandlerFunc *_prev_error_handler; - static IOErrorHandlerFunc *_prev_io_error_handler; - -public: - // This Mutex protects any X library calls, which all have to be - // single-threaded. - static LightReMutex _x_mutex; - public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - GraphicsPipe::init_type(); + x11GraphicsPipe::init_type(); register_type(_type_handle, "TinyXGraphicsPipe", - GraphicsPipe::get_class_type()); + x11GraphicsPipe::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/tinydisplay/tinyXGraphicsWindow.cxx b/panda/src/tinydisplay/tinyXGraphicsWindow.cxx index b6d442c6e6..8749f71cf7 100644 --- a/panda/src/tinydisplay/tinyXGraphicsWindow.cxx +++ b/panda/src/tinydisplay/tinyXGraphicsWindow.cxx @@ -30,20 +30,8 @@ #include "throw_event.h" #include "lightReMutexHolder.h" -#include -#include -#include -#include -#include - -#ifdef HAVE_LINUX_INPUT_H -#include -#endif - TypeHandle TinyXGraphicsWindow::_type_handle; -#define test_bit(bit, array) ((array)[(bit)/8] & (1<<((bit)&7))) - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsWindow::Constructor // Access: Public @@ -57,35 +45,14 @@ TinyXGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, int flags, GraphicsStateGuardian *gsg, GraphicsOutput *host) : - GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) + x11GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host) { - TinyXGraphicsPipe *tinyx_pipe; - DCAST_INTO_V(tinyx_pipe, _pipe); - _display = tinyx_pipe->get_display(); - _screen = tinyx_pipe->get_screen(); - _xwindow = (Window)NULL; _gc = (GC)NULL; - _ic = (XIC)NULL; - _awaiting_configure = false; - _wm_delete_window = tinyx_pipe->_wm_delete_window; - _net_wm_window_type = tinyx_pipe->_net_wm_window_type; - _net_wm_window_type_splash = tinyx_pipe->_net_wm_window_type_splash; - _net_wm_window_type_fullscreen = tinyx_pipe->_net_wm_window_type_fullscreen; - _net_wm_state = tinyx_pipe->_net_wm_state; - _net_wm_state_fullscreen = tinyx_pipe->_net_wm_state_fullscreen; - _net_wm_state_above = tinyx_pipe->_net_wm_state_above; - _net_wm_state_below = tinyx_pipe->_net_wm_state_below; - _net_wm_state_add = tinyx_pipe->_net_wm_state_add; - _net_wm_state_remove = tinyx_pipe->_net_wm_state_remove; _reduced_frame_buffer = NULL; _full_frame_buffer = NULL; _ximage = NULL; update_pixel_factor(); - - GraphicsWindowInputDevice device = - GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse"); - add_input_device(device); } //////////////////////////////////////////////////////////////////// @@ -95,48 +62,14 @@ TinyXGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, //////////////////////////////////////////////////////////////////// TinyXGraphicsWindow:: ~TinyXGraphicsWindow() { -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::move_pointer -// Access: Published, Virtual -// Description: Forces the pointer to the indicated position within -// the window, if possible. -// -// Returns true if successful, false on failure. This -// may fail if the mouse is not currently within the -// window, or if the API doesn't support this operation. -//////////////////////////////////////////////////////////////////// -bool TinyXGraphicsWindow:: -move_pointer(int device, int x, int y) { - // Note: this is not thread-safe; it should be called only from App. - // Probably not an issue. - if (device == 0) { - // Move the system mouse pointer. - if (!_properties.get_foreground() || - !_input_devices[0].get_pointer().get_in_window()) { - // If the window doesn't have input focus, or the mouse isn't - // currently within the window, forget it. - return false; - } - - const MouseData &md = _input_devices[0].get_pointer(); - if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) { - XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y); - _input_devices[0].set_pointer_in_window(x, y); - } - return true; - } else { - // Move a raw mouse. - if ((device < 1)||(device >= _input_devices.size())) { - return false; - } - _input_devices[device].set_pointer_in_window(x, y); - return true; + if (_gc != NULL && _display != NULL) { + XFreeGC(_display, _gc); + } + if (_ximage != NULL) { + XDestroyImage(_ximage); } } - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsWindow::begin_frame // Access: Public, Virtual @@ -464,145 +397,6 @@ process_events() { } } -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::set_properties_now -// Access: Public, Virtual -// Description: Applies the requested set of properties to the -// window, if possible, for instance to request a change -// in size or minimization status. -// -// The window properties are applied immediately, rather -// than waiting until the next frame. This implies that -// this method may *only* be called from within the -// window thread. -// -// The return value is true if the properties are set, -// false if they are ignored. This is mainly useful for -// derived classes to implement extensions to this -// function. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -set_properties_now(WindowProperties &properties) { - if (_pipe == (GraphicsPipe *)NULL) { - // If the pipe is null, we're probably closing down. - GraphicsWindow::set_properties_now(properties); - return; - } - - TinyXGraphicsPipe *tinyx_pipe; - DCAST_INTO_V(tinyx_pipe, _pipe); - - // Fullscreen mode is implemented with a hint to the window manager. - // However, we also implicitly set the origin to (0, 0) and the size - // to the desktop size, and request undecorated mode, in case the - // user has a less-capable window manager (or no window manager at - // all). - if (properties.get_fullscreen()) { - properties.set_undecorated(true); - properties.set_origin(0, 0); - properties.set_size(tinyx_pipe->get_display_width(), - tinyx_pipe->get_display_height()); - } - - GraphicsWindow::set_properties_now(properties); - if (!properties.is_any_specified()) { - // The base class has already handled this case. - return; - } - - // The window is already open; we are limited to what we can change - // on the fly. - - // We'll pass some property requests on as a window manager hint. - WindowProperties wm_properties = _properties; - wm_properties.add_properties(properties); - - // The window title may be changed by issuing another hint request. - // Assume this will be honored. - if (properties.has_title()) { - _properties.set_title(properties.get_title()); - properties.clear_title(); - } - - // Ditto for fullscreen mode. - if (properties.has_fullscreen()) { - _properties.set_fullscreen(properties.get_fullscreen()); - properties.clear_fullscreen(); - } - - // The size and position of an already-open window are changed via - // explicit X calls. These may still get intercepted by the window - // manager. Rather than changing _properties immediately, we'll - // wait for the ConfigureNotify message to come back. - XWindowChanges changes; - int value_mask = 0; - - if (properties.has_origin()) { - changes.x = properties.get_x_origin(); - changes.y = properties.get_y_origin(); - value_mask |= (CWX | CWY); - properties.clear_origin(); - } - if (properties.has_size()) { - changes.width = properties.get_x_size(); - changes.height = properties.get_y_size(); - value_mask |= (CWWidth | CWHeight); - properties.clear_size(); - } - if (properties.has_z_order()) { - // We'll send the classic stacking request through the standard - // interface, for users of primitive window managers; but we'll - // also send it as a window manager hint, for users of modern - // window managers. - _properties.set_z_order(properties.get_z_order()); - switch (properties.get_z_order()) { - case WindowProperties::Z_bottom: - changes.stack_mode = Below; - break; - - case WindowProperties::Z_normal: - changes.stack_mode = TopIf; - break; - - case WindowProperties::Z_top: - changes.stack_mode = Above; - break; - } - - value_mask |= (CWStackMode); - properties.clear_z_order(); - } - - if (value_mask != 0) { - XReconfigureWMWindow(_display, _xwindow, _screen, value_mask, &changes); - - // Don't draw anything until this is done reconfiguring. - _awaiting_configure = true; - } - - // We hide the cursor by setting it to an invisible pixmap. - if (properties.has_cursor_hidden()) { - _properties.set_cursor_hidden(properties.get_cursor_hidden()); - if (properties.get_cursor_hidden()) { - XDefineCursor(_display, _xwindow, tinyx_pipe->get_hidden_cursor()); - } else { - XDefineCursor(_display, _xwindow, None); - } - properties.clear_cursor_hidden(); - } - - if (properties.has_foreground()) { - if (properties.get_foreground()) { - XSetInputFocus(_display, _xwindow, RevertToPointerRoot, CurrentTime); - } else { - XSetInputFocus(_display, PointerRoot, RevertToPointerRoot, CurrentTime); - } - properties.clear_foreground(); - } - - set_wm_properties(wm_properties, true); -} - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsWindow::close_window // Access: Protected, Virtual @@ -619,25 +413,7 @@ close_window() { _active = false; } - if (_ic != (XIC)NULL) { - XDestroyIC(_ic); - _ic = (XIC)NULL; - } - - if (_gc != (GC)NULL) { - XFreeGC(_display, _gc); - _gc = (GC)NULL; - } - - if (_xwindow != (Window)NULL) { - XDestroyWindow(_display, _xwindow); - _xwindow = (Window)NULL; - - // This may be necessary if we just closed the last X window in an - // application, so the server hears the close request. - XFlush(_display); - } - GraphicsWindow::close_window(); + x11GraphicsWindow::close_window(); } //////////////////////////////////////////////////////////////////// @@ -836,927 +612,10 @@ open_window() { //////////////////////////////////////////////////////////////////// void TinyXGraphicsWindow:: pixel_factor_changed() { - GraphicsWindow::pixel_factor_changed(); + x11GraphicsWindow::pixel_factor_changed(); create_reduced_frame_buffer(); } -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::set_wm_properties -// Access: Private -// Description: Asks the window manager to set the appropriate -// properties. In X, these properties cannot be -// specified directly by the application; they must be -// requested via the window manager, which may or may -// not choose to honor the request. -// -// If already_mapped is true, the window has already -// been mapped (manifested) on the display. This means -// we may need to use a different action in some cases. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -set_wm_properties(const WindowProperties &properties, bool already_mapped) { - // Name the window if there is a name - XTextProperty window_name; - XTextProperty *window_name_p = (XTextProperty *)NULL; - if (properties.has_title()) { - char *name = (char *)properties.get_title().c_str(); - if (XStringListToTextProperty(&name, 1, &window_name) != 0) { - window_name_p = &window_name; - } - } - - // The size hints request a window of a particular size and/or a - // particular placement onscreen. - XSizeHints *size_hints_p = NULL; - if (properties.has_origin() || properties.has_size()) { - size_hints_p = XAllocSizeHints(); - if (size_hints_p != (XSizeHints *)NULL) { - if (properties.has_origin()) { - size_hints_p->x = properties.get_x_origin(); - size_hints_p->y = properties.get_y_origin(); - size_hints_p->flags |= USPosition; - } - if (properties.has_size()) { - size_hints_p->width = properties.get_x_size(); - size_hints_p->height = properties.get_y_size(); - size_hints_p->flags |= USSize; - - if (properties.has_fixed_size()) { - size_hints_p->min_width = properties.get_x_size(); - size_hints_p->min_height = properties.get_y_size(); - size_hints_p->max_width = properties.get_x_size(); - size_hints_p->max_height = properties.get_y_size(); - size_hints_p->flags |= (PMinSize | PMaxSize); - } - } - } - } - - // The window manager hints include requests to the window manager - // other than those specific to window geometry. - XWMHints *wm_hints_p = NULL; - wm_hints_p = XAllocWMHints(); - if (wm_hints_p != (XWMHints *)NULL) { - if (properties.has_minimized() && properties.get_minimized()) { - wm_hints_p->initial_state = IconicState; - } else { - wm_hints_p->initial_state = NormalState; - } - wm_hints_p->flags = StateHint; - } - - // Two competing window manager interfaces have evolved. One of - // them allows to set certain properties as a "type"; the other one - // as a "state". We'll try to honor both. - static const int max_type_data = 32; - PN_int32 type_data[max_type_data]; - int next_type_data = 0; - - static const int max_state_data = 32; - PN_int32 state_data[max_state_data]; - int next_state_data = 0; - - static const int max_set_data = 32; - class SetAction { - public: - inline SetAction() { } - inline SetAction(Atom state, Atom action) : _state(state), _action(action) { } - Atom _state; - Atom _action; - }; - SetAction set_data[max_set_data]; - int next_set_data = 0; - - if (properties.get_fullscreen()) { - // For a "fullscreen" request, we pass this through, hoping the - // window manager will support EWMH. - type_data[next_type_data++] = _net_wm_window_type_fullscreen; - - // We also request it as a state. - state_data[next_state_data++] = _net_wm_state_fullscreen; - set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, _net_wm_state_add); - } else { - set_data[next_set_data++] = SetAction(_net_wm_state_fullscreen, _net_wm_state_remove); - } - - // If we asked for a window without a border, there's no excellent - // way to arrange that. For users whose window managers follow the - // EWMH specification, we can ask for a "splash" screen, which is - // usually undecorated. It's not exactly right, but the spec - // doesn't give us an exactly-right option. - - // For other users, we'll totally punt and just set the window's - // Class to "Undecorated", and let the user configure his/her window - // manager not to put a border around windows of this class. - XClassHint *class_hints_p = NULL; - if (properties.get_undecorated()) { - class_hints_p = XAllocClassHint(); - class_hints_p->res_class = (char *)"Undecorated"; - - if (!properties.get_fullscreen()) { - type_data[next_type_data++] = _net_wm_window_type_splash; - } - } - - if (properties.has_z_order()) { - switch (properties.get_z_order()) { - case WindowProperties::Z_bottom: - state_data[next_state_data++] = _net_wm_state_below; - set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_add); - set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove); - break; - - case WindowProperties::Z_normal: - set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove); - set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_remove); - break; - - case WindowProperties::Z_top: - state_data[next_state_data++] = _net_wm_state_above; - set_data[next_set_data++] = SetAction(_net_wm_state_below, _net_wm_state_remove); - set_data[next_set_data++] = SetAction(_net_wm_state_above, _net_wm_state_add); - break; - } - } - - nassertv(next_type_data < max_type_data); - nassertv(next_state_data < max_state_data); - nassertv(next_set_data < max_set_data); - - XChangeProperty(_display, _xwindow, _net_wm_window_type, - XA_ATOM, 32, PropModeReplace, - (unsigned char *)type_data, next_type_data); - - // Request the state properties all at once. - XChangeProperty(_display, _xwindow, _net_wm_state, - XA_ATOM, 32, PropModeReplace, - (unsigned char *)state_data, next_state_data); - - if (already_mapped) { - // We have to request state changes differently when the window - // has been mapped. To do this, we need to send a client message - // to the root window for each change. - - TinyXGraphicsPipe *tinyx_pipe; - DCAST_INTO_V(tinyx_pipe, _pipe); - - for (int i = 0; i < next_set_data; ++i) { - XClientMessageEvent event; - memset(&event, 0, sizeof(event)); - - event.type = ClientMessage; - event.send_event = True; - event.display = _display; - event.window = _xwindow; - event.message_type = _net_wm_state; - event.format = 32; - event.data.l[0] = set_data[i]._action; - event.data.l[1] = set_data[i]._state; - event.data.l[2] = 0; - event.data.l[3] = 1; - - XSendEvent(_display, tinyx_pipe->get_root(), True, 0, (XEvent *)&event); - } - } - - XSetWMProperties(_display, _xwindow, window_name_p, window_name_p, - NULL, 0, size_hints_p, wm_hints_p, class_hints_p); - - if (size_hints_p != (XSizeHints *)NULL) { - XFree(size_hints_p); - } - if (wm_hints_p != (XWMHints *)NULL) { - XFree(wm_hints_p); - } - if (class_hints_p != (XClassHint *)NULL) { - XFree(class_hints_p); - } - - // Also, indicate to the window manager that we'd like to get a - // chance to close our windows cleanly, rather than being rudely - // disconnected from the X server if the user requests a window - // close. - Atom protocols[] = { - _wm_delete_window, - }; - - XSetWMProtocols(_display, _xwindow, protocols, - sizeof(protocols) / sizeof(Atom)); -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::setup_colormap -// Access: Private -// Description: Allocates a colormap appropriate to the visual and -// stores in in the _colormap method. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -setup_colormap(XVisualInfo *visual_info) { - TinyXGraphicsPipe *tinyx_pipe; - DCAST_INTO_V(tinyx_pipe, _pipe); - Window root_window = tinyx_pipe->get_root(); - - int visual_class = visual_info->c_class; - int rc, is_rgb; - - switch (visual_class) { - case TrueColor: - case DirectColor: - _colormap = XCreateColormap(_display, root_window, - visual_info->visual, AllocNone); - break; - case StaticColor: - case StaticGray: - case GrayScale: - _colormap = XCreateColormap(_display, root_window, - visual_info->visual, AllocNone); - break; - - default: - tinydisplay_cat.error() - << "Could not allocate a colormap for visual class " - << visual_class << ".\n"; - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::open_raw_mice -// Access: Private -// Description: Adds raw mice to the _input_devices list. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -open_raw_mice() -{ -#ifdef HAVE_LINUX_INPUT_H - bool any_present = false; - bool any_mice = false; - - for (int i=0; i<64; i++) { - uint8_t evtypes[EV_MAX/8 + 1]; - ostringstream fnb; - fnb << "/dev/input/event" << i; - string fn = fnb.str(); - int fd = open(fn.c_str(), O_RDONLY | O_NONBLOCK, 0); - if (fd >= 0) { - any_present = true; - char name[256]; - char phys[256]; - char uniq[256]; - if ((ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)|| - (ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0)|| - (ioctl(fd, EVIOCGPHYS(sizeof(uniq)), uniq) < 0)|| - (ioctl(fd, EVIOCGBIT(0, EV_MAX), &evtypes) < 0)) { - close(fd); - tinydisplay_cat.error() << - "Opening raw mice: ioctl failed on " << fn << "\n"; - } else { - if (test_bit(EV_REL, evtypes) || test_bit(EV_ABS, evtypes)) { - for (char *p=name; *p; p++) { - if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) { - *p = '_'; - } - } - for (char *p=uniq; *p; p++) { - if (((*p<'a')||(*p>'z')) && ((*p<'A')||(*p>'Z')) && ((*p<'0')||(*p>'9'))) { - *p = '_'; - } - } - string full_id = ((string)name) + "." + uniq; - MouseDeviceInfo inf; - inf._fd = fd; - inf._input_device_index = _input_devices.size(); - inf._io_buffer = ""; - _mouse_device_info.push_back(inf); - GraphicsWindowInputDevice device = - GraphicsWindowInputDevice::pointer_only(this, full_id); - add_input_device(device); - tinydisplay_cat.info() << "Raw mouse " << - inf._input_device_index << " detected: " << full_id << "\n"; - any_mice = true; - } else { - close(fd); - } - } - } else { - if ((errno == ENOENT)||(errno == ENOTDIR)) { - break; - } else { - any_present = true; - tinydisplay_cat.error() << - "Opening raw mice: " << strerror(errno) << " " << fn << "\n"; - } - } - } - - if (!any_present) { - tinydisplay_cat.error() << - "Opening raw mice: files not found: /dev/input/event*\n"; - } else if (!any_mice) { - tinydisplay_cat.error() << - "Opening raw mice: no mouse devices detected in /dev/input/event*\n"; - } -#else - tinydisplay_cat.error() << - "Opening raw mice: panda not compiled with raw mouse support.\n"; -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::poll_raw_mice -// Access: Private -// Description: Reads events from the raw mouse device files. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -poll_raw_mice() -{ -#ifdef HAVE_LINUX_INPUT_H - for (int dev=0; dev<_mouse_device_info.size(); dev++) { - MouseDeviceInfo &inf = _mouse_device_info[dev]; - - // Read all bytes into buffer. - if (inf._fd >= 0) { - while (1) { - char tbuf[1024]; - int nread = read(inf._fd, tbuf, sizeof(tbuf)); - if (nread > 0) { - inf._io_buffer += string(tbuf, nread); - } else { - if ((nread < 0)&&((errno == EWOULDBLOCK) || (errno==EAGAIN))) { - break; - } - close(inf._fd); - inf._fd = -1; - break; - } - } - } - - // Process events. - int nevents = inf._io_buffer.size() / sizeof(struct input_event); - if (nevents == 0) { - continue; - } - const input_event *events = (const input_event *)(inf._io_buffer.c_str()); - GraphicsWindowInputDevice &dev = _input_devices[inf._input_device_index]; - int x = dev.get_raw_pointer().get_x(); - int y = dev.get_raw_pointer().get_y(); - for (int i=0; i= BTN_MOUSE)&&(events[i].code < BTN_MOUSE+8)) { - int btn = events[i].code - BTN_MOUSE; - dev.set_pointer_in_window(x,y); - if (events[i].value) { - dev.button_down(MouseButton::button(btn)); - } else { - dev.button_up(MouseButton::button(btn)); - } - } - } - } - inf._io_buffer.erase(0,nevents*sizeof(struct input_event)); - dev.set_pointer_in_window(x,y); - } -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::handle_keystroke -// Access: Private -// Description: Generates a keystroke corresponding to the indicated -// X KeyPress event. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -handle_keystroke(XKeyEvent &event) { - _input_devices[0].set_pointer_in_window(event.x, event.y); - - if (_ic) { - // First, get the keystroke as a wide-character sequence. - static const int buffer_size = 256; - wchar_t buffer[buffer_size]; - Status status; - int len = XwcLookupString(_ic, &event, buffer, buffer_size, NULL, - &status); - if (status == XBufferOverflow) { - tinydisplay_cat.error() - << "Overflowed input buffer.\n"; - } - - // Now each of the returned wide characters represents a - // keystroke. - for (int i = 0; i < len; i++) { - _input_devices[0].keystroke(buffer[i]); - } - - } else { - // Without an input context, just get the ascii keypress. - ButtonHandle button = get_button(event, true); - if (button.has_ascii_equivalent()) { - _input_devices[0].keystroke(button.get_ascii_equivalent()); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::handle_keypress -// Access: Private -// Description: Generates a keypress corresponding to the indicated -// X KeyPress event. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -handle_keypress(XKeyEvent &event) { - _input_devices[0].set_pointer_in_window(event.x, event.y); - - // Now get the raw unshifted button. - ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_down(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_down(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_down(KeyboardButton::alt()); - } - if (button != ButtonHandle::none()) { - _input_devices[0].button_down(button); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::handle_keyrelease -// Access: Private -// Description: Generates a keyrelease corresponding to the indicated -// X KeyRelease event. -//////////////////////////////////////////////////////////////////// -void TinyXGraphicsWindow:: -handle_keyrelease(XKeyEvent &event) { - _input_devices[0].set_pointer_in_window(event.x, event.y); - - // Now get the raw unshifted button. - ButtonHandle button = get_button(event, false); - if (button == KeyboardButton::lcontrol() || button == KeyboardButton::rcontrol()) { - _input_devices[0].button_up(KeyboardButton::control()); - } - if (button == KeyboardButton::lshift() || button == KeyboardButton::rshift()) { - _input_devices[0].button_up(KeyboardButton::shift()); - } - if (button == KeyboardButton::lalt() || button == KeyboardButton::ralt()) { - _input_devices[0].button_up(KeyboardButton::alt()); - } - if (button != ButtonHandle::none()) { - _input_devices[0].button_up(button); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::get_button -// Access: Private -// Description: Returns the Panda ButtonHandle corresponding to the -// keyboard button indicated by the given key event. -//////////////////////////////////////////////////////////////////// -ButtonHandle TinyXGraphicsWindow:: -get_button(XKeyEvent &key_event, bool allow_shift) { - KeySym key = XLookupKeysym(&key_event, 0); - - if ((key_event.state & Mod2Mask) != 0) { - // Mod2Mask corresponds to NumLock being in effect. In this case, - // we want to get the alternate keysym associated with any keypad - // keys. Weird system. - KeySym k2; - ButtonHandle button; - switch (key) { - case XK_KP_Space: - case XK_KP_Tab: - case XK_KP_Enter: - case XK_KP_F1: - case XK_KP_F2: - case XK_KP_F3: - case XK_KP_F4: - case XK_KP_Equal: - case XK_KP_Multiply: - case XK_KP_Add: - case XK_KP_Separator: - case XK_KP_Subtract: - case XK_KP_Divide: - case XK_KP_Left: - case XK_KP_Up: - case XK_KP_Right: - case XK_KP_Down: - case XK_KP_Begin: - case XK_KP_Prior: - case XK_KP_Next: - case XK_KP_Home: - case XK_KP_End: - case XK_KP_Insert: - case XK_KP_Delete: - case XK_KP_0: - case XK_KP_1: - case XK_KP_2: - case XK_KP_3: - case XK_KP_4: - case XK_KP_5: - case XK_KP_6: - case XK_KP_7: - case XK_KP_8: - case XK_KP_9: - k2 = XLookupKeysym(&key_event, 1); - button = map_button(k2); - if (button != ButtonHandle::none()) { - return button; - } - // If that didn't produce a button we know, just fall through - // and handle the normal, un-numlocked key. - break; - - default: - break; - } - } - - if (allow_shift) { - // If shift is held down, get the shifted keysym. - if ((key_event.state & ShiftMask) != 0) { - KeySym k2 = XLookupKeysym(&key_event, 1); - ButtonHandle button = map_button(k2); - if (button != ButtonHandle::none()) { - return button; - } - } - - // If caps lock is down, shift lowercase letters to uppercase. We - // can do this in just the ASCII set, because we handle - // international keyboards elsewhere (via an input context). - if ((key_event.state & (ShiftMask | LockMask)) != 0) { - if (key >= XK_a and key <= XK_z) { - key += (XK_A - XK_a); - } - } - } - - return map_button(key); -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::map_button -// Access: Private -// Description: Maps from a single X keysym to Panda's ButtonHandle. -// Called by get_button(), above. -//////////////////////////////////////////////////////////////////// -ButtonHandle TinyXGraphicsWindow:: -map_button(KeySym key) { - switch (key) { - case XK_BackSpace: - return KeyboardButton::backspace(); - case XK_Tab: - case XK_KP_Tab: - return KeyboardButton::tab(); - case XK_Return: - case XK_KP_Enter: - return KeyboardButton::enter(); - case XK_Escape: - return KeyboardButton::escape(); - case XK_KP_Space: - case XK_space: - return KeyboardButton::space(); - case XK_exclam: - return KeyboardButton::ascii_key('!'); - case XK_quotedbl: - return KeyboardButton::ascii_key('"'); - case XK_numbersign: - return KeyboardButton::ascii_key('#'); - case XK_dollar: - return KeyboardButton::ascii_key('$'); - case XK_percent: - return KeyboardButton::ascii_key('%'); - case XK_ampersand: - return KeyboardButton::ascii_key('&'); - case XK_apostrophe: // == XK_quoteright - return KeyboardButton::ascii_key('\''); - case XK_parenleft: - return KeyboardButton::ascii_key('('); - case XK_parenright: - return KeyboardButton::ascii_key(')'); - case XK_asterisk: - case XK_KP_Multiply: - return KeyboardButton::ascii_key('*'); - case XK_plus: - case XK_KP_Add: - return KeyboardButton::ascii_key('+'); - case XK_comma: - case XK_KP_Separator: - return KeyboardButton::ascii_key(','); - case XK_minus: - case XK_KP_Subtract: - return KeyboardButton::ascii_key('-'); - case XK_period: - case XK_KP_Decimal: - return KeyboardButton::ascii_key('.'); - case XK_slash: - case XK_KP_Divide: - return KeyboardButton::ascii_key('/'); - case XK_0: - case XK_KP_0: - return KeyboardButton::ascii_key('0'); - case XK_1: - case XK_KP_1: - return KeyboardButton::ascii_key('1'); - case XK_2: - case XK_KP_2: - return KeyboardButton::ascii_key('2'); - case XK_3: - case XK_KP_3: - return KeyboardButton::ascii_key('3'); - case XK_4: - case XK_KP_4: - return KeyboardButton::ascii_key('4'); - case XK_5: - case XK_KP_5: - return KeyboardButton::ascii_key('5'); - case XK_6: - case XK_KP_6: - return KeyboardButton::ascii_key('6'); - case XK_7: - case XK_KP_7: - return KeyboardButton::ascii_key('7'); - case XK_8: - case XK_KP_8: - return KeyboardButton::ascii_key('8'); - case XK_9: - case XK_KP_9: - return KeyboardButton::ascii_key('9'); - case XK_colon: - return KeyboardButton::ascii_key(':'); - case XK_semicolon: - return KeyboardButton::ascii_key(';'); - case XK_less: - return KeyboardButton::ascii_key('<'); - case XK_equal: - case XK_KP_Equal: - return KeyboardButton::ascii_key('='); - case XK_greater: - return KeyboardButton::ascii_key('>'); - case XK_question: - return KeyboardButton::ascii_key('?'); - case XK_at: - return KeyboardButton::ascii_key('@'); - case XK_A: - return KeyboardButton::ascii_key('A'); - case XK_B: - return KeyboardButton::ascii_key('B'); - case XK_C: - return KeyboardButton::ascii_key('C'); - case XK_D: - return KeyboardButton::ascii_key('D'); - case XK_E: - return KeyboardButton::ascii_key('E'); - case XK_F: - return KeyboardButton::ascii_key('F'); - case XK_G: - return KeyboardButton::ascii_key('G'); - case XK_H: - return KeyboardButton::ascii_key('H'); - case XK_I: - return KeyboardButton::ascii_key('I'); - case XK_J: - return KeyboardButton::ascii_key('J'); - case XK_K: - return KeyboardButton::ascii_key('K'); - case XK_L: - return KeyboardButton::ascii_key('L'); - case XK_M: - return KeyboardButton::ascii_key('M'); - case XK_N: - return KeyboardButton::ascii_key('N'); - case XK_O: - return KeyboardButton::ascii_key('O'); - case XK_P: - return KeyboardButton::ascii_key('P'); - case XK_Q: - return KeyboardButton::ascii_key('Q'); - case XK_R: - return KeyboardButton::ascii_key('R'); - case XK_S: - return KeyboardButton::ascii_key('S'); - case XK_T: - return KeyboardButton::ascii_key('T'); - case XK_U: - return KeyboardButton::ascii_key('U'); - case XK_V: - return KeyboardButton::ascii_key('V'); - case XK_W: - return KeyboardButton::ascii_key('W'); - case XK_X: - return KeyboardButton::ascii_key('X'); - case XK_Y: - return KeyboardButton::ascii_key('Y'); - case XK_Z: - return KeyboardButton::ascii_key('Z'); - case XK_bracketleft: - return KeyboardButton::ascii_key('['); - case XK_backslash: - return KeyboardButton::ascii_key('\\'); - case XK_bracketright: - return KeyboardButton::ascii_key(']'); - case XK_asciicircum: - return KeyboardButton::ascii_key('^'); - case XK_underscore: - return KeyboardButton::ascii_key('_'); - case XK_grave: // == XK_quoteleft - return KeyboardButton::ascii_key('`'); - case XK_a: - return KeyboardButton::ascii_key('a'); - case XK_b: - return KeyboardButton::ascii_key('b'); - case XK_c: - return KeyboardButton::ascii_key('c'); - case XK_d: - return KeyboardButton::ascii_key('d'); - case XK_e: - return KeyboardButton::ascii_key('e'); - case XK_f: - return KeyboardButton::ascii_key('f'); - case XK_g: - return KeyboardButton::ascii_key('g'); - case XK_h: - return KeyboardButton::ascii_key('h'); - case XK_i: - return KeyboardButton::ascii_key('i'); - case XK_j: - return KeyboardButton::ascii_key('j'); - case XK_k: - return KeyboardButton::ascii_key('k'); - case XK_l: - return KeyboardButton::ascii_key('l'); - case XK_m: - return KeyboardButton::ascii_key('m'); - case XK_n: - return KeyboardButton::ascii_key('n'); - case XK_o: - return KeyboardButton::ascii_key('o'); - case XK_p: - return KeyboardButton::ascii_key('p'); - case XK_q: - return KeyboardButton::ascii_key('q'); - case XK_r: - return KeyboardButton::ascii_key('r'); - case XK_s: - return KeyboardButton::ascii_key('s'); - case XK_t: - return KeyboardButton::ascii_key('t'); - case XK_u: - return KeyboardButton::ascii_key('u'); - case XK_v: - return KeyboardButton::ascii_key('v'); - case XK_w: - return KeyboardButton::ascii_key('w'); - case XK_x: - return KeyboardButton::ascii_key('x'); - case XK_y: - return KeyboardButton::ascii_key('y'); - case XK_z: - return KeyboardButton::ascii_key('z'); - case XK_braceleft: - return KeyboardButton::ascii_key('{'); - case XK_bar: - return KeyboardButton::ascii_key('|'); - case XK_braceright: - return KeyboardButton::ascii_key('}'); - case XK_asciitilde: - return KeyboardButton::ascii_key('~'); - case XK_F1: - case XK_KP_F1: - return KeyboardButton::f1(); - case XK_F2: - case XK_KP_F2: - return KeyboardButton::f2(); - case XK_F3: - case XK_KP_F3: - return KeyboardButton::f3(); - case XK_F4: - case XK_KP_F4: - return KeyboardButton::f4(); - case XK_F5: - return KeyboardButton::f5(); - case XK_F6: - return KeyboardButton::f6(); - case XK_F7: - return KeyboardButton::f7(); - case XK_F8: - return KeyboardButton::f8(); - case XK_F9: - return KeyboardButton::f9(); - case XK_F10: - return KeyboardButton::f10(); - case XK_F11: - return KeyboardButton::f11(); - case XK_F12: - return KeyboardButton::f12(); - case XK_KP_Left: - case XK_Left: - return KeyboardButton::left(); - case XK_KP_Up: - case XK_Up: - return KeyboardButton::up(); - case XK_KP_Right: - case XK_Right: - return KeyboardButton::right(); - case XK_KP_Down: - case XK_Down: - return KeyboardButton::down(); - case XK_KP_Prior: - case XK_Prior: - return KeyboardButton::page_up(); - case XK_KP_Next: - case XK_Next: - return KeyboardButton::page_down(); - case XK_KP_Home: - case XK_Home: - return KeyboardButton::home(); - case XK_KP_End: - case XK_End: - return KeyboardButton::end(); - case XK_KP_Insert: - case XK_Insert: - return KeyboardButton::insert(); - case XK_KP_Delete: - case XK_Delete: - return KeyboardButton::del(); - case XK_Num_Lock: - return KeyboardButton::num_lock(); - case XK_Scroll_Lock: - return KeyboardButton::scroll_lock(); - case XK_Print: - return KeyboardButton::print_screen(); - case XK_Pause: - return KeyboardButton::pause(); - case XK_Shift_L: - return KeyboardButton::lshift(); - case XK_Shift_R: - return KeyboardButton::rshift(); - case XK_Control_L: - return KeyboardButton::lcontrol(); - case XK_Control_R: - return KeyboardButton::rcontrol(); - case XK_Alt_L: - return KeyboardButton::lalt(); - case XK_Alt_R: - return KeyboardButton::ralt(); - case XK_Meta_L: - case XK_Meta_R: - return KeyboardButton::meta(); - case XK_Caps_Lock: - return KeyboardButton::caps_lock(); - case XK_Shift_Lock: - return KeyboardButton::shift_lock(); - } - - return ButtonHandle::none(); -} - -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::get_mouse_button -// Access: Private -// Description: Returns the Panda ButtonHandle corresponding to the -// mouse button indicated by the given button event. -//////////////////////////////////////////////////////////////////// -ButtonHandle TinyXGraphicsWindow:: -get_mouse_button(XButtonEvent &button_event) { - int index = button_event.button; - if (index == x_wheel_up_button) { - return MouseButton::wheel_up(); - } else if (index == x_wheel_down_button) { - return MouseButton::wheel_down(); - } else if (index == x_wheel_left_button) { - return MouseButton::wheel_left(); - } else if (index == x_wheel_right_button) { - return MouseButton::wheel_right(); - } else { - return MouseButton::button(index - 1); - } -} -//////////////////////////////////////////////////////////////////// -// Function: TinyXGraphicsWindow::check_event -// Access: Private, Static -// Description: This function is used as a predicate to -// XCheckIfEvent() to determine if the indicated queued -// X event is relevant and should be returned to this -// window. -//////////////////////////////////////////////////////////////////// -Bool TinyXGraphicsWindow:: -check_event(Display *display, XEvent *event, char *arg) { - const TinyXGraphicsWindow *self = (TinyXGraphicsWindow *)arg; - - // We accept any event that is sent to our window. - return (event->xany.window == self->_xwindow); -} - //////////////////////////////////////////////////////////////////// // Function: TinyXGraphicsWindow::create_full_frame_buffer // Access: Private diff --git a/panda/src/tinydisplay/tinyXGraphicsWindow.h b/panda/src/tinydisplay/tinyXGraphicsWindow.h index 835df53335..8bfb1254e0 100644 --- a/panda/src/tinydisplay/tinyXGraphicsWindow.h +++ b/panda/src/tinydisplay/tinyXGraphicsWindow.h @@ -20,7 +20,7 @@ #ifdef HAVE_X11 #include "tinyXGraphicsPipe.h" -#include "graphicsWindow.h" +#include "x11GraphicsWindow.h" #include "buttonHandle.h" //////////////////////////////////////////////////////////////////// @@ -28,7 +28,7 @@ // Description : Opens a window on X11 to display the TinyPanda // software rendering. //////////////////////////////////////////////////////////////////// -class EXPCL_TINYDISPLAY TinyXGraphicsWindow : public GraphicsWindow { +class EXPCL_TINYDISPLAY TinyXGraphicsWindow : public x11GraphicsWindow { public: TinyXGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, const string &name, @@ -54,23 +54,6 @@ protected: virtual void pixel_factor_changed(); private: - void set_wm_properties(const WindowProperties &properties, - bool already_mapped); - - void setup_colormap(XVisualInfo *visual); - void handle_keystroke(XKeyEvent &event); - void handle_keypress(XKeyEvent &event); - void handle_keyrelease(XKeyEvent &event); - - ButtonHandle get_button(XKeyEvent &key_event, bool allow_shift); - ButtonHandle map_button(KeySym key); - ButtonHandle get_mouse_button(XButtonEvent &button_event); - - static Bool check_event(Display *display, XEvent *event, char *arg); - - void open_raw_mice(); - void poll_raw_mice(); - void create_full_frame_buffer(); void create_reduced_frame_buffer(); void create_ximage(); @@ -80,45 +63,19 @@ private: ZBuffer *_full_frame_buffer; int _pitch; XImage *_ximage; - - Display *_display; - int _screen; + GC _gc; + int _bytes_per_pixel; Visual *_visual; int _depth; - int _bytes_per_pixel; - Window _xwindow; - Colormap _colormap; - XIC _ic; - GC _gc; - - long _event_mask; - bool _awaiting_configure; - Atom _wm_delete_window; - Atom _net_wm_window_type; - Atom _net_wm_window_type_splash; - Atom _net_wm_window_type_fullscreen; - Atom _net_wm_state; - Atom _net_wm_state_fullscreen; - Atom _net_wm_state_above; - Atom _net_wm_state_below; - Atom _net_wm_state_add; - Atom _net_wm_state_remove; - - struct MouseDeviceInfo { - int _fd; - int _input_device_index; - string _io_buffer; - }; - pvector _mouse_device_info; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - GraphicsWindow::init_type(); + x11GraphicsWindow::init_type(); register_type(_type_handle, "TinyXGraphicsWindow", - GraphicsWindow::get_class_type()); + x11GraphicsWindow::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type();