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.cpp336
1 files changed, 165 insertions, 171 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index bed9cd6c784..bb98c0de19b 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -25,6 +25,7 @@
#ifdef WITH_INPUT_NDOF
# include "GHOST_NDOFManagerUnix.h"
#endif
+#include "GHOST_utildefines.h"
#ifdef WITH_XDND
# include "GHOST_DropTargetX11.h"
@@ -32,12 +33,8 @@
#include "GHOST_Debug.h"
-#if defined(WITH_GL_EGL)
-# include "GHOST_ContextEGL.h"
-# include <EGL/eglext.h>
-#else
-# include "GHOST_ContextGLX.h"
-#endif
+#include "GHOST_ContextEGL.h"
+#include "GHOST_ContextGLX.h"
#ifdef WITH_XF86KEYSYM
# include <X11/XF86keysym.h>
@@ -104,8 +101,7 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(nullptr), m_sta
m_display = XOpenDisplay(nullptr);
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 */
+ throw std::runtime_error("X11: Unable to open a display");
}
#ifdef USE_X11_ERROR_HANDLERS
@@ -234,10 +230,6 @@ GHOST_SystemX11::~GHOST_SystemX11()
clearXInputDevices();
#endif /* WITH_X11_XINPUT */
-#ifdef WITH_GL_EGL
- ::eglTerminate(::eglGetDisplay(m_display));
-#endif
-
if (m_xkb_descr) {
XkbFreeKeyboard(m_xkb_descr, XkbAllComponentsMask, true);
}
@@ -286,7 +278,7 @@ uint8_t GHOST_SystemX11::getNumDisplays() const
void GHOST_SystemX11::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
if (m_display) {
- /* NOTE(campbell): for this to work as documented,
+ /* NOTE(@campbellbarton): 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 dependency. */
getAllDisplayDimensions(width, height);
@@ -353,7 +345,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive,
- ((glSettings.flags & GHOST_glAlphaBackground) != 0),
(glSettings.flags & GHOST_glDebugContext) != 0);
if (window) {
@@ -374,6 +365,56 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title,
return window;
}
+#ifdef USE_EGL
+static GHOST_Context *create_egl_context(
+ GHOST_SystemX11 *system, Display *display, bool debug_context, int ver_major, int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextEGL(system,
+ false,
+ EGLNativeWindowType(nullptr),
+ EGLNativeDisplayType(display),
+ EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_EGL_CONTEXT_FLAGS |
+ (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
+ GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
+ EGL_OPENGL_API);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
+#endif
+
+static GHOST_Context *create_glx_context(Display *display,
+ bool debug_context,
+ int ver_major,
+ int ver_minor)
+{
+ GHOST_Context *context;
+ context = new GHOST_ContextGLX(false,
+ (Window) nullptr,
+ display,
+ (GLXFBConfig) nullptr,
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ ver_major,
+ ver_minor,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS |
+ (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ delete context;
+
+ return nullptr;
+}
/**
* Create a new off-screen context.
* Never explicitly delete the context, use #disposeContext() instead.
@@ -393,98 +434,33 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
const bool debug_context = (glSettings.flags & GHOST_glDebugContext) != 0;
-#if defined(WITH_GL_PROFILE_CORE)
- {
- const char *version_major = (char *)glewGetString(GLEW_VERSION_MAJOR);
- if (version_major != nullptr && version_major[0] == '1') {
- fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
- abort();
- }
- }
-#endif
-
- const int profile_mask =
-#ifdef WITH_GL_EGL
-# if defined(WITH_GL_PROFILE_CORE)
- EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT;
-# else
-# error // must specify either core or compat at build time
-# endif
-#else
-# if defined(WITH_GL_PROFILE_CORE)
- GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
-# elif defined(WITH_GL_PROFILE_COMPAT)
- GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
-# else
-# error // must specify either core or compat at build time
-# endif
-#endif
-
GHOST_Context *context;
+#ifdef USE_EGL
+ /* Try to initialize an EGL context. */
for (int minor = 5; minor >= 0; --minor) {
-#if defined(WITH_GL_EGL)
- context = new GHOST_ContextEGL(this,
- false,
- EGLNativeWindowType(nullptr),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(false,
- (Window) nullptr,
- m_display,
- (GLXFBConfig) nullptr,
- profile_mask,
- 4,
- minor,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
-#endif
-
- if (context->initializeDrawingContext()) {
+ context = create_egl_context(this, m_display, debug_context, 4, minor);
+ if (context != nullptr) {
return context;
}
- delete context;
+ }
+ context = create_egl_context(this, m_display, debug_context, 3, 3);
+ if (context != nullptr) {
+ return context;
}
-#if defined(WITH_GL_EGL)
- context = new GHOST_ContextEGL(this,
- false,
- EGLNativeWindowType(nullptr),
- EGLNativeDisplayType(m_display),
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_EGL_CONTEXT_FLAGS |
- (debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
- GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
- EGL_OPENGL_API);
-#else
- context = new GHOST_ContextGLX(false,
- (Window) nullptr,
- m_display,
- (GLXFBConfig) nullptr,
- profile_mask,
- 3,
- 3,
- GHOST_OPENGL_GLX_CONTEXT_FLAGS |
- (debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
- GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+ /* EGL initialization failed, try to fallback to a GLX context. */
#endif
-
- if (context->initializeDrawingContext()) {
+ for (int minor = 5; minor >= 0; --minor) {
+ context = create_glx_context(m_display, debug_context, 4, minor);
+ if (context != nullptr) {
+ return context;
+ }
+ }
+ context = create_glx_context(m_display, debug_context, 3, 3);
+ if (context != nullptr) {
return context;
}
- delete context;
return nullptr;
}
@@ -513,8 +489,9 @@ static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
bool GHOST_SystemX11::openX11_IM()
{
- if (!m_display)
+ if (!m_display) {
return false;
+ }
/* set locale modifiers such as `@im=ibus` specified by XMODIFIERS. */
XSetLocaleModifiers("");
@@ -584,7 +561,7 @@ struct init_timestamp_data {
Time timestamp;
};
-static Bool init_timestamp_scanner(Display *, XEvent *event, XPointer arg)
+static Bool init_timestamp_scanner(Display * /*display*/, XEvent *event, XPointer arg)
{
init_timestamp_data *data = reinterpret_cast<init_timestamp_data *>(arg);
switch (event->type) {
@@ -663,7 +640,7 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
/* 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 (ELEM(xevent.type, FocusIn, KeyPress)) {
if (!m_xim && openX11_IM()) {
GHOST_PRINT("Connected to XIM server\n");
}
@@ -672,11 +649,12 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
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)
+ 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());
+ }
}
}
}
@@ -724,9 +702,9 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
* 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] = {
+ if (ELEM(xev_next.type, KeyPress, KeyRelease)) {
+ /* XK_Hyper_L/R currently unused. */
+ const static KeySym modifiers[] = {
XK_Shift_L,
XK_Shift_R,
XK_Control_L,
@@ -737,16 +715,15 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent)
XK_Super_R,
};
- for (int i = 0; i < (int)(sizeof(modifiers) / sizeof(*modifiers)); i++) {
+ for (int i = 0; i < (int)ARRAY_SIZE(modifiers); i++) {
KeyCode kc = XKeysymToKeycode(m_display, modifiers[i]);
if (kc != 0 && ((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',
- nullptr,
- false));
+ false,
+ nullptr));
}
}
}
@@ -822,7 +799,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
/* Detect auto-repeat. */
bool is_repeat = false;
- if (xe->type == KeyPress || xe->type == KeyRelease) {
+ if (ELEM(xe->type, KeyPress, KeyRelease)) {
XKeyEvent *xke = &(xe->xkey);
/* Set to true if this key will repeat. */
@@ -889,9 +866,11 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
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)) {
+ if (ELEM(notify_event->devchange,
+ DeviceEnabled,
+ DeviceDisabled,
+ DeviceAdded,
+ DeviceRemoved)) {
refreshXInputDevices();
/* update all window events */
@@ -1014,7 +993,9 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case KeyRelease: {
XKeyEvent *xke = &(xe->xkey);
KeySym key_sym;
+ char *utf8_buf = nullptr;
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
@@ -1023,12 +1004,10 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
* 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 */
+ int len = 1; /* at least one null character will be stored */
#else
- char *utf8_buf = nullptr;
+ char utf8_array[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
#endif
-
GHOST_TEventType type = (xke->type == KeyPress) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp;
GHOST_TKey gkey;
@@ -1148,81 +1127,94 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
#endif
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
- /* Setting unicode on key-up events gives #XLookupNone status. */
- XIC xic = window->getX11_XIC();
- if (xic && xke->type == KeyPress) {
- Status status;
+ /* Only used for key-press. */
+ XIC xic = nullptr;
+#endif
- /* Use utf8 because its not locale repentant, from XORG docs. */
- if (!(len = Xutf8LookupString(
- xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) {
- utf8_buf[0] = '\0';
- }
+ if (xke->type == KeyPress) {
+ utf8_buf = utf8_array;
+#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
+ /* Setting unicode on key-up events gives #XLookupNone status. */
+ xic = window->getX11_XIC();
+ if (xic) {
+ Status status;
+
+ /* Use utf8 because its not locale repentant, 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 == 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 */
+ if (ELEM(status, XLookupChars, 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 {
- utf8_buf[0] = '\0';
+ 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 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);
+ utf8_buf[0] = '\0';
}
- }
- else {
- utf8_buf[0] = '\0';
- }
#endif
+ if (!utf8_buf[0] && ascii) {
+ utf8_buf[0] = ascii;
+ utf8_buf[1] = '\0';
+ }
+ }
- g_event = new GHOST_EventKey(
- getMilliSeconds(), type, window, gkey, ascii, utf8_buf, is_repeat);
+ g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, is_repeat, 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) {
+ if (xke->type == KeyPress && xic) {
unsigned char c;
int i = 0;
- while (1) {
- /* search character boundary */
- if ((unsigned char)utf8_buf[i++] > 0x7f) {
+ while (true) {
+ /* Search character boundary. */
+ if ((uchar)utf8_buf[i++] > 0x7f) {
for (; i < len; ++i) {
c = utf8_buf[i];
- if (c < 0x80 || c > 0xbf)
+ if (c < 0x80 || c > 0xbf) {
break;
+ }
}
}
- if (i >= len)
+ if (i >= len) {
break;
-
- /* enqueue previous character */
+ }
+ /* Enqueue previous character. */
pushEvent(g_event);
g_event = new GHOST_EventKey(
- getMilliSeconds(), type, window, gkey, '\0', &utf8_buf[i], is_repeat);
+ getMilliSeconds(), type, window, gkey, is_repeat, &utf8_buf[i]);
}
}
- if (utf8_buf != utf8_array)
+ if (utf8_buf != utf8_array) {
free(utf8_buf);
+ }
#endif
break;
@@ -1231,7 +1223,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case ButtonPress:
case ButtonRelease: {
XButtonEvent &xbe = xe->xbutton;
- GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
+ GHOST_TButton gbmask = GHOST_kButtonMaskLeft;
GHOST_TEventType type = (xbe.type == ButtonPress) ? GHOST_kEventButtonDown :
GHOST_kEventButtonUp;
@@ -1306,10 +1298,12 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
XIC xic = window->getX11_XIC();
if (xic) {
- if (xe->type == FocusIn)
+ if (xe->type == FocusIn) {
XSetICFocus(xic);
- else
+ }
+ else {
XUnsetICFocus(xic);
+ }
}
#endif
@@ -1449,8 +1443,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
nxe.xselection.time = xse->time;
/* Check to see if the requester is asking for String */
- if (xse->target == utf8_string || xse->target == string || xse->target == compound_text ||
- xse->target == c_string) {
+ if (ELEM(xse->target, utf8_string, string, compound_text, c_string)) {
if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
XChangeProperty(m_display,
xse->requestor,
@@ -1503,7 +1496,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
default: {
#ifdef WITH_X11_XINPUT
for (GHOST_TabletX11 &xtablet : m_xtablets) {
- if (xe->type == xtablet.MotionEvent || xe->type == xtablet.PressEvent) {
+ if (ELEM(xe->type, xtablet.MotionEvent, xtablet.PressEvent)) {
XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe;
if (data->deviceid != xtablet.ID) {
continue;
@@ -2367,10 +2360,11 @@ class DialogData {
/* Is the mouse inside the given button */
bool isInsideButton(XEvent &e, uint button_num)
{
- return ((e.xmotion.y > height - padding_y - button_height) &&
- (e.xmotion.y < height - padding_y) &&
- (e.xmotion.x > width - (padding_x + button_width) * button_num) &&
- (e.xmotion.x < width - padding_x - (padding_x + button_width) * (button_num - 1)));
+ return (
+ (e.xmotion.y > (int)(height - padding_y - button_height)) &&
+ (e.xmotion.y < (int)(height - padding_y)) &&
+ (e.xmotion.x > (int)(width - (padding_x + button_width) * button_num)) &&
+ (e.xmotion.x < (int)(width - padding_x - (padding_x + button_width) * (button_num - 1))));
}
};
@@ -2574,7 +2568,7 @@ int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
static bool is_filler_char(char c)
{
- return isspace(c) || c == '_' || c == '-' || c == ';' || c == ':';
+ return isspace(c) || ELEM(c, '_', '-', ';', ':');
}
/* These C functions are copied from Wine 3.12's `wintab.c` */
@@ -2674,7 +2668,7 @@ void GHOST_SystemX11::refreshXInputDevices()
XFree((void *)device_type);
}
- if (!(tablet_mode == GHOST_kTabletModeStylus || tablet_mode == GHOST_kTabletModeEraser)) {
+ if (!ELEM(tablet_mode, GHOST_kTabletModeStylus, GHOST_kTabletModeEraser)) {
continue;
}