summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qapplication_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qapplication_x11.cpp')
-rw-r--r--src/gui/kernel/qapplication_x11.cpp755
1 files changed, 488 insertions, 267 deletions
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index bf1251e..69dba40 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -78,11 +78,13 @@
#include <private/qcrashhandler_p.h>
#include <private/qcolor_p.h>
#include <private/qcursor_p.h>
+#include <private/qiconloader_p.h>
#include "qstyle.h"
#include "qmetaobject.h"
#include "qtimer.h"
#include "qlibrary.h"
#include <private/qgraphicssystemfactory_p.h>
+#include "qkde_p.h"
#if !defined (QT_NO_TABLET)
extern "C" {
@@ -130,6 +132,16 @@ extern "C" {
#include <private/qbackingstore_p.h>
+#ifdef QT_RX71_MULTITOUCH
+# include <qsocketnotifier.h>
+# include <linux/input.h>
+# include <errno.h>
+#endif
+
+#if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4)
+# define QT_NO_UNSETENV
+#endif
+
QT_BEGIN_NAMESPACE
//#define X_NOT_BROKEN
@@ -159,6 +171,8 @@ static const char * x11_atomnames = {
"WM_TAKE_FOCUS\0"
"_NET_WM_PING\0"
"_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
// ICCCM window state
"WM_STATE\0"
@@ -296,6 +310,10 @@ static const char * x11_atomnames = {
// XEMBED
"_XEMBED\0"
"_XEMBED_INFO\0"
+
+ "Wacom Stylus\0"
+ "Wacom Cursor\0"
+ "Wacom Eraser\0"
};
Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
@@ -506,6 +524,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
class QETWidget : public QWidget // event translator widget
{
public:
+ QWidgetPrivate* d_func() { return QWidget::d_func(); }
bool translateMouseEvent(const XEvent *);
void translatePaintEvent(const XEvent *);
bool translateConfigEvent(const XEvent *);
@@ -718,6 +737,44 @@ static int qt_xio_errhandler(Display *)
}
#endif
+#ifndef QT_NO_XSYNC
+struct qt_sync_request_event_data
+{
+ WId window;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_sync_request_event_data *data =
+ reinterpret_cast<qt_sync_request_event_data*>(arg);
+ if (event->type == ClientMessage &&
+ event->xany.window == data->window &&
+ event->xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) {
+ QWidget *w = QWidget::find(event->xany.window);
+ if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+#endif // QT_NO_XSYNC
static void qt_x11_create_intern_atoms()
{
@@ -759,26 +816,6 @@ Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
}
/*! \internal
- Gets the current KDE 3 or 4 home path
-*/
-QString QApplicationPrivate::kdeHome()
-{
- static QString kdeHomePath;
- if (kdeHomePath.isEmpty()) {
- kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
- if (kdeHomePath.isEmpty()) {
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
- QDir homeDir(QDir::homePath());
- QString kdeConfDir(QLatin1String("/.kde"));
- if (4 == kdeSessionVersion && homeDir.exists(QLatin1String(".kde4")))
- kdeConfDir = QLatin1String("/.kde4");
- kdeHomePath = QDir::homePath() + kdeConfDir;
- }
- }
- return kdeHomePath;
-}
-
-/*! \internal
apply the settings to the application
*/
bool QApplicationPrivate::x11_apply_settings()
@@ -834,30 +871,32 @@ bool QApplicationPrivate::x11_apply_settings()
}
// ### Fix properly for 4.6
- if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) {
+ bool usingGtkSettings = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
+ if (!usingGtkSettings) {
if (groupCount == QPalette::NColorGroups)
QApplicationPrivate::setSystemPalette(pal);
}
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
-
if (!appFont) {
- QFont font(QApplication::font());
- QString fontDescription;
- // Override Qt font if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
- QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- fontDescription = kdeSettings.value(QLatin1String("font")).toString();
- if (fontDescription.isEmpty()) {
- // KDE stores fonts without quotes
- fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
+ // ### Fix properly for 4.6
+ if (!usingGtkSettings) {
+ QFont font(QApplication::font());
+ QString fontDescription;
+ // Override Qt font if KDE4 settings can be used
+ if (X11->desktopVersion == 4) {
+ QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ fontDescription = kdeSettings.value(QLatin1String("font")).toString();
+ if (fontDescription.isEmpty()) {
+ // KDE stores fonts without quotes
+ fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
+ }
+ }
+ if (fontDescription.isEmpty())
+ fontDescription = settings.value(QLatin1String("font")).toString();
+ if (!fontDescription .isEmpty()) {
+ font.fromString(fontDescription );
+ QApplicationPrivate::setSystemFont(font);
}
- }
- if (fontDescription.isEmpty())
- fontDescription = settings.value(QLatin1String("font")).toString();
- if (!fontDescription .isEmpty()) {
- font.fromString(fontDescription );
- QApplicationPrivate::setSystemFont(font);
}
}
@@ -875,29 +914,15 @@ bool QApplicationPrivate::x11_apply_settings()
// read new QStyle
QString stylename = settings.value(QLatin1String("style")).toString();
- if (stylename.isEmpty() && !QApplicationPrivate::styleOverride && X11->use_xrender) {
- QStringList availableStyles = QStyleFactory::keys();
- // Override Qt style if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
- QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"),
- QLatin1String("Oxygen")).toString();
- foreach (const QString &style, availableStyles) {
- if (style.toLower() == kde4Style.toLower())
- stylename = kde4Style;
- }
- // Set QGtkStyle for GNOME
- } else if (X11->desktopEnvironment == DE_GNOME) {
- QString gtkStyleKey = QString::fromLatin1("GTK+");
- if (availableStyles.contains(gtkStyleKey))
- stylename = gtkStyleKey;
- }
+
+ if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) {
+ stylename = x11_desktop_style();
}
static QString currentStyleName = stylename;
if (QCoreApplication::startingUp()) {
- if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
- QApplicationPrivate::styleOverride = new QString(stylename);
+ if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
+ QApplicationPrivate::styleOverride = stylename;
} else {
if (currentStyleName != stylename) {
currentStyleName = stylename;
@@ -1047,24 +1072,6 @@ static void qt_set_input_encoding()
XFree((char *)data);
}
-// Reads a KDE color setting
-static QColor kdeColor(const QString &key)
-{
- QSettings kdeSettings(QApplicationPrivate::kdeHome() +
- QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- QVariant variant = kdeSettings.value(key);
- if (variant.isValid()) {
- QStringList values = variant.toStringList();
- if (values.size() == 3) {
- int r = values[0].toInt();
- int g = values[1].toInt();
- int b = values[2].toInt();
- return QColor(r, g, b);
- }
- }
- return QColor();
-}
-
// set font, foreground and background from x11 resources. The
// arguments may override the resource settings.
static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
@@ -1085,7 +1092,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
if (QApplication::desktopSettingsAware()) {
// first, read from settings
QApplicationPrivate::x11_apply_settings();
-
// the call to QApplication::style() below creates the system
// palette, which breaks the logic after the RESOURCE_MANAGER
// loop... so I have to save this value to be able to use it later
@@ -1231,9 +1237,10 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
QApplicationPrivate::setSystemFont(fnt);
}
+ // QGtkStyle sets it's own system palette
+ bool gtkStyle = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE);
-
- if (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty())) {// set app colors
+ if (!gtkStyle && (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty()))) {// set app colors
bool allowX11ColorNames = QColor::allowX11ColorNames();
QColor::setAllowX11ColorNames(true);
@@ -1269,41 +1276,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
bright_mode = true;
}
- if (kdeColors) {
- // Setup KDE palette
- QColor color;
- color = kdeColor(QLatin1String("buttonBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/BackgroundNormal"));
- if (color.isValid())
- btn = color;
-
- color = kdeColor(QLatin1String("background"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/BackgroundNormal"));
- if (color.isValid())
- bg = color;
-
- color = kdeColor(QLatin1String("foreground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/ForegroundNormal"));
- if (color.isValid()) {
- fg = color;
- }
-
- color = kdeColor(QLatin1String("windowForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Window/ForegroundNormal"));
- if (color.isValid())
- wfg = color;
-
- color = kdeColor(QLatin1String("windowBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundNormal"));
- if (color.isValid())
- base = color;
- }
-
QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg);
QColor disabled((fg.red() + btn.red()) / 2,
(fg.green() + btn.green())/ 2,
@@ -1316,34 +1288,6 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
highlight = QColor(selectBackground);
highlightText = QColor(selectForeground);
}
- // Use KDE3 or KDE4 color settings if present
- if (kdeColors) {
- QColor color = kdeColor(QLatin1String("selectBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/BackgroundNormal"));
- if (color.isValid())
- highlight = color;
-
- color = kdeColor(QLatin1String("selectForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Selection/ForegroundNormal"));
- if (color.isValid())
- highlightText = color;
-
- color = kdeColor(QLatin1String("alternateBackground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:View/BackgroundAlternate"));
- if (color.isValid())
- pal.setColor(QPalette::AlternateBase, color);
- else
- pal.setBrush(QPalette::AlternateBase, pal.base().color().darker(110));
-
- color = kdeColor(QLatin1String("buttonForeground"));
- if (!color.isValid())
- color = kdeColor(QLatin1String("Colors:Button/ForegroundNormal"));
- if (color.isValid())
- pal.setColor(QPalette::ButtonText, color);
- }
if (highlight.isValid() && highlightText.isValid()) {
pal.setColor(QPalette::Highlight, highlight);
@@ -1366,10 +1310,9 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
}
- // QGtkStyle sets it's own system palette
- if (!(QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"))) {
- QApplicationPrivate::setSystemPalette(pal);
- }
+ if (kdeColors)
+ pal = QKde::kdePalette().resolve(pal);
+ QApplicationPrivate::setSystemPalette(pal);
QColor::setAllowX11ColorNames(allowX11ColorNames);
}
@@ -1389,6 +1332,8 @@ static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
effects.contains(QLatin1String("animatetoolbox")));
}
+
+ QIconLoader::instance()->updateSystemTheme();
}
@@ -1583,6 +1528,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0;
static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0;
static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0;
static PtrWacomConfigTerm ptrWacomConfigTerm = 0;
+Q_GLOBAL_STATIC(QByteArray, wacomDeviceName)
#endif
#endif
@@ -1723,7 +1669,7 @@ void qt_init(QApplicationPrivate *priv, int,
X11->pattern_fills[i].screen = -1;
#endif
- X11->startupId = X11->originalStartupId = 0;
+ X11->startupId = 0;
int argc = priv->argc;
char **argv = priv->argv;
@@ -1905,10 +1851,20 @@ void qt_init(QApplicationPrivate *priv, int,
QX11InfoData *screen = X11->screens + s;
screen->ref = 1; // ensures it doesn't get deleted
screen->screen = s;
- screen->dpiX = (DisplayWidth(X11->display, s) * 254 + DisplayWidthMM(X11->display, s)*5)
- / (DisplayWidthMM(X11->display, s)*10);
- screen->dpiY = (DisplayHeight(X11->display, s) * 254 + DisplayHeightMM(X11->display, s)*5)
- / (DisplayHeightMM(X11->display, s)*10);
+
+ int widthMM = DisplayWidthMM(X11->display, s);
+ if (widthMM != 0) {
+ screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
+ } else {
+ screen->dpiX = 72;
+ }
+
+ int heightMM = DisplayHeightMM(X11->display, s);
+ if (heightMM != 0) {
+ screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
+ } else {
+ screen->dpiY = 72;
+ }
X11->argbVisuals[s] = 0;
X11->argbColormaps[s] = 0;
@@ -2084,6 +2040,13 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_RUNTIME_XCURSOR
#endif // QT_NO_XCURSOR
+#ifndef QT_NO_XSYNC
+ int xsync_evbase, xsync_errbase;
+ int major, minor;
+ if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
+ XSyncInitialize(X11->display, &major, &minor);
+#endif // QT_NO_XSYNC
+
#ifndef QT_NO_XINERAMA
#ifdef QT_RUNTIME_XINERAMA
X11->ptrXineramaQueryExtension = 0;
@@ -2245,6 +2208,7 @@ void qt_init(QApplicationPrivate *priv, int,
X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
ATOM(_NET_WM_CM_S0));
X11->desktopEnvironment = DE_UNKNOWN;
+ X11->desktopVersion = 0;
// See if the current window manager is using the freedesktop.org spec to give its name
Window windowManagerWindow = XNone;
@@ -2320,6 +2284,9 @@ void qt_init(QApplicationPrivate *priv, int,
XFree((char *)data);
}
+ if (X11->desktopEnvironment == DE_KDE)
+ X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+
qt_set_input_encoding();
qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
@@ -2355,13 +2322,6 @@ void qt_init(QApplicationPrivate *priv, int,
XAxisInfoPtr a;
XDevice *dev = 0;
-#if !defined(Q_OS_IRIX)
- // XFree86 divides a stylus and eraser into 2 devices, so we must do for both...
- const QString XFREENAMESTYLUS = QLatin1String("stylus");
- const QString XFREENAMEPEN = QLatin1String("pen");
- const QString XFREENAMEERASER = QLatin1String("eraser");
-#endif
-
if (X11->ptrXListInputDevices) {
devices = X11->ptrXListInputDevices(X11->display, &ndev);
if (!devices)
@@ -2376,18 +2336,19 @@ void qt_init(QApplicationPrivate *priv, int,
gotStylus = false;
gotEraser = false;
- QString devName = QString::fromLocal8Bit(devs->name).toLower();
#if defined(Q_OS_IRIX)
+ QString devName = QString::fromLocal8Bit(devs->name).toLower();
if (devName == QLatin1String(WACOM_NAME)) {
deviceType = QTabletEvent::Stylus;
gotStylus = true;
}
#else
- if (devName.startsWith(XFREENAMEPEN)
- || devName.startsWith(XFREENAMESTYLUS)) {
+ if (devs->type == ATOM(XWacomStylus)) {
deviceType = QTabletEvent::Stylus;
+ if (wacomDeviceName()->isEmpty())
+ wacomDeviceName()->append(devs->name);
gotStylus = true;
- } else if (devName.startsWith(XFREENAMEERASER)) {
+ } else if (devs->type == ATOM(XWacomEraser)) {
deviceType = QTabletEvent::XFreeEraser;
gotEraser = true;
}
@@ -2523,10 +2484,15 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_NO_TABLET
X11->startupId = getenv("DESKTOP_STARTUP_ID");
- X11->originalStartupId = X11->startupId;
- static char desktop_startup_id[] = "DESKTOP_STARTUP_ID=";
- putenv(desktop_startup_id);
-
+ if (X11->startupId) {
+#ifndef QT_NO_UNSETENV
+ unsetenv("DESKTOP_STARTUP_ID");
+#else
+ // it's a small memory leak, however we won't crash if Qt is
+ // unloaded and someones tries to use the envoriment.
+ putenv(strdup("DESKTOP_STARTUP_ID="));
+#endif
+ }
} else {
// read some non-GUI settings when not using the X server...
@@ -2585,31 +2551,35 @@ void qt_init(QApplicationPrivate *priv, int,
/*!
\internal
*/
-void QApplicationPrivate::x11_initialize_style()
+QString QApplicationPrivate::x11_desktop_style()
{
- if (QApplicationPrivate::app_style)
- return;
-
+ QString stylename;
switch(X11->desktopEnvironment) {
- case DE_KDE:
- if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique"));
- else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
- break;
- case DE_GNOME:
- if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks"));
- else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
- break;
- case DE_CDE:
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde"));
- break;
- default:
- // Don't do anything
+ case DE_KDE:
+ stylename = QKde::kdeStyle();
+ break;
+ case DE_GNOME: {
+ QStringList availableStyles = QStyleFactory::keys();
+ // Set QGtkStyle for GNOME if available
+ QString gtkStyleKey = QString::fromLatin1("GTK+");
+ if (availableStyles.contains(gtkStyleKey)) {
+ stylename = gtkStyleKey;
break;
+ }
+ if (X11->use_xrender)
+ stylename = QLatin1String("cleanlooks");
+ else
+ stylename = QLatin1String("windows");
+ break;
+ }
+ case DE_CDE:
+ stylename = QLatin1String("cde");
+ break;
+ default:
+ // Don't do anything
+ break;
}
+ return stylename;
}
void QApplicationPrivate::initializeWidgetPaletteHash()
@@ -2640,10 +2610,6 @@ void qt_cleanup()
#endif
}
- // restore original value back. This is also done in QWidgetPrivate::show_sys.
- if (X11->originalStartupId)
- putenv(X11->originalStartupId);
-
#ifndef QT_NO_XRENDER
for (int i = 0; i < X11->solid_fill_count; ++i) {
if (X11->solid_fills[i].picture)
@@ -2978,7 +2944,7 @@ QWidget *QApplication::topLevelAt(const QPoint &p)
void QApplication::syncX()
{
if (X11->display)
- XSync(X11->display, False); // don't discard events
+ XSync(X11->display, False); // don't discard events
}
@@ -3116,6 +3082,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
XSendEvent(event->xclient.display, event->xclient.window,
False, SubstructureNotifyMask|SubstructureRedirectMask, event);
}
+#ifndef QT_NO_XSYNC
+ } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (QTLWExtra *tlw = w->d_func()->maybeTopData()) {
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+#endif
}
} else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
widget->translateScrollDoneEvent(event);
@@ -3146,6 +3125,7 @@ int QApplication::x11ProcessEvent(XEvent* event)
{
Q_D(QApplication);
QScopedLoopLevelCounter loopLevelCounter(d->threadData);
+
#ifdef ALIEN_DEBUG
//qDebug() << "QApplication::x11ProcessEvent:" << event->type;
#endif
@@ -3351,19 +3331,10 @@ int QApplication::x11ProcessEvent(XEvent* event)
QSize oldSize(w->size());
w->data->crect.setWidth(DisplayWidth(X11->display, scr));
w->data->crect.setHeight(DisplayHeight(X11->display, scr));
- QVarLengthArray<QRect> oldSizes(desktop->numScreens());
- for (int i = 0; i < desktop->numScreens(); ++i)
- oldSizes[i] = desktop->screenGeometry(i);
QResizeEvent e(w->size(), oldSize);
QApplication::sendEvent(w, &e);
- for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) {
- if (oldSizes[i] != desktop->screenGeometry(i))
- emit desktop->resized(i);
- }
- for (int i = oldSizes.count(); i < desktop->numScreens(); ++i)
- emit desktop->resized(i); // added
- for (int i = desktop->numScreens(); i < oldSizes.count(); ++i)
- emit desktop->resized(i); // removed
+ if (w != desktop)
+ QApplication::sendEvent(desktop, &e);
}
#endif // QT_NO_XRANDR
@@ -4139,7 +4110,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
|| ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
&& qt_button_down == this)
|| (nextEvent.type == ClientMessage
- && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
+ && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) ||
+ (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) {
qApp->x11ProcessEvent(&nextEvent);
continue;
} else if (nextEvent.type != MotionNotify ||
@@ -4409,7 +4382,6 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
qt_last_mouse_receiver);
-
if (type == QEvent::MouseButtonPress
&& button == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
@@ -4478,8 +4450,7 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId)
WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
if (config == 0)
return;
- const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently)
- WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name);
+ WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData());
if (device == 0)
return;
unsigned keys[1];
@@ -4537,6 +4508,46 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId)
}
#endif
+struct qt_tablet_motion_data
+{
+ Time timestamp;
+ int tabletMotionType;
+ bool error; // found a reason to stop searching
+};
+
+static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg)
+{
+ qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
+ if (data->error)
+ return false;
+
+ if (event->type == MotionNotify)
+ return true;
+
+ data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between.
+ return false;
+}
+
+static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg)
+{
+ qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
+ if (data->error)
+ return false;
+
+ if (event->type == data->tabletMotionType) {
+ if (data->timestamp > 0) {
+ if ((reinterpret_cast<const XDeviceMotionEvent*>(event))->time > data->timestamp) {
+ data->error = true;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ data->error = event->type != MotionNotify; // we stop compression when another event gets in between.
+ return false;
+}
+
bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet)
{
#if defined (Q_OS_IRIX)
@@ -4563,16 +4574,14 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet
qreal rotation = 0;
int deviceType = QTabletEvent::NoDevice;
int pointerType = QTabletEvent::UnknownPointer;
- XEvent xinputMotionEvent;
XEvent mouseMotionEvent;
+ XEvent dummy;
const XDeviceMotionEvent *motion = 0;
XDeviceButtonEvent *button = 0;
const XProximityNotifyEvent *proximity = 0;
QEvent::Type t;
Qt::KeyboardModifiers modifiers = 0;
bool reinsertMouseEvent = false;
- bool neverFoundMouseEvent = true;
- XEvent xinputMotionEventNext;
XEvent mouseMotionEventSave;
#if !defined (Q_OS_IRIX)
XID device_id;
@@ -4580,72 +4589,40 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet
if (ev->type == tablet->xinput_motion) {
motion = reinterpret_cast<const XDeviceMotionEvent*>(ev);
- for (;;) {
- // get the corresponding mouseMotionEvent for motion
- if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) {
+
+ // Do event compression. Skip over tablet+mouse move events if there are newer ones.
+ qt_tablet_motion_data tabletMotionData;
+ tabletMotionData.tabletMotionType = tablet->xinput_motion;
+ while (true) {
+ // Find first mouse event since we expect them in pairs inside Qt
+ tabletMotionData.error =false;
+ tabletMotionData.timestamp = 0;
+ if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) {
mouseMotionEventSave = mouseMotionEvent;
reinsertMouseEvent = true;
- neverFoundMouseEvent = false;
-
- if (mouseMotionEvent.xmotion.time > motion->time) {
- XEvent xinputMotionEventLoop = *ev;
-
- // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event
- while (mouseMotionEvent.xmotion.time > (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEventLoop))->time) {
- if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
- xinputMotionEvent = xinputMotionEventLoop;
- }
- else {
- break;
- }
- }
- motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
- }
-
- // get the next xinputMotionEvent, for the next loop run
- if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) {
- XPutBackEvent(X11->display, &mouseMotionEvent);
- reinsertMouseEvent = false;
- break;
- }
-
- if (mouseMotionEvent.xmotion.time != motion->time) {
- // reinsert in order
- if (mouseMotionEvent.xmotion.time >= motion->time) {
- XPutBackEvent(X11->display, &mouseMotionEvent);
- XPutBackEvent(X11->display, &xinputMotionEventNext);
- // next entry in queue is xinputMotionEventNext
- }
- else {
- XPutBackEvent(X11->display, &xinputMotionEventNext);
- XPutBackEvent(X11->display, &mouseMotionEvent);
- // next entry in queue is mouseMotionEvent
- }
- reinsertMouseEvent = false;
- break;
- }
- }
- else {
+ } else {
break;
}
- xinputMotionEvent = xinputMotionEventNext;
- motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent));
- }
+ // Now discard any duplicate tablet events.
+ tabletMotionData.error = false;
+ tabletMotionData.timestamp = mouseMotionEvent.xmotion.time;
+ while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy);
+ }
- if (reinsertMouseEvent) {
- XPutBackEvent(X11->display, &mouseMotionEventSave);
+ // now check if there are more recent tablet motion events since we'll compress the current one with
+ // newer ones in that case
+ tabletMotionData.error = false;
+ tabletMotionData.timestamp = 0;
+ if (! XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
+ break; // done with compression
+ }
+ motion = reinterpret_cast<const XDeviceMotionEvent*>(&dummy);
}
- if (neverFoundMouseEvent) {
- XEvent xinputMotionEventLoop;
- bool eventFound = false;
- // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent
- while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) {
- xinputMotionEvent = xinputMotionEventLoop;
- eventFound = true;
- }
- if (eventFound) motion = reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent);
+ if (reinsertMouseEvent) {
+ XPutBackEvent(X11->display, &mouseMotionEventSave);
}
t = QEvent::TabletMove;
@@ -5018,6 +4995,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event)
return true;
}
+
//
// Paint event translation
//
@@ -5196,6 +5174,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
otherEvent.xconfigure.border_width;
}
}
+#ifndef QT_NO_XSYNC
+ qt_sync_request_event_data sync_event;
+ sync_event.window = internalWinId();
+ for (XEvent ev;;) {
+ if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
+ break;
+ }
+#endif // QT_NO_XSYNC
}
QRect cr (geometry());
@@ -5281,6 +5267,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
if (d->extra && d->extra->topextra)
d->extra->topextra->inTopLevelResize = false;
}
+#ifndef QT_NO_XSYNC
+ if (QTLWExtra *tlwExtra = d->maybeTopData()) {
+ if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
+ XSyncValue value;
+ XSyncIntsToValue(&value,
+ tlwExtra->newCounterValueLo,
+ tlwExtra->newCounterValueHi);
+
+ XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
+ tlwExtra->newCounterValueHi = 0;
+ tlwExtra->newCounterValueLo = 0;
+ }
+ }
+#endif
return true;
}
@@ -5898,4 +5898,225 @@ void QSessionManager::requestPhase2()
#endif // QT_NO_SESSIONMANAGER
+#if defined(QT_RX71_MULTITOUCH)
+
+static inline int testBit(const char *array, int bit)
+{
+ return (array[bit/8] & (1<<(bit%8)));
+}
+
+static int openRX71Device(const QByteArray &deviceName)
+{
+ int fd = open(deviceName, O_RDONLY | O_NONBLOCK);
+ if (fd == -1) {
+ fd = -errno;
+ return fd;
+ }
+
+ // fetch the event type mask and check that the device reports absolute coordinates
+ char eventTypeMask[(EV_MAX + sizeof(char) - 1) * sizeof(char) + 1];
+ memset(eventTypeMask, 0, sizeof(eventTypeMask));
+ if (ioctl(fd, EVIOCGBIT(0, sizeof(eventTypeMask)), eventTypeMask) < 0) {
+ close(fd);
+ return -1;
+ }
+ if (!testBit(eventTypeMask, EV_ABS)) {
+ close(fd);
+ return -1;
+ }
+
+ // make sure that we can get the absolute X and Y positions from the device
+ char absMask[(ABS_MAX + sizeof(char) - 1) * sizeof(char) + 1];
+ memset(absMask, 0, sizeof(absMask));
+ if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absMask)), absMask) < 0) {
+ close(fd);
+ return -1;
+ }
+ if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{
+ Q_Q(QApplication);
+
+ QByteArray deviceName = QByteArray("/dev/input/event");
+ int currentDeviceNumber = 0;
+ for (;;) {
+ int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++)));
+ if (fd == -ENOENT) {
+ // no more devices
+ break;
+ }
+ if (fd < 0) {
+ // not a touch device
+ continue;
+ }
+
+ struct input_absinfo abs_x, abs_y, abs_z;
+ ioctl(fd, EVIOCGABS(ABS_X), &abs_x);
+ ioctl(fd, EVIOCGABS(ABS_Y), &abs_y);
+ ioctl(fd, EVIOCGABS(ABS_Z), &abs_z);
+
+ int deviceNumber = allRX71TouchPoints.count();
+
+ QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
+ QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents()));
+
+ RX71TouchPointState touchPointState = {
+ socketNotifier,
+ QTouchEvent::TouchPoint(deviceNumber),
+
+ abs_x.minimum, abs_x.maximum, q->desktop()->screenGeometry().width(),
+ abs_y.minimum, abs_y.maximum, q->desktop()->screenGeometry().height(),
+ abs_z.minimum, abs_z.maximum
+ };
+ allRX71TouchPoints.append(touchPointState);
+ }
+
+ hasRX71MultiTouch = allRX71TouchPoints.count() > 1;
+ if (!hasRX71MultiTouch) {
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
+ QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
+ close(socketNotifier->socket());
+ delete socketNotifier;
+ }
+ allRX71TouchPoints.clear();
+ }
+}
+
+void QApplicationPrivate::cleanupMultitouch_sys()
+{
+ hasRX71MultiTouch = false;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
+ QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
+ close(socketNotifier->socket());
+ delete socketNotifier;
+ }
+ allRX71TouchPoints.clear();
+}
+
+bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber)
+{
+ RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber];
+ QSocketNotifier *socketNotifier = touchPointState.socketNotifier;
+ int fd = socketNotifier->socket();
+
+ QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint;
+
+ bool down = touchPoint.state() != Qt::TouchPointReleased;
+ if (down)
+ touchPoint.setState(Qt::TouchPointStationary);
+
+ bool changed = false;
+ for (;;) {
+ struct input_event inputEvent;
+ int bytesRead = read(fd, &inputEvent, sizeof(inputEvent));
+ if (bytesRead <= 0)
+ break;
+ if (bytesRead != sizeof(inputEvent)) {
+ qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()");
+ return false;
+ }
+
+ switch (inputEvent.type) {
+ case EV_SYN:
+ changed = true;
+ switch (touchPoint.state()) {
+ case Qt::TouchPointPressed:
+ case Qt::TouchPointReleased:
+ // make sure we don't compress pressed and releases with any other events
+ return changed;
+ default:
+ break;
+ }
+ continue;
+ case EV_KEY:
+ case EV_ABS:
+ break;
+ default:
+ qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type);
+ continue;
+ }
+
+ QPointF screenPos = touchPoint.screenPos();
+ switch (inputEvent.code) {
+ case BTN_TOUCH:
+ if (!down && inputEvent.value != 0)
+ touchPoint.setState(Qt::TouchPointPressed);
+ else if (down && inputEvent.value == 0)
+ touchPoint.setState(Qt::TouchPointReleased);
+ break;
+ case ABS_TOOL_WIDTH:
+ case ABS_VOLUME:
+ case ABS_PRESSURE:
+ // ignore for now
+ break;
+ case ABS_X:
+ {
+ qreal newValue = ((qreal(inputEvent.value - touchPointState.minX)
+ / qreal(touchPointState.maxX - touchPointState.minX))
+ * touchPointState.scaleX);
+ screenPos.rx() = newValue;
+ touchPoint.setScreenPos(screenPos);
+ break;
+ }
+ case ABS_Y:
+ {
+ qreal newValue = ((qreal(inputEvent.value - touchPointState.minY)
+ / qreal(touchPointState.maxY - touchPointState.minY))
+ * touchPointState.scaleY);
+ screenPos.ry() = newValue;
+ touchPoint.setScreenPos(screenPos);
+ break;
+ }
+ case ABS_Z:
+ {
+ // map Z (signal strength) to pressure for now
+ qreal newValue = (qreal(inputEvent.value - touchPointState.minZ)
+ / qreal(touchPointState.maxZ - touchPointState.minZ));
+ touchPoint.setPressure(newValue);
+ break;
+ }
+ default:
+ qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code);
+ continue;
+ }
+ }
+
+ if (down && touchPoint.state() != Qt::TouchPointReleased)
+ touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary);
+
+ return changed;
+}
+
+void QApplicationPrivate::_q_readRX71MultiTouchEvents()
+{
+ // read touch events from all devices
+ bool changed = false;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i)
+ changed = readRX71MultiTouchEvents(i) || changed;
+ if (!changed)
+ return;
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ for (int i = 0; i < allRX71TouchPoints.count(); ++i)
+ touchPoints.append(allRX71TouchPoints.at(i).touchPoint);
+
+ translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints);
+}
+
+#else // !QT_RX71_MULTITOUCH
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
+#endif // QT_RX71_MULTITOUCH
+
QT_END_NAMESPACE