Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern/GHOST_SystemX11.cpp')
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp3850
1 files changed, 1892 insertions, 1958 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index ef08a6d7bb7..4d467f3b913 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -55,13 +55,13 @@
#endif
#ifdef WITH_XF86KEYSYM
-#include <X11/XF86keysym.h>
+# include <X11/XF86keysym.h>
#endif
#ifdef WITH_X11_XFIXES
# include <X11/extensions/Xfixes.h>
/* Workaround for XWayland grab glitch: T53004. */
-#define WITH_XWAYLAND_HACK
+# define WITH_XWAYLAND_HACK
#endif
/* for XIWarpPointer */
@@ -92,12 +92,11 @@
* See T47228 and D1746 */
#define USE_NON_LATIN_KB_WORKAROUND
-static GHOST_TKey ghost_key_from_keysym(
- const KeySym key);
-static GHOST_TKey ghost_key_from_keycode(
- const XkbDescPtr xkb_descr, const KeyCode keycode);
-static GHOST_TKey ghost_key_from_keysym_or_keycode(
- const KeySym key, const XkbDescPtr xkb_descr, const KeyCode keycode);
+static GHOST_TKey ghost_key_from_keysym(const KeySym key);
+static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode);
+static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym key,
+ const XkbDescPtr xkb_descr,
+ const KeyCode keycode);
/* these are for copy and select copy */
static char *txt_cut_buffer = NULL;
@@ -109,285 +108,277 @@ static bool use_xwayland_hack = false;
using namespace std;
-GHOST_SystemX11::
-GHOST_SystemX11(
- )
- : GHOST_System(),
- m_xkb_descr(NULL),
- m_start_time(0)
+GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_time(0)
{
- XInitThreads();
- m_display = XOpenDisplay(NULL);
+ XInitThreads();
+ m_display = XOpenDisplay(NULL);
- if (!m_display) {
- std::cerr << "Unable to open a display" << std::endl;
- abort(); /* was return before, but this would just mean it will crash later */
- }
+ if (!m_display) {
+ std::cerr << "Unable to open a display" << std::endl;
+ abort(); /* was return before, but this would just mean it will crash later */
+ }
#ifdef USE_X11_ERROR_HANDLERS
- (void) XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
- (void) XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
+ (void)XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
+ (void)XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* note -- don't open connection to XIM server here, because the locale
- * has to be set before opening the connection but setlocale() has not
- * been called yet. the connection will be opened after entering
- * the event loop. */
- m_xim = NULL;
+ /* note -- don't open connection to XIM server here, because the locale
+ * has to be set before opening the connection but setlocale() has not
+ * been called yet. the connection will be opened after entering
+ * the event loop. */
+ m_xim = NULL;
#endif
-#define GHOST_INTERN_ATOM_IF_EXISTS(atom) { m_atom.atom = XInternAtom(m_display, #atom , True); } (void)0
-#define GHOST_INTERN_ATOM(atom) { m_atom.atom = XInternAtom(m_display, #atom , False); } (void)0
-
- GHOST_INTERN_ATOM_IF_EXISTS(WM_DELETE_WINDOW);
- GHOST_INTERN_ATOM(WM_PROTOCOLS);
- GHOST_INTERN_ATOM(WM_TAKE_FOCUS);
- GHOST_INTERN_ATOM(WM_STATE);
- GHOST_INTERN_ATOM(WM_CHANGE_STATE);
- GHOST_INTERN_ATOM(_NET_WM_STATE);
- GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
- GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
-
- GHOST_INTERN_ATOM(_NET_WM_STATE_FULLSCREEN);
- GHOST_INTERN_ATOM(_MOTIF_WM_HINTS);
- GHOST_INTERN_ATOM(TARGETS);
- GHOST_INTERN_ATOM(STRING);
- GHOST_INTERN_ATOM(COMPOUND_TEXT);
- GHOST_INTERN_ATOM(TEXT);
- GHOST_INTERN_ATOM(CLIPBOARD);
- GHOST_INTERN_ATOM(PRIMARY);
- GHOST_INTERN_ATOM(XCLIP_OUT);
- GHOST_INTERN_ATOM(INCR);
- GHOST_INTERN_ATOM(UTF8_STRING);
+#define GHOST_INTERN_ATOM_IF_EXISTS(atom) \
+ { \
+ m_atom.atom = XInternAtom(m_display, #atom, True); \
+ } \
+ (void)0
+#define GHOST_INTERN_ATOM(atom) \
+ { \
+ m_atom.atom = XInternAtom(m_display, #atom, False); \
+ } \
+ (void)0
+
+ GHOST_INTERN_ATOM_IF_EXISTS(WM_DELETE_WINDOW);
+ GHOST_INTERN_ATOM(WM_PROTOCOLS);
+ GHOST_INTERN_ATOM(WM_TAKE_FOCUS);
+ GHOST_INTERN_ATOM(WM_STATE);
+ GHOST_INTERN_ATOM(WM_CHANGE_STATE);
+ GHOST_INTERN_ATOM(_NET_WM_STATE);
+ GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+ GHOST_INTERN_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+
+ GHOST_INTERN_ATOM(_NET_WM_STATE_FULLSCREEN);
+ GHOST_INTERN_ATOM(_MOTIF_WM_HINTS);
+ GHOST_INTERN_ATOM(TARGETS);
+ GHOST_INTERN_ATOM(STRING);
+ GHOST_INTERN_ATOM(COMPOUND_TEXT);
+ GHOST_INTERN_ATOM(TEXT);
+ GHOST_INTERN_ATOM(CLIPBOARD);
+ GHOST_INTERN_ATOM(PRIMARY);
+ GHOST_INTERN_ATOM(XCLIP_OUT);
+ GHOST_INTERN_ATOM(INCR);
+ GHOST_INTERN_ATOM(UTF8_STRING);
#ifdef WITH_X11_XINPUT
- m_atom.TABLET = XInternAtom(m_display, XI_TABLET, False);
+ m_atom.TABLET = XInternAtom(m_display, XI_TABLET, False);
#endif
#undef GHOST_INTERN_ATOM_IF_EXISTS
#undef GHOST_INTERN_ATOM
- m_last_warp = 0;
- m_last_release_keycode = 0;
- m_last_release_time = 0;
+ m_last_warp = 0;
+ m_last_release_keycode = 0;
+ m_last_release_time = 0;
- /* compute the initial time */
- timeval tv;
- if (gettimeofday(&tv, NULL) == -1) {
- GHOST_ASSERT(false, "Could not instantiate timer!");
- }
+ /* compute the initial time */
+ timeval tv;
+ if (gettimeofday(&tv, NULL) == -1) {
+ GHOST_ASSERT(false, "Could not instantiate timer!");
+ }
- /* Taking care not to overflow the tv.tv_sec * 1000 */
- m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+ /* Taking care not to overflow the tv.tv_sec * 1000 */
+ m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
+ /* use detectable autorepeate, mac and windows also do this */
+ int use_xkb;
+ int xkb_opcode, xkb_event, xkb_error;
+ int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
- /* use detectable autorepeate, mac and windows also do this */
- int use_xkb;
- int xkb_opcode, xkb_event, xkb_error;
- int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
+ use_xkb = XkbQueryExtension(
+ m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
+ if (use_xkb) {
+ XkbSetDetectableAutoRepeat(m_display, true, NULL);
- use_xkb = XkbQueryExtension(m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
- if (use_xkb) {
- XkbSetDetectableAutoRepeat(m_display, true, NULL);
-
- m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd);
- if (m_xkb_descr) {
- XkbGetNames(m_display, XkbKeyNamesMask, m_xkb_descr);
- }
- }
+ m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd);
+ if (m_xkb_descr) {
+ XkbGetNames(m_display, XkbKeyNamesMask, m_xkb_descr);
+ }
+ }
#ifdef WITH_XWAYLAND_HACK
- use_xwayland_hack = getenv("WAYLAND_DISPLAY") != NULL;
+ use_xwayland_hack = getenv("WAYLAND_DISPLAY") != NULL;
#endif
#ifdef WITH_X11_XINPUT
- /* detect if we have xinput (for reuse) */
- {
- memset(&m_xinput_version, 0, sizeof(m_xinput_version));
- XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
- if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
- if (version->present) {
- m_xinput_version = *version;
- }
- XFree(version);
- }
- }
-
-#ifdef USE_XINPUT_HOTPLUG
- if (m_xinput_version.present) {
- XEventClass class_presence;
- int xi_presence;
- DevicePresence(m_display, xi_presence, class_presence);
- XSelectExtensionEvent(
- m_display,
- RootWindow(m_display, DefaultScreen(m_display)),
- &class_presence, 1);
- (void)xi_presence;
- }
-#endif /* USE_XINPUT_HOTPLUG */
-
- refreshXInputDevices();
-#endif /* WITH_X11_XINPUT */
+ /* detect if we have xinput (for reuse) */
+ {
+ memset(&m_xinput_version, 0, sizeof(m_xinput_version));
+ XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
+ if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
+ if (version->present) {
+ m_xinput_version = *version;
+ }
+ XFree(version);
+ }
+ }
+
+# ifdef USE_XINPUT_HOTPLUG
+ if (m_xinput_version.present) {
+ XEventClass class_presence;
+ int xi_presence;
+ DevicePresence(m_display, xi_presence, class_presence);
+ XSelectExtensionEvent(
+ m_display, RootWindow(m_display, DefaultScreen(m_display)), &class_presence, 1);
+ (void)xi_presence;
+ }
+# endif /* USE_XINPUT_HOTPLUG */
+
+ refreshXInputDevices();
+#endif /* WITH_X11_XINPUT */
}
-GHOST_SystemX11::
-~GHOST_SystemX11()
+GHOST_SystemX11::~GHOST_SystemX11()
{
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- if (m_xim) {
- XCloseIM(m_xim);
- }
+ if (m_xim) {
+ XCloseIM(m_xim);
+ }
#endif
#ifdef WITH_X11_XINPUT
- /* Close tablet devices. */
- clearXInputDevices();
+ /* Close tablet devices. */
+ clearXInputDevices();
#endif /* WITH_X11_XINPUT */
- if (m_xkb_descr) {
- XkbFreeKeyboard (m_xkb_descr, XkbAllComponentsMask, true);
- }
+ if (m_xkb_descr) {
+ XkbFreeKeyboard(m_xkb_descr, XkbAllComponentsMask, true);
+ }
- XCloseDisplay(m_display);
+ XCloseDisplay(m_display);
}
-
-GHOST_TSuccess
-GHOST_SystemX11::
-init()
+GHOST_TSuccess GHOST_SystemX11::init()
{
- GHOST_TSuccess success = GHOST_System::init();
+ GHOST_TSuccess success = GHOST_System::init();
- if (success) {
+ if (success) {
#ifdef WITH_INPUT_NDOF
- m_ndofManager = new GHOST_NDOFManagerUnix(*this);
+ m_ndofManager = new GHOST_NDOFManagerUnix(*this);
#endif
- m_displayManager = new GHOST_DisplayManagerX11(this);
+ m_displayManager = new GHOST_DisplayManagerX11(this);
- if (m_displayManager) {
- return GHOST_kSuccess;
- }
- }
+ if (m_displayManager) {
+ return GHOST_kSuccess;
+ }
+ }
- return GHOST_kFailure;
+ return GHOST_kFailure;
}
-GHOST_TUns64
-GHOST_SystemX11::
-getMilliSeconds() const
+GHOST_TUns64 GHOST_SystemX11::getMilliSeconds() const
{
- timeval tv;
- if (gettimeofday(&tv, NULL) == -1) {
- GHOST_ASSERT(false, "Could not compute time!");
- }
+ timeval tv;
+ if (gettimeofday(&tv, NULL) == -1) {
+ GHOST_ASSERT(false, "Could not compute time!");
+ }
- /* Taking care not to overflow the tv.tv_sec * 1000 */
- return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
+ /* Taking care not to overflow the tv.tv_sec * 1000 */
+ return GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000 - m_start_time;
}
-GHOST_TUns8
-GHOST_SystemX11::
-getNumDisplays() const
+GHOST_TUns8 GHOST_SystemX11::getNumDisplays() const
{
- return GHOST_TUns8(1);
+ return GHOST_TUns8(1);
}
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
-void
-GHOST_SystemX11::
-getMainDisplayDimensions(
- GHOST_TUns32& width,
- GHOST_TUns32& height) const
+void GHOST_SystemX11::getMainDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
{
- if (m_display) {
- /* note, for this to work as documented,
- * we would need to use Xinerama check r54370 for code that did this,
- * we've since removed since its not worth the extra dep - campbell */
- getAllDisplayDimensions(width, height);
- }
+ if (m_display) {
+ /* note, for this to work as documented,
+ * we would need to use Xinerama check r54370 for code that did this,
+ * we've since removed since its not worth the extra dep - campbell */
+ getAllDisplayDimensions(width, height);
+ }
}
-
/**
* Returns the dimensions of the main display on this system.
* \return The dimension of the main display.
*/
-void
-GHOST_SystemX11::
-getAllDisplayDimensions(
- GHOST_TUns32& width,
- GHOST_TUns32& height) const
+void GHOST_SystemX11::getAllDisplayDimensions(GHOST_TUns32 &width, GHOST_TUns32 &height) const
{
- if (m_display) {
- width = DisplayWidth(m_display, DefaultScreen(m_display));
- height = DisplayHeight(m_display, DefaultScreen(m_display));
- }
+ if (m_display) {
+ width = DisplayWidth(m_display, DefaultScreen(m_display));
+ height = DisplayHeight(m_display, DefaultScreen(m_display));
+ }
}
/**
* 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 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 glSettings: Misc OpenGL settings.
* \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).
+ * \param parentWindow Parent (embedder) window
+ * \return The new window (or 0 if creation failed).
*/
-GHOST_IWindow *
-GHOST_SystemX11::
-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,
- const GHOST_TEmbedderWindowID parentWindow)
+GHOST_IWindow *GHOST_SystemX11::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,
+ const GHOST_TEmbedderWindowID parentWindow)
{
- GHOST_WindowX11 *window = NULL;
-
- if (!m_display) return 0;
-
- window = new GHOST_WindowX11(this, m_display, title,
- left, top, width, height,
- state, parentWindow, type,
- ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
- ((glSettings.flags & GHOST_glAlphaBackground) != 0),
- glSettings.numOfAASamples, (glSettings.flags & GHOST_glDebugContext) != 0);
-
- if (window) {
- /* Both are now handle in GHOST_WindowX11.cpp
- * Focus and Delete atoms. */
-
- if (window->getValid()) {
- /* Store the pointer to the window */
- m_windowManager->addWindow(window);
- m_windowManager->setActiveWindow(window);
- pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
- }
- else {
- delete window;
- window = NULL;
- }
- }
- return window;
+ GHOST_WindowX11 *window = NULL;
+
+ if (!m_display)
+ return 0;
+
+ window = new GHOST_WindowX11(this,
+ m_display,
+ title,
+ left,
+ top,
+ width,
+ height,
+ state,
+ parentWindow,
+ type,
+ ((glSettings.flags & GHOST_glStereoVisual) != 0),
+ exclusive,
+ ((glSettings.flags & GHOST_glAlphaBackground) != 0),
+ glSettings.numOfAASamples,
+ (glSettings.flags & GHOST_glDebugContext) != 0);
+
+ if (window) {
+ /* Both are now handle in GHOST_WindowX11.cpp
+ * Focus and Delete atoms. */
+
+ if (window->getValid()) {
+ /* Store the pointer to the window */
+ m_windowManager->addWindow(window);
+ m_windowManager->setActiveWindow(window);
+ pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
+ }
+ else {
+ delete window;
+ window = NULL;
+ }
+ }
+ return window;
}
bool GHOST_SystemX11::supportsNativeDialogs(void)
{
- return false;
+ return false;
}
/**
@@ -395,76 +386,76 @@ bool GHOST_SystemX11::supportsNativeDialogs(void)
* Never explicitly delete the context, use disposeContext() instead.
* \return The new context (or 0 if creation failed).
*/
-GHOST_IContext *
-GHOST_SystemX11::
-createOffscreenContext()
+GHOST_IContext *GHOST_SystemX11::createOffscreenContext()
{
- // During development:
- // try 4.x compatibility profile
- // try 3.3 compatibility profile
- // fall back to 3.0 if needed
- //
- // Final Blender 2.8:
- // try 4.x core profile
- // try 3.3 core profile
- // no fallbacks
+ // During development:
+ // try 4.x compatibility profile
+ // try 3.3 compatibility profile
+ // fall back to 3.0 if needed
+ //
+ // Final Blender 2.8:
+ // try 4.x core profile
+ // try 3.3 core profile
+ // no fallbacks
#if defined(WITH_GL_PROFILE_CORE)
- {
- const char *version_major = (char*)glewGetString(GLEW_VERSION_MAJOR);
- if (version_major != NULL && version_major[0] == '1') {
- fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
- abort();
- }
- }
+ {
+ const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
+ if (version_major != NULL && version_major[0] == '1') {
+ fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
+ abort();
+ }
+ }
#endif
- const int profile_mask =
+ const int profile_mask =
#if defined(WITH_GL_PROFILE_CORE)
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
#elif defined(WITH_GL_PROFILE_COMPAT)
- GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
#else
-# error // must specify either core or compat at build time
+# error // must specify either core or compat at build time
#endif
- GHOST_Context *context;
-
- for (int minor = 5; minor >= 0; --minor) {
- context = new GHOST_ContextGLX(
- false,
- 0,
- (Window)NULL,
- m_display,
- (GLXFBConfig)NULL,
- profile_mask,
- 4, minor,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS | (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-
- if (context->initializeDrawingContext())
- return context;
- else
- delete context;
- }
-
- context = new GHOST_ContextGLX(
- false,
- 0,
- (Window)NULL,
- m_display,
- (GLXFBConfig)NULL,
- profile_mask,
- 3, 3,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS | (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-
- if (context->initializeDrawingContext())
- return context;
- else
- delete context;
-
- return NULL;
+ GHOST_Context *context;
+
+ for (int minor = 5; minor >= 0; --minor) {
+ context = new GHOST_ContextGLX(false,
+ 0,
+ (Window)NULL,
+ m_display,
+ (GLXFBConfig)NULL,
+ profile_mask,
+ 4,
+ minor,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS |
+ (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+ }
+
+ context = new GHOST_ContextGLX(false,
+ 0,
+ (Window)NULL,
+ m_display,
+ (GLXFBConfig)NULL,
+ profile_mask,
+ 3,
+ 3,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS |
+ (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+
+ return NULL;
}
/**
@@ -472,1743 +463,1695 @@ createOffscreenContext()
* \param context Pointer to the context to be disposed.
* \return Indication of success.
*/
-GHOST_TSuccess
-GHOST_SystemX11::
-disposeContext(GHOST_IContext *context)
+GHOST_TSuccess GHOST_SystemX11::disposeContext(GHOST_IContext *context)
{
- delete context;
+ delete context;
- return GHOST_kSuccess;
+ return GHOST_kSuccess;
}
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
{
- GHOST_PRINT("XIM server died\n");
+ GHOST_PRINT("XIM server died\n");
- if (ptr)
- *(XIM *)ptr = NULL;
+ if (ptr)
+ *(XIM *)ptr = NULL;
}
bool GHOST_SystemX11::openX11_IM()
{
- if (!m_display)
- return false;
+ if (!m_display)
+ return false;
- /* set locale modifiers such as "@im=ibus" specified by XMODIFIERS */
- XSetLocaleModifiers("");
+ /* set locale modifiers such as "@im=ibus" specified by XMODIFIERS */
+ XSetLocaleModifiers("");
- m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
- if (!m_xim)
- return false;
+ m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS);
+ if (!m_xim)
+ return false;
- XIMCallback destroy;
- destroy.callback = (XIMProc)destroyIMCallback;
- destroy.client_data = (XPointer)&m_xim;
- XSetIMValues(m_xim, XNDestroyCallback, &destroy, NULL);
- return true;
+ XIMCallback destroy;
+ destroy.callback = (XIMProc)destroyIMCallback;
+ destroy.client_data = (XPointer)&m_xim;
+ XSetIMValues(m_xim, XNDestroyCallback, &destroy, NULL);
+ return true;
}
#endif
-GHOST_WindowX11 *
-GHOST_SystemX11::
-findGhostWindow(
- Window xwind) const
+GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const
{
- if (xwind == 0) return NULL;
+ if (xwind == 0)
+ return NULL;
- /* It is not entirely safe to do this as the backptr may point
- * to a window that has recently been removed.
- * We should always check the window manager's list of windows
- * and only process events on these windows. */
+ /* It is not entirely safe to do this as the backptr may point
+ * to a window that has recently been removed.
+ * We should always check the window manager's list of windows
+ * and only process events on these windows. */
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
- vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
- vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
-
- for (; win_it != win_end; ++win_it) {
- GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
- if (window->getXWindow() == xwind) {
- return window;
- }
- }
- return NULL;
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
+ for (; win_it != win_end; ++win_it) {
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ if (window->getXWindow() == xwind) {
+ return window;
+ }
+ }
+ return NULL;
}
static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep)
{
- int fd = ConnectionNumber(display);
- fd_set fds;
+ int fd = ConnectionNumber(display);
+ fd_set fds;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
- if (maxSleep == -1) {
- select(fd + 1, &fds, NULL, NULL, NULL);
- }
- else {
- timeval tv;
+ if (maxSleep == -1) {
+ select(fd + 1, &fds, NULL, NULL, NULL);
+ }
+ else {
+ timeval tv;
- tv.tv_sec = maxSleep / 1000;
- tv.tv_usec = (maxSleep - tv.tv_sec * 1000) * 1000;
+ tv.tv_sec = maxSleep / 1000;
+ tv.tv_usec = (maxSleep - tv.tv_sec * 1000) * 1000;
- select(fd + 1, &fds, NULL, NULL, &tv);
- }
+ select(fd + 1, &fds, NULL, NULL, &tv);
+ }
}
/* This function borrowed from Qt's X11 support
* qclipboard_x11.cpp
* */
struct init_timestamp_data {
- Time timestamp;
+ Time timestamp;
};
static Bool init_timestamp_scanner(Display *, XEvent *event, XPointer arg)
{
- init_timestamp_data *data =
- reinterpret_cast<init_timestamp_data *>(arg);
- switch (event->type) {
- case ButtonPress:
- case ButtonRelease:
- data->timestamp = event->xbutton.time;
- break;
- case MotionNotify:
- data->timestamp = event->xmotion.time;
- break;
- case KeyPress:
- case KeyRelease:
- data->timestamp = event->xkey.time;
- break;
- case PropertyNotify:
- data->timestamp = event->xproperty.time;
- break;
- case EnterNotify:
- case LeaveNotify:
- data->timestamp = event->xcrossing.time;
- break;
- case SelectionClear:
- data->timestamp = event->xselectionclear.time;
- break;
- default:
- break;
- }
-
- return false;
+ init_timestamp_data *data = reinterpret_cast<init_timestamp_data *>(arg);
+ switch (event->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ data->timestamp = event->xbutton.time;
+ break;
+ case MotionNotify:
+ data->timestamp = event->xmotion.time;
+ break;
+ case KeyPress:
+ case KeyRelease:
+ data->timestamp = event->xkey.time;
+ break;
+ case PropertyNotify:
+ data->timestamp = event->xproperty.time;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ data->timestamp = event->xcrossing.time;
+ break;
+ case SelectionClear:
+ data->timestamp = event->xselectionclear.time;
+ break;
+ default:
+ break;
+ }
+
+ return false;
}
-Time
-GHOST_SystemX11::
-lastEventTime(Time default_time) {
- init_timestamp_data data;
- data.timestamp = default_time;
- XEvent ev;
- XCheckIfEvent(m_display, &ev, &init_timestamp_scanner, (XPointer) & data);
+Time GHOST_SystemX11::lastEventTime(Time default_time)
+{
+ init_timestamp_data data;
+ data.timestamp = default_time;
+ XEvent ev;
+ XCheckIfEvent(m_display, &ev, &init_timestamp_scanner, (XPointer)&data);
- return data.timestamp;
+ return data.timestamp;
}
-bool
-GHOST_SystemX11::
-processEvents(
- bool waitForEvent)
+bool GHOST_SystemX11::processEvents(bool waitForEvent)
{
- /* Get all the current events -- translate them into
- * ghost events and call base class pushEvent() method. */
+ /* Get all the current events -- translate them into
+ * ghost events and call base class pushEvent() method. */
- bool anyProcessed = false;
+ bool anyProcessed = false;
- do {
- GHOST_TimerManager *timerMgr = getTimerManager();
+ do {
+ GHOST_TimerManager *timerMgr = getTimerManager();
- if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
- GHOST_TUns64 next = timerMgr->nextFireTime();
+ if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
+ GHOST_TUns64 next = timerMgr->nextFireTime();
- if (next == GHOST_kFireTimeNever) {
- SleepTillEvent(m_display, -1);
- }
- else {
- GHOST_TInt64 maxSleep = next - getMilliSeconds();
+ if (next == GHOST_kFireTimeNever) {
+ SleepTillEvent(m_display, -1);
+ }
+ else {
+ GHOST_TInt64 maxSleep = next - getMilliSeconds();
- if (maxSleep >= 0)
- SleepTillEvent(m_display, next - getMilliSeconds());
- }
- }
+ if (maxSleep >= 0)
+ SleepTillEvent(m_display, next - getMilliSeconds());
+ }
+ }
- if (timerMgr->fireTimers(getMilliSeconds())) {
- anyProcessed = true;
- }
+ if (timerMgr->fireTimers(getMilliSeconds())) {
+ anyProcessed = true;
+ }
- while (XPending(m_display)) {
- XEvent xevent;
- XNextEvent(m_display, &xevent);
+ while (XPending(m_display)) {
+ XEvent xevent;
+ XNextEvent(m_display, &xevent);
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* open connection to XIM server and create input context (XIC)
- * when receiving the first FocusIn or KeyPress event after startup,
- * or recover XIM and XIC when the XIM server has been restarted */
- if (xevent.type == FocusIn || xevent.type == KeyPress) {
- if (!m_xim && openX11_IM()) {
- GHOST_PRINT("Connected to XIM server\n");
- }
-
- if (m_xim) {
- GHOST_WindowX11 * window = findGhostWindow(xevent.xany.window);
- if (window && !window->getX11_XIC() && window->createX11_XIC()) {
- GHOST_PRINT("XIM input context created\n");
- if (xevent.type == KeyPress)
- /* we can assume the window has input focus
- * here, because key events are received only
- * when the window is focused. */
- XSetICFocus(window->getX11_XIC());
- }
- }
- }
-
- /* dispatch event to XIM server */
- if ((XFilterEvent(&xevent, (Window)NULL) == True)) {
- /* do nothing now, the event is consumed by XIM. */
- continue;
- }
+ /* open connection to XIM server and create input context (XIC)
+ * when receiving the first FocusIn or KeyPress event after startup,
+ * or recover XIM and XIC when the XIM server has been restarted */
+ if (xevent.type == FocusIn || xevent.type == KeyPress) {
+ if (!m_xim && openX11_IM()) {
+ GHOST_PRINT("Connected to XIM server\n");
+ }
+
+ if (m_xim) {
+ GHOST_WindowX11 *window = findGhostWindow(xevent.xany.window);
+ if (window && !window->getX11_XIC() && window->createX11_XIC()) {
+ GHOST_PRINT("XIM input context created\n");
+ if (xevent.type == KeyPress)
+ /* we can assume the window has input focus
+ * here, because key events are received only
+ * when the window is focused. */
+ XSetICFocus(window->getX11_XIC());
+ }
+ }
+ }
+
+ /* dispatch event to XIM server */
+ if ((XFilterEvent(&xevent, (Window)NULL) == True)) {
+ /* do nothing now, the event is consumed by XIM. */
+ continue;
+ }
#endif
- /* when using autorepeat, some keypress events can actually come *after* the
- * last keyrelease. The next code takes care of that */
- if (xevent.type == KeyRelease) {
- m_last_release_keycode = xevent.xkey.keycode;
- m_last_release_time = xevent.xkey.time;
- }
- else if (xevent.type == KeyPress) {
- if ((xevent.xkey.keycode == m_last_release_keycode) && ((xevent.xkey.time <= m_last_release_time)))
- continue;
- }
-
- processEvent(&xevent);
- anyProcessed = true;
-
+ /* when using autorepeat, some keypress events can actually come *after* the
+ * last keyrelease. The next code takes care of that */
+ if (xevent.type == KeyRelease) {
+ m_last_release_keycode = xevent.xkey.keycode;
+ m_last_release_time = xevent.xkey.time;
+ }
+ else if (xevent.type == KeyPress) {
+ if ((xevent.xkey.keycode == m_last_release_keycode) &&
+ ((xevent.xkey.time <= m_last_release_time)))
+ continue;
+ }
+
+ processEvent(&xevent);
+ anyProcessed = true;
#ifdef USE_UNITY_WORKAROUND
- /* note: processEvent() can't include this code because
- * KeymapNotify event have no valid window information. */
-
- /* the X server generates KeymapNotify event immediately after
- * every EnterNotify and FocusIn event. we handle this event
- * to correct modifier states. */
- if (xevent.type == FocusIn) {
- /* use previous event's window, because KeymapNotify event
- * has no window information. */
- GHOST_WindowX11 *window = findGhostWindow(xevent.xany.window);
- if (window && XPending(m_display) >= 2) {
- XNextEvent(m_display, &xevent);
-
- if (xevent.type == KeymapNotify) {
- XEvent xev_next;
-
- /* check if KeyPress or KeyRelease event was generated
- * in order to confirm the window is active. */
- XPeekEvent(m_display, &xev_next);
-
- if (xev_next.type == KeyPress || xev_next.type == KeyRelease) {
- /* XK_Hyper_L/R currently unused */
- const static KeySym modifiers[8] = {XK_Shift_L, XK_Shift_R,
- XK_Control_L, XK_Control_R,
- XK_Alt_L, XK_Alt_R,
- XK_Super_L, XK_Super_R};
-
- for (int i = 0; i < (sizeof(modifiers) / sizeof(*modifiers)); i++) {
- KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]);
- if (((xevent.xkeymap.key_vector[kc >> 3] >> (kc & 7)) & 1) != 0) {
- pushEvent(new GHOST_EventKey(
- getMilliSeconds(),
- GHOST_kEventKeyDown,
- window,
- ghost_key_from_keysym(modifiers[i]),
- '\0',
- NULL));
- }
- }
- }
- }
- }
- }
-#endif /* USE_UNITY_WORKAROUND */
-
- }
-
- if (generateWindowExposeEvents()) {
- anyProcessed = true;
- }
+ /* note: processEvent() can't include this code because
+ * KeymapNotify event have no valid window information. */
+
+ /* the X server generates KeymapNotify event immediately after
+ * every EnterNotify and FocusIn event. we handle this event
+ * to correct modifier states. */
+ if (xevent.type == FocusIn) {
+ /* use previous event's window, because KeymapNotify event
+ * has no window information. */
+ GHOST_WindowX11 *window = findGhostWindow(xevent.xany.window);
+ if (window && XPending(m_display) >= 2) {
+ XNextEvent(m_display, &xevent);
+
+ if (xevent.type == KeymapNotify) {
+ XEvent xev_next;
+
+ /* check if KeyPress or KeyRelease event was generated
+ * in order to confirm the window is active. */
+ XPeekEvent(m_display, &xev_next);
+
+ if (xev_next.type == KeyPress || xev_next.type == KeyRelease) {
+ /* XK_Hyper_L/R currently unused */
+ const static KeySym modifiers[8] = {XK_Shift_L,
+ XK_Shift_R,
+ XK_Control_L,
+ XK_Control_R,
+ XK_Alt_L,
+ XK_Alt_R,
+ XK_Super_L,
+ XK_Super_R};
+
+ for (int i = 0; i < (sizeof(modifiers) / sizeof(*modifiers)); i++) {
+ KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]);
+ if (((xevent.xkeymap.key_vector[kc >> 3] >> (kc & 7)) & 1) != 0) {
+ pushEvent(new GHOST_EventKey(getMilliSeconds(),
+ GHOST_kEventKeyDown,
+ window,
+ ghost_key_from_keysym(modifiers[i]),
+ '\0',
+ NULL));
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_UNITY_WORKAROUND */
+ }
+
+ if (generateWindowExposeEvents()) {
+ anyProcessed = true;
+ }
#ifdef WITH_INPUT_NDOF
- if (static_cast<GHOST_NDOFManagerUnix *>(m_ndofManager)->processEvents()) {
- anyProcessed = true;
- }
+ if (static_cast<GHOST_NDOFManagerUnix *>(m_ndofManager)->processEvents()) {
+ anyProcessed = true;
+ }
#endif
- } while (waitForEvent && !anyProcessed);
+ } while (waitForEvent && !anyProcessed);
- return anyProcessed;
+ return anyProcessed;
}
-
#ifdef WITH_X11_XINPUT
static bool checkTabletProximity(Display *display, XDevice *device)
{
- /* we could have true/false/not-found return value, but for now false is OK */
-
- /* see: state.c from xinput, to get more data out of the device */
- XDeviceState *state;
-
- if (device == NULL) {
- return false;
- }
-
- /* needed since unplugging will abort() without this */
- GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
-
- state = XQueryDeviceState(display, device);
-
- GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
-
- if (state) {
- XInputClass *cls = state->data;
- // printf("%d class%s :\n", state->num_classes,
- // (state->num_classes > 1) ? "es" : "");
- for (int loop = 0; loop < state->num_classes; loop++) {
- switch (cls->c_class) {
- case ValuatorClass:
- XValuatorState *val_state = (XValuatorState *)cls;
- // printf("ValuatorClass Mode=%s Proximity=%s\n",
- // val_state->mode & 1 ? "Absolute" : "Relative",
- // val_state->mode & 2 ? "Out" : "In");
-
- if ((val_state->mode & 2) == 0) {
- XFreeDeviceState(state);
- return true;
- }
- break;
- }
- cls = (XInputClass *) ((char *)cls + cls->length);
- }
- XFreeDeviceState(state);
- }
- return false;
+ /* we could have true/false/not-found return value, but for now false is OK */
+
+ /* see: state.c from xinput, to get more data out of the device */
+ XDeviceState *state;
+
+ if (device == NULL) {
+ return false;
+ }
+
+ /* needed since unplugging will abort() without this */
+ GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
+
+ state = XQueryDeviceState(display, device);
+
+ GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
+
+ if (state) {
+ XInputClass *cls = state->data;
+ // printf("%d class%s :\n", state->num_classes,
+ // (state->num_classes > 1) ? "es" : "");
+ for (int loop = 0; loop < state->num_classes; loop++) {
+ switch (cls->c_class) {
+ case ValuatorClass:
+ XValuatorState *val_state = (XValuatorState *)cls;
+ // printf("ValuatorClass Mode=%s Proximity=%s\n",
+ // val_state->mode & 1 ? "Absolute" : "Relative",
+ // val_state->mode & 2 ? "Out" : "In");
+
+ if ((val_state->mode & 2) == 0) {
+ XFreeDeviceState(state);
+ return true;
+ }
+ break;
+ }
+ cls = (XInputClass *)((char *)cls + cls->length);
+ }
+ XFreeDeviceState(state);
+ }
+ return false;
}
#endif /* WITH_X11_XINPUT */
-void
-GHOST_SystemX11::processEvent(XEvent *xe)
+void GHOST_SystemX11::processEvent(XEvent *xe)
{
- GHOST_WindowX11 *window = findGhostWindow(xe->xany.window);
- GHOST_Event *g_event = NULL;
+ GHOST_WindowX11 *window = findGhostWindow(xe->xany.window);
+ GHOST_Event *g_event = NULL;
#ifdef USE_XINPUT_HOTPLUG
- /* Hot-Plug support */
- if (m_xinput_version.present) {
- XEventClass class_presence;
- int xi_presence;
-
- DevicePresence(m_display, xi_presence, class_presence);
- (void)class_presence;
-
- if (xe->type == xi_presence) {
- XDevicePresenceNotifyEvent *notify_event = (XDevicePresenceNotifyEvent *)xe;
- if ((notify_event->devchange == DeviceEnabled) ||
- (notify_event->devchange == DeviceDisabled) ||
- (notify_event->devchange == DeviceAdded) ||
- (notify_event->devchange == DeviceRemoved))
- {
- refreshXInputDevices();
-
- /* update all window events */
- {
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
- vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
- vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
-
- for (; win_it != win_end; ++win_it) {
- GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
- window->refreshXInputDevices();
- }
- }
- }
- }
- }
-#endif /* USE_XINPUT_HOTPLUG */
-
-
- if (!window) {
- return;
- }
+ /* Hot-Plug support */
+ if (m_xinput_version.present) {
+ XEventClass class_presence;
+ int xi_presence;
+
+ DevicePresence(m_display, xi_presence, class_presence);
+ (void)class_presence;
+
+ if (xe->type == xi_presence) {
+ XDevicePresenceNotifyEvent *notify_event = (XDevicePresenceNotifyEvent *)xe;
+ if ((notify_event->devchange == DeviceEnabled) ||
+ (notify_event->devchange == DeviceDisabled) ||
+ (notify_event->devchange == DeviceAdded) || (notify_event->devchange == DeviceRemoved)) {
+ refreshXInputDevices();
+
+ /* update all window events */
+ {
+ vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
+
+ for (; win_it != win_end; ++win_it) {
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ window->refreshXInputDevices();
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_XINPUT_HOTPLUG */
+
+ if (!window) {
+ return;
+ }
#ifdef WITH_X11_XINPUT
- /* Proximity-Out Events are not reliable, if the tablet is active - check on each event
- * this adds a little overhead but only while the tablet is in use.
- * in the future we could have a ghost call window->CheckTabletProximity()
- * but for now enough parts of the code are checking 'Active'
- * - campbell */
- if (window->GetTabletData()->Active != GHOST_kTabletModeNone) {
- bool any_proximity = false;
-
- for (GHOST_TabletX11& xtablet: m_xtablets) {
- if (checkTabletProximity(xe->xany.display, xtablet.Device)) {
- any_proximity = true;
- }
- }
-
- if (!any_proximity) {
- // printf("proximity disable\n");
- window->GetTabletData()->Active = GHOST_kTabletModeNone;
- }
- }
+ /* Proximity-Out Events are not reliable, if the tablet is active - check on each event
+ * this adds a little overhead but only while the tablet is in use.
+ * in the future we could have a ghost call window->CheckTabletProximity()
+ * but for now enough parts of the code are checking 'Active'
+ * - campbell */
+ if (window->GetTabletData()->Active != GHOST_kTabletModeNone) {
+ bool any_proximity = false;
+
+ for (GHOST_TabletX11 &xtablet : m_xtablets) {
+ if (checkTabletProximity(xe->xany.display, xtablet.Device)) {
+ any_proximity = true;
+ }
+ }
+
+ if (!any_proximity) {
+ // printf("proximity disable\n");
+ window->GetTabletData()->Active = GHOST_kTabletModeNone;
+ }
+ }
#endif /* WITH_X11_XINPUT */
- switch (xe->type) {
- case Expose:
- {
- XExposeEvent & xee = xe->xexpose;
-
- if (xee.count == 0) {
- /* Only generate a single expose event
- * per read of the event queue. */
-
- g_event = new
- GHOST_Event(
- getMilliSeconds(),
- GHOST_kEventWindowUpdate,
- window
- );
- }
- break;
- }
-
- case MotionNotify:
- {
- XMotionEvent &xme = xe->xmotion;
+ switch (xe->type) {
+ case Expose: {
+ XExposeEvent &xee = xe->xexpose;
+
+ if (xee.count == 0) {
+ /* Only generate a single expose event
+ * per read of the event queue. */
+
+ g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window);
+ }
+ break;
+ }
+
+ case MotionNotify: {
+ XMotionEvent &xme = xe->xmotion;
#ifdef WITH_X11_XINPUT
- bool is_tablet = window->GetTabletData()->Active != GHOST_kTabletModeNone;
+ bool is_tablet = window->GetTabletData()->Active != GHOST_kTabletModeNone;
#else
- bool is_tablet = false;
+ bool is_tablet = false;
#endif
- if (is_tablet == false && window->getCursorGrabModeIsWarp()) {
- GHOST_TInt32 x_new = xme.x_root;
- GHOST_TInt32 y_new = xme.y_root;
- GHOST_TInt32 x_accum, y_accum;
- GHOST_Rect bounds;
-
- /* fallback to window bounds */
- if (window->getCursorGrabBounds(bounds) == GHOST_kFailure)
- window->getClientBounds(bounds);
-
- /* could also clamp to screen bounds
- * wrap with a window outside the view will fail atm */
- bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */
- window->getCursorGrabAccum(x_accum, y_accum);
-
- if (x_new != xme.x_root || y_new != xme.y_root) {
- if (xme.time > m_last_warp) {
- /* when wrapping we don't need to add an event because the
- * setCursorPosition call will cause a new event after */
- setCursorPosition(x_new, y_new); /* wrap */
- window->setCursorGrabAccum(x_accum + (xme.x_root - x_new), y_accum + (xme.y_root - y_new));
- m_last_warp = lastEventTime(xme.time);
- }
- else {
- setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
- }
- }
- else {
- g_event = new
- GHOST_EventCursor(
- getMilliSeconds(),
- GHOST_kEventCursorMove,
- window,
- xme.x_root + x_accum,
- xme.y_root + y_accum
- );
- }
- }
- else {
- g_event = new
- GHOST_EventCursor(
- getMilliSeconds(),
- GHOST_kEventCursorMove,
- window,
- xme.x_root,
- xme.y_root
- );
- }
- break;
- }
-
- case KeyPress:
- case KeyRelease:
- {
- XKeyEvent *xke = &(xe->xkey);
- KeySym key_sym;
- char ascii;
+ if (is_tablet == false && window->getCursorGrabModeIsWarp()) {
+ GHOST_TInt32 x_new = xme.x_root;
+ GHOST_TInt32 y_new = xme.y_root;
+ GHOST_TInt32 x_accum, y_accum;
+ GHOST_Rect bounds;
+
+ /* fallback to window bounds */
+ if (window->getCursorGrabBounds(bounds) == GHOST_kFailure)
+ window->getClientBounds(bounds);
+
+ /* could also clamp to screen bounds
+ * wrap with a window outside the view will fail atm */
+ bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */
+ window->getCursorGrabAccum(x_accum, y_accum);
+
+ if (x_new != xme.x_root || y_new != xme.y_root) {
+ if (xme.time > m_last_warp) {
+ /* when wrapping we don't need to add an event because the
+ * setCursorPosition call will cause a new event after */
+ setCursorPosition(x_new, y_new); /* wrap */
+ window->setCursorGrabAccum(x_accum + (xme.x_root - x_new),
+ y_accum + (xme.y_root - y_new));
+ m_last_warp = lastEventTime(xme.time);
+ }
+ else {
+ setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
+ }
+ }
+ else {
+ g_event = new GHOST_EventCursor(getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ window,
+ xme.x_root + x_accum,
+ xme.y_root + y_accum);
+ }
+ }
+ else {
+ g_event = new GHOST_EventCursor(
+ getMilliSeconds(), GHOST_kEventCursorMove, window, xme.x_root, xme.y_root);
+ }
+ break;
+ }
+
+ case KeyPress:
+ case KeyRelease: {
+ XKeyEvent *xke = &(xe->xkey);
+ KeySym key_sym;
+ char ascii;
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* utf8_array[] is initial buffer used for Xutf8LookupString().
- * if the length of the utf8 string exceeds this array, allocate
- * another memory area and call Xutf8LookupString() again.
- * the last 5 bytes are used to avoid segfault that might happen
- * at the end of this buffer when the constructor of GHOST_EventKey
- * reads 6 bytes regardless of the effective data length. */
- char utf8_array[16 * 6 + 5]; /* 16 utf8 characters */
- char *utf8_buf = utf8_array;
- int len = 1; /* at least one null character will be stored */
+ /* utf8_array[] is initial buffer used for Xutf8LookupString().
+ * if the length of the utf8 string exceeds this array, allocate
+ * another memory area and call Xutf8LookupString() again.
+ * the last 5 bytes are used to avoid segfault that might happen
+ * at the end of this buffer when the constructor of GHOST_EventKey
+ * reads 6 bytes regardless of the effective data length. */
+ char utf8_array[16 * 6 + 5]; /* 16 utf8 characters */
+ char *utf8_buf = utf8_array;
+ int len = 1; /* at least one null character will be stored */
#else
- char *utf8_buf = NULL;
+ char *utf8_buf = NULL;
#endif
- GHOST_TEventType type = (xke->type == KeyPress) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
+ GHOST_TEventType type = (xke->type == KeyPress) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
- GHOST_TKey gkey;
+ GHOST_TKey gkey;
#ifdef USE_NON_LATIN_KB_WORKAROUND
- /* XXX Code below is kinda awfully convoluted... Issues are:
- *
- * - In keyboards like latin ones, numbers need a 'Shift' to be accessed but key_sym
- * is unmodified (or anyone swapping the keys with xmodmap).
- *
- * - XLookupKeysym seems to always use first defined keymap (see T47228), which generates
- * keycodes unusable by ghost_key_from_keysym for non-latin-compatible keymaps.
- *
- * To address this, we:
- *
- * - Try to get a 'number' key_sym using XLookupKeysym (with virtual shift modifier),
- * in a very restrictive set of cases.
- * - Fallback to XLookupString to get a key_sym from active user-defined keymap.
- *
- * Note that:
- * - This effectively 'lock' main number keys to always output number events (except when using alt-gr).
- * - This enforces users to use an ascii-compatible keymap with Blender - but at least it gives
- * predictable and consistent results.
- *
- * Also, note that nothing in XLib sources [1] makes it obvious why those two functions give different
- * key_sym results...
- *
- * [1] http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/KeyBind.c
- */
- KeySym key_sym_str;
- /* Mode_switch 'modifier' is AltGr - when this one or Shift are enabled, we do not want to apply
- * that 'forced number' hack. */
- const unsigned int mode_switch_mask = XkbKeysymToModifiers(xke->display, XK_Mode_switch);
- const unsigned int number_hack_forbidden_kmods_mask = mode_switch_mask | ShiftMask;
- if ((xke->keycode >= 10 && xke->keycode < 20) && ((xke->state & number_hack_forbidden_kmods_mask) == 0)) {
- key_sym = XLookupKeysym(xke, ShiftMask);
- if (!((key_sym >= XK_0) && (key_sym <= XK_9))) {
- key_sym = XLookupKeysym(xke, 0);
- }
- }
- else {
- key_sym = XLookupKeysym(xke, 0);
- }
-
- if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) {
- ascii = '\0';
- }
-
- /* Only allow a limited set of keys from XLookupKeysym, all others we take from XLookupString,
- * unless it gives unknown key... */
- gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode);
- switch (gkey) {
- case GHOST_kKeyRightAlt:
- case GHOST_kKeyLeftAlt:
- case GHOST_kKeyRightShift:
- case GHOST_kKeyLeftShift:
- case GHOST_kKeyRightControl:
- case GHOST_kKeyLeftControl:
- case GHOST_kKeyOS:
- case GHOST_kKey0:
- case GHOST_kKey1:
- case GHOST_kKey2:
- case GHOST_kKey3:
- case GHOST_kKey4:
- case GHOST_kKey5:
- case GHOST_kKey6:
- case GHOST_kKey7:
- case GHOST_kKey8:
- case GHOST_kKey9:
- case GHOST_kKeyNumpad0:
- case GHOST_kKeyNumpad1:
- case GHOST_kKeyNumpad2:
- case GHOST_kKeyNumpad3:
- case GHOST_kKeyNumpad4:
- case GHOST_kKeyNumpad5:
- case GHOST_kKeyNumpad6:
- case GHOST_kKeyNumpad7:
- case GHOST_kKeyNumpad8:
- case GHOST_kKeyNumpad9:
- case GHOST_kKeyNumpadPeriod:
- case GHOST_kKeyNumpadEnter:
- case GHOST_kKeyNumpadPlus:
- case GHOST_kKeyNumpadMinus:
- case GHOST_kKeyNumpadAsterisk:
- case GHOST_kKeyNumpadSlash:
- break;
- default:
- {
- GHOST_TKey gkey_str = ghost_key_from_keysym(key_sym_str);
- if (gkey_str != GHOST_kKeyUnknown) {
- gkey = gkey_str;
- }
- }
- }
+ /* XXX Code below is kinda awfully convoluted... Issues are:
+ *
+ * - In keyboards like latin ones, numbers need a 'Shift' to be accessed but key_sym
+ * is unmodified (or anyone swapping the keys with xmodmap).
+ *
+ * - XLookupKeysym seems to always use first defined keymap (see T47228), which generates
+ * keycodes unusable by ghost_key_from_keysym for non-latin-compatible keymaps.
+ *
+ * To address this, we:
+ *
+ * - Try to get a 'number' key_sym using XLookupKeysym (with virtual shift modifier),
+ * in a very restrictive set of cases.
+ * - Fallback to XLookupString to get a key_sym from active user-defined keymap.
+ *
+ * Note that:
+ * - This effectively 'lock' main number keys to always output number events (except when using alt-gr).
+ * - This enforces users to use an ascii-compatible keymap with Blender - but at least it gives
+ * predictable and consistent results.
+ *
+ * Also, note that nothing in XLib sources [1] makes it obvious why those two functions give different
+ * key_sym results...
+ *
+ * [1] http://cgit.freedesktop.org/xorg/lib/libX11/tree/src/KeyBind.c
+ */
+ KeySym key_sym_str;
+ /* Mode_switch 'modifier' is AltGr - when this one or Shift are enabled, we do not want to apply
+ * that 'forced number' hack. */
+ const unsigned int mode_switch_mask = XkbKeysymToModifiers(xke->display, XK_Mode_switch);
+ const unsigned int number_hack_forbidden_kmods_mask = mode_switch_mask | ShiftMask;
+ if ((xke->keycode >= 10 && xke->keycode < 20) &&
+ ((xke->state & number_hack_forbidden_kmods_mask) == 0)) {
+ key_sym = XLookupKeysym(xke, ShiftMask);
+ if (!((key_sym >= XK_0) && (key_sym <= XK_9))) {
+ key_sym = XLookupKeysym(xke, 0);
+ }
+ }
+ else {
+ key_sym = XLookupKeysym(xke, 0);
+ }
+
+ if (!XLookupString(xke, &ascii, 1, &key_sym_str, NULL)) {
+ ascii = '\0';
+ }
+
+ /* Only allow a limited set of keys from XLookupKeysym, all others we take from XLookupString,
+ * unless it gives unknown key... */
+ gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode);
+ switch (gkey) {
+ case GHOST_kKeyRightAlt:
+ case GHOST_kKeyLeftAlt:
+ case GHOST_kKeyRightShift:
+ case GHOST_kKeyLeftShift:
+ case GHOST_kKeyRightControl:
+ case GHOST_kKeyLeftControl:
+ case GHOST_kKeyOS:
+ case GHOST_kKey0:
+ case GHOST_kKey1:
+ case GHOST_kKey2:
+ case GHOST_kKey3:
+ case GHOST_kKey4:
+ case GHOST_kKey5:
+ case GHOST_kKey6:
+ case GHOST_kKey7:
+ case GHOST_kKey8:
+ case GHOST_kKey9:
+ case GHOST_kKeyNumpad0:
+ case GHOST_kKeyNumpad1:
+ case GHOST_kKeyNumpad2:
+ case GHOST_kKeyNumpad3:
+ case GHOST_kKeyNumpad4:
+ case GHOST_kKeyNumpad5:
+ case GHOST_kKeyNumpad6:
+ case GHOST_kKeyNumpad7:
+ case GHOST_kKeyNumpad8:
+ case GHOST_kKeyNumpad9:
+ case GHOST_kKeyNumpadPeriod:
+ case GHOST_kKeyNumpadEnter:
+ case GHOST_kKeyNumpadPlus:
+ case GHOST_kKeyNumpadMinus:
+ case GHOST_kKeyNumpadAsterisk:
+ case GHOST_kKeyNumpadSlash:
+ break;
+ default: {
+ GHOST_TKey gkey_str = ghost_key_from_keysym(key_sym_str);
+ if (gkey_str != GHOST_kKeyUnknown) {
+ gkey = gkey_str;
+ }
+ }
+ }
#else
- /* In keyboards like latin ones,
- * numbers needs a 'Shift' to be accessed but key_sym
- * is unmodified (or anyone swapping the keys with xmodmap).
- *
- * Here we look at the 'Shifted' version of the key.
- * If it is a number, then we take it instead of the normal key.
- *
- * The modified key is sent in the 'ascii's variable anyway.
- */
- if ((xke->keycode >= 10 && xke->keycode < 20) &&
- ((key_sym = XLookupKeysym(xke, ShiftMask)) >= XK_0) && (key_sym <= XK_9))
- {
- /* pass (keep shift'ed key_sym) */
- }
- else {
- /* regular case */
- key_sym = XLookupKeysym(xke, 0);
- }
-
- gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode);
-
- if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
- ascii = '\0';
- }
+ /* In keyboards like latin ones,
+ * numbers needs a 'Shift' to be accessed but key_sym
+ * is unmodified (or anyone swapping the keys with xmodmap).
+ *
+ * Here we look at the 'Shifted' version of the key.
+ * If it is a number, then we take it instead of the normal key.
+ *
+ * The modified key is sent in the 'ascii's variable anyway.
+ */
+ if ((xke->keycode >= 10 && xke->keycode < 20) &&
+ ((key_sym = XLookupKeysym(xke, ShiftMask)) >= XK_0) && (key_sym <= XK_9)) {
+ /* pass (keep shift'ed key_sym) */
+ }
+ else {
+ /* regular case */
+ key_sym = XLookupKeysym(xke, 0);
+ }
+
+ gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode);
+
+ if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
+ ascii = '\0';
+ }
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* getting unicode on key-up events gives XLookupNone status */
- XIC xic = window->getX11_XIC();
- if (xic && xke->type == KeyPress) {
- Status status;
-
- /* use utf8 because its not locale depentant, from xorg docs */
- if (!(len = Xutf8LookupString(xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) {
- utf8_buf[0] = '\0';
- }
-
- if (status == XBufferOverflow) {
- utf8_buf = (char *) malloc(len + 5);
- len = Xutf8LookupString(xic, xke, utf8_buf, len, &key_sym, &status);
- }
-
- if ((status == XLookupChars || status == XLookupBoth)) {
- if ((unsigned char)utf8_buf[0] >= 32) { /* not an ascii control character */
- /* do nothing for now, this is valid utf8 */
- }
- else {
- utf8_buf[0] = '\0';
- }
- }
- else if (status == XLookupKeySym) {
- /* this key doesn't have a text representation, it is a command
- * key of some sort */
- }
- else {
- printf("Bad keycode lookup. Keysym 0x%x Status: %s\n",
- (unsigned int) key_sym,
- (status == XLookupNone ? "XLookupNone" :
- status == XLookupKeySym ? "XLookupKeySym" :
- "Unknown status"));
-
- printf("'%.*s' %p %p\n", len, utf8_buf, xic, m_xim);
- }
- }
- else {
- utf8_buf[0] = '\0';
- }
+ /* getting unicode on key-up events gives XLookupNone status */
+ XIC xic = window->getX11_XIC();
+ if (xic && xke->type == KeyPress) {
+ Status status;
+
+ /* use utf8 because its not locale depentant, from xorg docs */
+ if (!(len = Xutf8LookupString(
+ xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) {
+ utf8_buf[0] = '\0';
+ }
+
+ if (status == XBufferOverflow) {
+ utf8_buf = (char *)malloc(len + 5);
+ len = Xutf8LookupString(xic, xke, utf8_buf, len, &key_sym, &status);
+ }
+
+ if ((status == XLookupChars || status == XLookupBoth)) {
+ if ((unsigned char)utf8_buf[0] >= 32) { /* not an ascii control character */
+ /* do nothing for now, this is valid utf8 */
+ }
+ else {
+ utf8_buf[0] = '\0';
+ }
+ }
+ else if (status == XLookupKeySym) {
+ /* this key doesn't have a text representation, it is a command
+ * key of some sort */
+ }
+ else {
+ printf("Bad keycode lookup. Keysym 0x%x Status: %s\n",
+ (unsigned int)key_sym,
+ (status == XLookupNone ?
+ "XLookupNone" :
+ status == XLookupKeySym ? "XLookupKeySym" : "Unknown status"));
+
+ printf("'%.*s' %p %p\n", len, utf8_buf, xic, m_xim);
+ }
+ }
+ else {
+ utf8_buf[0] = '\0';
+ }
#endif
- g_event = new
- GHOST_EventKey(
- getMilliSeconds(),
- type,
- window,
- gkey,
- ascii,
- utf8_buf
- );
+ g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, ascii, utf8_buf);
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* when using IM for some languages such as Japanese,
- * one event inserts multiple utf8 characters */
- if (xic && xke->type == KeyPress) {
- unsigned char c;
- int i = 0;
- while (1) {
- /* search character boundary */
- if ((unsigned char)utf8_buf[i++] > 0x7f) {
- for (; i < len; ++i) {
- c = utf8_buf[i];
- if (c < 0x80 || c > 0xbf) break;
- }
- }
-
- if (i >= len) break;
-
- /* enqueue previous character */
- pushEvent(g_event);
-
- g_event = new
- GHOST_EventKey(
- getMilliSeconds(),
- type,
- window,
- gkey,
- '\0',
- &utf8_buf[i]
- );
- }
- }
-
- if (utf8_buf != utf8_array)
- free(utf8_buf);
+ /* when using IM for some languages such as Japanese,
+ * one event inserts multiple utf8 characters */
+ if (xic && xke->type == KeyPress) {
+ unsigned char c;
+ int i = 0;
+ while (1) {
+ /* search character boundary */
+ if ((unsigned char)utf8_buf[i++] > 0x7f) {
+ for (; i < len; ++i) {
+ c = utf8_buf[i];
+ if (c < 0x80 || c > 0xbf)
+ break;
+ }
+ }
+
+ if (i >= len)
+ break;
+
+ /* enqueue previous character */
+ pushEvent(g_event);
+
+ g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, '\0', &utf8_buf[i]);
+ }
+ }
+
+ if (utf8_buf != utf8_array)
+ free(utf8_buf);
#endif
- break;
- }
-
- case ButtonPress:
- case ButtonRelease:
- {
- XButtonEvent & xbe = xe->xbutton;
- GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
- GHOST_TEventType type = (xbe.type == ButtonPress) ?
- GHOST_kEventButtonDown : GHOST_kEventButtonUp;
-
- /* process wheel mouse events and break, only pass on press events */
- if (xbe.button == Button4) {
- if (xbe.type == ButtonPress)
- g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1);
- break;
- }
- else if (xbe.button == Button5) {
- if (xbe.type == ButtonPress)
- g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1);
- break;
- }
-
- /* process rest of normal mouse buttons */
- if (xbe.button == Button1)
- gbmask = GHOST_kButtonMaskLeft;
- else if (xbe.button == Button2)
- gbmask = GHOST_kButtonMaskMiddle;
- else if (xbe.button == Button3)
- gbmask = GHOST_kButtonMaskRight;
- /* It seems events 6 and 7 are for horizontal scrolling.
- * you can re-order button mapping like this... (swaps 6,7 with 8,9)
- * xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"
- */
- else if (xbe.button == 6)
- gbmask = GHOST_kButtonMaskButton6;
- else if (xbe.button == 7)
- gbmask = GHOST_kButtonMaskButton7;
- else if (xbe.button == 8)
- gbmask = GHOST_kButtonMaskButton4;
- else if (xbe.button == 9)
- gbmask = GHOST_kButtonMaskButton5;
- else
- break;
-
- g_event = new
- GHOST_EventButton(
- getMilliSeconds(),
- type,
- window,
- gbmask
- );
- break;
- }
-
- /* change of size, border, layer etc. */
- case ConfigureNotify:
- {
- /* XConfigureEvent & xce = xe->xconfigure; */
-
- g_event = new
- GHOST_Event(
- getMilliSeconds(),
- GHOST_kEventWindowSize,
- window
- );
- break;
- }
-
- case FocusIn:
- case FocusOut:
- {
- XFocusChangeEvent &xfe = xe->xfocus;
-
- /* TODO: make sure this is the correct place for activate/deactivate */
- // printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window);
-
- /* May have to look at the type of event and filter some out. */
-
- GHOST_TEventType gtype = (xfe.type == FocusIn) ?
- GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
+ break;
+ }
+
+ case ButtonPress:
+ case ButtonRelease: {
+ XButtonEvent &xbe = xe->xbutton;
+ GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
+ GHOST_TEventType type = (xbe.type == ButtonPress) ? GHOST_kEventButtonDown :
+ GHOST_kEventButtonUp;
+
+ /* process wheel mouse events and break, only pass on press events */
+ if (xbe.button == Button4) {
+ if (xbe.type == ButtonPress)
+ g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1);
+ break;
+ }
+ else if (xbe.button == Button5) {
+ if (xbe.type == ButtonPress)
+ g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1);
+ break;
+ }
+
+ /* process rest of normal mouse buttons */
+ if (xbe.button == Button1)
+ gbmask = GHOST_kButtonMaskLeft;
+ else if (xbe.button == Button2)
+ gbmask = GHOST_kButtonMaskMiddle;
+ else if (xbe.button == Button3)
+ gbmask = GHOST_kButtonMaskRight;
+ /* It seems events 6 and 7 are for horizontal scrolling.
+ * you can re-order button mapping like this... (swaps 6,7 with 8,9)
+ * xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"
+ */
+ else if (xbe.button == 6)
+ gbmask = GHOST_kButtonMaskButton6;
+ else if (xbe.button == 7)
+ gbmask = GHOST_kButtonMaskButton7;
+ else if (xbe.button == 8)
+ gbmask = GHOST_kButtonMaskButton4;
+ else if (xbe.button == 9)
+ gbmask = GHOST_kButtonMaskButton5;
+ else
+ break;
+
+ g_event = new GHOST_EventButton(getMilliSeconds(), type, window, gbmask);
+ break;
+ }
+
+ /* change of size, border, layer etc. */
+ case ConfigureNotify: {
+ /* XConfigureEvent & xce = xe->xconfigure; */
+
+ g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window);
+ break;
+ }
+
+ case FocusIn:
+ case FocusOut: {
+ XFocusChangeEvent &xfe = xe->xfocus;
+
+ /* TODO: make sure this is the correct place for activate/deactivate */
+ // printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window);
+
+ /* May have to look at the type of event and filter some out. */
+
+ GHOST_TEventType gtype = (xfe.type == FocusIn) ? GHOST_kEventWindowActivate :
+ GHOST_kEventWindowDeactivate;
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- XIC xic = window->getX11_XIC();
- if (xic) {
- if (xe->type == FocusIn)
- XSetICFocus(xic);
- else
- XUnsetICFocus(xic);
- }
+ XIC xic = window->getX11_XIC();
+ if (xic) {
+ if (xe->type == FocusIn)
+ XSetICFocus(xic);
+ else
+ XUnsetICFocus(xic);
+ }
#endif
- g_event = new
- GHOST_Event(
- getMilliSeconds(),
- gtype,
- window
- );
- break;
-
- }
- case ClientMessage:
- {
- XClientMessageEvent & xcme = xe->xclient;
-
- if (((Atom)xcme.data.l[0]) == m_atom.WM_DELETE_WINDOW) {
- g_event = new
- GHOST_Event(
- getMilliSeconds(),
- GHOST_kEventWindowClose,
- window
- );
- }
- else if (((Atom)xcme.data.l[0]) == m_atom.WM_TAKE_FOCUS) {
- XWindowAttributes attr;
- Window fwin;
- int revert_to;
-
- /* as ICCCM say, we need reply this event
- * with a SetInputFocus, the data[1] have
- * the valid timestamp (send by the wm).
- *
- * Some WM send this event before the
- * window is really mapped (for example
- * change from virtual desktop), so we need
- * to be sure that our windows is mapped
- * or this call fail and close blender.
- */
- if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
- if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
- if (attr.map_state == IsViewable) {
- if (fwin != xcme.window)
- XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
- }
- }
- }
- }
- else {
+ g_event = new GHOST_Event(getMilliSeconds(), gtype, window);
+ break;
+ }
+ case ClientMessage: {
+ XClientMessageEvent &xcme = xe->xclient;
+
+ if (((Atom)xcme.data.l[0]) == m_atom.WM_DELETE_WINDOW) {
+ g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
+ }
+ else if (((Atom)xcme.data.l[0]) == m_atom.WM_TAKE_FOCUS) {
+ XWindowAttributes attr;
+ Window fwin;
+ int revert_to;
+
+ /* as ICCCM say, we need reply this event
+ * with a SetInputFocus, the data[1] have
+ * the valid timestamp (send by the wm).
+ *
+ * Some WM send this event before the
+ * window is really mapped (for example
+ * change from virtual desktop), so we need
+ * to be sure that our windows is mapped
+ * or this call fail and close blender.
+ */
+ if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
+ if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
+ if (attr.map_state == IsViewable) {
+ if (fwin != xcme.window)
+ XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
+ }
+ }
+ }
+ }
+ else {
#ifdef WITH_XDND
- /* try to handle drag event (if there's no such events, GHOST_HandleClientMessage will return zero) */
- if (window->getDropTarget()->GHOST_HandleClientMessage(xe) == false) {
- /* Unknown client message, ignore */
- }
+ /* try to handle drag event (if there's no such events, GHOST_HandleClientMessage will return zero) */
+ if (window->getDropTarget()->GHOST_HandleClientMessage(xe) == false) {
+ /* Unknown client message, ignore */
+ }
#else
- /* Unknown client message, ignore */
+ /* Unknown client message, ignore */
#endif
- }
-
- break;
- }
-
- case DestroyNotify:
- ::exit(-1);
- /* We're not interested in the following things.(yet...) */
- case NoExpose:
- case GraphicsExpose:
- break;
-
- case EnterNotify:
- case LeaveNotify:
- {
- /* XCrossingEvents pointer leave enter window.
- * also do cursor move here, MotionNotify only
- * happens when motion starts & ends inside window.
- * we only do moves when the crossing mode is 'normal'
- * (really crossing between windows) since some windowmanagers
- * also send grab/ungrab crossings for mousewheel events.
- */
- XCrossingEvent &xce = xe->xcrossing;
- if (xce.mode == NotifyNormal) {
- g_event = new
- GHOST_EventCursor(
- getMilliSeconds(),
- GHOST_kEventCursorMove,
- window,
- xce.x_root,
- xce.y_root
- );
- }
-
- // printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window);
-
- if (xce.type == EnterNotify)
- m_windowManager->setActiveWindow(window);
- else
- m_windowManager->setWindowInactive(window);
-
- break;
- }
- case MapNotify:
- /*
- * From ICCCM:
- * [ Clients can select for StructureNotify on their
- * top-level windows to track transition between
- * Normal and Iconic states. Receipt of a MapNotify
- * event will indicate a transition to the Normal
- * state, and receipt of an UnmapNotify event will
- * indicate a transition to the Iconic state. ]
- */
- if (window->m_post_init == True) {
- /*
- * Now we are sure that the window is
- * mapped, so only need change the state.
- */
- window->setState(window->m_post_state);
- window->m_post_init = False;
- }
- break;
- case UnmapNotify:
- break;
- case MappingNotify:
- case ReparentNotify:
- break;
- case SelectionRequest:
- {
- XEvent nxe;
- Atom target, utf8_string, string, compound_text, c_string;
- XSelectionRequestEvent *xse = &xe->xselectionrequest;
-
- target = XInternAtom(m_display, "TARGETS", False);
- utf8_string = XInternAtom(m_display, "UTF8_STRING", False);
- string = XInternAtom(m_display, "STRING", False);
- compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
- c_string = XInternAtom(m_display, "C_STRING", False);
-
- /* support obsolete clients */
- if (xse->property == None) {
- xse->property = xse->target;
- }
-
- nxe.xselection.type = SelectionNotify;
- nxe.xselection.requestor = xse->requestor;
- nxe.xselection.property = xse->property;
- nxe.xselection.display = xse->display;
- nxe.xselection.selection = xse->selection;
- nxe.xselection.target = xse->target;
- nxe.xselection.time = xse->time;
-
- /* Check to see if the requestor is asking for String */
- if (xse->target == utf8_string ||
- xse->target == string ||
- xse->target == compound_text ||
- xse->target == c_string)
- {
- if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
- XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace,
- (unsigned char *)txt_select_buffer, strlen(txt_select_buffer));
- }
- else if (xse->selection == XInternAtom(m_display, "CLIPBOARD", False)) {
- XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace,
- (unsigned char *)txt_cut_buffer, strlen(txt_cut_buffer));
- }
- }
- else if (xse->target == target) {
- Atom alist[5];
- alist[0] = target;
- alist[1] = utf8_string;
- alist[2] = string;
- alist[3] = compound_text;
- alist[4] = c_string;
- XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 32, PropModeReplace,
- (unsigned char *)alist, 5);
- XFlush(m_display);
- }
- else {
- /* Change property to None because we do not support anything but STRING */
- nxe.xselection.property = None;
- }
-
- /* Send the event to the client 0 0 == False, SelectionNotify */
- XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
- XFlush(m_display);
- break;
- }
-
- default:
- {
+ }
+
+ break;
+ }
+
+ case DestroyNotify:
+ ::exit(-1);
+ /* We're not interested in the following things.(yet...) */
+ case NoExpose:
+ case GraphicsExpose:
+ break;
+
+ case EnterNotify:
+ case LeaveNotify: {
+ /* XCrossingEvents pointer leave enter window.
+ * also do cursor move here, MotionNotify only
+ * happens when motion starts & ends inside window.
+ * we only do moves when the crossing mode is 'normal'
+ * (really crossing between windows) since some windowmanagers
+ * also send grab/ungrab crossings for mousewheel events.
+ */
+ XCrossingEvent &xce = xe->xcrossing;
+ if (xce.mode == NotifyNormal) {
+ g_event = new GHOST_EventCursor(
+ getMilliSeconds(), GHOST_kEventCursorMove, window, xce.x_root, xce.y_root);
+ }
+
+ // printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window);
+
+ if (xce.type == EnterNotify)
+ m_windowManager->setActiveWindow(window);
+ else
+ m_windowManager->setWindowInactive(window);
+
+ break;
+ }
+ case MapNotify:
+ /*
+ * From ICCCM:
+ * [ Clients can select for StructureNotify on their
+ * top-level windows to track transition between
+ * Normal and Iconic states. Receipt of a MapNotify
+ * event will indicate a transition to the Normal
+ * state, and receipt of an UnmapNotify event will
+ * indicate a transition to the Iconic state. ]
+ */
+ if (window->m_post_init == True) {
+ /*
+ * Now we are sure that the window is
+ * mapped, so only need change the state.
+ */
+ window->setState(window->m_post_state);
+ window->m_post_init = False;
+ }
+ break;
+ case UnmapNotify:
+ break;
+ case MappingNotify:
+ case ReparentNotify:
+ break;
+ case SelectionRequest: {
+ XEvent nxe;
+ Atom target, utf8_string, string, compound_text, c_string;
+ XSelectionRequestEvent *xse = &xe->xselectionrequest;
+
+ target = XInternAtom(m_display, "TARGETS", False);
+ utf8_string = XInternAtom(m_display, "UTF8_STRING", False);
+ string = XInternAtom(m_display, "STRING", False);
+ compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
+ c_string = XInternAtom(m_display, "C_STRING", False);
+
+ /* support obsolete clients */
+ if (xse->property == None) {
+ xse->property = xse->target;
+ }
+
+ nxe.xselection.type = SelectionNotify;
+ nxe.xselection.requestor = xse->requestor;
+ nxe.xselection.property = xse->property;
+ nxe.xselection.display = xse->display;
+ nxe.xselection.selection = xse->selection;
+ nxe.xselection.target = xse->target;
+ nxe.xselection.time = xse->time;
+
+ /* Check to see if the requestor is asking for String */
+ if (xse->target == utf8_string || xse->target == string || xse->target == compound_text ||
+ xse->target == c_string) {
+ if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
+ XChangeProperty(m_display,
+ xse->requestor,
+ xse->property,
+ xse->target,
+ 8,
+ PropModeReplace,
+ (unsigned char *)txt_select_buffer,
+ strlen(txt_select_buffer));
+ }
+ else if (xse->selection == XInternAtom(m_display, "CLIPBOARD", False)) {
+ XChangeProperty(m_display,
+ xse->requestor,
+ xse->property,
+ xse->target,
+ 8,
+ PropModeReplace,
+ (unsigned char *)txt_cut_buffer,
+ strlen(txt_cut_buffer));
+ }
+ }
+ else if (xse->target == target) {
+ Atom alist[5];
+ alist[0] = target;
+ alist[1] = utf8_string;
+ alist[2] = string;
+ alist[3] = compound_text;
+ alist[4] = c_string;
+ XChangeProperty(m_display,
+ xse->requestor,
+ xse->property,
+ xse->target,
+ 32,
+ PropModeReplace,
+ (unsigned char *)alist,
+ 5);
+ XFlush(m_display);
+ }
+ else {
+ /* Change property to None because we do not support anything but STRING */
+ nxe.xselection.property = None;
+ }
+
+ /* Send the event to the client 0 0 == False, SelectionNotify */
+ XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
+ XFlush(m_display);
+ break;
+ }
+
+ default: {
#ifdef WITH_X11_XINPUT
- for (GHOST_TabletX11& xtablet: m_xtablets) {
- if (xe->type == xtablet.MotionEvent || xe->type == xtablet.PressEvent) {
- XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
- if (data->deviceid != xtablet.ID) {
- continue;
- }
-
- const unsigned char axis_first = data->first_axis;
- const unsigned char axes_end = axis_first + data->axes_count; /* after the last */
- int axis_value;
-
- /* stroke might begin without leading ProxyIn event,
- * this happens when window is opened when stylus is already hovering
- * around tablet surface */
- window->GetTabletData()->Active = xtablet.mode;
-
- /* Note: This event might be generated with incomplete dataset (don't exactly know why, looks like in
- * some cases, if the value does not change, it is not included in subsequent XDeviceMotionEvent
- * events). So we have to check which values this event actually contains!
- */
-
-#define AXIS_VALUE_GET(axis, val) \
- ((axis_first <= axis && axes_end > axis) && ((void)(val = data->axis_data[axis - axis_first]), true))
-
- if (AXIS_VALUE_GET(2, axis_value)) {
- window->GetTabletData()->Pressure = axis_value / ((float)xtablet.PressureLevels);
- }
-
- /* the (short) cast and the & 0xffff is bizarre and unexplained anywhere,
- * but I got garbage data without it. Found it in the xidump.c source --matt
- *
- * The '& 0xffff' just truncates the value to its two lowest bytes, this probably means
- * some drivers do not properly set the whole int value? Since we convert to float afterward,
- * I don't think we need to cast to short here, but do not have a device to check this. --mont29
- */
- if (AXIS_VALUE_GET(3, axis_value)) {
- window->GetTabletData()->Xtilt = (short)(axis_value & 0xffff) /
- ((float)xtablet.XtiltLevels);
- }
- if (AXIS_VALUE_GET(4, axis_value)) {
- window->GetTabletData()->Ytilt = (short)(axis_value & 0xffff) /
- ((float)xtablet.YtiltLevels);
- }
-
-#undef AXIS_VALUE_GET
-
- }
- else if (xe->type == xtablet.ProxInEvent) {
- XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe;
- if (data->deviceid != xtablet.ID) {
- continue;
- }
-
- window->GetTabletData()->Active = xtablet.mode;
- }
- else if (xe->type == xtablet.ProxOutEvent) {
- window->GetTabletData()->Active = GHOST_kTabletModeNone;
- }
- }
-#endif // WITH_X11_XINPUT
- break;
- }
- }
-
- if (g_event) {
- pushEvent(g_event);
- }
+ for (GHOST_TabletX11 &xtablet : m_xtablets) {
+ if (xe->type == xtablet.MotionEvent || xe->type == xtablet.PressEvent) {
+ XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
+ if (data->deviceid != xtablet.ID) {
+ continue;
+ }
+
+ const unsigned char axis_first = data->first_axis;
+ const unsigned char axes_end = axis_first + data->axes_count; /* after the last */
+ int axis_value;
+
+ /* stroke might begin without leading ProxyIn event,
+ * this happens when window is opened when stylus is already hovering
+ * around tablet surface */
+ window->GetTabletData()->Active = xtablet.mode;
+
+ /* Note: This event might be generated with incomplete dataset (don't exactly know why, looks like in
+ * some cases, if the value does not change, it is not included in subsequent XDeviceMotionEvent
+ * events). So we have to check which values this event actually contains!
+ */
+
+# define AXIS_VALUE_GET(axis, val) \
+ ((axis_first <= axis && axes_end > axis) && \
+ ((void)(val = data->axis_data[axis - axis_first]), true))
+
+ if (AXIS_VALUE_GET(2, axis_value)) {
+ window->GetTabletData()->Pressure = axis_value / ((float)xtablet.PressureLevels);
+ }
+
+ /* the (short) cast and the & 0xffff is bizarre and unexplained anywhere,
+ * but I got garbage data without it. Found it in the xidump.c source --matt
+ *
+ * The '& 0xffff' just truncates the value to its two lowest bytes, this probably means
+ * some drivers do not properly set the whole int value? Since we convert to float afterward,
+ * I don't think we need to cast to short here, but do not have a device to check this. --mont29
+ */
+ if (AXIS_VALUE_GET(3, axis_value)) {
+ window->GetTabletData()->Xtilt = (short)(axis_value & 0xffff) /
+ ((float)xtablet.XtiltLevels);
+ }
+ if (AXIS_VALUE_GET(4, axis_value)) {
+ window->GetTabletData()->Ytilt = (short)(axis_value & 0xffff) /
+ ((float)xtablet.YtiltLevels);
+ }
+
+# undef AXIS_VALUE_GET
+ }
+ else if (xe->type == xtablet.ProxInEvent) {
+ XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe;
+ if (data->deviceid != xtablet.ID) {
+ continue;
+ }
+
+ window->GetTabletData()->Active = xtablet.mode;
+ }
+ else if (xe->type == xtablet.ProxOutEvent) {
+ window->GetTabletData()->Active = GHOST_kTabletModeNone;
+ }
+ }
+#endif // WITH_X11_XINPUT
+ break;
+ }
+ }
+
+ if (g_event) {
+ pushEvent(g_event);
+ }
}
-GHOST_TSuccess
-GHOST_SystemX11::
-getModifierKeys(
- GHOST_ModifierKeys& keys) const
+GHOST_TSuccess GHOST_SystemX11::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- /* analyse the masks retuned from XQueryPointer. */
-
- memset((void *)m_keyboard_vector, 0, sizeof(m_keyboard_vector));
-
- XQueryKeymap(m_display, (char *)m_keyboard_vector);
-
- /* now translate key symbols into keycodes and
- * test with vector. */
-
- const static KeyCode shift_l = XKeysymToKeycode(m_display, XK_Shift_L);
- const static KeyCode shift_r = XKeysymToKeycode(m_display, XK_Shift_R);
- const static KeyCode control_l = XKeysymToKeycode(m_display, XK_Control_L);
- const static KeyCode control_r = XKeysymToKeycode(m_display, XK_Control_R);
- const static KeyCode alt_l = XKeysymToKeycode(m_display, XK_Alt_L);
- const static KeyCode alt_r = XKeysymToKeycode(m_display, XK_Alt_R);
- const static KeyCode super_l = XKeysymToKeycode(m_display, XK_Super_L);
- const static KeyCode super_r = XKeysymToKeycode(m_display, XK_Super_R);
-
- /* shift */
- keys.set(GHOST_kModifierKeyLeftShift, ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) != 0);
- keys.set(GHOST_kModifierKeyRightShift, ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) != 0);
- /* control */
- keys.set(GHOST_kModifierKeyLeftControl, ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) != 0);
- keys.set(GHOST_kModifierKeyRightControl, ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) != 0);
- /* alt */
- keys.set(GHOST_kModifierKeyLeftAlt, ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) != 0);
- keys.set(GHOST_kModifierKeyRightAlt, ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) != 0);
- /* super (windows) - only one GHOST-kModifierKeyOS, so mapping to either */
- keys.set(GHOST_kModifierKeyOS, ( ((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) ||
- ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1) ) != 0);
-
- return GHOST_kSuccess;
+ /* analyse the masks retuned from XQueryPointer. */
+
+ memset((void *)m_keyboard_vector, 0, sizeof(m_keyboard_vector));
+
+ XQueryKeymap(m_display, (char *)m_keyboard_vector);
+
+ /* now translate key symbols into keycodes and
+ * test with vector. */
+
+ const static KeyCode shift_l = XKeysymToKeycode(m_display, XK_Shift_L);
+ const static KeyCode shift_r = XKeysymToKeycode(m_display, XK_Shift_R);
+ const static KeyCode control_l = XKeysymToKeycode(m_display, XK_Control_L);
+ const static KeyCode control_r = XKeysymToKeycode(m_display, XK_Control_R);
+ const static KeyCode alt_l = XKeysymToKeycode(m_display, XK_Alt_L);
+ const static KeyCode alt_r = XKeysymToKeycode(m_display, XK_Alt_R);
+ const static KeyCode super_l = XKeysymToKeycode(m_display, XK_Super_L);
+ const static KeyCode super_r = XKeysymToKeycode(m_display, XK_Super_R);
+
+ /* shift */
+ keys.set(GHOST_kModifierKeyLeftShift,
+ ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) != 0);
+ keys.set(GHOST_kModifierKeyRightShift,
+ ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) != 0);
+ /* control */
+ keys.set(GHOST_kModifierKeyLeftControl,
+ ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) != 0);
+ keys.set(GHOST_kModifierKeyRightControl,
+ ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) != 0);
+ /* alt */
+ keys.set(GHOST_kModifierKeyLeftAlt, ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) != 0);
+ keys.set(GHOST_kModifierKeyRightAlt, ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) != 0);
+ /* super (windows) - only one GHOST-kModifierKeyOS, so mapping to either */
+ keys.set(GHOST_kModifierKeyOS,
+ (((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) ||
+ ((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1)) != 0);
+
+ return GHOST_kSuccess;
}
-GHOST_TSuccess
-GHOST_SystemX11::
-getButtons(
- GHOST_Buttons& buttons) const
+GHOST_TSuccess GHOST_SystemX11::getButtons(GHOST_Buttons &buttons) const
{
- Window root_return, child_return;
- int rx, ry, wx, wy;
- unsigned int mask_return;
-
- if (XQueryPointer(m_display,
- RootWindow(m_display, DefaultScreen(m_display)),
- &root_return,
- &child_return,
- &rx, &ry,
- &wx, &wy,
- &mask_return) == True)
- {
- buttons.set(GHOST_kButtonMaskLeft, (mask_return & Button1Mask) != 0);
- buttons.set(GHOST_kButtonMaskMiddle, (mask_return & Button2Mask) != 0);
- buttons.set(GHOST_kButtonMaskRight, (mask_return & Button3Mask) != 0);
- }
- else {
- return GHOST_kFailure;
- }
-
- return GHOST_kSuccess;
+ Window root_return, child_return;
+ int rx, ry, wx, wy;
+ unsigned int mask_return;
+
+ if (XQueryPointer(m_display,
+ RootWindow(m_display, DefaultScreen(m_display)),
+ &root_return,
+ &child_return,
+ &rx,
+ &ry,
+ &wx,
+ &wy,
+ &mask_return) == True) {
+ buttons.set(GHOST_kButtonMaskLeft, (mask_return & Button1Mask) != 0);
+ buttons.set(GHOST_kButtonMaskMiddle, (mask_return & Button2Mask) != 0);
+ buttons.set(GHOST_kButtonMaskRight, (mask_return & Button3Mask) != 0);
+ }
+ else {
+ return GHOST_kFailure;
+ }
+
+ return GHOST_kSuccess;
}
-static GHOST_TSuccess getCursorPosition_impl(
- Display *display,
- GHOST_TInt32& x,
- GHOST_TInt32& y,
- Window *child_return)
+static GHOST_TSuccess getCursorPosition_impl(Display *display,
+ GHOST_TInt32 &x,
+ GHOST_TInt32 &y,
+ Window *child_return)
{
- int rx, ry, wx, wy;
- unsigned int mask_return;
- Window root_return;
-
- if (XQueryPointer(
- display,
- RootWindow(display, DefaultScreen(display)),
- &root_return,
- child_return,
- &rx, &ry,
- &wx, &wy,
- &mask_return
- ) == False) {
- return GHOST_kFailure;
- }
- else {
- x = rx;
- y = ry;
- }
- return GHOST_kSuccess;
+ int rx, ry, wx, wy;
+ unsigned int mask_return;
+ Window root_return;
+
+ if (XQueryPointer(display,
+ RootWindow(display, DefaultScreen(display)),
+ &root_return,
+ child_return,
+ &rx,
+ &ry,
+ &wx,
+ &wy,
+ &mask_return) == False) {
+ return GHOST_kFailure;
+ }
+ else {
+ x = rx;
+ y = ry;
+ }
+ return GHOST_kSuccess;
}
-GHOST_TSuccess
-GHOST_SystemX11::
-getCursorPosition(
- GHOST_TInt32& x,
- GHOST_TInt32& y) const
+GHOST_TSuccess GHOST_SystemX11::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
{
- Window child_return;
- return getCursorPosition_impl(m_display, x, y, &child_return);
+ Window child_return;
+ return getCursorPosition_impl(m_display, x, y, &child_return);
}
-
-GHOST_TSuccess
-GHOST_SystemX11::
-setCursorPosition(
- GHOST_TInt32 x,
- GHOST_TInt32 y)
+GHOST_TSuccess GHOST_SystemX11::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
{
- /* This is a brute force move in screen coordinates
- * XWarpPointer does relative moves so first determine the
- * current pointer position. */
+ /* This is a brute force move in screen coordinates
+ * XWarpPointer does relative moves so first determine the
+ * current pointer position. */
- int cx, cy;
+ int cx, cy;
#ifdef WITH_XWAYLAND_HACK
- Window child_return = None;
- if (getCursorPosition_impl(m_display, cx, cy, &child_return) == GHOST_kFailure) {
- return GHOST_kFailure;
- }
+ Window child_return = None;
+ if (getCursorPosition_impl(m_display, cx, cy, &child_return) == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
#else
- if (getCursorPosition(cx, cy) == GHOST_kFailure) {
- return GHOST_kFailure;
- }
+ if (getCursorPosition(cx, cy) == GHOST_kFailure) {
+ return GHOST_kFailure;
+ }
#endif
- int relx = x - cx;
- int rely = y - cy;
+ int relx = x - cx;
+ int rely = y - cy;
#ifdef WITH_XWAYLAND_HACK
- if (use_xwayland_hack) {
- if (child_return != None) {
- XFixesHideCursor(m_display, child_return);
- }
- }
+ if (use_xwayland_hack) {
+ if (child_return != None) {
+ XFixesHideCursor(m_display, child_return);
+ }
+ }
#endif
#if defined(WITH_X11_XINPUT) && defined(USE_X11_XINPUT_WARP)
- if ((m_xinput_version.present) &&
- (m_xinput_version.major_version >= 2))
- {
- /* Needed to account for XInput "Coordinate Transformation Matrix", see T48901 */
- int device_id;
- if (XIGetClientPointer(m_display, None, &device_id) != False) {
- XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, relx, rely);
- }
- }
- else
+ if ((m_xinput_version.present) && (m_xinput_version.major_version >= 2)) {
+ /* Needed to account for XInput "Coordinate Transformation Matrix", see T48901 */
+ int device_id;
+ if (XIGetClientPointer(m_display, None, &device_id) != False) {
+ XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, relx, rely);
+ }
+ }
+ else
#endif
- {
- XWarpPointer(m_display, None, None, 0, 0, 0, 0, relx, rely);
- }
+ {
+ XWarpPointer(m_display, None, None, 0, 0, 0, 0, relx, rely);
+ }
#ifdef WITH_XWAYLAND_HACK
- if (use_xwayland_hack) {
- if (child_return != None) {
- XFixesShowCursor(m_display, child_return);
- }
- }
+ if (use_xwayland_hack) {
+ if (child_return != None) {
+ XFixesShowCursor(m_display, child_return);
+ }
+ }
#endif
- XSync(m_display, 0); /* Sync to process all requests */
+ XSync(m_display, 0); /* Sync to process all requests */
- return GHOST_kSuccess;
+ return GHOST_kSuccess;
}
-
-void
-GHOST_SystemX11::
-addDirtyWindow(
- GHOST_WindowX11 *bad_wind)
+void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind)
{
- GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
+ GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
- m_dirty_windows.push_back(bad_wind);
+ m_dirty_windows.push_back(bad_wind);
}
-
-bool
-GHOST_SystemX11::
-generateWindowExposeEvents()
+bool GHOST_SystemX11::generateWindowExposeEvents()
{
- vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
- vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
- bool anyProcessed = false;
-
- for (; w_start != w_end; ++w_start) {
- GHOST_Event *g_event = new
- GHOST_Event(
- getMilliSeconds(),
- GHOST_kEventWindowUpdate,
- *w_start
- );
-
- (*w_start)->validate();
-
- if (g_event) {
- pushEvent(g_event);
- anyProcessed = true;
- }
- }
-
- m_dirty_windows.clear();
- return anyProcessed;
+ vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
+ vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
+ bool anyProcessed = false;
+
+ for (; w_start != w_end; ++w_start) {
+ GHOST_Event *g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, *w_start);
+
+ (*w_start)->validate();
+
+ if (g_event) {
+ pushEvent(g_event);
+ anyProcessed = true;
+ }
+ }
+
+ m_dirty_windows.clear();
+ return anyProcessed;
}
-static GHOST_TKey
-ghost_key_from_keysym_or_keycode(const KeySym keysym, XkbDescPtr xkb_descr, const KeyCode keycode)
+static GHOST_TKey ghost_key_from_keysym_or_keycode(const KeySym keysym,
+ XkbDescPtr xkb_descr,
+ const KeyCode keycode)
{
- GHOST_TKey type = ghost_key_from_keysym(keysym);
- if (type == GHOST_kKeyUnknown) {
- if (xkb_descr) {
- type = ghost_key_from_keycode(xkb_descr, keycode);
- }
- }
- return type;
+ GHOST_TKey type = ghost_key_from_keysym(keysym);
+ if (type == GHOST_kKeyUnknown) {
+ if (xkb_descr) {
+ type = ghost_key_from_keycode(xkb_descr, keycode);
+ }
+ }
+ return type;
}
-#define GXMAP(k, x, y) case x: k = y; break
+#define GXMAP(k, x, y) \
+ case x: \
+ k = y; \
+ break
-static GHOST_TKey
-ghost_key_from_keysym(const KeySym key)
+static GHOST_TKey ghost_key_from_keysym(const KeySym key)
{
- GHOST_TKey type;
-
- if ((key >= XK_A) && (key <= XK_Z)) {
- type = GHOST_TKey(key - XK_A + int(GHOST_kKeyA));
- }
- else if ((key >= XK_a) && (key <= XK_z)) {
- type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
- }
- else if ((key >= XK_0) && (key <= XK_9)) {
- type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
- }
- else if ((key >= XK_F1) && (key <= XK_F24)) {
- type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
- }
- else {
- switch (key) {
- GXMAP(type, XK_BackSpace, GHOST_kKeyBackSpace);
- GXMAP(type, XK_Tab, GHOST_kKeyTab);
- GXMAP(type, XK_ISO_Left_Tab, GHOST_kKeyTab);
- GXMAP(type, XK_Return, GHOST_kKeyEnter);
- GXMAP(type, XK_Escape, GHOST_kKeyEsc);
- GXMAP(type, XK_space, GHOST_kKeySpace);
-
- GXMAP(type, XK_Linefeed, GHOST_kKeyLinefeed);
- GXMAP(type, XK_semicolon, GHOST_kKeySemicolon);
- GXMAP(type, XK_period, GHOST_kKeyPeriod);
- GXMAP(type, XK_comma, GHOST_kKeyComma);
- GXMAP(type, XK_quoteright, GHOST_kKeyQuote);
- GXMAP(type, XK_quoteleft, GHOST_kKeyAccentGrave);
- GXMAP(type, XK_minus, GHOST_kKeyMinus);
- GXMAP(type, XK_plus, GHOST_kKeyPlus);
- GXMAP(type, XK_slash, GHOST_kKeySlash);
- GXMAP(type, XK_backslash, GHOST_kKeyBackslash);
- GXMAP(type, XK_equal, GHOST_kKeyEqual);
- GXMAP(type, XK_bracketleft, GHOST_kKeyLeftBracket);
- GXMAP(type, XK_bracketright, GHOST_kKeyRightBracket);
- GXMAP(type, XK_Pause, GHOST_kKeyPause);
-
- GXMAP(type, XK_Shift_L, GHOST_kKeyLeftShift);
- GXMAP(type, XK_Shift_R, GHOST_kKeyRightShift);
- GXMAP(type, XK_Control_L, GHOST_kKeyLeftControl);
- GXMAP(type, XK_Control_R, GHOST_kKeyRightControl);
- GXMAP(type, XK_Alt_L, GHOST_kKeyLeftAlt);
- GXMAP(type, XK_Alt_R, GHOST_kKeyRightAlt);
- GXMAP(type, XK_Super_L, GHOST_kKeyOS);
- GXMAP(type, XK_Super_R, GHOST_kKeyOS);
-
- GXMAP(type, XK_Insert, GHOST_kKeyInsert);
- GXMAP(type, XK_Delete, GHOST_kKeyDelete);
- GXMAP(type, XK_Home, GHOST_kKeyHome);
- GXMAP(type, XK_End, GHOST_kKeyEnd);
- GXMAP(type, XK_Page_Up, GHOST_kKeyUpPage);
- GXMAP(type, XK_Page_Down, GHOST_kKeyDownPage);
-
- GXMAP(type, XK_Left, GHOST_kKeyLeftArrow);
- GXMAP(type, XK_Right, GHOST_kKeyRightArrow);
- GXMAP(type, XK_Up, GHOST_kKeyUpArrow);
- GXMAP(type, XK_Down, GHOST_kKeyDownArrow);
-
- GXMAP(type, XK_Caps_Lock, GHOST_kKeyCapsLock);
- GXMAP(type, XK_Scroll_Lock, GHOST_kKeyScrollLock);
- GXMAP(type, XK_Num_Lock, GHOST_kKeyNumLock);
-
- /* keypad events */
-
- GXMAP(type, XK_KP_0, GHOST_kKeyNumpad0);
- GXMAP(type, XK_KP_1, GHOST_kKeyNumpad1);
- GXMAP(type, XK_KP_2, GHOST_kKeyNumpad2);
- GXMAP(type, XK_KP_3, GHOST_kKeyNumpad3);
- GXMAP(type, XK_KP_4, GHOST_kKeyNumpad4);
- GXMAP(type, XK_KP_5, GHOST_kKeyNumpad5);
- GXMAP(type, XK_KP_6, GHOST_kKeyNumpad6);
- GXMAP(type, XK_KP_7, GHOST_kKeyNumpad7);
- GXMAP(type, XK_KP_8, GHOST_kKeyNumpad8);
- GXMAP(type, XK_KP_9, GHOST_kKeyNumpad9);
- GXMAP(type, XK_KP_Decimal, GHOST_kKeyNumpadPeriod);
-
- GXMAP(type, XK_KP_Insert, GHOST_kKeyNumpad0);
- GXMAP(type, XK_KP_End, GHOST_kKeyNumpad1);
- GXMAP(type, XK_KP_Down, GHOST_kKeyNumpad2);
- GXMAP(type, XK_KP_Page_Down, GHOST_kKeyNumpad3);
- GXMAP(type, XK_KP_Left, GHOST_kKeyNumpad4);
- GXMAP(type, XK_KP_Begin, GHOST_kKeyNumpad5);
- GXMAP(type, XK_KP_Right, GHOST_kKeyNumpad6);
- GXMAP(type, XK_KP_Home, GHOST_kKeyNumpad7);
- GXMAP(type, XK_KP_Up, GHOST_kKeyNumpad8);
- GXMAP(type, XK_KP_Page_Up, GHOST_kKeyNumpad9);
- GXMAP(type, XK_KP_Delete, GHOST_kKeyNumpadPeriod);
-
- GXMAP(type, XK_KP_Enter, GHOST_kKeyNumpadEnter);
- GXMAP(type, XK_KP_Add, GHOST_kKeyNumpadPlus);
- GXMAP(type, XK_KP_Subtract, GHOST_kKeyNumpadMinus);
- GXMAP(type, XK_KP_Multiply, GHOST_kKeyNumpadAsterisk);
- GXMAP(type, XK_KP_Divide, GHOST_kKeyNumpadSlash);
-
- /* Media keys in some keyboards and laptops with XFree86/Xorg */
+ GHOST_TKey type;
+
+ if ((key >= XK_A) && (key <= XK_Z)) {
+ type = GHOST_TKey(key - XK_A + int(GHOST_kKeyA));
+ }
+ else if ((key >= XK_a) && (key <= XK_z)) {
+ type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
+ }
+ else if ((key >= XK_0) && (key <= XK_9)) {
+ type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
+ }
+ else if ((key >= XK_F1) && (key <= XK_F24)) {
+ type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
+ }
+ else {
+ switch (key) {
+ GXMAP(type, XK_BackSpace, GHOST_kKeyBackSpace);
+ GXMAP(type, XK_Tab, GHOST_kKeyTab);
+ GXMAP(type, XK_ISO_Left_Tab, GHOST_kKeyTab);
+ GXMAP(type, XK_Return, GHOST_kKeyEnter);
+ GXMAP(type, XK_Escape, GHOST_kKeyEsc);
+ GXMAP(type, XK_space, GHOST_kKeySpace);
+
+ GXMAP(type, XK_Linefeed, GHOST_kKeyLinefeed);
+ GXMAP(type, XK_semicolon, GHOST_kKeySemicolon);
+ GXMAP(type, XK_period, GHOST_kKeyPeriod);
+ GXMAP(type, XK_comma, GHOST_kKeyComma);
+ GXMAP(type, XK_quoteright, GHOST_kKeyQuote);
+ GXMAP(type, XK_quoteleft, GHOST_kKeyAccentGrave);
+ GXMAP(type, XK_minus, GHOST_kKeyMinus);
+ GXMAP(type, XK_plus, GHOST_kKeyPlus);
+ GXMAP(type, XK_slash, GHOST_kKeySlash);
+ GXMAP(type, XK_backslash, GHOST_kKeyBackslash);
+ GXMAP(type, XK_equal, GHOST_kKeyEqual);
+ GXMAP(type, XK_bracketleft, GHOST_kKeyLeftBracket);
+ GXMAP(type, XK_bracketright, GHOST_kKeyRightBracket);
+ GXMAP(type, XK_Pause, GHOST_kKeyPause);
+
+ GXMAP(type, XK_Shift_L, GHOST_kKeyLeftShift);
+ GXMAP(type, XK_Shift_R, GHOST_kKeyRightShift);
+ GXMAP(type, XK_Control_L, GHOST_kKeyLeftControl);
+ GXMAP(type, XK_Control_R, GHOST_kKeyRightControl);
+ GXMAP(type, XK_Alt_L, GHOST_kKeyLeftAlt);
+ GXMAP(type, XK_Alt_R, GHOST_kKeyRightAlt);
+ GXMAP(type, XK_Super_L, GHOST_kKeyOS);
+ GXMAP(type, XK_Super_R, GHOST_kKeyOS);
+
+ GXMAP(type, XK_Insert, GHOST_kKeyInsert);
+ GXMAP(type, XK_Delete, GHOST_kKeyDelete);
+ GXMAP(type, XK_Home, GHOST_kKeyHome);
+ GXMAP(type, XK_End, GHOST_kKeyEnd);
+ GXMAP(type, XK_Page_Up, GHOST_kKeyUpPage);
+ GXMAP(type, XK_Page_Down, GHOST_kKeyDownPage);
+
+ GXMAP(type, XK_Left, GHOST_kKeyLeftArrow);
+ GXMAP(type, XK_Right, GHOST_kKeyRightArrow);
+ GXMAP(type, XK_Up, GHOST_kKeyUpArrow);
+ GXMAP(type, XK_Down, GHOST_kKeyDownArrow);
+
+ GXMAP(type, XK_Caps_Lock, GHOST_kKeyCapsLock);
+ GXMAP(type, XK_Scroll_Lock, GHOST_kKeyScrollLock);
+ GXMAP(type, XK_Num_Lock, GHOST_kKeyNumLock);
+
+ /* keypad events */
+
+ GXMAP(type, XK_KP_0, GHOST_kKeyNumpad0);
+ GXMAP(type, XK_KP_1, GHOST_kKeyNumpad1);
+ GXMAP(type, XK_KP_2, GHOST_kKeyNumpad2);
+ GXMAP(type, XK_KP_3, GHOST_kKeyNumpad3);
+ GXMAP(type, XK_KP_4, GHOST_kKeyNumpad4);
+ GXMAP(type, XK_KP_5, GHOST_kKeyNumpad5);
+ GXMAP(type, XK_KP_6, GHOST_kKeyNumpad6);
+ GXMAP(type, XK_KP_7, GHOST_kKeyNumpad7);
+ GXMAP(type, XK_KP_8, GHOST_kKeyNumpad8);
+ GXMAP(type, XK_KP_9, GHOST_kKeyNumpad9);
+ GXMAP(type, XK_KP_Decimal, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type, XK_KP_Insert, GHOST_kKeyNumpad0);
+ GXMAP(type, XK_KP_End, GHOST_kKeyNumpad1);
+ GXMAP(type, XK_KP_Down, GHOST_kKeyNumpad2);
+ GXMAP(type, XK_KP_Page_Down, GHOST_kKeyNumpad3);
+ GXMAP(type, XK_KP_Left, GHOST_kKeyNumpad4);
+ GXMAP(type, XK_KP_Begin, GHOST_kKeyNumpad5);
+ GXMAP(type, XK_KP_Right, GHOST_kKeyNumpad6);
+ GXMAP(type, XK_KP_Home, GHOST_kKeyNumpad7);
+ GXMAP(type, XK_KP_Up, GHOST_kKeyNumpad8);
+ GXMAP(type, XK_KP_Page_Up, GHOST_kKeyNumpad9);
+ GXMAP(type, XK_KP_Delete, GHOST_kKeyNumpadPeriod);
+
+ GXMAP(type, XK_KP_Enter, GHOST_kKeyNumpadEnter);
+ GXMAP(type, XK_KP_Add, GHOST_kKeyNumpadPlus);
+ GXMAP(type, XK_KP_Subtract, GHOST_kKeyNumpadMinus);
+ GXMAP(type, XK_KP_Multiply, GHOST_kKeyNumpadAsterisk);
+ GXMAP(type, XK_KP_Divide, GHOST_kKeyNumpadSlash);
+
+ /* Media keys in some keyboards and laptops with XFree86/Xorg */
#ifdef WITH_XF86KEYSYM
- GXMAP(type, XF86XK_AudioPlay, GHOST_kKeyMediaPlay);
- GXMAP(type, XF86XK_AudioStop, GHOST_kKeyMediaStop);
- GXMAP(type, XF86XK_AudioPrev, GHOST_kKeyMediaFirst);
- GXMAP(type, XF86XK_AudioRewind, GHOST_kKeyMediaFirst);
- GXMAP(type, XF86XK_AudioNext, GHOST_kKeyMediaLast);
-#ifdef XF86XK_AudioForward /* Debian lenny's XF86keysym.h has no XF86XK_AudioForward define */
- GXMAP(type, XF86XK_AudioForward, GHOST_kKeyMediaLast);
+ GXMAP(type, XF86XK_AudioPlay, GHOST_kKeyMediaPlay);
+ GXMAP(type, XF86XK_AudioStop, GHOST_kKeyMediaStop);
+ GXMAP(type, XF86XK_AudioPrev, GHOST_kKeyMediaFirst);
+ GXMAP(type, XF86XK_AudioRewind, GHOST_kKeyMediaFirst);
+ GXMAP(type, XF86XK_AudioNext, GHOST_kKeyMediaLast);
+# ifdef XF86XK_AudioForward /* Debian lenny's XF86keysym.h has no XF86XK_AudioForward define */
+ GXMAP(type, XF86XK_AudioForward, GHOST_kKeyMediaLast);
+# endif
#endif
-#endif
- default:
+ default:
#ifdef GHOST_DEBUG
- printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key);
+ printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key);
#endif
- type = GHOST_kKeyUnknown;
- break;
- }
- }
+ type = GHOST_kKeyUnknown;
+ break;
+ }
+ }
- return type;
+ return type;
}
#undef GXMAP
#define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
-static GHOST_TKey
-ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode)
+static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode)
{
- GHOST_ASSERT(XkbKeyNameLength == 4, "Name length is invalid!");
- if (keycode >= xkb_descr->min_key_code && keycode <= xkb_descr->max_key_code) {
- const char *id_str = xkb_descr->names->keys[keycode].name;
- const uint32_t id = MAKE_ID(id_str[0], id_str[1], id_str[2], id_str[3]);
- switch (id) {
- case MAKE_ID('T', 'L', 'D', 'E'):
- return GHOST_kKeyAccentGrave;
+ GHOST_ASSERT(XkbKeyNameLength == 4, "Name length is invalid!");
+ if (keycode >= xkb_descr->min_key_code && keycode <= xkb_descr->max_key_code) {
+ const char *id_str = xkb_descr->names->keys[keycode].name;
+ const uint32_t id = MAKE_ID(id_str[0], id_str[1], id_str[2], id_str[3]);
+ switch (id) {
+ case MAKE_ID('T', 'L', 'D', 'E'):
+ return GHOST_kKeyAccentGrave;
#ifdef GHOST_DEBUG
- default:
- printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str);
- break;
+ default:
+ printf("%s unhandled keycode: %.*s\n", __func__, XkbKeyNameLength, id_str);
+ break;
#endif
- }
- }
- else if (keycode != 0) {
- GHOST_ASSERT(false, "KeyCode out of range!");
- }
- return GHOST_kKeyUnknown;
+ }
+ }
+ else if (keycode != 0) {
+ GHOST_ASSERT(false, "KeyCode out of range!");
+ }
+ return GHOST_kKeyUnknown;
}
#undef MAKE_ID
/* from xclip.c xcout() v0.11 */
-#define XCLIB_XCOUT_NONE 0 /* no context */
-#define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */
-#define XCLIB_XCOUT_INCR 2 /* in an incr loop */
-#define XCLIB_XCOUT_FALLBACK 3 /* STRING failed, need fallback to UTF8 */
-#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compouned */
-#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compouned failed, move to text. */
-#define XCLIB_XCOUT_FALLBACK_TEXT 6
+#define XCLIB_XCOUT_NONE 0 /* no context */
+#define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */
+#define XCLIB_XCOUT_INCR 2 /* in an incr loop */
+#define XCLIB_XCOUT_FALLBACK 3 /* STRING failed, need fallback to UTF8 */
+#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compouned */
+#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compouned failed, move to text. */
+#define XCLIB_XCOUT_FALLBACK_TEXT 6
/* Retrieves the contents of a selections. */
void GHOST_SystemX11::getClipboard_xcout(const XEvent *evt,
- Atom sel, Atom target, unsigned char **txt,
- unsigned long *len, unsigned int *context) const
+ Atom sel,
+ Atom target,
+ unsigned char **txt,
+ unsigned long *len,
+ unsigned int *context) const
{
- Atom pty_type;
- int pty_format;
- unsigned char *buffer;
- unsigned long pty_size, pty_items;
- unsigned char *ltxt = *txt;
-
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
- vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
- GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
- Window win = window->getXWindow();
-
- switch (*context) {
- /* There is no context, do an XConvertSelection() */
- case XCLIB_XCOUT_NONE:
- /* Initialise return length to 0 */
- if (*len > 0) {
- free(*txt);
- *len = 0;
- }
-
- /* Send a selection request */
- XConvertSelection(m_display, sel, target, m_atom.XCLIP_OUT, win, CurrentTime);
- *context = XCLIB_XCOUT_SENTCONVSEL;
- return;
-
- case XCLIB_XCOUT_SENTCONVSEL:
- if (evt->type != SelectionNotify)
- return;
-
- if (target == m_atom.UTF8_STRING && evt->xselection.property == None) {
- *context = XCLIB_XCOUT_FALLBACK_UTF8;
- return;
- }
- else if (target == m_atom.COMPOUND_TEXT && evt->xselection.property == None) {
- *context = XCLIB_XCOUT_FALLBACK_COMP;
- return;
- }
- else if (target == m_atom.TEXT && evt->xselection.property == None) {
- *context = XCLIB_XCOUT_FALLBACK_TEXT;
- return;
- }
-
- /* find the size and format of the data in property */
- XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, 0, False,
- AnyPropertyType, &pty_type, &pty_format,
- &pty_items, &pty_size, &buffer);
- XFree(buffer);
-
- if (pty_type == m_atom.INCR) {
- /* start INCR mechanism by deleting property */
- XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
- XFlush(m_display);
- *context = XCLIB_XCOUT_INCR;
- return;
- }
-
- /* if it's not incr, and not format == 8, then there's
- * nothing in the selection (that xclip understands, anyway) */
-
- if (pty_format != 8) {
- *context = XCLIB_XCOUT_NONE;
- return;
- }
-
- // not using INCR mechanism, just read the property
- XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, (long) pty_size,
- False, AnyPropertyType, &pty_type,
- &pty_format, &pty_items, &pty_size, &buffer);
-
- /* finished with property, delete it */
- XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
-
- /* copy the buffer to the pointer for returned data */
- ltxt = (unsigned char *) malloc(pty_items);
- memcpy(ltxt, buffer, pty_items);
-
- /* set the length of the returned data */
- *len = pty_items;
- *txt = ltxt;
-
- /* free the buffer */
- XFree(buffer);
-
- *context = XCLIB_XCOUT_NONE;
-
- /* complete contents of selection fetched, return 1 */
- return;
-
- case XCLIB_XCOUT_INCR:
- /* To use the INCR method, we basically delete the
- * property with the selection in it, wait for an
- * event indicating that the property has been created,
- * then read it, delete it, etc. */
-
- /* make sure that the event is relevant */
- if (evt->type != PropertyNotify)
- return;
-
- /* skip unless the property has a new value */
- if (evt->xproperty.state != PropertyNewValue)
- return;
-
- /* check size and format of the property */
- XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, 0, False,
- AnyPropertyType, &pty_type, &pty_format,
- &pty_items, &pty_size, &buffer);
-
- if (pty_format != 8) {
- /* property does not contain text, delete it
- * to tell the other X client that we have read
- * it and to send the next property */
- XFree(buffer);
- XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
- return;
- }
-
- if (pty_size == 0) {
- /* no more data, exit from loop */
- XFree(buffer);
- XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
- *context = XCLIB_XCOUT_NONE;
-
- /* this means that an INCR transfer is now
- * complete, return 1 */
- return;
- }
-
- XFree(buffer);
-
- /* if we have come this far, the property contains
- * text, we know the size. */
- XGetWindowProperty(m_display, win, m_atom.XCLIP_OUT, 0, (long) pty_size,
- False, AnyPropertyType, &pty_type, &pty_format,
- &pty_items, &pty_size, &buffer);
-
- /* allocate memory to accommodate data in *txt */
- if (*len == 0) {
- *len = pty_items;
- ltxt = (unsigned char *) malloc(*len);
- }
- else {
- *len += pty_items;
- ltxt = (unsigned char *) realloc(ltxt, *len);
- }
-
- /* add data to ltxt */
- memcpy(&ltxt[*len - pty_items], buffer, pty_items);
-
- *txt = ltxt;
- XFree(buffer);
-
- /* delete property to get the next item */
- XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
- XFlush(m_display);
- return;
- }
- return;
+ Atom pty_type;
+ int pty_format;
+ unsigned char *buffer;
+ unsigned long pty_size, pty_items;
+ unsigned char *ltxt = *txt;
+
+ vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ Window win = window->getXWindow();
+
+ switch (*context) {
+ /* There is no context, do an XConvertSelection() */
+ case XCLIB_XCOUT_NONE:
+ /* Initialise return length to 0 */
+ if (*len > 0) {
+ free(*txt);
+ *len = 0;
+ }
+
+ /* Send a selection request */
+ XConvertSelection(m_display, sel, target, m_atom.XCLIP_OUT, win, CurrentTime);
+ *context = XCLIB_XCOUT_SENTCONVSEL;
+ return;
+
+ case XCLIB_XCOUT_SENTCONVSEL:
+ if (evt->type != SelectionNotify)
+ return;
+
+ if (target == m_atom.UTF8_STRING && evt->xselection.property == None) {
+ *context = XCLIB_XCOUT_FALLBACK_UTF8;
+ return;
+ }
+ else if (target == m_atom.COMPOUND_TEXT && evt->xselection.property == None) {
+ *context = XCLIB_XCOUT_FALLBACK_COMP;
+ return;
+ }
+ else if (target == m_atom.TEXT && evt->xselection.property == None) {
+ *context = XCLIB_XCOUT_FALLBACK_TEXT;
+ return;
+ }
+
+ /* find the size and format of the data in property */
+ XGetWindowProperty(m_display,
+ win,
+ m_atom.XCLIP_OUT,
+ 0,
+ 0,
+ False,
+ AnyPropertyType,
+ &pty_type,
+ &pty_format,
+ &pty_items,
+ &pty_size,
+ &buffer);
+ XFree(buffer);
+
+ if (pty_type == m_atom.INCR) {
+ /* start INCR mechanism by deleting property */
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
+ XFlush(m_display);
+ *context = XCLIB_XCOUT_INCR;
+ return;
+ }
+
+ /* if it's not incr, and not format == 8, then there's
+ * nothing in the selection (that xclip understands, anyway) */
+
+ if (pty_format != 8) {
+ *context = XCLIB_XCOUT_NONE;
+ return;
+ }
+
+ // not using INCR mechanism, just read the property
+ XGetWindowProperty(m_display,
+ win,
+ m_atom.XCLIP_OUT,
+ 0,
+ (long)pty_size,
+ False,
+ AnyPropertyType,
+ &pty_type,
+ &pty_format,
+ &pty_items,
+ &pty_size,
+ &buffer);
+
+ /* finished with property, delete it */
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
+
+ /* copy the buffer to the pointer for returned data */
+ ltxt = (unsigned char *)malloc(pty_items);
+ memcpy(ltxt, buffer, pty_items);
+
+ /* set the length of the returned data */
+ *len = pty_items;
+ *txt = ltxt;
+
+ /* free the buffer */
+ XFree(buffer);
+
+ *context = XCLIB_XCOUT_NONE;
+
+ /* complete contents of selection fetched, return 1 */
+ return;
+
+ case XCLIB_XCOUT_INCR:
+ /* To use the INCR method, we basically delete the
+ * property with the selection in it, wait for an
+ * event indicating that the property has been created,
+ * then read it, delete it, etc. */
+
+ /* make sure that the event is relevant */
+ if (evt->type != PropertyNotify)
+ return;
+
+ /* skip unless the property has a new value */
+ if (evt->xproperty.state != PropertyNewValue)
+ return;
+
+ /* check size and format of the property */
+ XGetWindowProperty(m_display,
+ win,
+ m_atom.XCLIP_OUT,
+ 0,
+ 0,
+ False,
+ AnyPropertyType,
+ &pty_type,
+ &pty_format,
+ &pty_items,
+ &pty_size,
+ &buffer);
+
+ if (pty_format != 8) {
+ /* property does not contain text, delete it
+ * to tell the other X client that we have read
+ * it and to send the next property */
+ XFree(buffer);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
+ return;
+ }
+
+ if (pty_size == 0) {
+ /* no more data, exit from loop */
+ XFree(buffer);
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
+ *context = XCLIB_XCOUT_NONE;
+
+ /* this means that an INCR transfer is now
+ * complete, return 1 */
+ return;
+ }
+
+ XFree(buffer);
+
+ /* if we have come this far, the property contains
+ * text, we know the size. */
+ XGetWindowProperty(m_display,
+ win,
+ m_atom.XCLIP_OUT,
+ 0,
+ (long)pty_size,
+ False,
+ AnyPropertyType,
+ &pty_type,
+ &pty_format,
+ &pty_items,
+ &pty_size,
+ &buffer);
+
+ /* allocate memory to accommodate data in *txt */
+ if (*len == 0) {
+ *len = pty_items;
+ ltxt = (unsigned char *)malloc(*len);
+ }
+ else {
+ *len += pty_items;
+ ltxt = (unsigned char *)realloc(ltxt, *len);
+ }
+
+ /* add data to ltxt */
+ memcpy(&ltxt[*len - pty_items], buffer, pty_items);
+
+ *txt = ltxt;
+ XFree(buffer);
+
+ /* delete property to get the next item */
+ XDeleteProperty(m_display, win, m_atom.XCLIP_OUT);
+ XFlush(m_display);
+ return;
+ }
+ return;
}
GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
{
- Atom sseln;
- Atom target = m_atom.UTF8_STRING;
- Window owner;
-
- /* from xclip.c doOut() v0.11 */
- unsigned char *sel_buf;
- unsigned long sel_len = 0;
- XEvent evt;
- unsigned int context = XCLIB_XCOUT_NONE;
-
- if (selection == True)
- sseln = m_atom.PRIMARY;
- else
- sseln = m_atom.CLIPBOARD;
-
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
- vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
- GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
- Window win = window->getXWindow();
-
- /* check if we are the owner. */
- owner = XGetSelectionOwner(m_display, sseln);
- if (owner == win) {
- if (sseln == m_atom.CLIPBOARD) {
- sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1);
- strcpy((char *)sel_buf, txt_cut_buffer);
- return sel_buf;
- }
- else {
- sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1);
- strcpy((char *)sel_buf, txt_select_buffer);
- return sel_buf;
- }
- }
- else if (owner == None)
- return(NULL);
-
- while (1) {
- /* only get an event if xcout() is doing something */
- if (context != XCLIB_XCOUT_NONE)
- XNextEvent(m_display, &evt);
-
- /* fetch the selection, or part of it */
- getClipboard_xcout(&evt, sseln, target, &sel_buf, &sel_len, &context);
-
- /* fallback is needed. set XA_STRING to target and restart the loop. */
- if (context == XCLIB_XCOUT_FALLBACK) {
- context = XCLIB_XCOUT_NONE;
- target = m_atom.STRING;
- continue;
- }
- else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
- /* utf8 fail, move to compouned text. */
- context = XCLIB_XCOUT_NONE;
- target = m_atom.COMPOUND_TEXT;
- continue;
- }
- else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
- /* compouned text fail, move to text. */
- context = XCLIB_XCOUT_NONE;
- target = m_atom.TEXT;
- continue;
- }
- else if (context == XCLIB_XCOUT_FALLBACK_TEXT) {
- /* text fail, nothing else to try, break. */
- context = XCLIB_XCOUT_NONE;
- }
-
- /* only continue if xcout() is doing something */
- if (context == XCLIB_XCOUT_NONE)
- break;
- }
-
- if (sel_len) {
- /* only print the buffer out, and free it, if it's not
- * empty
- */
- unsigned char *tmp_data = (unsigned char *) malloc(sel_len + 1);
- memcpy((char *)tmp_data, (char *)sel_buf, sel_len);
- tmp_data[sel_len] = '\0';
-
- if (sseln == m_atom.STRING)
- XFree(sel_buf);
- else
- free(sel_buf);
-
- return tmp_data;
- }
- return(NULL);
+ Atom sseln;
+ Atom target = m_atom.UTF8_STRING;
+ Window owner;
+
+ /* from xclip.c doOut() v0.11 */
+ unsigned char *sel_buf;
+ unsigned long sel_len = 0;
+ XEvent evt;
+ unsigned int context = XCLIB_XCOUT_NONE;
+
+ if (selection == True)
+ sseln = m_atom.PRIMARY;
+ else
+ sseln = m_atom.CLIPBOARD;
+
+ vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ Window win = window->getXWindow();
+
+ /* check if we are the owner. */
+ owner = XGetSelectionOwner(m_display, sseln);
+ if (owner == win) {
+ if (sseln == m_atom.CLIPBOARD) {
+ sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1);
+ strcpy((char *)sel_buf, txt_cut_buffer);
+ return sel_buf;
+ }
+ else {
+ sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1);
+ strcpy((char *)sel_buf, txt_select_buffer);
+ return sel_buf;
+ }
+ }
+ else if (owner == None)
+ return (NULL);
+
+ while (1) {
+ /* only get an event if xcout() is doing something */
+ if (context != XCLIB_XCOUT_NONE)
+ XNextEvent(m_display, &evt);
+
+ /* fetch the selection, or part of it */
+ getClipboard_xcout(&evt, sseln, target, &sel_buf, &sel_len, &context);
+
+ /* fallback is needed. set XA_STRING to target and restart the loop. */
+ if (context == XCLIB_XCOUT_FALLBACK) {
+ context = XCLIB_XCOUT_NONE;
+ target = m_atom.STRING;
+ continue;
+ }
+ else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
+ /* utf8 fail, move to compouned text. */
+ context = XCLIB_XCOUT_NONE;
+ target = m_atom.COMPOUND_TEXT;
+ continue;
+ }
+ else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
+ /* compouned text fail, move to text. */
+ context = XCLIB_XCOUT_NONE;
+ target = m_atom.TEXT;
+ continue;
+ }
+ else if (context == XCLIB_XCOUT_FALLBACK_TEXT) {
+ /* text fail, nothing else to try, break. */
+ context = XCLIB_XCOUT_NONE;
+ }
+
+ /* only continue if xcout() is doing something */
+ if (context == XCLIB_XCOUT_NONE)
+ break;
+ }
+
+ if (sel_len) {
+ /* only print the buffer out, and free it, if it's not
+ * empty
+ */
+ unsigned char *tmp_data = (unsigned char *)malloc(sel_len + 1);
+ memcpy((char *)tmp_data, (char *)sel_buf, sel_len);
+ tmp_data[sel_len] = '\0';
+
+ if (sseln == m_atom.STRING)
+ XFree(sel_buf);
+ else
+ free(sel_buf);
+
+ return tmp_data;
+ }
+ return (NULL);
}
void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
{
- Window m_window, owner;
-
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
- vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
- GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
- m_window = window->getXWindow();
-
- if (buffer) {
- if (selection == False) {
- XSetSelectionOwner(m_display, m_atom.CLIPBOARD, m_window, CurrentTime);
- owner = XGetSelectionOwner(m_display, m_atom.CLIPBOARD);
- if (txt_cut_buffer)
- free((void *)txt_cut_buffer);
-
- txt_cut_buffer = (char *) malloc(strlen(buffer) + 1);
- strcpy(txt_cut_buffer, buffer);
- }
- else {
- XSetSelectionOwner(m_display, m_atom.PRIMARY, m_window, CurrentTime);
- owner = XGetSelectionOwner(m_display, m_atom.PRIMARY);
- if (txt_select_buffer)
- free((void *)txt_select_buffer);
-
- txt_select_buffer = (char *) malloc(strlen(buffer) + 1);
- strcpy(txt_select_buffer, buffer);
- }
-
- if (owner != m_window)
- fprintf(stderr, "failed to own primary\n");
- }
+ Window m_window, owner;
+
+ vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ m_window = window->getXWindow();
+
+ if (buffer) {
+ if (selection == False) {
+ XSetSelectionOwner(m_display, m_atom.CLIPBOARD, m_window, CurrentTime);
+ owner = XGetSelectionOwner(m_display, m_atom.CLIPBOARD);
+ if (txt_cut_buffer)
+ free((void *)txt_cut_buffer);
+
+ txt_cut_buffer = (char *)malloc(strlen(buffer) + 1);
+ strcpy(txt_cut_buffer, buffer);
+ }
+ else {
+ XSetSelectionOwner(m_display, m_atom.PRIMARY, m_window, CurrentTime);
+ owner = XGetSelectionOwner(m_display, m_atom.PRIMARY);
+ if (txt_select_buffer)
+ free((void *)txt_select_buffer);
+
+ txt_select_buffer = (char *)malloc(strlen(buffer) + 1);
+ strcpy(txt_select_buffer, buffer);
+ }
+
+ if (owner != m_window)
+ fprintf(stderr, "failed to own primary\n");
+ }
}
#ifdef WITH_XDND
GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
- GHOST_TDragnDropTypes draggedObjectType,
- GHOST_IWindow *window,
- int mouseX, int mouseY,
- void *data)
+ GHOST_TDragnDropTypes draggedObjectType,
+ GHOST_IWindow *window,
+ int mouseX,
+ int mouseY,
+ void *data)
{
- GHOST_SystemX11 *system = ((GHOST_SystemX11 *)getSystem());
- return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
- eventType,
- draggedObjectType,
- window, mouseX, mouseY, data)
- );
+ GHOST_SystemX11 *system = ((GHOST_SystemX11 *)getSystem());
+ return system->pushEvent(new GHOST_EventDragnDrop(
+ system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data));
}
#endif
/**
@@ -2220,28 +2163,31 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
*/
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *event)
{
- char error_code_str[512];
-
- XGetErrorText(display, event->error_code, error_code_str, sizeof(error_code_str));
-
- fprintf(stderr,
- "Received X11 Error:\n"
- "\terror code: %d\n"
- "\trequest code: %d\n"
- "\tminor code: %d\n"
- "\terror text: %s\n",
- event->error_code, event->request_code, event->minor_code, error_code_str);
-
- /* No exit! - but keep lint happy */
- return 0;
+ char error_code_str[512];
+
+ XGetErrorText(display, event->error_code, error_code_str, sizeof(error_code_str));
+
+ fprintf(stderr,
+ "Received X11 Error:\n"
+ "\terror code: %d\n"
+ "\trequest code: %d\n"
+ "\tminor code: %d\n"
+ "\terror text: %s\n",
+ event->error_code,
+ event->request_code,
+ event->minor_code,
+ error_code_str);
+
+ /* No exit! - but keep lint happy */
+ return 0;
}
int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
{
- fprintf(stderr, "Ignoring Xlib error: error IO\n");
+ fprintf(stderr, "Ignoring Xlib error: error IO\n");
- /* No exit! - but keep lint happy */
- return 0;
+ /* No exit! - but keep lint happy */
+ return 0;
}
#ifdef WITH_X11_XINPUT
@@ -2249,22 +2195,22 @@ int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
/* These C functions are copied from Wine 3.12's wintab.c */
static bool match_token(const char *haystack, const char *needle)
{
- const char *p, *q;
- for (p = haystack; *p; ) {
- while (*p && isspace(*p))
- p++;
- if (!*p)
- break;
-
- for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
- p++;
- if (!*q && (isspace(*p) || !*p))
- return true;
-
- while (*p && !isspace(*p))
- p++;
- }
- return false;
+ const char *p, *q;
+ for (p = haystack; *p;) {
+ while (*p && isspace(*p))
+ p++;
+ if (!*p)
+ break;
+
+ for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
+ p++;
+ if (!*q && (isspace(*p) || !*p))
+ return true;
+
+ while (*p && !isspace(*p))
+ p++;
+ }
+ return false;
}
/* Determining if an X device is a Tablet style device is an imperfect science.
@@ -2279,130 +2225,118 @@ static bool match_token(const char *haystack, const char *needle)
*/
static GHOST_TTabletMode tablet_mode_from_name(const char *name, const char *type)
{
- int i;
- static const char* tablet_stylus_whitelist[] = {
- "stylus",
- "wizardpen",
- "acecad",
- "pen",
- NULL
- };
-
- static const char* type_blacklist[] = {
- "pad",
- "cursor",
- "touch",
- NULL
- };
-
- /* Skip some known unsupported types. */
- for (i=0; type_blacklist[i] != NULL; i++) {
- if (type && (strcasecmp(type, type_blacklist[i]) == 0)) {
- return GHOST_kTabletModeNone;
- }
- }
-
- /* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
- for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
- if (type && match_token(type, tablet_stylus_whitelist[i])) {
- return GHOST_kTabletModeStylus;
- }
- }
- if (type && match_token(type, "eraser")) {
- return GHOST_kTabletModeEraser;
- }
- for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
- if (name && match_token(name, tablet_stylus_whitelist[i])) {
- return GHOST_kTabletModeStylus;
- }
- }
- if (name && match_token(name, "eraser")) {
- return GHOST_kTabletModeEraser;
- }
-
- return GHOST_kTabletModeNone;
+ int i;
+ static const char *tablet_stylus_whitelist[] = {"stylus", "wizardpen", "acecad", "pen", NULL};
+
+ static const char *type_blacklist[] = {"pad", "cursor", "touch", NULL};
+
+ /* Skip some known unsupported types. */
+ for (i = 0; type_blacklist[i] != NULL; i++) {
+ if (type && (strcasecmp(type, type_blacklist[i]) == 0)) {
+ return GHOST_kTabletModeNone;
+ }
+ }
+
+ /* First check device type to avoid cases where name is "Pen and Eraser" and type is "ERASER" */
+ for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
+ if (type && match_token(type, tablet_stylus_whitelist[i])) {
+ return GHOST_kTabletModeStylus;
+ }
+ }
+ if (type && match_token(type, "eraser")) {
+ return GHOST_kTabletModeEraser;
+ }
+ for (i = 0; tablet_stylus_whitelist[i] != NULL; i++) {
+ if (name && match_token(name, tablet_stylus_whitelist[i])) {
+ return GHOST_kTabletModeStylus;
+ }
+ }
+ if (name && match_token(name, "eraser")) {
+ return GHOST_kTabletModeEraser;
+ }
+
+ return GHOST_kTabletModeNone;
}
/* End code copied from Wine. */
void GHOST_SystemX11::refreshXInputDevices()
{
- if (m_xinput_version.present) {
- /* Close tablet devices. */
- clearXInputDevices();
-
- /* Install our error handler to override Xlib's termination behavior */
- GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
-
- {
- int device_count;
- XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
-
-
- for (int i = 0; i < device_count; ++i) {
- char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
- GHOST_TTabletMode tablet_mode = tablet_mode_from_name(device_info[i].name, device_type);
-
-// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
-
- if (device_type) {
- XFree((void *)device_type);
- }
-
- if (!(tablet_mode == GHOST_kTabletModeStylus || tablet_mode == GHOST_kTabletModeEraser)) {
- continue;
- }
-
- GHOST_TabletX11 xtablet = {tablet_mode};
- xtablet.ID = device_info[i].id;
- xtablet.Device = XOpenDevice(m_display, xtablet.ID);
-
- if (xtablet.Device != NULL) {
- /* Find how many pressure levels tablet has */
- XAnyClassPtr ici = device_info[i].inputclassinfo;
-
- for (int j = 0; j < xtablet.Device->num_classes; ++j) {
- if (ici->c_class == ValuatorClass) {
- XValuatorInfo *xvi = (XValuatorInfo *)ici;
- xtablet.PressureLevels = xvi->axes[2].max_value;
-
- if (xvi->num_axes > 3) {
- /* this is assuming that the tablet has the same tilt resolution in both
- * positive and negative directions. It would be rather weird if it didn't.. */
- xtablet.XtiltLevels = xvi->axes[3].max_value;
- xtablet.YtiltLevels = xvi->axes[4].max_value;
- }
- else {
- xtablet.XtiltLevels = 0;
- xtablet.YtiltLevels = 0;
- }
-
- break;
- }
-
- ici = (XAnyClassPtr)(((char *)ici) + ici->length);
- }
-
- m_xtablets.push_back(xtablet);
- }
-
- }
-
- XFreeDeviceList(device_info);
- }
-
- GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
- }
+ if (m_xinput_version.present) {
+ /* Close tablet devices. */
+ clearXInputDevices();
+
+ /* Install our error handler to override Xlib's termination behavior */
+ GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
+
+ {
+ int device_count;
+ XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
+
+ for (int i = 0; i < device_count; ++i) {
+ char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) :
+ NULL;
+ GHOST_TTabletMode tablet_mode = tablet_mode_from_name(device_info[i].name, device_type);
+
+ // printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
+
+ if (device_type) {
+ XFree((void *)device_type);
+ }
+
+ if (!(tablet_mode == GHOST_kTabletModeStylus || tablet_mode == GHOST_kTabletModeEraser)) {
+ continue;
+ }
+
+ GHOST_TabletX11 xtablet = {tablet_mode};
+ xtablet.ID = device_info[i].id;
+ xtablet.Device = XOpenDevice(m_display, xtablet.ID);
+
+ if (xtablet.Device != NULL) {
+ /* Find how many pressure levels tablet has */
+ XAnyClassPtr ici = device_info[i].inputclassinfo;
+
+ for (int j = 0; j < xtablet.Device->num_classes; ++j) {
+ if (ici->c_class == ValuatorClass) {
+ XValuatorInfo *xvi = (XValuatorInfo *)ici;
+ xtablet.PressureLevels = xvi->axes[2].max_value;
+
+ if (xvi->num_axes > 3) {
+ /* this is assuming that the tablet has the same tilt resolution in both
+ * positive and negative directions. It would be rather weird if it didn't.. */
+ xtablet.XtiltLevels = xvi->axes[3].max_value;
+ xtablet.YtiltLevels = xvi->axes[4].max_value;
+ }
+ else {
+ xtablet.XtiltLevels = 0;
+ xtablet.YtiltLevels = 0;
+ }
+
+ break;
+ }
+
+ ici = (XAnyClassPtr)(((char *)ici) + ici->length);
+ }
+
+ m_xtablets.push_back(xtablet);
+ }
+ }
+
+ XFreeDeviceList(device_info);
+ }
+
+ GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
+ }
}
void GHOST_SystemX11::clearXInputDevices()
{
- for (GHOST_TabletX11& xtablet: m_xtablets) {
- if (xtablet.Device)
- XCloseDevice(m_display, xtablet.Device);
- }
+ for (GHOST_TabletX11 &xtablet : m_xtablets) {
+ if (xtablet.Device)
+ XCloseDevice(m_display, xtablet.Device);
+ }
- m_xtablets.clear();
+ m_xtablets.clear();
}
#endif /* WITH_X11_XINPUT */