Files
test2/intern/ghost/intern/GHOST_SystemX11.h
Campbell Barton 6ce0ddae96 GHOST/X11: Hotplug support for xinput
Allows to plug/unplug different tablets while Blender is running.

Also fixes crash unplugging tablet while Blender runs (T48750).
2016-06-28 16:08:39 +10:00

413 lines
9.5 KiB
C++

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file ghost/intern/GHOST_SystemX11.h
* \ingroup GHOST
* Declaration of GHOST_SystemX11 class.
*/
#ifndef __GHOST_SYSTEMX11_H__
#define __GHOST_SYSTEMX11_H__
#include <X11/Xlib.h>
#include "GHOST_System.h"
#include "../GHOST_Types.h"
// For tablets
#ifdef WITH_X11_XINPUT
# include <X11/extensions/XInput.h>
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
# define GHOST_X11_RES_NAME "Blender" /* res_name */
# define GHOST_X11_RES_CLASS "Blender" /* res_class */
#endif
/* generic error handlers */
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
#define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var) \
struct { \
XErrorHandler handler; \
XIOErrorHandler handler_io; \
} var = { \
XSetErrorHandler(GHOST_X11_ApplicationErrorHandler), \
XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler), \
}
#define GHOST_X11_ERROR_HANDLERS_RESTORE(var) \
{ \
(void)XSetErrorHandler(var.handler); \
(void)XSetIOErrorHandler(var.handler_io); \
} ((void)0)
class GHOST_WindowX11;
/**
* X11 Implementation of GHOST_System class.
* \see GHOST_System.
* \author Laurence Bourn
* \date October 26, 2001
*/
class GHOST_SystemX11 : public GHOST_System {
public:
/**
* Constructor
* this class should only be instanciated by GHOST_ISystem.
*/
GHOST_SystemX11(
);
/**
* Destructor.
*/
~GHOST_SystemX11();
GHOST_TSuccess
init(
);
/**
* \section Interface Inherited from GHOST_ISystem
*/
/**
* Returns the system time.
* Returns the number of milliseconds since the start of the system process.
* \return The number of milliseconds.
*/
GHOST_TUns64
getMilliSeconds(
) const;
/**
* Returns the number of displays on this system.
* \return The number of displays.
*/
GHOST_TUns8
getNumDisplays(
) const;
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
void
getMainDisplayDimensions(
GHOST_TUns32& width,
GHOST_TUns32& height
) const;
/**
* Returns the dimensions of all displays on this system.
* \return The dimension of the main display.
*/
void
getAllDisplayDimensions(
GHOST_TUns32& width,
GHOST_TUns32& height
) const;
/**
* Create a new window.
* The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead.
* \param title The name of the window (displayed in the title bar of the window if the OS supports it).
* \param left The coordinate of the left edge of the window.
* \param top The coordinate of the top edge of the window.
* \param width The width the window.
* \param height The height the window.
* \param state The state of the window when opened.
* \param type The type of drawing context installed in this window.
* \param stereoVisual Create a stereo visual for quad buffered stereo.
* \param exclusive Use to show the window ontop and ignore others
* (used fullscreen).
* \param parentWindow Parent (embedder) window
* \return The new window (or 0 if creation failed).
*/
GHOST_IWindow *
createWindow(
const STR_String& title,
GHOST_TInt32 left,
GHOST_TInt32 top,
GHOST_TUns32 width,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0
);
/**
* Retrieves events from the system and stores them in the queue.
* \param waitForEvent Flag to wait for an event (or return immediately).
* \return Indication of the presence of events.
*/
bool
processEvents(
bool waitForEvent
);
GHOST_TSuccess
getCursorPosition(
GHOST_TInt32& x,
GHOST_TInt32& y
) const;
GHOST_TSuccess
setCursorPosition(
GHOST_TInt32 x,
GHOST_TInt32 y
);
/**
* Returns the state of all modifier keys.
* \param keys The state of all modifier keys (true == pressed).
* \return Indication of success.
*/
GHOST_TSuccess
getModifierKeys(
GHOST_ModifierKeys& keys
) const;
/**
* Returns the state of the mouse buttons (ouside the message queue).
* \param buttons The state of the buttons.
* \return Indication of success.
*/
GHOST_TSuccess
getButtons(
GHOST_Buttons& buttons
) const;
/**
* Flag a window as dirty. This will
* generate a GHOST window update event on a call to processEvents()
*/
void
addDirtyWindow(
GHOST_WindowX11 *bad_wind
);
/**
* return a pointer to the X11 display structure
*/
Display *
getXDisplay(
) {
return m_display;
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
XIM
getX11_XIM()
{
return m_xim;
}
#endif
/* Helped function for get data from the clipboard. */
void getClipboard_xcout(const XEvent *evt, Atom sel, Atom target,
unsigned char **txt, unsigned long *len,
unsigned int *context) const;
/**
* Returns unsigned char from CUT_BUFFER0
* \param selection Get selection, X11 only feature
* \return Returns the Clipboard indicated by Flag
*/
GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* \param buffer The buffer to copy to the clipboard
* \param selection Set the selection into the clipboard, X11 only feature
*/
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
#ifdef WITH_XDND
/**
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
* Called by GHOST_DropTargetX11 class.
* \param eventType The type of drag'n'drop event
* \param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap)
* \param mouseX x mouse coordinate (in window coordinates)
* \param mouseY y mouse coordinate
* \param window The window on which the event occurred
* \return Indication whether the event was handled.
*/
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data);
#endif
/**
* \see GHOST_ISystem
*/
int toggleConsole(int /*action*/) {
return 0;
}
#ifdef WITH_X11_XINPUT
typedef struct GHOST_TabletX11 {
XDevice *StylusDevice;
XDevice *EraserDevice;
XID StylusID, EraserID;
int MotionEvent;
int ProxInEvent;
int ProxOutEvent;
int PressEvent;
int MotionEventEraser;
int ProxInEventEraser;
int ProxOutEventEraser;
int PressEventEraser;
int PressureLevels;
int XtiltLevels, YtiltLevels;
} GHOST_TabletX11;
GHOST_TabletX11 &GetXTablet()
{
return m_xtablet;
}
#endif // WITH_X11_XINPUT
struct {
/**
* Atom used for ICCCM, WM-spec and Motif.
* We only need get this atom at the start, it's relative
* to the display not the window and are public for every
* window that need it.
*/
Atom WM_STATE;
Atom WM_CHANGE_STATE;
Atom _NET_WM_STATE;
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_FULLSCREEN;
Atom _MOTIF_WM_HINTS;
Atom WM_TAKE_FOCUS;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
/* Atoms for Selection, copy & paste. */
Atom TARGETS;
Atom STRING;
Atom COMPOUND_TEXT;
Atom TEXT;
Atom CLIPBOARD;
Atom PRIMARY;
Atom XCLIP_OUT;
Atom INCR;
Atom UTF8_STRING;
#ifdef WITH_X11_XINPUT
Atom TABLET;
#endif
} m_atom;
#ifdef WITH_X11_XINPUT
XExtensionVersion m_xinput_version;
#endif
private:
Display *m_display;
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
XIM m_xim;
#endif
#ifdef WITH_X11_XINPUT
/* Tablet devices */
GHOST_TabletX11 m_xtablet;
#endif
/// The vector of windows that need to be updated.
std::vector<GHOST_WindowX11 *> m_dirty_windows;
/// Start time at initialization.
GHOST_TUns64 m_start_time;
/// A vector of keyboard key masks
char m_keyboard_vector[32];
/* to prevent multiple warp, we store the time of the last warp event
* and stop accumulating all events generated before that */
Time m_last_warp;
/* detect autorepeat glitch */
unsigned int m_last_release_keycode;
Time m_last_release_time;
/**
* Return the ghost window associated with the
* X11 window xwind
*/
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
bool openX11_IM();
#endif
#ifdef WITH_X11_XINPUT
void refreshXInputDevices();
#endif
GHOST_WindowX11 *
findGhostWindow(
Window xwind
) const;
void
processEvent(
XEvent *xe
);
Time
lastEventTime(
Time default_time
);
bool
generateWindowExposeEvents(
);
};
#endif