Merge lp:~gerboland/webbrowser-app/formFactor-support into lp:webbrowser-app

Proposed by Gerry Boland
Status: Needs review
Proposed branch: lp:~gerboland/webbrowser-app/formFactor-support
Merge into: lp:webbrowser-app
Diff against target: 298 lines (+99/-67)
5 files modified
src/Ubuntu/Components/Extras/Browser/CMakeLists.txt (+2/-0)
src/Ubuntu/Web/CMakeLists.txt (+2/-0)
src/Ubuntu/Web/UbuntuWebContext.qml (+3/-2)
src/Ubuntu/Web/UserAgent02.qml (+2/-6)
src/Ubuntu/Web/plugin.cpp (+90/-59)
To merge this branch: bzr merge lp:~gerboland/webbrowser-app/formFactor-support
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+286790@code.launchpad.net

Commit message

Use formFactor property supplied by ubuntumirclient QPA where possible. Remove smallScreen heuristics

DO NOT LAND YET. This is (a) something for MWC, and (b) a request for comments if this approach looks reasonable to you

To post a comment you must log in.
Revision history for this message
Olivier Tilloy (osomon) wrote :

I’m not seeing any formFactor property defined on UserAgent02, so I doubt the onFormFactorChanged handler in UbuntuWebContext.qml would work.

Note that I’m currently working on a branch that removes the 'formFactor' property from the Ubuntu.Web plugin’s context object¹, so it’s kind of ironical that you’re adding it back in another branch. I really don’t think the default user agent (and corresponding overrides) should be tied to the "form factor" (whatever that means in a world of convergence). How does mir determine whether a device is a phone or a desktop, or a tablet? Is that a solid API that we are going to support and publicize?

Even if that was a sensible thing to do, we most probably don’t want to get a mobile UX on a tablet. Well, at least not a 10" tablet. On a 7" tablet maybe. See where the screenDiagonal property comes from?

As a side note, the dependency on Qt5Gui_PRIVATE is not very welcome, given that we’ve been steadily working towards entirely removing the dependencies on private Qt packages (ask Mirv about it).

¹ https://code.launchpad.net/~osomon/webbrowser-app/remove-formFactor/+merge/285539

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

> I’m not seeing any formFactor property defined on UserAgent02, so I doubt the
> onFormFactorChanged handler in UbuntuWebContext.qml would work.

Code untested. Was struggling to cross compile & deploy, sbuild unhappy with me today.

> Note that I’m currently working on a branch that removes the 'formFactor'
> property from the Ubuntu.Web plugin’s context object¹, so it’s kind of
> ironical that you’re adding it back in another branch. I really don’t think
> the default user agent (and corresponding overrides) should be tied to the
> "form factor" (whatever that means in a world of convergence). How does mir
> determine whether a device is a phone or a desktop, or a tablet? Is that a
> solid API that we are going to support and publicize?

I obviously have no idea of your plans, this was just an attempt at replacing your screen heuristic with something more concrete.

Form Factor will be a hint to the application to tell it what mode the shell is in, on each screen. Mir supports it, shell will do its best to set it correctly. I would hope the average app author has no need for such a property, any form factor specific behaviour would be encapsulated in the UITK.

> Even if that was a sensible thing to do, we most probably don’t want to get a
> mobile UX on a tablet. Well, at least not a 10" tablet. On a 7" tablet maybe.
> See where the screenDiagonal property comes from?

Is your call. The goal of this was to indicate that you can learn if the app is running on a tablet or a desktop UI at the time.

> As a side note, the dependency on Qt5Gui_PRIVATE is not very welcome, given
> that we’ve been steadily working towards entirely removing the dependencies on
> private Qt packages (ask Mirv about it).

Qt doesn't have a nice way to export it to apps yet, hence having to resort to private Qt headers. As I mentioned in a comment, a better solution is for the UITK to do that for you. This isn't the final solution.
Thanks for the comments!

1359. By Gerry Boland

formFactor not in scope, fix

Revision history for this message
Olivier Tilloy (osomon) wrote :

> > Even if that was a sensible thing to do, we most probably don’t want
> > to get a mobile UX on a tablet. Well, at least not a 10" tablet. On
> > a 7" tablet maybe. See where the screenDiagonal property comes from?
>
> Is your call. The goal of this was to indicate that you can learn if
> the app is running on a tablet or a desktop UI at the time.

Thanks, and that’s useful, but I’m not convinced that (or at least that *alone*) is enough to decide what the default UA string should be. I have started a conversation with design about that, we need to come to a consensus. Until that happens, I’d rather keep the current implementation based on screen size (I’m not against refining it though).

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

> > I’m not seeing any formFactor property defined on UserAgent02, so I doubt
> the
> > onFormFactorChanged handler in UbuntuWebContext.qml would work.
>
> Code untested. Was struggling to cross compile & deploy, sbuild unhappy with
> me today.
>
> > Note that I’m currently working on a branch that removes the 'formFactor'
> > property from the Ubuntu.Web plugin’s context object¹, so it’s kind of
> > ironical that you’re adding it back in another branch. I really don’t think
> > the default user agent (and corresponding overrides) should be tied to the
> > "form factor" (whatever that means in a world of convergence). How does mir
> > determine whether a device is a phone or a desktop, or a tablet? Is that a
> > solid API that we are going to support and publicize?
>
> I obviously have no idea of your plans, this was just an attempt at replacing
> your screen heuristic with something more concrete.
>
> Form Factor will be a hint to the application to tell it what mode the shell
> is in, on each screen. Mir supports it, shell will do its best to set it
> correctly. I would hope the average app author has no need for such a
> property, any form factor specific behaviour would be encapsulated in the
> UITK.
>

It sounds like this might be useful for bug 1545088, bug 1547145 and bug 1547102. How does the shell determine what the hint is?

> > Even if that was a sensible thing to do, we most probably don’t want to get
> a
> > mobile UX on a tablet. Well, at least not a 10" tablet. On a 7" tablet
> maybe.
> > See where the screenDiagonal property comes from?
>
> Is your call. The goal of this was to indicate that you can learn if the app
> is running on a tablet or a desktop UI at the time.
>
> > As a side note, the dependency on Qt5Gui_PRIVATE is not very welcome, given
> > that we’ve been steadily working towards entirely removing the dependencies
> on
> > private Qt packages (ask Mirv about it).
>
> Qt doesn't have a nice way to export it to apps yet, hence having to resort to
> private Qt headers. As I mentioned in a comment, a better solution is for the
> UITK to do that for you. This isn't the final solution.
> Thanks for the comments!

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

1359. By Gerry Boland

formFactor not in scope, fix

1358. By Gerry Boland

Use formFactor property supplied by ubuntumirclient QPA where possible. Remove smallScreen heuristics

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Ubuntu/Components/Extras/Browser/CMakeLists.txt'
--- src/Ubuntu/Components/Extras/Browser/CMakeLists.txt 2015-06-22 10:29:20 +0000
+++ src/Ubuntu/Components/Extras/Browser/CMakeLists.txt 2016-02-22 12:16:23 +0000
@@ -10,6 +10,8 @@
1010
11set(PLUGIN_SRC plugin.cpp)11set(PLUGIN_SRC plugin.cpp)
1212
13include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
14
13add_library(${PLUGIN} MODULE ${PLUGIN_SRC})15add_library(${PLUGIN} MODULE ${PLUGIN_SRC})
14target_link_libraries(${PLUGIN}16target_link_libraries(${PLUGIN}
15 Qt5::Core17 Qt5::Core
1618
=== modified file 'src/Ubuntu/Web/CMakeLists.txt'
--- src/Ubuntu/Web/CMakeLists.txt 2015-08-25 13:56:58 +0000
+++ src/Ubuntu/Web/CMakeLists.txt 2016-02-22 12:16:23 +0000
@@ -10,6 +10,8 @@
1010
11set(PLUGIN_SRC plugin.cpp)11set(PLUGIN_SRC plugin.cpp)
1212
13include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
14
13add_library(${PLUGIN} MODULE ${PLUGIN_SRC})15add_library(${PLUGIN} MODULE ${PLUGIN_SRC})
14target_link_libraries(${PLUGIN}16target_link_libraries(${PLUGIN}
15 Qt5::Core17 Qt5::Core
1618
=== modified file 'src/Ubuntu/Web/UbuntuWebContext.qml'
--- src/Ubuntu/Web/UbuntuWebContext.qml 2015-12-11 10:30:42 +0000
+++ src/Ubuntu/Web/UbuntuWebContext.qml 2016-02-22 12:16:23 +0000
@@ -70,13 +70,14 @@
70 ]70 ]
7171
72 property QtObject __ua: UserAgent02 {72 property QtObject __ua: UserAgent02 {
73 onSmallScreenChanged: reloadOverrides()73 readonly property string formFactor: formFactor
74 onFormFactorChanged: reloadOverrides()
74 Component.onCompleted: reloadOverrides()75 Component.onCompleted: reloadOverrides()
7576
76 property string _target: ""77 property string _target: ""
7778
78 function reloadOverrides() {79 function reloadOverrides() {
79 var target = smallScreen ? "mobile" : "desktop"80 var target = formFactor === "MOBILE" ? "mobile" : "desktop"
80 if (target == _target) return81 if (target == _target) return
81 _target = target82 _target = target
82 var script = "ua-overrides-%1.js".arg(target)83 var script = "ua-overrides-%1.js".arg(target)
8384
=== modified file 'src/Ubuntu/Web/UserAgent02.qml'
--- src/Ubuntu/Web/UserAgent02.qml 2015-12-10 10:43:04 +0000
+++ src/Ubuntu/Web/UserAgent02.qml 2016-02-22 12:16:23 +0000
@@ -28,10 +28,6 @@
28 */28 */
2929
30QtObject {30QtObject {
31 // Empirical value: screens smaller than 19cm are considered small enough that a
32 // mobile UA string is used, screens bigger than that will get desktop content.
33 readonly property bool smallScreen: screenDiagonal < 190
34
35 // %1: Ubuntu version, e.g. "14.04"31 // %1: Ubuntu version, e.g. "14.04"
36 // %2: optional token to specify further attributes of the platform, e.g. "like Android"32 // %2: optional token to specify further attributes of the platform, e.g. "like Android"
37 // %3: optional hardware ID token33 // %3: optional hardware ID token
@@ -50,7 +46,7 @@
50 // FIXME: compute at build time (using lsb_release)46 // FIXME: compute at build time (using lsb_release)
51 readonly property string _ubuntuVersion: "14.04"47 readonly property string _ubuntuVersion: "14.04"
5248
53 readonly property string _attributes: smallScreen ? "like Android 4.4" : ""49 readonly property string _attributes: formFactor === "MOBILE" ? "like Android 4.4" : ""
5450
55 readonly property string _hardwareID: ""51 readonly property string _hardwareID: ""
5652
@@ -63,7 +59,7 @@
63 // every time we rebase on a newer chromium.59 // every time we rebase on a newer chromium.
64 readonly property string _chromiumVersion: "35.0.1870.2"60 readonly property string _chromiumVersion: "35.0.1870.2"
6561
66 readonly property string _formFactor: smallScreen ? "Mobile" : ""62 readonly property string _formFactor: formFactor === "MOBILE" ? "Mobile" : ""
6763
68 readonly property string _more: ""64 readonly property string _more: ""
6965
7066
=== modified file 'src/Ubuntu/Web/plugin.cpp'
--- src/Ubuntu/Web/plugin.cpp 2015-12-10 22:01:05 +0000
+++ src/Ubuntu/Web/plugin.cpp 2016-02-22 12:16:23 +0000
@@ -34,14 +34,15 @@
34#include <QtQml>34#include <QtQml>
35#include <QtQml/QQmlInfo>35#include <QtQml/QQmlInfo>
3636
37#include <QtGui/qpa/qplatformnativeinterface.h>
38
37class UbuntuWebPluginContext : public QObject39class UbuntuWebPluginContext : public QObject
38{40{
39 Q_OBJECT41 Q_OBJECT
4042
41 Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged)43 Q_PROPERTY(QString cacheLocation READ cacheLocation NOTIFY cacheLocationChanged)
42 Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged)44 Q_PROPERTY(QString dataLocation READ dataLocation NOTIFY dataLocationChanged)
43 Q_PROPERTY(QString formFactor READ formFactor CONSTANT)45 Q_PROPERTY(QString formFactor READ formFactor NOTIFY formFactorChanged)
44 Q_PROPERTY(qreal screenDiagonal READ screenDiagonal NOTIFY screenDiagonalChanged)
45 Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged)46 Q_PROPERTY(int cacheSizeHint READ cacheSizeHint NOTIFY cacheSizeHintChanged)
46 Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT)47 Q_PROPERTY(QString webviewDevtoolsDebugHost READ devtoolsHost CONSTANT)
47 Q_PROPERTY(int webviewDevtoolsDebugPort READ devtoolsPort CONSTANT)48 Q_PROPERTY(int webviewDevtoolsDebugPort READ devtoolsPort CONSTANT)
@@ -53,7 +54,6 @@
53 QString cacheLocation() const;54 QString cacheLocation() const;
54 QString dataLocation() const;55 QString dataLocation() const;
55 QString formFactor();56 QString formFactor();
56 qreal screenDiagonal() const;
57 int cacheSizeHint() const;57 int cacheSizeHint() const;
58 QString devtoolsHost();58 QString devtoolsHost();
59 int devtoolsPort();59 int devtoolsPort();
@@ -62,15 +62,15 @@
62Q_SIGNALS:62Q_SIGNALS:
63 void cacheLocationChanged() const;63 void cacheLocationChanged() const;
64 void dataLocationChanged() const;64 void dataLocationChanged() const;
65 void screenDiagonalChanged() const;65 void formFactorChanged() const;
66 void cacheSizeHintChanged() const;66 void cacheSizeHintChanged() const;
6767
68private Q_SLOTS:68private Q_SLOTS:
69 void onFocusWindowChanged(QWindow* window);69 void onWindowPropertyChanged(QPlatformWindow* window, const QString &property);
70 void updateScreen();
7170
72private:71private:
73 qreal m_screenDiagonal; // in millimeters72 void prepareFormFactor();
73 QString readFormFactorFromPlatform(QPlatformWindow *window);
74 QString m_formFactor;74 QString m_formFactor;
75 QString m_devtoolsHost;75 QString m_devtoolsHost;
76 int m_devtoolsPort;76 int m_devtoolsPort;
@@ -80,30 +80,57 @@
8080
81UbuntuWebPluginContext::UbuntuWebPluginContext(QObject* parent)81UbuntuWebPluginContext::UbuntuWebPluginContext(QObject* parent)
82 : QObject(parent)82 : QObject(parent)
83 , m_screenDiagonal(0)
84 , m_devtoolsPort(-2)83 , m_devtoolsPort(-2)
85 , m_hostMappingRulesQueried(false)84 , m_hostMappingRulesQueried(false)
86{85{
87 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(cacheLocationChanged()));86 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(cacheLocationChanged()));
88 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(dataLocationChanged()));87 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(dataLocationChanged()));
89 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(cacheSizeHintChanged()));88 connect(qApp, SIGNAL(applicationNameChanged()), SIGNAL(cacheSizeHintChanged()));
90 updateScreen();89 prepareFormFactor();
91 connect(qApp, SIGNAL(focusWindowChanged(QWindow*)), SLOT(onFocusWindowChanged(QWindow*)));
92}90}
9391
94void UbuntuWebPluginContext::updateScreen()92namespace {
93 // This implementation only considers two possible form factors: desktop,
94 // and mobile (which includes phones and tablets).
95 // XXX: do we need to consider other form factors, such as tablet?
96 const char* DESKTOP = "desktop";
97 const char* MOBILE = "mobile";
98} // anonymous namespace
99
100void UbuntuWebPluginContext::prepareFormFactor()
95{101{
96 QWindow* window = qApp->focusWindow();102 // The "DESKTOP_MODE" environment variable can be used to force the form
97 if (window) {103 // factor to desktop, when set to any valid value other than 0.
98 QScreen* screen = window->screen();104 const char* DESKTOP_MODE_ENV_VAR = "DESKTOP_MODE";
99 if (screen) {105 if (qEnvironmentVariableIsSet(DESKTOP_MODE_ENV_VAR)) {
100 QSizeF size = screen->physicalSize();106 QByteArray stringValue = qgetenv(DESKTOP_MODE_ENV_VAR);
101 qreal diagonal = qSqrt(size.width() * size.width() + size.height() * size.height());107 bool ok = false;
102 if (diagonal != m_screenDiagonal) {108 int value = stringValue.toInt(&ok);
103 m_screenDiagonal = diagonal;109 if (ok) {
104 Q_EMIT screenDiagonalChanged();110 m_formFactor = (value == 0) ? MOBILE : DESKTOP;
111 return;
112 }
113 }
114
115 // If using QtUbuntu, try fetch formFactor property, falling back to assumption of mobile if that fails
116 QString platform = QGuiApplication::platformName();
117 if (platform != "ubuntumirclient") {
118 m_formFactor = DESKTOP;
119 } else { // We will get notifications of a "formFactor" property changing from the QPA for all windows
120 auto nativeInterface = qGuiApp->platformNativeInterface();
121 connect(nativeInterface,
122 SIGNAL(windowPropertyChanged(QPlatformWindow*, const QString&)),
123 SLOT(onWindowPropertyChanged(QPlatformWindow*, const QString&)));
124
125 auto window = qGuiApp->allWindows().first(); // FIXME: context property not suitable for per-window formFactor
126 if (window) {
127 auto formFactor = readFormFactorFromPlatform(window->handle());
128 if (!formFactor.isEmpty()) {
129 m_formFactor = formFactor;
130 return;
105 }131 }
106 }132 }
133 m_formFactor = MOBILE; // fallback position
107 }134 }
108}135}
109136
@@ -131,43 +158,9 @@
131158
132QString UbuntuWebPluginContext::formFactor()159QString UbuntuWebPluginContext::formFactor()
133{160{
134 if (m_formFactor.isEmpty()) {
135 // This implementation only considers two possible form factors: desktop,
136 // and mobile (which includes phones and tablets).
137 // XXX: do we need to consider other form factors, such as tablet?
138 const char* DESKTOP = "desktop";
139 const char* MOBILE = "mobile";
140
141 // The "DESKTOP_MODE" environment variable can be used to force the form
142 // factor to desktop, when set to any valid value other than 0.
143 const char* DESKTOP_MODE_ENV_VAR = "DESKTOP_MODE";
144 if (qEnvironmentVariableIsSet(DESKTOP_MODE_ENV_VAR)) {
145 QByteArray stringValue = qgetenv(DESKTOP_MODE_ENV_VAR);
146 bool ok = false;
147 int value = stringValue.toInt(&ok);
148 if (ok) {
149 m_formFactor = (value == 0) ? MOBILE : DESKTOP;
150 return m_formFactor;
151 }
152 }
153
154 // XXX: Assume that QtUbuntu means mobile, which is currently the case,
155 // but may not remain true forever.
156 QString platform = QGuiApplication::platformName();
157 if ((platform == "ubuntu") || (platform == "ubuntumirclient")) {
158 m_formFactor = MOBILE;
159 } else {
160 m_formFactor = DESKTOP;
161 }
162 }
163 return m_formFactor;161 return m_formFactor;
164}162}
165163
166qreal UbuntuWebPluginContext::screenDiagonal() const
167{
168 return m_screenDiagonal;
169}
170
171int UbuntuWebPluginContext::cacheSizeHint() const164int UbuntuWebPluginContext::cacheSizeHint() const
172{165{
173 if (QCoreApplication::applicationName() == "webbrowser-app") {166 if (QCoreApplication::applicationName() == "webbrowser-app") {
@@ -242,11 +235,49 @@
242 return m_devtoolsPort;235 return m_devtoolsPort;
243}236}
244237
245void UbuntuWebPluginContext::onFocusWindowChanged(QWindow* window)238void UbuntuWebPluginContext::onWindowPropertyChanged(QPlatformWindow *window, const QString &property)
246{239{
247 updateScreen();240 if (property != QStringLiteral("formFactor")) {
248 if (window) {241 return;
249 connect(window, SIGNAL(screenChanged(QScreen*)), SLOT(updateScreen()));242 }
243
244 auto formFactor = readFormFactorFromPlatform(window);
245 if (!formFactor.isEmpty()) {
246 m_formFactor = formFactor;
247 Q_EMIT formFactorChanged();
248 }
249}
250
251// FIXME: this should be a per-window/screen property nicely wrapped by the UITK
252QString UbuntuWebPluginContext::readFormFactorFromPlatform(QPlatformWindow *window)
253{
254 auto nativeInterface = qGuiApp->platformNativeInterface();
255 QVariant formFactorVal = nativeInterface->windowProperty(window, QStringLiteral("formFactor"));
256 if (!formFactorVal.isValid()) {
257 return QString();
258 }
259
260 // taken from MirFormFactor enum in mirclient/common.h
261 typedef enum MirFormFactor
262 {
263 mir_form_factor_unknown,
264 mir_form_factor_phone,
265 mir_form_factor_tablet,
266 mir_form_factor_monitor,
267 mir_form_factor_tv,
268 mir_form_factor_projector,
269 } MirFormFactor;
270
271 bool ok;
272 auto formFactor = static_cast<MirFormFactor>(formFactorVal.toInt(&ok));
273 if (!ok) {
274 return QString();
275 }
276
277 if (formFactor == mir_form_factor_phone || formFactor == mir_form_factor_tablet) {
278 return MOBILE;
279 } else {
280 return DESKTOP;
250 }281 }
251}282}
252283

Subscribers

People subscribed via source and target branches

to status/vote changes: