summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-06-27 16:52:21 +0200
committerAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-06-27 16:52:35 +0200
commitec5a99b0515779ff5ec3df6bd657127b4e037823 (patch)
treec5dc52e8892b6740123469276dcb303a81d9fd56 /src
parent56bea56b2d8fabc4b09d41531177a22d9297ce2c (diff)
parent722732d1f089630ad517aef8f94325a51186b274 (diff)
Merge remote-tracking branch 'origin/5.6' into 5.7
Diffstat (limited to 'src')
-rw-r--r--src/core/gyp_run.pro13
-rw-r--r--src/core/render_widget_host_view_qt.cpp87
-rw-r--r--src/core/render_widget_host_view_qt.h1
-rw-r--r--src/core/web_event_factory.cpp11
-rw-r--r--src/webengine/api/qquickwebengineview.cpp36
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h2
-rw-r--r--src/webengine/doc/src/qtwebengine-index.qdoc4
-rw-r--r--src/webengine/doc/src/qtwebengine-qmlmodule.qdoc2
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.cpp12
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.h1
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp36
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h2
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp7
13 files changed, 186 insertions, 28 deletions
diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro
index a1b33e258..8c4aeb163 100644
--- a/src/core/gyp_run.pro
+++ b/src/core/gyp_run.pro
@@ -89,9 +89,16 @@ contains(QT_ARCH, "arm") {
contains(QT_ARCH, "mips") {
GYP_CONFIG += target_arch=mipsel
- contains(QMAKE_CFLAGS, "mips32r6"): mips_arch_variant=\"r6\"
- else: contains(QMAKE_CFLAGS, "mips32r2"): mips_arch_variant=\"r2\"
- else: contains(QMAKE_CFLAGS, "mips32"): mips_arch_variant=\"r1\"
+ MARCH = $$extractCFlag("-march=.*")
+ !isEmpty(MARCH) {
+ equals(MARCH, "mips32r6"): GYP_CONFIG += mips_arch_variant=\"r6\"
+ else: equals(MARCH, "mips32r2"): GYP_CONFIG += mips_arch_variant=\"r2\"
+ else: equals(MARCH, "mips32"): GYP_CONFIG += mips_arch_variant=\"r1\"
+ } else {
+ contains(QMAKE_CFLAGS, "mips32r6"): GYP_CONFIG += mips_arch_variant=\"r6\"
+ else: contains(QMAKE_CFLAGS, "mips32r2"): GYP_CONFIG += mips_arch_variant=\"r2\"
+ else: contains(QMAKE_CFLAGS, "mips32"): GYP_CONFIG += mips_arch_variant=\"r1\"
+ }
contains(QMAKE_CFLAGS, "-mdsp2"): GYP_CONFIG += mips_dsp_rev=2
else: contains(QMAKE_CFLAGS, "-mdsp"): GYP_CONFIG += mips_dsp_rev=1
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 99e4da27e..f45db6bf4 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -239,6 +239,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
, m_didFirstVisuallyNonEmptyLayout(false)
, m_adapterClient(0)
, m_imeInProgress(false)
+ , m_receivedEmptyImeText(false)
, m_anchorPositionWithinSelection(0)
, m_cursorPositionWithinSelection(0)
, m_initPending(false)
@@ -949,6 +950,19 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event)
QCursor::setPos(m_lockedMousePosition);
}
+ if (m_imeInProgress && event->type() == QMouseEvent::MouseButtonPress) {
+ m_imeInProgress = false;
+ // Tell input method to commit the pre-edit string entered so far, and finish the
+ // composition operation.
+#ifdef Q_OS_WIN
+ // Yes the function name is counter-intuitive, but commit isn't actually implemented
+ // by the Windows QPA, and reset does exactly what is necessary in this case.
+ qApp->inputMethod()->reset();
+#else
+ qApp->inputMethod()->commit();
+#endif
+ }
+
m_host->ForwardMouseEvent(webEvent);
}
@@ -957,15 +971,16 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev)
if (IsMouseLocked() && ev->key() == Qt::Key_Escape && ev->type() == QEvent::KeyRelease)
UnlockMouse();
- if (m_imeInProgress) {
+ if (m_receivedEmptyImeText) {
// IME composition was not finished with a valid commit string.
// We're getting the composition result in a key event.
if (ev->key() != 0) {
// The key event is not a result of an IME composition. Cancel IME.
m_host->ImeCancelComposition();
- m_imeInProgress = false;
+ m_receivedEmptyImeText = false;
} else {
if (ev->type() == QEvent::KeyRelease) {
+ m_receivedEmptyImeText = false;
m_host->ImeConfirmComposition(toString16(ev->text()), gfx::Range::InvalidRange(),
false);
m_imeInProgress = false;
@@ -1005,6 +1020,25 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
const QList<QInputMethodEvent::Attribute> &attributes = ev->attributes();
std::vector<blink::WebCompositionUnderline> underlines;
+ auto ensureValidSelectionRange = [&]() {
+ if (!selectionRange.IsValid()) {
+ // We did not receive a valid selection range, hence the range is going to mark the
+ // cursor position.
+ int newCursorPosition =
+ (cursorPositionInPreeditString < 0) ? preeditString.length()
+ : cursorPositionInPreeditString;
+ selectionRange.set_start(newCursorPosition);
+ selectionRange.set_end(newCursorPosition);
+ }
+ };
+
+ auto setCompositionForPreEditString = [&](){
+ ensureValidSelectionRange();
+ m_host->ImeSetComposition(toString16(preeditString),
+ underlines,
+ selectionRange.start(),
+ selectionRange.end());
+ };
Q_FOREACH (const QInputMethodEvent::Attribute &attribute, attributes) {
switch (attribute.type) {
@@ -1018,8 +1052,11 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
break;
}
case QInputMethodEvent::Cursor:
- if (attribute.length)
- cursorPositionInPreeditString = attribute.start;
+ // Always set the position of the cursor, even if it's marked invisible by Qt, otherwise
+ // there is no way the user will know which part of the composition string will be
+ // changed, when performing an IME-specific action (like selecting a different word
+ // suggestion).
+ cursorPositionInPreeditString = attribute.start;
break;
case QInputMethodEvent::Selection:
selectionRange.set_start(qMin(attribute.start, (attribute.start + attribute.length)));
@@ -1034,16 +1071,42 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
gfx::Range replacementRange = (replacementLength > 0) ? gfx::Range(replacementStart, replacementStart + replacementLength)
: gfx::Range::InvalidRange();
m_host->ImeConfirmComposition(toString16(commitString), replacementRange, false);
- m_imeInProgress = false;
- } else if (!preeditString.isEmpty()) {
- if (!selectionRange.IsValid()) {
- // We did not receive a valid selection range, hence the range is going to mark the cursor position.
- int newCursorPosition = (cursorPositionInPreeditString < 0) ? preeditString.length() : cursorPositionInPreeditString;
- selectionRange.set_start(newCursorPosition);
- selectionRange.set_end(newCursorPosition);
+
+ // We might get a commit string and a pre-edit string in a single event, which means
+ // we need to confirm the怀last composition, and start a new composition.
+ if (!preeditString.isEmpty()) {
+ setCompositionForPreEditString();
+ m_imeInProgress = true;
+ } else {
+ m_imeInProgress = false;
}
- m_host->ImeSetComposition(toString16(preeditString), underlines, selectionRange.start(), selectionRange.end());
+ m_receivedEmptyImeText = false;
+
+ } else if (!preeditString.isEmpty()) {
+ setCompositionForPreEditString();
m_imeInProgress = true;
+ m_receivedEmptyImeText = false;
+ } else {
+ // There are so-far two known cases, when an empty QInputMethodEvent is received.
+ // First one happens when backspace is used to remove the last character in the pre-edit
+ // string, thus signaling the end of the composition.
+ // The second one happens (on Windows) when a Korean char gets composed, but instead of
+ // the event having a commit string, both strings are empty, and the actual char is received
+ // as a QKeyEvent after the QInputMethodEvent is processed.
+ // In lieu of the second case, we can't simply cancel the composition on an empty event,
+ // and then add the Korean char when QKeyEvent is received, because that leads to text
+ // flickering in the textarea (or any other element).
+ // Instead we postpone the processing of the empty QInputMethodEvent by posting it
+ // to the same focused object, and cancelling the composition on the next event loop tick.
+ if (!m_receivedEmptyImeText && m_imeInProgress) {
+ m_receivedEmptyImeText = true;
+ m_imeInProgress = false;
+ QInputMethodEvent *eventCopy = new QInputMethodEvent(*ev);
+ QGuiApplication::postEvent(qApp->focusObject(), eventCopy);
+ } else {
+ m_receivedEmptyImeText = false;
+ m_host->ImeCancelComposition();
+ }
}
}
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 67e7461b3..523d1c49d 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -241,6 +241,7 @@ private:
ui::TextInputType m_currentInputType;
bool m_imeInProgress;
+ bool m_receivedEmptyImeText;
QRect m_cursorRect;
size_t m_anchorPositionWithinSelection;
size_t m_cursorPositionWithinSelection;
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index 505a684eb..10809a764 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -659,14 +659,11 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev, doub
webEvent.modifiers = modifiersForEvent(ev);
webEvent.timeStampSeconds = currentTimeForEvent(ev);
- if (ev->orientation() == Qt::Horizontal)
- webEvent.wheelTicksX = ev->delta() / 120.0f;
- else
- webEvent.wheelTicksY = ev->delta() / 120.0f;
+ webEvent.wheelTicksX = ev->angleDelta().x() / QWheelEvent::DefaultDeltasPerStep;
+ webEvent.wheelTicksY = ev->angleDelta().y() / QWheelEvent::DefaultDeltasPerStep;
-
- // Since we report the scroll by the pixel, convert the delta to pixel distance using standard scroll step.
- // Use the same single scroll step as QTextEdit (in QTextEditPrivate::init [h,v]bar->setSingleStep)
+ // We can't use the device specific QWheelEvent::pixelDelta(), so we calculate
+ // a pixel delta based on ticks and scroll per line.
static const float cDefaultQtScrollStep = 20.f;
webEvent.deltaX = webEvent.wheelTicksX * wheelScrollLines * cDefaultQtScrollStep;
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index ac25cd4d2..ced8c1452 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -93,6 +93,27 @@
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
+QQuickWebEngineView::WebAction editorActionForKeyEvent(QKeyEvent* event)
+{
+ static struct {
+ QKeySequence::StandardKey standardKey;
+ QQuickWebEngineView::WebAction action;
+ } editorActions[] = {
+ { QKeySequence::Cut, QQuickWebEngineView::Cut },
+ { QKeySequence::Copy, QQuickWebEngineView::Copy },
+ { QKeySequence::Paste, QQuickWebEngineView::Paste },
+ { QKeySequence::Undo, QQuickWebEngineView::Undo },
+ { QKeySequence::Redo, QQuickWebEngineView::Redo },
+ { QKeySequence::SelectAll, QQuickWebEngineView::SelectAll },
+ { QKeySequence::UnknownKey, QQuickWebEngineView::NoWebAction }
+ };
+ for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
+ if (event == editorActions[i].standardKey)
+ return editorActions[i].action;
+
+ return QQuickWebEngineView::NoWebAction;
+}
+
#ifndef QT_NO_ACCESSIBILITY
static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *object)
{
@@ -343,7 +364,8 @@ void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<Cert
Q_Q(QQuickWebEngineView);
QQuickWebEngineCertificateError *quickController = new QQuickWebEngineCertificateError(errorController);
- QQmlEngine::setObjectOwnership(quickController, QQmlEngine::JavaScriptOwnership);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(quickController);
Q_EMIT q->certificateError(quickController);
if (!quickController->deferred() && !quickController->answered())
quickController->rejectCertificate();
@@ -526,6 +548,18 @@ void QQuickWebEngineViewPrivate::focusContainer()
void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event)
{
Q_Q(QQuickWebEngineView);
+#ifdef Q_OS_OSX
+ if (event->type() == QEvent::KeyPress) {
+ QQuickWebEngineView::WebAction action = editorActionForKeyEvent(event);
+ if (action != QQuickWebEngineView::NoWebAction) {
+ // Try triggering a registered short-cut
+ if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcut(event))
+ return;
+ q->triggerWebAction(action);
+ return;
+ }
+ }
+#endif
if (q->parentItem())
q->window()->sendEvent(q->parentItem(), event);
}
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 1b5198110..f13bfd09a 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -73,6 +73,8 @@ class QQmlContext;
class QQuickWebEngineSettings;
class QQuickWebEngineFaviconProvider;
+QQuickWebEngineView::WebAction editorActionForKeyEvent(QKeyEvent* event);
+
#ifdef ENABLE_QML_TESTSUPPORT_API
class QQuickWebEngineTestSupport;
#endif
diff --git a/src/webengine/doc/src/qtwebengine-index.qdoc b/src/webengine/doc/src/qtwebengine-index.qdoc
index e7314fcf9..fd7fe2351 100644
--- a/src/webengine/doc/src/qtwebengine-index.qdoc
+++ b/src/webengine/doc/src/qtwebengine-index.qdoc
@@ -38,10 +38,6 @@
\annotatedlist qtwebengine-modules
- For Qt Quick applications, Qt WebEngine provides the following QML modules:
-
- \annotatedlist qtwebengine-qmlmodules
-
\section1 Articles and Guides
\list
diff --git a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
index 954562e38..87022262d 100644
--- a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
+++ b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
@@ -27,7 +27,7 @@
\qmlmodule QtWebEngine 1.3
\title Qt WebEngine QML Types
\brief Provides QML types for rendering web content within a QML application
- \ingroup qtwebengine-qmlmodules
+ \ingroup qtwebengine-modules
The QML types can be imported into your application using the following import statements in
your .qml file:
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
index 5e39cc2b3..d0bd67e6a 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
@@ -210,6 +210,18 @@ void RenderWidgetHostViewQtDelegateQuick::inputMethodStateChanged(bool editorVis
}
+bool RenderWidgetHostViewQtDelegateQuick::event(QEvent *event)
+{
+ if (event->type() == QEvent::ShortcutOverride) {
+ if (editorActionForKeyEvent(static_cast<QKeyEvent*>(event)) != QQuickWebEngineView::NoWebAction) {
+ event->accept();
+ return true;
+ }
+ }
+
+ return QQuickItem::event(event);
+}
+
void RenderWidgetHostViewQtDelegateQuick::focusInEvent(QFocusEvent *event)
{
m_client->forwardEvent(event);
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h
index 66bc63732..c51ca3408 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h
@@ -77,6 +77,7 @@ public:
virtual void setClearColor(const QColor &) Q_DECL_OVERRIDE { }
protected:
+ virtual bool event(QEvent *event) Q_DECL_OVERRIDE;
virtual void focusInEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
virtual void focusOutEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index bb0db402b..db1915b9f 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -83,6 +83,8 @@
#include <QStyle>
#include <QUrl>
+#include <private/qguiapplication_p.h>
+
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
@@ -103,6 +105,27 @@ static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::Wind
}
}
+QWebEnginePage::WebAction editorActionForKeyEvent(QKeyEvent* event)
+{
+ static struct {
+ QKeySequence::StandardKey standardKey;
+ QWebEnginePage::WebAction action;
+ } editorActions[] = {
+ { QKeySequence::Cut, QWebEnginePage::Cut },
+ { QKeySequence::Copy, QWebEnginePage::Copy },
+ { QKeySequence::Paste, QWebEnginePage::Paste },
+ { QKeySequence::Undo, QWebEnginePage::Undo },
+ { QKeySequence::Redo, QWebEnginePage::Redo },
+ { QKeySequence::SelectAll, QWebEnginePage::SelectAll },
+ { QKeySequence::UnknownKey, QWebEnginePage::NoWebAction }
+ };
+ for (int i = 0; editorActions[i].standardKey != QKeySequence::UnknownKey; ++i)
+ if (event == editorActions[i].standardKey)
+ return editorActions[i].action;
+
+ return QWebEnginePage::NoWebAction;
+}
+
QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
: adapter(new WebContentsAdapter)
, history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
@@ -244,6 +267,19 @@ void QWebEnginePagePrivate::focusContainer()
void QWebEnginePagePrivate::unhandledKeyEvent(QKeyEvent *event)
{
+#ifdef Q_OS_OSX
+ Q_Q(QWebEnginePage);
+ if (event->type() == QEvent::KeyPress) {
+ QWebEnginePage::WebAction action = editorActionForKeyEvent(event);
+ if (action != QWebEnginePage::NoWebAction) {
+ // Try triggering a registered short-cut
+ if (QGuiApplicationPrivate::instance()->shortcutMap.tryShortcut(event))
+ return;
+ q->triggerAction(action);
+ return;
+ }
+ }
+#endif
if (view && view->parentWidget())
QGuiApplication::sendEvent(view->parentWidget(), event);
}
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index c0b1b9a4e..fb0b85268 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -71,6 +71,8 @@ class QWebEngineProfile;
class QWebEngineSettings;
class QWebEngineView;
+QWebEnginePage::WebAction editorActionForKeyEvent(QKeyEvent* event);
+
class QWebEnginePagePrivate : public QtWebEngineCore::WebContentsAdapterClient
{
public:
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
index 99621b602..f0385a252 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -326,6 +326,13 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
}
}
+ if (event->type() == QEvent::ShortcutOverride) {
+ if (editorActionForKeyEvent(static_cast<QKeyEvent*>(event)) != QWebEnginePage::NoWebAction) {
+ event->accept();
+ return true;
+ }
+ }
+
if (event->type() == QEvent::MouseButtonDblClick) {
// QWidget keeps the Qt4 behavior where the DblClick event would replace the Press event.
// QtQuick is different by sending both the Press and DblClick events for the second press