Merge remote-tracking branch 'origin/5.6' into 5.7
Change-Id: I9cfefaf22b010fca937be77979f5fb50574bb71e
This commit is contained in:
commit
d10e4c193b
@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
class MyCocoaEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE;
|
||||
};
|
||||
//! [0]
|
@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
|
||||
** Contact: http://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
#include "mycocoaeventfilter.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
bool CocoaNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
|
||||
{
|
||||
if (eventType == "mac_generic_NSEvent") {
|
||||
NSEvent *event = static_cast<NSEvent *>(message);
|
||||
if ([event type] == NSKeyDown) {
|
||||
// Handle key event
|
||||
qDebug() << QString::fromNSString([event characters]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//! [0]
|
@ -0,0 +1,5 @@
|
||||
#! [0]
|
||||
HEADERS += mycocoaeventfilter.h
|
||||
OBJECTIVE_SOURCES += mycocoaeventfilter.mm
|
||||
LIBS += -framework AppKit
|
||||
#! [0]
|
@ -83,7 +83,7 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\property QAbstractProxyModel::sourceModel
|
||||
|
||||
\brief the source model this proxy model.
|
||||
\brief the source model of this proxy model.
|
||||
*/
|
||||
|
||||
//detects the deletion of the source model
|
||||
|
@ -96,14 +96,25 @@ QAbstractNativeEventFilter::~QAbstractNativeEventFilter()
|
||||
In both cases, the \a message can be casted to a MSG pointer.
|
||||
The \a result pointer is only used on Windows, and corresponds to the LRESULT pointer.
|
||||
|
||||
On Mac, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an EventRef.
|
||||
On macOS, \a eventType is set to "mac_generic_NSEvent", and the \a message can be casted to an NSEvent pointer.
|
||||
|
||||
In your reimplementation of this function, if you want to filter
|
||||
the \a message out, i.e. stop it being handled further, return
|
||||
true; otherwise return false.
|
||||
|
||||
Example:
|
||||
\b {Linux example}
|
||||
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.cpp 0
|
||||
|
||||
\b {macOS example}
|
||||
|
||||
mycocoaeventfilter.h:
|
||||
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.h 0
|
||||
|
||||
mycocoaeventfilter.mm:
|
||||
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.mm 0
|
||||
|
||||
myapp.pro:
|
||||
\snippet code/src_corelib_kernel_qabstractnativeeventfilter.pro 0
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -585,7 +585,7 @@ void QBrush::detach(Qt::BrushStyle newStyle)
|
||||
if (newStyle == d->style && d->ref.load() == 1)
|
||||
return;
|
||||
|
||||
QScopedPointer<QBrushData> x;
|
||||
QScopedPointer<QBrushData, QBrushDataPointerDeleter> x;
|
||||
switch(newStyle) {
|
||||
case Qt::TexturePattern: {
|
||||
QTexturedBrushData *tbd = new QTexturedBrushData;
|
||||
@ -601,28 +601,30 @@ void QBrush::detach(Qt::BrushStyle newStyle)
|
||||
}
|
||||
case Qt::LinearGradientPattern:
|
||||
case Qt::RadialGradientPattern:
|
||||
case Qt::ConicalGradientPattern:
|
||||
x.reset(new QGradientBrushData);
|
||||
case Qt::ConicalGradientPattern: {
|
||||
QGradientBrushData *gbd = new QGradientBrushData;
|
||||
switch (d->style) {
|
||||
case Qt::LinearGradientPattern:
|
||||
case Qt::RadialGradientPattern:
|
||||
case Qt::ConicalGradientPattern:
|
||||
static_cast<QGradientBrushData *>(x.data())->gradient =
|
||||
gbd->gradient =
|
||||
static_cast<QGradientBrushData *>(d.data())->gradient;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
x.reset(gbd);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
x.reset(new QBrushData);
|
||||
break;
|
||||
}
|
||||
x->ref.store(1);
|
||||
x->ref.store(1); // must be first lest the QBrushDataPointerDeleter turns into a no-op
|
||||
x->style = newStyle;
|
||||
x->color = d->color;
|
||||
x->transform = d->transform;
|
||||
d.reset(x.take());
|
||||
d.swap(x);
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,8 +59,15 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap")
|
||||
// simple builtin US keymap
|
||||
#include "qevdevkeyboard_defaultmap_p.h"
|
||||
|
||||
QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile)
|
||||
: m_device(device), m_fd(fd), m_notify(Q_NULLPTR),
|
||||
void QFdContainer::reset() Q_DECL_NOTHROW
|
||||
{
|
||||
if (m_fd >= 0)
|
||||
qt_safe_close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile)
|
||||
: m_device(device), m_fd(fd.release()), m_notify(Q_NULLPTR),
|
||||
m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
|
||||
m_no_zap(disableZap), m_do_compose(enableCompose),
|
||||
m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
|
||||
@ -75,16 +82,13 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool
|
||||
unloadKeymap();
|
||||
|
||||
// socket notifier for events on the keyboard device
|
||||
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
|
||||
m_notify = new QSocketNotifier(m_fd.get(), QSocketNotifier::Read, this);
|
||||
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKeycode()));
|
||||
}
|
||||
|
||||
QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
|
||||
{
|
||||
unloadKeymap();
|
||||
|
||||
if (m_fd >= 0)
|
||||
qt_safe_close(m_fd);
|
||||
}
|
||||
|
||||
QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
|
||||
@ -118,13 +122,12 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
|
||||
|
||||
qCDebug(qLcEvdevKey) << "Opening keyboard at" << device;
|
||||
|
||||
int fd;
|
||||
fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
|
||||
if (fd >= 0) {
|
||||
::ioctl(fd, EVIOCGRAB, grab);
|
||||
QFdContainer fd(qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0));
|
||||
if (fd.get() >= 0) {
|
||||
::ioctl(fd.get(), EVIOCGRAB, grab);
|
||||
if (repeatDelay > 0 && repeatRate > 0) {
|
||||
int kbdrep[2] = { repeatDelay, repeatRate };
|
||||
::ioctl(fd, EVIOCSREP, kbdrep);
|
||||
::ioctl(fd.get(), EVIOCSREP, kbdrep);
|
||||
}
|
||||
|
||||
return new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile);
|
||||
@ -144,7 +147,7 @@ void QEvdevKeyboardHandler::switchLed(int led, bool state)
|
||||
led_ie.code = led;
|
||||
led_ie.value = state;
|
||||
|
||||
qt_safe_write(m_fd, &led_ie, sizeof(led_ie));
|
||||
qt_safe_write(m_fd.get(), &led_ie, sizeof(led_ie));
|
||||
}
|
||||
|
||||
void QEvdevKeyboardHandler::readKeycode()
|
||||
@ -153,7 +156,7 @@ void QEvdevKeyboardHandler::readKeycode()
|
||||
int n = 0;
|
||||
|
||||
forever {
|
||||
int result = qt_safe_read(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
|
||||
int result = qt_safe_read(m_fd.get(), reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
|
||||
|
||||
if (result == 0) {
|
||||
qWarning("evdevkeyboard: Got EOF from the input device");
|
||||
@ -166,8 +169,7 @@ void QEvdevKeyboardHandler::readKeycode()
|
||||
if (errno == ENODEV) {
|
||||
delete m_notify;
|
||||
m_notify = Q_NULLPTR;
|
||||
qt_safe_close(m_fd);
|
||||
m_fd = -1;
|
||||
m_fd.reset();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -478,7 +480,7 @@ void QEvdevKeyboardHandler::unloadKeymap()
|
||||
//Set locks according to keyboard leds
|
||||
quint16 ledbits[1];
|
||||
memset(ledbits, 0, sizeof(ledbits));
|
||||
if (::ioctl(m_fd, EVIOCGLED(sizeof(ledbits)), ledbits) < 0) {
|
||||
if (::ioctl(m_fd.get(), EVIOCGLED(sizeof(ledbits)), ledbits) < 0) {
|
||||
qWarning("evdevkeyboard: Failed to query led states");
|
||||
switchLed(LED_NUML,false);
|
||||
switchLed(LED_CAPSL, false);
|
||||
|
@ -129,12 +129,25 @@ inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Composi
|
||||
return ds << c.first << c.second << c.result;
|
||||
}
|
||||
|
||||
class QFdContainer
|
||||
{
|
||||
int m_fd;
|
||||
Q_DISABLE_COPY(QFdContainer);
|
||||
public:
|
||||
explicit QFdContainer(int fd = -1) Q_DECL_NOTHROW : m_fd(fd) {}
|
||||
~QFdContainer() { reset(); }
|
||||
|
||||
int get() const Q_DECL_NOTHROW { return m_fd; }
|
||||
|
||||
int release() Q_DECL_NOTHROW { int result = m_fd; m_fd = -1; return result; }
|
||||
void reset() Q_DECL_NOTHROW;
|
||||
};
|
||||
|
||||
class QEvdevKeyboardHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile);
|
||||
QEvdevKeyboardHandler(const QString &device, QFdContainer &fd, bool disableZap, bool enableCompose, const QString &keymapFile);
|
||||
~QEvdevKeyboardHandler();
|
||||
|
||||
enum KeycodeAction {
|
||||
@ -187,7 +200,7 @@ private:
|
||||
void switchLed(int, bool);
|
||||
|
||||
QString m_device;
|
||||
int m_fd;
|
||||
QFdContainer m_fd;
|
||||
QSocketNotifier *m_notify;
|
||||
|
||||
// keymap handling
|
||||
|
@ -252,6 +252,8 @@ QStringList QConnmanManagerInterface::getServices()
|
||||
bool QConnmanManagerInterface::requestScan(const QString &type)
|
||||
{
|
||||
bool scanned = false;
|
||||
if (technologiesMap.isEmpty())
|
||||
getTechnologies();
|
||||
Q_FOREACH (QConnmanTechnologyInterface *tech, technologiesMap) {
|
||||
if (tech->type() == type) {
|
||||
tech->scan();
|
||||
|
@ -330,6 +330,11 @@ void QCocoaGLContext::updateSurfaceFormat()
|
||||
|
||||
[pixelFormat release];
|
||||
|
||||
GLint swapInterval = -1;
|
||||
[m_context getValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
|
||||
if (swapInterval >= 0)
|
||||
m_format.setSwapInterval(swapInterval);
|
||||
|
||||
// Restore the original context
|
||||
CGLSetCurrentContext(oldContext);
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ QIOSMenu::QIOSMenu()
|
||||
: QPlatformMenu()
|
||||
, m_tag(0)
|
||||
, m_enabled(true)
|
||||
, m_visible(true)
|
||||
, m_visible(false)
|
||||
, m_text(QString())
|
||||
, m_menuType(DefaultMenu)
|
||||
, m_effectiveMenuType(DefaultMenu)
|
||||
@ -412,7 +412,7 @@ void QIOSMenu::handleItemSelected(QIOSMenuItem *menuItem)
|
||||
|
||||
void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
|
||||
{
|
||||
if (m_currentMenu == this || !m_visible || !m_enabled || !parentWindow)
|
||||
if (m_currentMenu == this || !parentWindow)
|
||||
return;
|
||||
|
||||
emit aboutToShow();
|
||||
@ -439,6 +439,8 @@ void QIOSMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect, c
|
||||
toggleShowUsingUIPickerView(true);
|
||||
break;
|
||||
}
|
||||
|
||||
m_visible = true;
|
||||
}
|
||||
|
||||
void QIOSMenu::dismiss()
|
||||
@ -460,6 +462,7 @@ void QIOSMenu::dismiss()
|
||||
}
|
||||
|
||||
m_currentMenu = 0;
|
||||
m_visible = false;
|
||||
}
|
||||
|
||||
void QIOSMenu::toggleShowUsingUIMenuController(bool show)
|
||||
|
@ -228,6 +228,10 @@
|
||||
|
||||
@implementation QIOSViewController
|
||||
|
||||
@synthesize prefersStatusBarHidden;
|
||||
@synthesize preferredStatusBarUpdateAnimation;
|
||||
@synthesize preferredStatusBarStyle;
|
||||
|
||||
- (id)initWithQIOSScreen:(QIOSScreen *)screen
|
||||
{
|
||||
if (self = [self init]) {
|
||||
|
@ -91,7 +91,7 @@ QIOSWindow::~QIOSWindow()
|
||||
// practice this doesn't seem to happen when removing the view from its superview. To ensure that
|
||||
// Qt's internal state for touch and mouse handling is kept consistent, we therefor have to force
|
||||
// cancellation of all touch events.
|
||||
[m_view touchesCancelled:0 withEvent:0];
|
||||
[m_view touchesCancelled:[NSSet set] withEvent:0];
|
||||
|
||||
clearAccessibleCache();
|
||||
m_view->m_qioswindow = 0;
|
||||
|
@ -423,7 +423,8 @@
|
||||
// We do this by assuming that there are no cases where a
|
||||
// sub-set of the active touch events are intentionally cancelled.
|
||||
|
||||
if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
|
||||
NSInteger count = static_cast<NSInteger>([touches count]);
|
||||
if (count != 0 && count != m_activeTouches.count())
|
||||
qWarning("Subset of active touches cancelled by UIKit");
|
||||
|
||||
m_activeTouches.clear();
|
||||
|
@ -748,8 +748,7 @@ void QXcbKeyboard::updateKeymap()
|
||||
// update xkb state object
|
||||
xkb_state_unref(xkb_state);
|
||||
xkb_state = new_state;
|
||||
if (!connection()->hasXKB())
|
||||
updateXKBMods();
|
||||
updateXKBMods();
|
||||
|
||||
checkForLatinLayout();
|
||||
}
|
||||
@ -774,32 +773,37 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
|
||||
}
|
||||
#endif
|
||||
|
||||
void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 state)
|
||||
{
|
||||
const quint32 modsDepressed = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_DEPRESSED);
|
||||
const quint32 modsLatched = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LATCHED);
|
||||
const quint32 modsLocked = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LOCKED);
|
||||
const quint32 xkbMask = xkbModMask(state);
|
||||
|
||||
const quint32 latched = modsLatched & xkbMask;
|
||||
const quint32 locked = modsLocked & xkbMask;
|
||||
quint32 depressed = modsDepressed & xkbMask;
|
||||
// set modifiers in depressed if they don't appear in any of the final masks
|
||||
depressed |= ~(depressed | latched | locked) & xkbMask;
|
||||
|
||||
const xkb_state_component newState
|
||||
= xkb_state_update_mask(kb_state,
|
||||
depressed,
|
||||
latched,
|
||||
locked,
|
||||
0,
|
||||
0,
|
||||
(state >> 13) & 3); // bits 13 and 14 report the state keyboard group
|
||||
|
||||
if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
|
||||
//qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
|
||||
{
|
||||
if (m_config && !connection()->hasXKB()) {
|
||||
const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||
const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
|
||||
const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
|
||||
const quint32 xkbMask = xkbModMask(state);
|
||||
|
||||
const quint32 latched = modsLatched & xkbMask;
|
||||
const quint32 locked = modsLocked & xkbMask;
|
||||
quint32 depressed = modsDepressed & xkbMask;
|
||||
// set modifiers in depressed if they don't appear in any of the final masks
|
||||
depressed |= ~(depressed | latched | locked) & xkbMask;
|
||||
|
||||
const xkb_state_component newState
|
||||
= xkb_state_update_mask(xkb_state,
|
||||
depressed,
|
||||
latched,
|
||||
locked,
|
||||
0,
|
||||
0,
|
||||
(state >> 13) & 3); // bits 13 and 14 report the state keyboard group
|
||||
|
||||
if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
|
||||
//qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
|
||||
}
|
||||
updateXKBStateFromState(xkb_state, state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1463,7 +1467,16 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
|
||||
if (type == QEvent::KeyPress)
|
||||
targetWindow->updateNetWmUserTime(time);
|
||||
|
||||
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code);
|
||||
// Have a temporary keyboard state filled in from state
|
||||
// this way we allow for synthetic events to have different state
|
||||
// from the current state i.e. you can have Alt+Ctrl pressed
|
||||
// and receive a synthetic key event that has neither Alt nor Ctrl pressed
|
||||
struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
|
||||
if (!kb_state)
|
||||
return;
|
||||
updateXKBStateFromState(kb_state, state);
|
||||
|
||||
xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
|
||||
|
||||
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
|
||||
QMetaMethod method;
|
||||
@ -1482,11 +1495,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
|
||||
Q_ARG(uint, code),
|
||||
Q_ARG(uint, state),
|
||||
Q_ARG(bool, type == QEvent::KeyPress));
|
||||
if (retval)
|
||||
if (retval) {
|
||||
xkb_state_unref(kb_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString string = lookupString(xkb_state, code);
|
||||
QString string = lookupString(kb_state, code);
|
||||
|
||||
// Ιf control modifier is set we should prefer latin character, this is
|
||||
// used for standard shortcuts in checks like "key == QKeySequence::Copy",
|
||||
@ -1557,6 +1572,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
|
||||
QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
|
||||
code, sym, state, string, isAutoRepeat);
|
||||
}
|
||||
xkb_state_unref(kb_state);
|
||||
}
|
||||
|
||||
QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
|
||||
|
@ -104,6 +104,8 @@ protected:
|
||||
void checkForLatinLayout();
|
||||
|
||||
private:
|
||||
void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
|
||||
|
||||
bool m_config;
|
||||
xcb_keycode_t m_autorepeat_code;
|
||||
|
||||
|
@ -459,6 +459,24 @@ void tst_QTextDocument::findMultiple()
|
||||
cursor = doc->find(expr, cursor);
|
||||
QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
|
||||
QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
|
||||
|
||||
QRegularExpression regularExpression("bar");
|
||||
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
cursor = doc->find(regularExpression, cursor, QTextDocument::FindBackward);
|
||||
QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
|
||||
QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
|
||||
cursor = doc->find(regularExpression, cursor, QTextDocument::FindBackward);
|
||||
QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
|
||||
QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
|
||||
|
||||
cursor.movePosition(QTextCursor::Start);
|
||||
cursor = doc->find(regularExpression, cursor);
|
||||
QCOMPARE(cursor.selectionStart(), text.indexOf("bar"));
|
||||
QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
|
||||
cursor = doc->find(regularExpression, cursor);
|
||||
QCOMPARE(cursor.selectionStart(), text.lastIndexOf("bar"));
|
||||
QCOMPARE(cursor.selectionEnd(), cursor.selectionStart() + 3);
|
||||
}
|
||||
|
||||
void tst_QTextDocument::basicIsModifiedChecks()
|
||||
|
@ -26,14 +26,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QOpenGLWindow>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QPainter>
|
||||
#include <QElapsedTimer>
|
||||
#include <QCommandLineParser>
|
||||
#include <QScreen>
|
||||
#include <QtGui>
|
||||
|
||||
const char applicationDescription[] = "\n\
|
||||
This application opens multiple windows and continuously schedules updates for\n\
|
||||
@ -62,67 +55,95 @@ class Window : public QOpenGLWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Window(int n) : idx(n) {
|
||||
r = g = b = fps = 0;
|
||||
y = 0;
|
||||
Window(int index) : windowNumber(index + 1), x(0), framesSwapped(0) {
|
||||
|
||||
color = QColor::fromHsl((index * 30) % 360, 255, 127).toRgb();
|
||||
|
||||
resize(200, 200);
|
||||
|
||||
setObjectName(QString("Window %1").arg(windowNumber));
|
||||
|
||||
connect(this, SIGNAL(frameSwapped()), SLOT(frameSwapped()));
|
||||
fpsTimer.start();
|
||||
}
|
||||
|
||||
void paintGL() {
|
||||
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
||||
f->glClearColor(r, g, b, 1);
|
||||
f->glClearColor(color.redF(), color.greenF(), color.blueF(), 1);
|
||||
f->glClear(GL_COLOR_BUFFER_BIT);
|
||||
switch (idx % 3) {
|
||||
case 0:
|
||||
r += 0.005f;
|
||||
break;
|
||||
case 1:
|
||||
g += 0.005f;
|
||||
break;
|
||||
case 2:
|
||||
b += 0.005f;
|
||||
break;
|
||||
}
|
||||
if (r > 1)
|
||||
r = 0;
|
||||
if (g > 1)
|
||||
g = 0;
|
||||
if (b > 1)
|
||||
b = 0;
|
||||
|
||||
QPainter p(this);
|
||||
p.setPen(Qt::white);
|
||||
p.drawText(QPoint(20, y), QString(QLatin1String("Window %1 (%2 FPS)")).arg(idx).arg(fps));
|
||||
y += 1;
|
||||
if (y > height() - 20)
|
||||
y = 20;
|
||||
|
||||
update();
|
||||
QPainter painter(this);
|
||||
painter.drawLine(x, 0, x, height());
|
||||
x = ++x % width();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void frameSwapped() {
|
||||
++framesSwapped;
|
||||
if (fpsTimer.elapsed() > 1000) {
|
||||
fps = qRound(framesSwapped * (1000.0 / fpsTimer.elapsed()));
|
||||
framesSwapped = 0;
|
||||
fpsTimer.restart();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
protected:
|
||||
void exposeEvent(QExposeEvent *event) {
|
||||
if (!isExposed())
|
||||
return;
|
||||
|
||||
QSurfaceFormat format = context()->format();
|
||||
qDebug() << this << format.swapBehavior() << "with Vsync =" << (format.swapInterval() ? "ON" : "OFF");
|
||||
if (format.swapInterval() != requestedFormat().swapInterval())
|
||||
qWarning() << "WARNING: Did not get requested swap interval of" << requestedFormat().swapInterval() << "for" << this;
|
||||
|
||||
QOpenGLWindow::exposeEvent(event);
|
||||
}
|
||||
|
||||
void mousePressEvent(QMouseEvent *event) {
|
||||
qDebug() << this << event;
|
||||
color.setHsl((color.hue() + 90) % 360, color.saturation(), color.lightness());
|
||||
color = color.toRgb();
|
||||
}
|
||||
|
||||
private:
|
||||
int idx;
|
||||
GLfloat r, g, b;
|
||||
int y;
|
||||
int windowNumber;
|
||||
QColor color;
|
||||
int x;
|
||||
|
||||
int framesSwapped;
|
||||
QElapsedTimer fpsTimer;
|
||||
int fps;
|
||||
friend void printFps();
|
||||
};
|
||||
|
||||
static const qreal kFpsInterval = 500;
|
||||
|
||||
void printFps()
|
||||
{
|
||||
static QElapsedTimer timer;
|
||||
if (!timer.isValid()) {
|
||||
timer.start();
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal frameFactor = (kFpsInterval / timer.elapsed()) * (1000.0 / kFpsInterval);
|
||||
|
||||
QDebug output = qDebug().nospace();
|
||||
|
||||
qreal averageFps = 0;
|
||||
const QWindowList windows = QGuiApplication::topLevelWindows();
|
||||
for (int i = 0; i < windows.size(); ++i) {
|
||||
Window *w = qobject_cast<Window*>(windows.at(i));
|
||||
Q_ASSERT(w);
|
||||
|
||||
int fps = qRound(w->framesSwapped * frameFactor);
|
||||
output << (i + 1) << "=" << fps << ", ";
|
||||
|
||||
averageFps += fps;
|
||||
w->framesSwapped = 0;
|
||||
}
|
||||
averageFps = qRound(averageFps / windows.size());
|
||||
qreal msPerFrame = 1000.0 / averageFps;
|
||||
|
||||
output << "avg=" << averageFps << ", ms=" << msPerFrame;
|
||||
|
||||
timer.restart();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
@ -144,30 +165,24 @@ int main(int argc, char **argv)
|
||||
|
||||
parser.process(app);
|
||||
|
||||
QSurfaceFormat fmt;
|
||||
if (parser.isSet(noVsyncOption)) {
|
||||
qDebug("swap interval 0 (no throttling)");
|
||||
fmt.setSwapInterval(0);
|
||||
} else {
|
||||
qDebug("swap interval 1 (sync to vblank)");
|
||||
}
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
QSurfaceFormat defaultSurfaceFormat;
|
||||
defaultSurfaceFormat.setSwapInterval(parser.isSet(noVsyncOption) ? 0 : 1);
|
||||
QSurfaceFormat::setDefaultFormat(defaultSurfaceFormat);
|
||||
|
||||
QRect availableGeometry = app.primaryScreen()->availableGeometry();
|
||||
|
||||
int numberOfWindows = qMax(parser.value(numWindowsOption).toInt(), 1);
|
||||
QList<QWindow *> windows;
|
||||
for (int i = 0; i < numberOfWindows; ++i) {
|
||||
Window *w = new Window(i + 1);
|
||||
Window *w = new Window(i);
|
||||
windows << w;
|
||||
|
||||
if (i == 0 && parser.isSet(vsyncOneOption)) {
|
||||
qDebug("swap interval 1 for first window only");
|
||||
QSurfaceFormat vsyncedSurfaceFormat = fmt;
|
||||
QSurfaceFormat vsyncedSurfaceFormat = defaultSurfaceFormat;
|
||||
vsyncedSurfaceFormat.setSwapInterval(1);
|
||||
w->setFormat(vsyncedSurfaceFormat);
|
||||
fmt.setSwapInterval(0);
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
defaultSurfaceFormat.setSwapInterval(0);
|
||||
QSurfaceFormat::setDefaultFormat(defaultSurfaceFormat);
|
||||
}
|
||||
|
||||
static int windowWidth = w->width() + 20;
|
||||
@ -182,9 +197,15 @@ int main(int argc, char **argv)
|
||||
QPoint position = availableGeometry.topLeft();
|
||||
position += QPoint(col * windowWidth, row * windowHeight);
|
||||
w->setFramePosition(position);
|
||||
w->show();
|
||||
w->showNormal();
|
||||
}
|
||||
|
||||
QTimer fpsTimer;
|
||||
fpsTimer.setInterval(kFpsInterval);
|
||||
fpsTimer.setTimerType(Qt::PreciseTimer);
|
||||
QObject::connect(&fpsTimer, &QTimer::timeout, &printFps);
|
||||
fpsTimer.start();
|
||||
|
||||
int r = app.exec();
|
||||
qDeleteAll(windows);
|
||||
return r;
|
||||
|
Loading…
Reference in New Issue
Block a user