summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-04-11 14:36:55 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-04-11 14:36:55 +0200
commit98d3e40fb7c88b670a93e73dace2d0f05a5f903c (patch)
treeb1292124a86c219fb434db4ec28e8f805ff52287 /src/plugins/platforms/xcb
parenta74e4b85be83e2da47f4a1d8fcf0e78079335b80 (diff)
parentbab494e4d046f5617d19f5fec35eeff94377c51f (diff)
Merge remote-tracking branch 'origin/stable' into dev
Conflicts: mkspecs/qnx-armv7le-qcc/qplatformdefs.h src/printsupport/kernel/qcups.cpp src/widgets/styles/qstyle.h tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp Change-Id: Ia41e13051169a6d4a8a1267548e7d47b859bb267
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp33
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp28
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp50
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h11
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
5 files changed, 78 insertions, 46 deletions
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 1579797f85..57d6bc580b 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -94,14 +94,23 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
, m_gc_window(0)
{
Q_XCB_NOOP(connection());
- m_xcb_image = xcb_image_create_native(xcb_connection(),
- size.width(),
- size.height(),
- XCB_IMAGE_FORMAT_Z_PIXMAP,
- depth,
- 0,
- ~0,
- 0);
+
+ const xcb_setup_t *setup = xcb_get_setup(xcb_connection());
+ xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
+ xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
+ for (; fmt != fmtend; ++fmt)
+ if (fmt->depth == depth)
+ break;
+
+ Q_ASSERT(fmt != fmtend);
+
+ m_xcb_image = xcb_image_create(size.width(), size.height(),
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ fmt->scanline_pad,
+ fmt->depth, fmt->bits_per_pixel, 0,
+ QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST,
+ XCB_IMAGE_ORDER_MSB_FIRST,
+ 0, ~0, 0);
const int segmentSize = m_xcb_image->stride * m_xcb_image->height;
if (!segmentSize)
@@ -209,10 +218,13 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s
// at least 16384 bytes. That should be enough for quite large images.
Q_ASSERT(rows_per_put > 0);
+ // Convert the image to the native byte order.
+ xcb_image_t *converted_image = xcb_image_native(xcb_connection(), m_xcb_image, 1);
+
while (height > 0) {
int rows = std::min(height, rows_per_put);
- xcb_image_t *subimage = xcb_image_subimage(m_xcb_image, src_x, src_y, width, rows,
+ xcb_image_t *subimage = xcb_image_subimage(converted_image, src_x, src_y, width, rows,
0, 0, 0);
xcb_image_put(xcb_connection(),
window,
@@ -228,6 +240,9 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s
target_y += rows;
height -= rows;
}
+
+ if (converted_image != m_xcb_image)
+ xcb_image_destroy(converted_image);
}
Q_XCB_NOOP(connection());
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 66b8401ea2..f5f6c712c5 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -93,10 +93,37 @@
QT_BEGIN_NAMESPACE
#ifdef XCB_USE_XLIB
+static const char * const xcbConnectionErrors[] = {
+ "No error", /* Error 0 */
+ "I/O error", /* XCB_CONN_ERROR */
+ "Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
+ "Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
+ "Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
+ "Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
+ "No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
+ "Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
+};
+
static int nullErrorHandler(Display *, XErrorEvent *)
{
return 0;
}
+
+static int ioErrorHandler(Display *dpy)
+{
+ xcb_connection_t *conn = XGetXCBConnection(dpy);
+ if (conn != NULL) {
+ /* Print a message with a textual description of the error */
+ int code = xcb_connection_has_error(conn);
+ const char *str = "Unknown error";
+ int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
+ if (code >= 0 && code < arrayLength)
+ str = xcbConnectionErrors[code];
+
+ qWarning("The X11 connection broke: %s (code %d)", str, code);
+ }
+ return _XDefaultIOError(dpy);
+}
#endif
QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens,
@@ -284,6 +311,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_connection = XGetXCBConnection(dpy);
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
XSetErrorHandler(nullErrorHandler);
+ XSetIOErrorHandler(ioErrorHandler);
m_xlib_display = dpy;
}
#else
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 92b24f4722..69601f44d4 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -663,23 +663,17 @@ void QXcbKeyboard::clearXKBConfig()
memset(&xkb_names, 0, sizeof(xkb_names));
}
-void QXcbKeyboard::printKeymapError(const QString &error) const
+void QXcbKeyboard::printKeymapError(const char *error) const
{
- qWarning() << "Qt: " << error;
- // check if XKB config root is a valid path
- const QDir xkbRoot = qEnvironmentVariableIsSet("QT_XKB_CONFIG_ROOT")
- ? QString::fromLocal8Bit(qgetenv("QT_XKB_CONFIG_ROOT"))
- : DFLT_XKB_CONFIG_ROOT;
- if (!xkbRoot.exists() || xkbRoot.dirName() != "xkb") {
- qWarning() << "Set QT_XKB_CONFIG_ROOT to provide a valid XKB configuration data path, current search paths: "
- << xkbRoot.path() << ". Use ':' as separator to provide several search paths.";
- return;
+ qWarning() << error;
+ if (xkb_context) {
+ qWarning() << "Current XKB configuration data search paths are: ";
+ for (unsigned int i = 0; i < xkb_context_num_include_paths(xkb_context); ++i)
+ qWarning() << xkb_context_include_path_get(xkb_context, i);
}
- qWarning() << "_XKB_RULES_NAMES property contains:" << "\nrules : " << xkb_names.rules <<
- "\nmodel : " << xkb_names.model << "\nlayout : " << xkb_names.layout <<
- "\nvariant : " << xkb_names.variant << "\noptions : " << xkb_names.options <<
- "\nIf this looks like a valid keyboard layout information then you might need to "
- "update XKB configuration data on the system (http://cgit.freedesktop.org/xkeyboard-config/).";
+ qWarning() << "Use QT_XKB_CONFIG_ROOT environmental variable to provide an additional search path, "
+ "add ':' as separator to provide several search paths and/or make sure that XKB configuration data "
+ "directory contains recent enough contents, to update please see http://cgit.freedesktop.org/xkeyboard-config/ .";
}
void QXcbKeyboard::updateKeymap()
@@ -696,7 +690,7 @@ void QXcbKeyboard::updateKeymap()
xkb_context = xkb_context_new((xkb_context_flags)0);
}
if (!xkb_context) {
- printKeymapError("Failed to create XKB context!");
+ printKeymapError("Qt: Failed to create XKB context!");
m_config = false;
return;
}
@@ -731,8 +725,7 @@ void QXcbKeyboard::updateKeymap()
if (xkb_keymap) {
new_state = xkb_state_new(xkb_keymap);
} else {
- // failed to compile from RMLVO, give a verbose error message
- printKeymapError("Qt: Failed to compile a keymap!");
+ printKeymapError("Failed to compile a keymap!");
m_config = false;
return;
}
@@ -863,7 +856,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
return QList<int>();
QList<int> result;
- int baseQtKey = keysymToQtKey(sym, modifiers, keysymToUnicode(sym));
+ int baseQtKey = keysymToQtKey(sym, modifiers, lookupString(kb_state, event->nativeScanCode()));
result += (baseQtKey + modifiers); // The base key is _always_ valid, of course
xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift");
@@ -910,7 +903,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
continue;
Qt::KeyboardModifiers mods = modifiers & ~neededMods;
- qtKey = keysymToQtKey(sym, mods, keysymToUnicode(sym));
+ qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, event->nativeScanCode()));
if (qtKey == baseQtKey)
continue;
@@ -986,10 +979,10 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
, xkb_context(0)
, xkb_keymap(0)
, xkb_state(0)
- , core_device_id(0)
{
memset(&xkb_names, 0, sizeof(xkb_names));
#ifndef QT_NO_XKB
+ core_device_id = 0;
if (connection->hasXKB()) {
updateVModMapping();
updateVModToRModMapping();
@@ -1326,7 +1319,8 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
}
Qt::KeyboardModifiers modifiers = translateModifiers(state);
- QString string = keysymToUnicode(sym);
+
+ QString string = lookupString(xkb_state, code);
int count = string.size();
string.truncate(count);
@@ -1389,16 +1383,12 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
}
}
-QString QXcbKeyboard::keysymToUnicode(xcb_keysym_t sym) const
+QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
{
QByteArray chars;
- int bytes;
- chars.resize(7);
- bytes = xkb_keysym_to_utf8(sym, chars.data(), chars.size());
- if (bytes == -1)
- qWarning("QXcbKeyboard::handleKeyEvent - buffer too small");
- chars.resize(bytes-1);
-
+ chars.resize(1 + xkb_state_key_get_utf8(state, code, 0, 0));
+ // equivalent of XLookupString
+ xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
return QString::fromUtf8(chars);
}
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 36ce1ea2f0..11b7429aca 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -48,10 +48,7 @@
#include <xkbcommon/xkbcommon.h>
#ifndef QT_NO_XKB
-// note: extern won't be needed from libxkbcommon 0.4.1 and above
-extern "C" {
#include <xkbcommon/xkbcommon-x11.h>
-}
#endif
#include <QEvent>
@@ -79,9 +76,9 @@ public:
void updateXKBMods();
quint32 xkbModMask(quint16 state);
void updateXKBStateFromCore(quint16 state);
+#ifndef QT_NO_XKB
// when XKEYBOARD is present on the X server
int coreDeviceId() const { return core_device_id; }
-#ifndef QT_NO_XKB
void updateXKBState(xcb_xkb_state_notify_event_t *state);
#endif
@@ -89,10 +86,10 @@ protected:
void handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time);
void resolveMaskConflicts();
- QString keysymToUnicode(xcb_keysym_t sym) const;
+ QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
int keysymToQtKey(xcb_keysym_t keysym) const;
int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const;
- void printKeymapError(const QString &error) const;
+ void printKeymapError(const char *error) const;
void readXKBConfig();
void clearXKBConfig();
@@ -134,9 +131,11 @@ private:
xkb_mod_index_t mod5;
};
_xkb_mods xkb_mods;
+#ifndef QT_NO_XKB
// when XKEYBOARD is present on the X server
_mod_masks vmod_masks;
int core_device_id;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index bed6eb59dc..5a2002f1d4 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1174,7 +1174,7 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
void QXcbWindow::setTransparentForMouseEvents(bool transparent)
{
- if (transparent == m_transparent)
+ if (!connection()->hasXFixes() || transparent == m_transparent)
return;
xcb_rectangle_t rectangle;