1/*! 2 \inmodule QtWebKit 3 \page qtwebkit-goes-mobile.html 4 \title Qt WebKit Goes Mobile 5 \contentspage Qt WebKit 6 \section1 Overview 7 8 A lot of effort has been put into Qt WebKit to make it attractive for 9 use on mobile devices. 10 11 The goal of this tutorial is to help you understand the mobile 12 features and how to make the best of them, in other words, how to 13 create a good mobile web view that can be used on touch devices. 14 15 If you want to target mobile devices you should consider using \l{QGraphicsWebView} 16 instead of \l{QWebView}. Since \l{QWebView} is based on the \l{QWidget} 17 system, it cannot easily support rotation, overlays, hardware accelerated 18 compositing and tiling. If you need a \l{QWidget} anyway, you can always 19 construct a \l{QGraphicsView} (which is a \l{QWidget}) with a \l{QGraphicsWebView} inside. 20 21 So let's start with a very simple \l{QGraphicsWebView} based "browser": 22 23 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 0 24 25 Here we set up a \l{QGraphicsView} application and add a 26 \l{QGraphicsWebView} to the scene. Notice 27 that we're disabling the scrollbars on the QGraphicsView because Qt WebKit 28 handles scrolling and scrollbars automatically. This is to allow scrolling 29 optimizations and to enable web authors to interact with the scrollbars, 30 for instance, to style them differently. 31 32 On touch-based mobile devices a feature known as tiling is often used. It 33 is used due to the interaction model (touch) as well as a scrolling 34 optimization. With this optimization we will have to deal with scrolling 35 ourselves, and we will have to disable features like scroll bar styling. 36 This is not usually a problem, since mobile browsers do not usually show 37 scroll bars, but use scroll indicators instead. 38 39 Tiling basically means that the contents of the viewport is separated into 40 a grid of tiles, so that when you update an area, instead of just updating 41 the area, you actually update the whole tile or sub-regions of it. 42 This offers a few advantages for scrolling as, when you scroll, you do not need 43 to repaint the new visible area for each scroll step, but you simply update a row 44 of tiles each time; these tiles are often only partly on the screen. 45 This minimizes all the painting calls that we have to do and enables kinetic scrolling. 46 47 Loading, rendering, and laying out are blocking operations. Though barely 48 noticeable on desktop machines, these operations can block for a long time 49 on a mobile device, letting the user believe the application has become 50 unresponsive. Additionally, scrolling will also stall when the user uses 51 his fingers to scroll, leading to a bad user experience. 52 53 One way to overcome this issue, is to do all loading, laying out and 54 painting (basically all non-UI related work) in another thread or process, and 55 just blit the result from the web process/thread to the UI. There is research 56 in progress to enable this for a future version of Qt WebKit, using WebKit2, but for now, 57 freezing the backing store can help when performing a zooming operation, for instance. 58 This will be discussed later, in the \l{#Enabling the Tiling}{Enabling the Tiling} section. 59 60 When using tiles, you can blit any tile available when scrolling. When no tile is available you 61 can show a checkerboard tile instead, not letting the scrolling wait for the 62 tiles to be updated. This results in a responsive interface, with the only 63 disadvantage that you might see checkerboard tiles from time to time. 64 65 The use of tiles also helps with zooming. Repainting at each zoom level change during 66 a zoom animation is basically impossible on a mobile device (or desktop for 67 that matter) and thus, with tiling, you can stop the tiles from being updated and 68 just scale the existing tiles. Then, at the end of the animation, update 69 tiles on top of the scaled ones. For now we will ignore the blocking 70 issue and concentrate on the tiling and the interaction model. 71 More information about Tiling can be found here: \l{http://doc.qt.nokia.com/4.7/qwebsettings.html#WebAttribute-enum} (see the entry for TiledBackingStoreEnabled). 72 73 74 \section1 Resize to Contents 75 76 When using tiling, we want the \l{QGraphicsWebView} to act as our 77 content, as it supports tiling. In order for this we need to make it 78 resize itself to the size of its contents. For this we will use 79 \l{QGraphicsWebView::resizesToContents}. 80 81 This setting removes the scroll bars for us on the main frame and 82 makes our \l{QGraphicsWebView} resize itself to the size of its content. 83 84 Enabling it is as easy as setting the property: 85 86 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 1 87 88 The property should be used in conjunction with the 89 QWebPage::preferredContentsSize property. If not explicitly set, 90 it is automatically set to a reasonable value. 91 92 If we expand our mobile web view to the size of the contents 93 of its contained page, the view will be bigger than the device screen. 94 95 96 \section1 Using a View as the Window onto the Contents 97 98 The idea is to have a custom widget which has a \l{QGraphicsWebView} as a 99 class member. Remember that the QGraphicsWebView will be as big as its 100 content's size, so this custom widget will serve as a viewport onto the 101 web view. 102 103 The following code snippet illustrates this: 104 105 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 2 106 107 In order to properly handle mouse events, you must install an event filter 108 on the web view or stack it behind its parent object 109 (\l{QGraphicsItem::ItemStacksBehindParent}). By doing this the mouse events will 110 reach a \c{MobileWebView} instance before they reach the member 111 \l{QGraphicsWebView}. Keep in mind that you'll need to add some logic in order 112 to distinguish between different mouse events and gestures, such as a 113 single click, double click and click-and-pan. Besides, scrolling and 114 zooming will have to be implemented manually. 115 116 117 \section1 Adjusting How Contents are Laid Out 118 119 When testing the above on a device, you will notice that many pages are not 120 laid out very nicely. In particular, the width of the content may be larger 121 than the width of the device. This is due to the way web contents are laid 122 out. First, the viewport width is used for fitting the contents. If the 123 contents do not fit due to a non-flexible element with a width larger than 124 the viewport width, the minimum possible width will be used. As most pages 125 are written with a desktop browser in mind, that makes only very few sites 126 fit into the width of a mobile device. 127 128 Qt WebKit has a way to force a layout to a given width or height. What really 129 matters here is the width. If you lay out a page to a given width, it will get 130 that width and images might be cropped. The width or height is also used for 131 laying out fixed elements, but when we resize the \l{QGraphicsWebView} to the 132 size of the contents, fixed elements will not be relative to the view, which is 133 the behavior found on most mobile browsers. 134 135 We saw that the QWebPage::preferredContentsSize property is automatically set 136 to a reasonable value when using \l{QGraphicsWebView::resizesToContents}. 137 138 As you can imagine, laying out with a smaller viewport can cause pages to 139 break, therefore a default value has been chosen so that it almost breaks no 140 pages while still making pages fit. This value is 960x800. If the device 141 has a greater resolution, this value can be changed like this: 142 143 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 3 144 145 You can play around with this and find a suitable size for your device, 146 but we will keep the default size for now. 147 148 149 \section1 The 'viewport' Meta-Tag 150 151 As some sites do not work with 960 pixels width or want to have control of 152 how the page is laid out, Qt WebKit, Android, Firefox Mobile and 153 the iPhone Safari browser support a meta-tag called \c viewport. This makes 154 it possible for a web page to let the browser know how it wants to be shown. 155 More info can be found in the 156 \l{http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/usingtheviewport/usingtheviewport.html}{Safari Developer Library}. 157 158 You must connect the signal \c{QWebPage::viewportChangeRequested(const 159 QWebPage::ViewportHints& hints)} to a slot of your mobile web view and use what 160 is provided by \l{QWebPage::ViewportHints} to update your viewport size, scale 161 range, and so on. 162 163 164 \section1 Enabling the Tiling 165 166 We haven't actually enabled tiling yet, so let's go ahead and do that. That 167 is very simple as it is basically a setting: 168 169 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 4 170 171 Note that, if you are going to add animations to your zooming or scaling 172 operations or want to implement fancy kinetic scrolling you might want to 173 take a look at \l{QGraphicsWebView::setTiledBackingStoreFrozen()}. With this, 174 you can avoid updates to your tiles during an animation, for instance. 175 176 177 \section1 Avoiding Scrollable Subelements 178 179 One big issue with the above is that, iframes and sites using frames can 180 contain scrollable subelements. That doesn't work well with the touch 181 interaction model, as you want a finger swipe to scroll the whole page and not 182 end up just scrolling a subframe. Most mobile browsers work around this by 183 enabling something called frame flattening. Going straight to the point: 184 185 \snippet webkitsnippets/qtwebkit_goes_mobile_snippets.cpp 5 186 187 This will make all frames from a web page expand themselves to the size of 188 their contents, keeping us free of scrollable subareas. 189 190 191*/ 192