Merge remote-tracking branch 'origin/5.7' into dev

Conflicts:
	.qmake.conf
	examples/wayland/minimal-qml/main.qml

Change-Id: Ic34029a6aa77f2b359f40258a05421d82efd5b37
This commit is contained in:
Liang Qi 2016-08-02 10:44:58 +02:00
commit 70d36235b1
11 changed files with 141 additions and 71 deletions

View File

@ -39,7 +39,9 @@
#include <QObject>
#include <QtWaylandClient/qwaylandclientexport.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
struct wl_registry;
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {

View File

@ -137,6 +137,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
, mLastInputSerial(0)
, mLastInputDevice(0)
, mLastInputWindow(0)
, mLastKeyboardFocus(Q_NULLPTR)
, mSyncCallback(Q_NULLPTR)
{
qRegisterMetaType<uint32_t>("uint32_t");
@ -393,6 +395,73 @@ void QWaylandDisplay::setLastInputDevice(QWaylandInputDevice *device, uint32_t s
mLastInputWindow = win;
}
bool QWaylandDisplay::shellManagesActiveState() const
{
//TODO: This should be part of a shell interface used by the shell protocol implementations
return mShellXdg;
}
void QWaylandDisplay::handleWindowActivated(QWaylandWindow *window)
{
if (mActiveWindows.contains(window))
return;
mActiveWindows.append(window);
requestWaylandSync();
}
void QWaylandDisplay::handleWindowDeactivated(QWaylandWindow *window)
{
Q_ASSERT(!mActiveWindows.empty());
if (mActiveWindows.last() == window)
requestWaylandSync();
mActiveWindows.removeOne(window);
}
void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice)
{
QWaylandWindow *keyboardFocus = inputDevice->keyboardFocus();
if (!shellManagesActiveState() && mLastKeyboardFocus != keyboardFocus) {
if (keyboardFocus)
handleWindowActivated(keyboardFocus);
if (mLastKeyboardFocus)
handleWindowDeactivated(mLastKeyboardFocus);
}
mLastKeyboardFocus = inputDevice->keyboardFocus();
}
void QWaylandDisplay::handleWaylandSync()
{
// This callback is used to set the window activation because we may get an activate/deactivate
// pair, and the latter one would be lost in the QWindowSystemInterface queue, if we issue the
// handleWindowActivated() calls immediately.
QWindow *activeWindow = mActiveWindows.empty() ? Q_NULLPTR : mActiveWindows.last()->window();
if (activeWindow != QGuiApplication::focusWindow())
QWindowSystemInterface::handleWindowActivated(activeWindow);
}
const wl_callback_listener QWaylandDisplay::syncCallbackListener = {
[](void *data, struct wl_callback *callback, uint32_t time){
Q_UNUSED(time);
wl_callback_destroy(callback);
QWaylandDisplay *display = static_cast<QWaylandDisplay *>(data);
display->mSyncCallback = Q_NULLPTR;
display->handleWaylandSync();
}
};
void QWaylandDisplay::requestWaylandSync()
{
if (mSyncCallback)
return;
mSyncCallback = wl_display_sync(mDisplay);
wl_callback_add_listener(mSyncCallback, &syncCallbackListener, this);
}
}
QT_END_NAMESPACE

View File

@ -54,6 +54,7 @@
#include <QtCore/QObject>
#include <QtCore/QRect>
#include <QtCore/QPointer>
#include <QtCore/QVector>
#include <QtCore/QWaitCondition>
@ -174,6 +175,11 @@ public:
QWaylandWindow *lastInputWindow() const;
void setLastInputDevice(QWaylandInputDevice *device, uint32_t serial, QWaylandWindow *window);
bool shellManagesActiveState() const;
void handleWindowActivated(QWaylandWindow *window);
void handleWindowDeactivated(QWaylandWindow *window);
void handleKeyboardFocusChanged(QWaylandInputDevice *inputDevice);
public slots:
void blockingReadEvents();
void flushRequests();
@ -183,6 +189,9 @@ private:
void exitWithError();
void checkError() const;
void handleWaylandSync();
void requestWaylandSync();
struct Listener {
RegistryListener listener;
void *data;
@ -213,6 +222,10 @@ private:
uint32_t mLastInputSerial;
QWaylandInputDevice *mLastInputDevice;
QPointer<QWaylandWindow> mLastInputWindow;
QWaylandWindow *mLastKeyboardFocus;
QVector<QWaylandWindow *> mActiveWindows;
struct wl_callback *mSyncCallback;
static const wl_callback_listener syncCallbackListener;
void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE;
void registry_global_remove(uint32_t id) Q_DECL_OVERRIDE;

View File

@ -335,8 +335,9 @@ void QWaylandTextInput::zwp_text_input_v2_keysym(uint32_t time, uint32_t sym, ui
Qt::KeyboardModifiers qtModifiers = modifiersToQtModifiers(modifiers);
QEvent::Type type = QWaylandXkb::toQtEventType(state);
const QString &text = QWaylandXkb::textFromKeysym(sym, qtModifiers);
int qtkey = QWaylandXkb::keysymToQtKey(sym, qtModifiers, text);
QString text;
int qtkey;
std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, qtModifiers);
QWindowSystemInterface::handleKeyEvent(QGuiApplication::focusWindow(),
time, type, qtkey, qtModifiers, text);

View File

@ -78,7 +78,6 @@ QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
, mXkbMap(0)
, mXkbState(0)
#endif
, mFocusCallback(0)
, mNativeModifiers(0)
{
connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
@ -131,8 +130,6 @@ QWaylandInputDevice::Keyboard::~Keyboard()
#endif
if (mFocus)
QWindowSystemInterface::handleWindowActivated(0);
if (mFocusCallback)
wl_callback_destroy(mFocusCallback);
if (mParent->mVersion >= 3)
wl_keyboard_release(object());
else
@ -614,10 +611,7 @@ void QWaylandInputDevice::Keyboard::keyboard_enter(uint32_t time, struct wl_surf
QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);
mFocus = window;
if (!mFocusCallback) {
mFocusCallback = wl_display_sync(mParent->mDisplay);
wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::Keyboard::callback, this);
}
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
}
void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surface *surface)
@ -632,33 +626,11 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
mFocus = NULL;
// Use a callback to set the focus because we may get a leave/enter pair, and
// the latter one would be lost in the QWindowSystemInterface queue, if
// we issue the handleWindowActivated() calls immediately.
if (!mFocusCallback) {
mFocusCallback = wl_display_sync(mParent->mDisplay);
wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::Keyboard::callback, this);
}
mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
mRepeatTimer.stop();
}
const wl_callback_listener QWaylandInputDevice::Keyboard::callback = {
QWaylandInputDevice::Keyboard::focusCallback
};
void QWaylandInputDevice::Keyboard::focusCallback(void *data, struct wl_callback *callback, uint32_t time)
{
Q_UNUSED(time);
Q_UNUSED(callback);
QWaylandInputDevice::Keyboard *self = static_cast<QWaylandInputDevice::Keyboard *>(data);
if (self->mFocusCallback) {
wl_callback_destroy(self->mFocusCallback);
self->mFocusCallback = 0;
}
QWindowSystemInterface::handleWindowActivated(self->mFocus ? self->mFocus->window() : 0);
}
static void sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false, ushort count = 1)
@ -707,8 +679,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
Qt::KeyboardModifiers modifiers = mParent->modifiers();
text = QWaylandXkb::textFromKeysym(sym, modifiers);
qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text);
std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers);
sendKey(window->window(), time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);
#else

View File

@ -197,7 +197,6 @@ public:
xkb_keymap *mXkbMap;
xkb_state *mXkbState;
#endif
struct wl_callback *mFocusCallback;
uint32_t mNativeModifiers;
int mRepeatKey;
@ -209,9 +208,6 @@ public:
#endif
QTimer mRepeatTimer;
static const wl_callback_listener callback;
static void focusCallback(void *data, struct wl_callback *callback, uint32_t time);
Qt::KeyboardModifiers modifiers() const;
private slots:

View File

@ -308,29 +308,37 @@ void QWaylandShmBackingStore::updateDecorations()
QPainter decorationPainter(entireSurface());
decorationPainter.setCompositionMode(QPainter::CompositionMode_Source);
QImage sourceImage = windowDecoration()->contentImage();
QRect target;
qreal dp = sourceImage.devicePixelRatio();
int dpWidth = int(sourceImage.width() / dp);
int dpHeight = int(sourceImage.height() / dp);
QMatrix sourceMatrix;
sourceMatrix.scale(dp, dp);
QRect target; // needs to be in device independent pixels
//Top
target.setX(0);
target.setY(0);
target.setWidth(sourceImage.width());
target.setWidth(dpWidth);
target.setHeight(windowDecorationMargins().top());
decorationPainter.drawImage(target, sourceImage, target);
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
//Left
target.setWidth(windowDecorationMargins().left());
target.setHeight(sourceImage.height());
decorationPainter.drawImage(target, sourceImage, target);
target.setHeight(dpHeight);
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
//Right
target.setX(sourceImage.width() - windowDecorationMargins().right());
decorationPainter.drawImage(target, sourceImage, target);
target.setX(dpWidth - windowDecorationMargins().right());
target.setWidth(windowDecorationMargins().right());
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
//Bottom
target.setX(0);
target.setY(sourceImage.height() - windowDecorationMargins().bottom());
target.setWidth(sourceImage.width());
target.setY(dpHeight - windowDecorationMargins().bottom());
target.setWidth(dpWidth);
target.setHeight(windowDecorationMargins().bottom());
decorationPainter.drawImage(target, sourceImage, target);
decorationPainter.drawImage(target, sourceImage, sourceMatrix.mapRect(target));
}
QWaylandAbstractDecoration *QWaylandShmBackingStore::windowDecoration() const

View File

@ -58,6 +58,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(struct ::xdg_surface *xdg_surface, QWayla
, m_maximized(false)
, m_minimized(false)
, m_fullscreen(false)
, m_active(false)
, m_extendedWindow(Q_NULLPTR)
{
if (window->display()->windowExtension())
@ -66,6 +67,9 @@ QWaylandXdgSurface::QWaylandXdgSurface(struct ::xdg_surface *xdg_surface, QWayla
QWaylandXdgSurface::~QWaylandXdgSurface()
{
if (m_active)
window()->display()->handleWindowDeactivated(m_window);
xdg_surface_destroy(object());
delete m_extendedWindow;
}
@ -182,6 +186,7 @@ void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height, st
size_t numStates = states->size / sizeof(uint32_t);
bool aboutToMaximize = false;
bool aboutToFullScreen = false;
bool aboutToActivate = false;
for (size_t i = 0; i < numStates; i++) {
switch (state[i]) {
@ -195,13 +200,21 @@ void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height, st
m_normalSize = QSize(width, height);
break;
case XDG_SURFACE_STATE_ACTIVATED:
// TODO: here about the missing window activation
aboutToActivate = true;
break;
default:
break;
}
}
if (!m_active && aboutToActivate) {
m_active = true;
window()->display()->handleWindowActivated(m_window);
} else if (m_active && !aboutToActivate) {
m_active = false;
window()->display()->handleWindowDeactivated(m_window);
}
if (!m_fullscreen && aboutToFullScreen) {
if (!m_maximized)
m_normalSize = m_window->window()->frameGeometry().size();

View File

@ -112,6 +112,7 @@ private:
bool m_maximized;
bool m_minimized;
bool m_fullscreen;
bool m_active;
QSize m_normalSize;
QMargins m_margins;
QWaylandExtendedSurface *m_extendedWindow;

View File

@ -293,8 +293,13 @@ static xkb_keysym_t toKeysymFromTable(uint32_t key)
return 0;
}
int QWaylandXkb::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text)
std::pair<int, QString> QWaylandXkb::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers)
{
QString text;
uint utf32 = xkb_keysym_to_utf32(keysym);
if (utf32)
text = QString::fromUcs4(&utf32, 1);
int code = 0;
if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
@ -316,7 +321,13 @@ int QWaylandXkb::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modif
code = lookupKeysym(keysym);
}
return code;
// Map control + letter to proper text
if (utf32 >= 'A' && utf32 <= '~' && (modifiers & Qt::ControlModifier)) {
utf32 &= ~0x60;
text = QString::fromUcs4(&utf32, 1);
}
return { code, text };
}
Qt::KeyboardModifiers QWaylandXkb::modifiers(struct xkb_state *state)
@ -342,22 +353,6 @@ QEvent::Type QWaylandXkb::toQtEventType(uint32_t state)
return state != 0 ? QEvent::KeyPress : QEvent::KeyRelease;
}
QString QWaylandXkb::textFromKeysym(uint32_t keysym, Qt::KeyboardModifiers modifiers)
{
uint utf32 = xkb_keysym_to_utf32(keysym);
// Map control + letter to proper text
if (utf32 >= 'A' && utf32 <= '~' && (modifiers & Qt::ControlModifier)) {
utf32 &= ~0x60;
return QString::fromUcs4(&utf32, 1);
}
if (utf32)
return QString::fromUcs4(&utf32, 1);
return QString();
}
QVector<xkb_keysym_t> QWaylandXkb::toKeysym(QKeyEvent *event)
{
QVector<xkb_keysym_t> keysyms;

View File

@ -47,6 +47,8 @@
#include <QEvent>
#include <xkbcommon/xkbcommon.h>
#include <utility>
QT_BEGIN_NAMESPACE
class QKeyEvent;
@ -54,11 +56,10 @@ class QKeyEvent;
class QWaylandXkb
{
public:
static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text);
static std::pair<int, QString> keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers);
static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
static QEvent::Type toQtEventType(uint32_t state);
static QString textFromKeysym(uint32_t keysym, Qt::KeyboardModifiers modifiers);
static QVector<xkb_keysym_t> toKeysym(QKeyEvent *event);
};