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:
commit
70d36235b1
@ -39,7 +39,9 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QtWaylandClient/qwaylandclientexport.h>
|
||||
#include <QtWaylandClient/private/qwayland-wayland.h>
|
||||
|
||||
struct wl_registry;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtWaylandClient {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user