• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Joone Hur <joone@kldp.org>
3  * Copyright (C) 2010 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 #include "webkitviewportattributes.h"
23 
24 #include "Chrome.h"
25 #include "Frame.h"
26 #include "Page.h"
27 #include "webkitglobalsprivate.h"
28 #include "webkitviewportattributesprivate.h"
29 #include "webkitwebviewprivate.h"
30 #include <glib/gi18n-lib.h>
31 
32 /**
33  * SECTION:webkitviewportattributes
34  * @short_description: Represents the viewport properties of a web page
35  * @see_also: #WebKitWebView::viewport-attributes-recompute-requested
36  * @see_also: #WebKitWebView::viewport-attributes-changed
37  *
38  * #WebKitViewportAttributes offers the viewport properties to user agents to
39  * control the viewport layout. It contains the viewport size, initial scale with limits,
40  * and information about whether a user is able to scale the contents in the viewport.
41  * This makes a web page fit the device screen.
42  *
43  * The #WebKitWebView::viewport-attributes-changed signal will be emitted with #WebKitViewportAttributes
44  * when the viewport attributes are updated in the case of loading web pages contain
45  * the viewport properties and calling webkit_viewport_attributes_recompute.
46  *
47  * If the device size, available size, desktop width, or device DPI needs to be changed due to
48  * a consequence of an explicit browser request (caused by screen rotation, resizing, or similar reasons),
49  * You should call #webkit_viewport_attributes_recompute to recompute the viewport properties and
50  * override those values in the handler of #WebKitWebView::viewport-attributes-recompute-requested signal.
51  *
52  * For more information on the viewport properties, refer to the Safari reference library at
53  * http://developer.apple.com/safari/library/documentation/appleapplications/reference/safarihtmlref/articles/metatags.html
54  *
55  * <informalexample><programlisting>
56  * /<!-- -->* Connect to the viewport-attributes-changes signal *<!-- -->/
57  * WebKitViewportAttributes* attributes = webkit_web_view_get_viewport_attributes (web_view);
58  * g_signal_connect (web_view, "viewport-attributes-recompute-requested", G_CALLBACK (viewport_recompute_cb), window);
59  * g_signal_connect (web_view, "viewport-attributes-changed", G_CALLBACK (viewport_changed_cb), window);
60  * g_signal_connect (attributes, "notify::valid", G_CALLBACK (viewport_valid_changed_cb), web_view);
61  *
62  * /<!-- -->* Handle the viewport-attributes-recompute-requested signal to override the device width *<!-- -->/
63  * static void
64  * viewport_recompute_cb (WebKitWebView* web_view, WebKitViewportAttributes* attributes, GtkWidget* window)
65  * {
66  *     int override_available_width = 480;
67  *     g_object_set (G_OBJECT(attributes), "available-width", override_available_width, NULL);
68  * }
69  *
70  * /<!-- -->* Handle the viewport-attributes-changed signal to recompute the initial scale factor *<!-- -->/
71  * static void
72  * viewport_changed_cb (WebKitWebView* web_view, WebKitViewportAttributes* attributes, gpointer data)
73  * {
74  *     gfloat initialScale;
75  *     g_object_get (G_OBJECT (atributes), "initial-scale-factor", &initialScale, NULL);
76  *     webkit_web_view_set_zoom_level (web_view, initialScale);
77  * }
78  *
79  * /<!-- -->* Handle the notify::valid signal to initialize the zoom level *<!-- -->/
80  * static void
81  * viewport_valid_changed_cb (WebKitViewportAttributes* attributes, GParamSpec* pspec, WebKitWebView* web_view)
82  * {
83  *     gboolean is_valid;
84  *     g_object_get (attributes, "valid", &is_valid, NULL);
85  *     if (!is_valid)
86  *         webkit_web_view_set_zoom_level (web_view, 1.0);
87  * }
88  * </programlisting></informalexample>
89  */
90 
91 using namespace WebKit;
92 using namespace WebCore;
93 
94 enum {
95     PROP_0,
96 
97     PROP_DEVICE_WIDTH,
98     PROP_DEVICE_HEIGHT,
99     PROP_AVAILABLE_WIDTH,
100     PROP_AVAILABLE_HEIGHT,
101     PROP_DESKTOP_WIDTH,
102     PROP_DEVICE_DPI,
103     PROP_WIDTH,
104     PROP_HEIGHT,
105     PROP_INITIAL_SCALE_FACTOR,
106     PROP_MINIMUM_SCALE_FACTOR,
107     PROP_MAXIMUM_SCALE_FACTOR,
108     PROP_DEVICE_PIXEL_RATIO,
109     PROP_USER_SCALABLE,
110     PROP_VALID
111 };
112 
113 G_DEFINE_TYPE(WebKitViewportAttributes, webkit_viewport_attributes, G_TYPE_OBJECT);
114 
115 static void webkit_viewport_attributes_get_property(GObject* object, guint propertyID, GValue* value, GParamSpec* paramSpec);
116 static void webkit_viewport_attributes_set_property(GObject* object, guint propertyID, const GValue* value, GParamSpec* paramSpec);
117 
webkit_viewport_attributes_class_init(WebKitViewportAttributesClass * kclass)118 static void webkit_viewport_attributes_class_init(WebKitViewportAttributesClass* kclass)
119 {
120     GObjectClass* gobjectClass = G_OBJECT_CLASS(kclass);
121     gobjectClass->get_property = webkit_viewport_attributes_get_property;
122     gobjectClass->set_property = webkit_viewport_attributes_set_property;
123 
124     /**
125      * WebKitViewportAttributs:device-width:
126      *
127      * The width of the screen. This value is always automatically
128      * pre-computed during a viewport attributes recomputation, and
129      * can be overridden by the handler of
130      * WebKitWebView::viewport-attributes-recompute-requested. You
131      * should not do that unless you have a very good reason.
132      *
133      * Since: 1.3.8
134      */
135     g_object_class_install_property(gobjectClass,
136                                     PROP_DEVICE_WIDTH,
137                                     g_param_spec_int(
138                                     "device-width",
139                                     _("Device Width"),
140                                     _("The width of the screen."),
141                                     0,
142                                     G_MAXINT,
143                                     0,
144                                     WEBKIT_PARAM_READWRITE));
145 
146     /**
147      * WebKitViewportAttributs:device-height:
148      *
149      * The height of the screen. This value is always automatically
150      * pre-computed during a viewport attributes recomputation, and
151      * can be overriden by the handler of
152      * WebKitWebView::viewport-attributes-recompute-requested. You
153      * should not do that unless you have a very good reason.
154      *
155      * Since: 1.3.8
156      */
157     g_object_class_install_property(gobjectClass,
158                                     PROP_DEVICE_HEIGHT,
159                                     g_param_spec_int(
160                                     "device-height",
161                                     _("Device Height"),
162                                     _("The height of the screen."),
163                                     0,
164                                     G_MAXINT,
165                                     0,
166                                     WEBKIT_PARAM_READWRITE));
167 
168     /**
169      * WebKitViewportAttributs:available-width:
170      *
171      * The width of the current visible area. This will usually be the
172      * same as the space allocated to the widget, but in some cases
173      * you may have decided to make the widget bigger than the visible
174      * area. This value is by default initialized to the size
175      * allocated by the widget, but you can override it in the handler
176      * of WebKitWebView::viewport-attributes-recompute-requested to
177      * let the engine know what the visible area is.
178      *
179      * Since: 1.3.8
180      */
181     g_object_class_install_property(gobjectClass,
182                                     PROP_AVAILABLE_WIDTH,
183                                     g_param_spec_int(
184                                     "available-width",
185                                     _("Available Width"),
186                                     _("The width of the visible area."),
187                                     0,
188                                     G_MAXINT,
189                                     0,
190                                     WEBKIT_PARAM_READWRITE));
191 
192     /**
193      * WebKitViewportAttributs:available-height:
194      *
195      * The height of the current visible area. This will usually be the
196      * same as the space allocated to the widget, but in some cases
197      * you may have decided to make the widget bigger than the visible
198      * area. This value is by default initialized to the size
199      * allocated by the widget, but you can override it in the handler
200      * of WebKitWebView::viewport-attributes-recompute-requested to
201      * let the engine know what the visible area is.
202      *
203      * Since: 1.3.8
204      */
205     g_object_class_install_property(gobjectClass,
206                                     PROP_AVAILABLE_HEIGHT,
207                                     g_param_spec_int(
208                                     "available-height",
209                                     _("Available Height"),
210                                     _("The height of the visible area."),
211                                     0,
212                                     G_MAXINT,
213                                     0,
214                                     WEBKIT_PARAM_READWRITE));
215 
216     /**
217      * WebKitViewportAttributs:desktop-width:
218      *
219      * The width of viewport that works well for most web pages designed for
220      * desktop. This value is initialized to 980 pixels by default and used
221      * during a viewport attributes recomputation. Also, it can be overriden by
222      * the handler of WebKitWebView::viewport-attributes-recompute-requested.
223      * You should not do that unless you have a very good reason.
224      *
225      * Since: 1.3.8
226      */
227     g_object_class_install_property(gobjectClass,
228                                     PROP_DESKTOP_WIDTH,
229                                     g_param_spec_int(
230                                     "desktop-width",
231                                     _("Desktop Width"),
232                                     _("The width of viewport that works well for most web pages designed for desktop."),
233                                     0,
234                                     G_MAXINT,
235                                     980,
236                                     WEBKIT_PARAM_READWRITE));
237 
238     /**
239      * WebKitViewportAttributs:device-dpi:
240      *
241      * The number of dots per inch of the screen. This value is
242      * initialized to 160 dpi by default and used during a viewport
243      * attributes recomputation, because it is the dpi of the original
244      * iPhone and Android devices. Also, it can be overriden by the
245      * handler of WebKitWebView::viewport-attributes-recompute-requested.
246      * You should not do that unless you have a very good reason.
247      *
248      * Since: 1.3.8
249      */
250     g_object_class_install_property(gobjectClass,
251                                     PROP_DEVICE_DPI,
252                                     g_param_spec_int(
253                                     "device-dpi",
254                                     _("Device DPI"),
255                                     _("The number of dots per inch of the screen."),
256                                     0,
257                                     G_MAXINT,
258                                     160,
259                                     WEBKIT_PARAM_READWRITE));
260 
261     /**
262      * WebKitViewportAttributs:width:
263      *
264      * The width of the viewport. Before getting this property,
265      * you need to make sure that #WebKitViewportAttributes is valid.
266      *
267      * Since: 1.3.8
268      */
269     g_object_class_install_property(gobjectClass,
270                                     PROP_WIDTH,
271                                     g_param_spec_int(
272                                     "width",
273                                     _("Width"),
274                                     _("The width of the viewport."),
275                                     0,
276                                     G_MAXINT,
277                                     0,
278                                     WEBKIT_PARAM_READABLE));
279 
280     /**
281      * WebKitViewportAttributs:height:
282      *
283      * The height of the viewport. Before getting this property,
284      * you need to make sure that #WebKitViewportAttributes is valid.
285      *
286      * Since: 1.3.8
287      */
288     g_object_class_install_property(gobjectClass,
289                                     PROP_HEIGHT,
290                                     g_param_spec_int(
291                                     "height",
292                                     _("Height"),
293                                     _("The height of the viewport."),
294                                     0,
295                                     G_MAXINT,
296                                     0,
297                                     WEBKIT_PARAM_READABLE));
298 
299     /**
300      * WebKitViewportAttributs:initial-scale-factor:
301      *
302      * The initial scale of the viewport. Before getting this property,
303      * you need to make sure that #WebKitViewportAttributes is valid.
304      *
305      * Since: 1.3.8
306      */
307     g_object_class_install_property(gobjectClass,
308                                     PROP_INITIAL_SCALE_FACTOR,
309                                     g_param_spec_float(
310                                     "initial-scale-factor",
311                                     _("Initial Scale Factor"),
312                                     _("The initial scale of the viewport."),
313                                     -1,
314                                     G_MAXFLOAT,
315                                     -1,
316                                     WEBKIT_PARAM_READABLE));
317 
318     /**
319      * WebKitViewportAttributs:minimum-scale-factor:
320      *
321      * The minimum scale of the viewport. Before getting this property,
322      * you need to make sure that #WebKitViewportAttributes is valid.
323      *
324      * Since: 1.3.8
325      */
326     g_object_class_install_property(gobjectClass,
327                                     PROP_MINIMUM_SCALE_FACTOR,
328                                     g_param_spec_float(
329                                     "minimum-scale-factor",
330                                     _("Minimum Scale Factor"),
331                                     _("The minimum scale of the viewport."),
332                                     -1,
333                                     G_MAXFLOAT,
334                                     -1,
335                                     WEBKIT_PARAM_READABLE));
336 
337     /**
338      * WebKitViewportAttributs:maximum-scale-factor:
339      *
340      * The maximum scale of the viewport. Before getting this property,
341      * you need to make sure that #WebKitViewportAttributes is valid.
342      *
343      * Since: 1.3.8
344      */
345     g_object_class_install_property(gobjectClass,
346                                     PROP_MAXIMUM_SCALE_FACTOR,
347                                     g_param_spec_float(
348                                     "maximum-scale-factor",
349                                     _("Maximum Scale Factor"),
350                                     _("The maximum scale of the viewport."),
351                                     -1,
352                                     G_MAXFLOAT,
353                                     -1,
354                                     WEBKIT_PARAM_READABLE));
355 
356     /**
357      * WebKitViewportAttributs:device-pixel-ratio:
358      *
359      * The device pixel ratio of the viewport. Before getting this property,
360      * you need to make sure that #WebKitViewportAttributes is valid.
361      *
362      * Since: 1.3.8
363      */
364     g_object_class_install_property(gobjectClass,
365                                     PROP_DEVICE_PIXEL_RATIO,
366                                     g_param_spec_float(
367                                     "device-pixel-ratio",
368                                     _("Device Pixel Ratio"),
369                                     _("The device pixel ratio of the viewport."),
370                                     -1,
371                                     G_MAXFLOAT,
372                                     -1,
373                                     WEBKIT_PARAM_READABLE));
374 
375     /**
376      * WebKitViewportAttributs:user-scalable:
377      *
378      * Determines whether or not the user can zoom in and out.
379      * Before getting this property, you need to make sure that
380      * #WebKitViewportAttributes is valid.
381      *
382      * Since: 1.3.8
383      */
384     g_object_class_install_property(gobjectClass,
385                                     PROP_USER_SCALABLE,
386                                     g_param_spec_boolean(
387                                     _("user-scalable"),
388                                     _("User Scalable"),
389                                     _("Determines whether or not the user can zoom in and out."),
390                                     TRUE,
391                                     WEBKIT_PARAM_READABLE));
392 
393     /**
394      * WebKitViewportAttributs:valid:
395      *
396      * Determines whether or not the attributes are valid.
397      * #WebKitViewportAttributes are only valid on pages
398      * which have a viewport meta tag, and have already
399      * had the attributes calculated.
400      *
401      * Since: 1.3.8
402      */
403     g_object_class_install_property(gobjectClass,
404                                     PROP_VALID,
405                                     g_param_spec_boolean(
406                                     _("valid"),
407                                     _("Valid"),
408                                     _("Determines whether or not the attributes are valid, and can be used."),
409                                     FALSE,
410                                     WEBKIT_PARAM_READABLE));
411 
412     g_type_class_add_private(kclass, sizeof(WebKitViewportAttributesPrivate));
413 }
414 
webkit_viewport_attributes_init(WebKitViewportAttributes * viewport)415 static void webkit_viewport_attributes_init(WebKitViewportAttributes* viewport)
416 {
417     viewport->priv = G_TYPE_INSTANCE_GET_PRIVATE(viewport, WEBKIT_TYPE_VIEWPORT_ATTRIBUTES, WebKitViewportAttributesPrivate);
418 
419     viewport->priv->deviceWidth = 0;
420     viewport->priv->deviceHeight = 0;
421     viewport->priv->availableWidth = 0;
422     viewport->priv->availableHeight = 0;
423     viewport->priv->desktopWidth = 980; // This value works well for most web pages designed for desktop browsers.
424     viewport->priv->deviceDPI = 160; // It is the dpi of the original iPhone and Android devices.
425     viewport->priv->width = 0;
426     viewport->priv->height = 0;
427     viewport->priv->initialScaleFactor = -1;
428     viewport->priv->minimumScaleFactor = -1;
429     viewport->priv->maximumScaleFactor = -1;
430     viewport->priv->devicePixelRatio = -1;
431     viewport->priv->userScalable = TRUE;
432     viewport->priv->isValid = FALSE;
433 }
434 
webkit_viewport_attributes_get_property(GObject * object,guint propertyID,GValue * value,GParamSpec * paramSpec)435 static void webkit_viewport_attributes_get_property(GObject* object, guint propertyID, GValue* value, GParamSpec* paramSpec)
436 {
437     WebKitViewportAttributes* viewportAttributes = WEBKIT_VIEWPORT_ATTRIBUTES(object);
438     WebKitViewportAttributesPrivate* priv = viewportAttributes->priv;
439 
440     switch (propertyID) {
441     case PROP_DEVICE_WIDTH:
442         g_value_set_int(value, priv->deviceWidth);
443         break;
444     case PROP_DEVICE_HEIGHT:
445         g_value_set_int(value, priv->deviceHeight);
446         break;
447     case PROP_AVAILABLE_WIDTH:
448         g_value_set_int(value, priv->availableWidth);
449         break;
450     case PROP_AVAILABLE_HEIGHT:
451         g_value_set_int(value, priv->availableHeight);
452         break;
453     case PROP_DESKTOP_WIDTH:
454         g_value_set_int(value, priv->desktopWidth);
455         break;
456     case PROP_DEVICE_DPI:
457         g_value_set_int(value, priv->deviceDPI);
458         break;
459     case PROP_WIDTH:
460         g_value_set_int(value, priv->width);
461         break;
462     case PROP_HEIGHT:
463         g_value_set_int(value, priv->height);
464         break;
465     case PROP_INITIAL_SCALE_FACTOR:
466         g_value_set_float(value, priv->initialScaleFactor);
467         break;
468     case PROP_MINIMUM_SCALE_FACTOR:
469         g_value_set_float(value, priv->minimumScaleFactor);
470         break;
471     case PROP_MAXIMUM_SCALE_FACTOR:
472         g_value_set_float(value, priv->maximumScaleFactor);
473         break;
474     case PROP_DEVICE_PIXEL_RATIO:
475         g_value_set_float(value, priv->devicePixelRatio);
476         break;
477     case PROP_USER_SCALABLE:
478         g_value_set_boolean(value, priv->userScalable);
479         break;
480     case PROP_VALID:
481         g_value_set_boolean(value, priv->isValid);
482         break;
483     default:
484         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, paramSpec);
485         break;
486     }
487 }
488 
webkit_viewport_attributes_set_property(GObject * object,guint propertyID,const GValue * value,GParamSpec * paramSpec)489 static void webkit_viewport_attributes_set_property(GObject* object, guint propertyID, const GValue* value, GParamSpec* paramSpec)
490 {
491     WebKitViewportAttributes* viewportAttributes = WEBKIT_VIEWPORT_ATTRIBUTES(object);
492     WebKitViewportAttributesPrivate* priv = viewportAttributes->priv;
493 
494     switch (propertyID) {
495     case PROP_DEVICE_WIDTH:
496         priv->deviceWidth = g_value_get_int(value);
497         break;
498     case PROP_DEVICE_HEIGHT:
499         priv->deviceHeight = g_value_get_int(value);
500         break;
501     case PROP_AVAILABLE_WIDTH:
502         priv->availableWidth = g_value_get_int(value);
503         break;
504     case PROP_AVAILABLE_HEIGHT:
505         priv->availableHeight = g_value_get_int(value);
506         break;
507     case PROP_DESKTOP_WIDTH:
508         priv->desktopWidth = g_value_get_int(value);
509         break;
510     case PROP_DEVICE_DPI:
511         priv->deviceDPI = g_value_get_int(value);
512         break;
513     default:
514         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, paramSpec);
515         break;
516     }
517 }
518 
webkitViewportAttributesRecompute(WebKitViewportAttributes * viewportAttributes)519 void webkitViewportAttributesRecompute(WebKitViewportAttributes* viewportAttributes)
520 {
521     WebKitViewportAttributesPrivate* priv = viewportAttributes->priv;
522     WebKitWebView* webView = priv->webView;
523 
524     IntRect windowRect(webView->priv->corePage->chrome()->windowRect());
525     priv->deviceWidth = windowRect.width();
526     priv->deviceHeight = windowRect.height();
527 
528     IntRect rect(webView->priv->corePage->chrome()->pageRect());
529     priv->availableWidth = rect.width();
530     priv->availableHeight = rect.height();
531 
532     // First of all, we give the application an opportunity to override some of the values.
533     g_signal_emit_by_name(webView, "viewport-attributes-recompute-requested", viewportAttributes);
534 
535     ViewportArguments arguments = webView->priv->corePage->mainFrame()->document()->viewportArguments();
536 
537     ViewportAttributes attributes = computeViewportAttributes(arguments, priv->desktopWidth, priv->deviceWidth, priv->deviceHeight, priv->deviceDPI, IntSize(priv->availableWidth, priv->availableHeight));
538 
539     priv->width = attributes.layoutSize.width();
540     priv->height = attributes.layoutSize.height();
541     priv->initialScaleFactor = attributes.initialScale;
542     priv->minimumScaleFactor = attributes.minimumScale;
543     priv->maximumScaleFactor = attributes.maximumScale;
544     priv->devicePixelRatio = attributes.devicePixelRatio;
545     priv->userScalable = static_cast<bool>(arguments.userScalable);
546 
547     if (!priv->isValid) {
548         priv->isValid = TRUE;
549         g_object_notify(G_OBJECT(viewportAttributes), "valid");
550     }
551 
552     // Now let the application know it is safe to use the new values.
553     g_signal_emit_by_name(webView, "viewport-attributes-changed", viewportAttributes);
554 }
555 
556 /**
557  * webkit_viewport_attributes_recompute:
558  * @viewportAttributes: a #WebKitViewportAttributes
559  *
560  * Recompute the optimal viewport attributes and emit the viewport-attribute-changed signal.
561  * The viewport-attributes-recompute-requested signal also will be handled to override
562  * the device size, available size, desktop width, or device DPI.
563  *
564  * Since: 1.3.8
565  */
webkit_viewport_attributes_recompute(WebKitViewportAttributes * viewportAttributes)566 void webkit_viewport_attributes_recompute(WebKitViewportAttributes* viewportAttributes)
567 {
568     if (!viewportAttributes->priv->isValid)
569         return;
570     webkitViewportAttributesRecompute(viewportAttributes);
571 }
572