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

Change-Id: I75a8ddc0652f3c6f438ef98e940c9357450d29c6
This commit is contained in:
Liang Qi 2016-08-01 11:03:33 +02:00
commit d04de01e80
7 changed files with 118 additions and 46 deletions

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

@ -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)

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;