Changeset 108522 in webkit


Ignore:
Timestamp:
Feb 22, 2012 10:56:25 AM (12 years ago)
Author:
Philippe Normand
Message:

[GTK] FullScreen signals
https://bugs.webkit.org/show_bug.cgi?id=76181

Reviewed by Martin Robinson.

Source/WebKit/gtk:

Added entering-fullscreen and leaving-fullscreen signals, meant to
be used by the user agent to be notified when an element requests
full screen display and when the full screen display is to be
disabled.

  • WebCoreSupport/ChromeClientGtk.cpp:

(WebKit::ChromeClient::supportsFullScreenForElement):
(WebKit::onFullscreenGtkKeyPressEvent):
(WebKit::ChromeClient::cancelFullScreen):
(WebKit::ChromeClient::enterFullScreenForElement):
(WebKit::ChromeClient::exitFullScreenForElement):

  • WebCoreSupport/ChromeClientGtk.h:
  • tests/testwebview.c:
  • webkit/webkitwebview.cpp:

(webkit_web_view_real_entering_fullscreen):
(webkit_web_view_real_leaving_fullscreen):
(webkit_web_view_class_init):

  • webkit/webkitwebview.h:

Tools:

Use the two new entering/leaving fullscreen signals to hide/show
the tool bar, the status bar and ask the user's permission before
entering fullscreen.

  • GtkLauncher/main.c:

(webViewFullscreenMessageWindowClose):
(webViewWindowStateEvent):
(hide_widget):
(show_widget):
(webViewEnteringFullScreen):
(webViewLeavingFullScreen):
(createBrowser):
(createWindow):

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/gtk/ChangeLog

    r108462 r108522  
     12012-02-20  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GTK] FullScreen signals
     4        https://bugs.webkit.org/show_bug.cgi?id=76181
     5
     6        Reviewed by Martin Robinson.
     7
     8        Added entering-fullscreen and leaving-fullscreen signals, meant to
     9        be used by the user agent to be notified when an element requests
     10        full screen display and when the full screen display is to be
     11        disabled.
     12
     13        * WebCoreSupport/ChromeClientGtk.cpp:
     14        (WebKit::ChromeClient::supportsFullScreenForElement):
     15        (WebKit::onFullscreenGtkKeyPressEvent):
     16        (WebKit::ChromeClient::cancelFullScreen):
     17        (WebKit::ChromeClient::enterFullScreenForElement):
     18        (WebKit::ChromeClient::exitFullScreenForElement):
     19        * WebCoreSupport/ChromeClientGtk.h:
     20        * tests/testwebview.c:
     21        * webkit/webkitwebview.cpp:
     22        (webkit_web_view_real_entering_fullscreen):
     23        (webkit_web_view_real_leaving_fullscreen):
     24        (webkit_web_view_class_init):
     25        * webkit/webkitwebview.h:
     26
    1272012-02-22  Ryosuke Niwa  <rniwa@webkit.org>
    228
  • trunk/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp

    r108459 r108522  
    5252#include "SearchPopupMenuGtk.h"
    5353#include "SecurityOrigin.h"
     54#include "WebKitDOMBinding.h"
     55#include "WebKitDOMHTMLElementPrivate.h"
    5456#include "WindowFeatures.h"
    5557#include "webkitgeolocationpolicydecision.h"
     
    6264#include "webkitwebviewprivate.h"
    6365#include "webkitwebwindowfeaturesprivate.h"
     66#include <gdk/gdk.h>
     67#include <gdk/gdkkeysyms.h>
    6468#include <glib.h>
    6569#include <glib/gi18n-lib.h>
     
    922926bool ChromeClient::supportsFullScreenForElement(const WebCore::Element* element, bool withKeyboard)
    923927{
    924     return true;
     928    return !withKeyboard;
     929}
     930
     931static gboolean onFullscreenGtkKeyPressEvent(GtkWidget* widget, GdkEventKey* event, ChromeClient* chromeClient)
     932{
     933    switch (event->keyval) {
     934    case GDK_KEY_Escape:
     935    case GDK_KEY_f:
     936    case GDK_KEY_F:
     937        chromeClient->cancelFullScreen();
     938        return TRUE;
     939    default:
     940        break;
     941    }
     942
     943    return FALSE;
     944}
     945
     946void ChromeClient::cancelFullScreen()
     947{
     948    ASSERT(m_fullScreenElement);
     949    m_fullScreenElement->document()->webkitCancelFullScreen();
    925950}
    926951
    927952void ChromeClient::enterFullScreenForElement(WebCore::Element* element)
    928953{
     954    gboolean returnValue;
     955    GRefPtr<WebKitDOMHTMLElement> kitElement(adoptGRef(kit(reinterpret_cast<HTMLElement*>(element))));
     956    g_signal_emit_by_name(m_webView, "entering-fullscreen", kitElement.get(), &returnValue);
     957    if (returnValue)
     958        return;
     959
     960    GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
     961    if (!widgetIsOnscreenToplevelWindow(window))
     962        return;
     963
     964    g_signal_connect(window, "key-press-event", G_CALLBACK(onFullscreenGtkKeyPressEvent), this);
     965
     966    m_fullScreenElement = adoptRef(element);
     967
    929968    element->document()->webkitWillEnterFullScreenForElement(element);
    930969    m_adjustmentWatcher.disableAllScrollbars();
    931 #if ENABLE(VIDEO)
    932     if (element->tagName() == "VIDEO")
    933         enterFullscreenForNode(static_cast<Node*>(element));
    934 #endif
     970    gtk_window_fullscreen(GTK_WINDOW(window));
    935971    element->document()->webkitDidEnterFullScreenForElement(element);
    936972}
     
    938974void ChromeClient::exitFullScreenForElement(WebCore::Element* element)
    939975{
     976    gboolean returnValue;
     977    GRefPtr<WebKitDOMHTMLElement> kitElement(adoptGRef(kit(reinterpret_cast<HTMLElement*>(element))));
     978    g_signal_emit_by_name(m_webView, "leaving-fullscreen", kitElement.get(), &returnValue);
     979    if (returnValue)
     980        return;
     981
     982    GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
     983    ASSERT(widgetIsOnscreenToplevelWindow(window));
     984    g_signal_handlers_disconnect_by_func(window, reinterpret_cast<void*>(onFullscreenGtkKeyPressEvent), this);
     985
    940986    element->document()->webkitWillExitFullScreenForElement(element);
     987    gtk_window_unfullscreen(GTK_WINDOW(window));
    941988    m_adjustmentWatcher.enableAllScrollbars();
    942 #if ENABLE(VIDEO)
    943     if (element->tagName() == "VIDEO")
    944         webViewExitFullscreen(m_webView);
    945 #endif
    946989    element->document()->webkitDidExitFullScreenForElement(element);
     990    m_fullScreenElement.clear();
    947991}
    948992#endif
  • trunk/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h

    r108459 r108522  
    156156        virtual void enterFullScreenForElement(Element*);
    157157        virtual void exitFullScreenForElement(Element*);
     158        void cancelFullScreen();
    158159#endif
    159160
     
    187188
    188189        void invalidateWidgetRect(const IntRect&);
     190#if ENABLE(FULLSCREEN_API)
     191        RefPtr<Element> m_fullScreenElement;
     192#endif
    189193    };
    190194}
  • trunk/Source/WebKit/gtk/tests/testwebview.c

    r108278 r108522  
    417417}
    418418
     419static gboolean emitKeyStroke(WebKitWebView* webView)
     420{
     421    GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
     422    pressEvent->key.keyval = GDK_KEY_f;
     423    GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(webView));
     424    pressEvent->key.window = window;
     425    g_object_ref(pressEvent->key.window);
     426
     427    GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(window));
     428    gdk_event_set_device(pressEvent, gdk_device_manager_get_client_pointer(manager));
     429
     430    // When synthesizing an event, an invalid hardware_keycode value
     431    // can cause it to be badly processed by Gtk+.
     432    GdkKeymapKey* keys;
     433    gint n_keys;
     434    if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), GDK_KEY_f, &keys, &n_keys)) {
     435        pressEvent->key.hardware_keycode = keys[0].keycode;
     436        g_free(keys);
     437    }
     438
     439    GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
     440    gtk_main_do_event(pressEvent);
     441    gdk_event_free(pressEvent);
     442    releaseEvent->key.type = GDK_KEY_RELEASE;
     443    gtk_main_do_event(releaseEvent);
     444    gdk_event_free(releaseEvent);
     445
     446    return FALSE;
     447}
     448
     449static gboolean entering_fullscreen_cb(WebKitWebView* webView, GObject* element, gboolean blocked)
     450{
     451    if (blocked)
     452        g_main_loop_quit(loop);
     453    else
     454        g_timeout_add(200, (GSourceFunc) emitKeyStroke, webView);
     455    return blocked;
     456}
     457
     458static gboolean leaving_fullscreen_cb(WebKitWebView* webView, GObject* element, gpointer data)
     459{
     460    g_main_loop_quit(loop);
     461    return FALSE;
     462}
     463
     464static void test_webkit_web_view_fullscreen(gconstpointer blocked)
     465{
     466    GtkWidget* window;
     467    GtkWidget* web_view;
     468    WebKitWebSettings *settings;
     469
     470    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     471    web_view = webkit_web_view_new();
     472
     473    settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(web_view));
     474    g_object_set(settings, "enable-fullscreen", TRUE, NULL);
     475    webkit_web_view_set_settings(WEBKIT_WEB_VIEW(web_view), settings);
     476
     477    gtk_container_add(GTK_CONTAINER(window), web_view);
     478
     479    gtk_widget_show_all(window);
     480
     481    loop = g_main_loop_new(NULL, TRUE);
     482
     483    g_signal_connect(web_view, "entering-fullscreen", G_CALLBACK(entering_fullscreen_cb), (gpointer) blocked);
     484    g_signal_connect(web_view, "leaving-fullscreen", G_CALLBACK(leaving_fullscreen_cb), NULL);
     485
     486    webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body>"
     487                   "<script>"
     488                   "var eventName = 'keypress';"
     489                   "document.addEventListener(eventName, function () {"
     490                   "    document.documentElement.webkitRequestFullScreen();"
     491                   "}, false);"
     492                   "</script></body></html>", NULL, NULL, NULL);
     493
     494    g_timeout_add(100, (GSourceFunc) emitKeyStroke, WEBKIT_WEB_VIEW(web_view));
     495    g_main_loop_run(loop);
     496
     497    gtk_widget_destroy(window);
     498}
     499
    419500int main(int argc, char** argv)
    420501{
     
    446527    g_test_add_func("/webkit/webview/webview-in-offscreen-window-does-not-crash", test_webkit_web_view_in_offscreen_window_does_not_crash);
    447528    g_test_add_func("/webkit/webview/webview-does-not-steal-focus", test_webkit_web_view_does_not_steal_focus);
     529    g_test_add_data_func("/webkit/webview/fullscreen", GINT_TO_POINTER(FALSE), test_webkit_web_view_fullscreen);
     530    g_test_add_data_func("/webkit/webview/fullscreen-blocked", GINT_TO_POINTER(TRUE), test_webkit_web_view_fullscreen);
    448531
    449532    return g_test_run ();
  • trunk/Source/WebKit/gtk/webkit/webkitwebview.cpp

    r108459 r108522  
    213213    RESOURCE_CONTENT_LENGTH_RECEIVED,
    214214    RESOURCE_LOAD_FAILED,
     215    ENTERING_FULLSCREEN,
     216    LEAVING_FULLSCREEN,
    215217
    216218    LAST_SIGNAL
     
    13011303}
    13021304
     1305static gboolean webkit_web_view_real_entering_fullscreen(WebKitWebView* webView)
     1306{
     1307    return FALSE;
     1308}
     1309
     1310static gboolean webkit_web_view_real_leaving_fullscreen(WebKitWebView* webView)
     1311{
     1312    return FALSE;
     1313}
     1314
    13031315static void webkit_web_view_dispose(GObject* object)
    13041316{
     
    26552667            G_TYPE_NONE, 1,
    26562668            WEBKIT_TYPE_VIEWPORT_ATTRIBUTES);
     2669
     2670    /**
     2671     * WebKitWebView::entering-fullscreen:
     2672     * @web_view: the #WebKitWebView on which the signal is emitted.
     2673     * @element: the #WebKitDOMHTMLElement which has requested full screen display.
     2674     *
     2675     * Emitted when JavaScript code calls
     2676     * <function>element.webkitRequestFullScreen</function>. If the
     2677     * signal is not handled the WebView will proceed to full screen
     2678     * its top level window. This signal can be used by client code to
     2679     * request permission to the user prior doing the full screen
     2680     * transition and eventually prepare the top-level window
     2681     * (e.g. hide some widgets that would otherwise be part of the
     2682     * full screen window).
     2683     *
     2684     * Returns: %TRUE to stop other handlers from being invoked for the event.
     2685     *    %FALSE to continue emission of the event.
     2686     *
     2687     * Since: 1.9.0
     2688     */
     2689    webkit_web_view_signals[ENTERING_FULLSCREEN] =
     2690            g_signal_new("entering-fullscreen",
     2691                         G_TYPE_FROM_CLASS(webViewClass),
     2692                         G_SIGNAL_RUN_LAST,
     2693                         G_STRUCT_OFFSET(WebKitWebViewClass, entering_fullscreen),
     2694                         g_signal_accumulator_true_handled, 0,
     2695                         webkit_marshal_BOOLEAN__OBJECT,
     2696                         G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT);
     2697
     2698
     2699    /**
     2700     * WebKitWebView::leaving-fullscreen:
     2701     * @web_view: the #WebKitWebView on which the signal is emitted.
     2702     * @element: the #WebKitDOMHTMLElement which is currently displayed full screen.
     2703     *
     2704     * Emitted when the WebView is about to restore its top level
     2705     * window out of its full screen state. This signal can be used by
     2706     * client code to restore widgets hidden during the
     2707     * entering-fullscreen stage for instance.
     2708     *
     2709     * Returns: %TRUE to stop other handlers from being invoked for the event.
     2710     *    %FALSE to continue emission of the event.
     2711     *
     2712     * Since: 1.9.0
     2713     */
     2714    webkit_web_view_signals[LEAVING_FULLSCREEN] =
     2715            g_signal_new("leaving-fullscreen",
     2716                         G_TYPE_FROM_CLASS(webViewClass),
     2717                         G_SIGNAL_RUN_LAST,
     2718                         G_STRUCT_OFFSET(WebKitWebViewClass, leaving_fullscreen),
     2719                         g_signal_accumulator_true_handled, 0,
     2720                         webkit_marshal_BOOLEAN__OBJECT,
     2721                         G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_DOM_HTML_ELEMENT);
    26572722
    26582723    /*
     
    27642829    webViewClass->move_cursor = webkit_web_view_real_move_cursor;
    27652830    webViewClass->should_allow_editing_action = webkit_web_view_real_should_allow_editing_action;
     2831    webViewClass->entering_fullscreen = webkit_web_view_real_entering_fullscreen;
     2832    webViewClass->leaving_fullscreen = webkit_web_view_real_leaving_fullscreen;
    27662833
    27672834    GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
  • trunk/Source/WebKit/gtk/webkit/webkitwebview.h

    r100642 r108522  
    177177    void                       (* redo)                   (WebKitWebView        *web_view);
    178178    gboolean                   (* should_allow_editing_action) (WebKitWebView   *web_view);
     179    gboolean                   (* entering_fullscreen) (WebKitWebView   *web_view);
     180    gboolean                   (* leaving_fullscreen) (WebKitWebView   *web_view);
    179181
    180182    /* Padding for future expansion */
    181183    void (*_webkit_reserved0) (void);
    182     void (*_webkit_reserved1) (void);
    183     void (*_webkit_reserved2) (void);
    184184};
    185185
  • trunk/Tools/ChangeLog

    r108516 r108522  
     12012-02-20  Philippe Normand  <pnormand@igalia.com>
     2
     3        [GTK] FullScreen signals
     4        https://bugs.webkit.org/show_bug.cgi?id=76181
     5
     6        Reviewed by Martin Robinson.
     7
     8        Use the two new entering/leaving fullscreen signals to hide/show
     9        the tool bar, the status bar and ask the user's permission before
     10        entering fullscreen.
     11
     12        * GtkLauncher/main.c:
     13        (webViewFullscreenMessageWindowClose):
     14        (webViewWindowStateEvent):
     15        (hide_widget):
     16        (show_widget):
     17        (webViewEnteringFullScreen):
     18        (webViewLeavingFullScreen):
     19        (createBrowser):
     20        (createWindow):
     21
    1222012-02-22  Rob Flack  <flackr@chromium.org>
    223
  • trunk/Tools/GtkLauncher/main.c

    r108459 r108522  
    124124}
    125125
    126 static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView)
     126static gboolean webViewFullscreenMessageWindowClose(GtkWidget *dialog)
     127{
     128    if (GTK_IS_WIDGET(dialog))
     129        gtk_widget_destroy(dialog);
     130    return FALSE;
     131}
     132
     133static gboolean webViewWindowStateEvent(GtkWidget *widget, GdkEventWindowState *event, WebKitWebView *webView)
     134{
     135    if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
     136        WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
     137        const gchar *uri = webkit_web_frame_get_uri(frame);
     138        GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
     139        if (!gtk_widget_is_toplevel(window) || !GTK_IS_WINDOW(window) || GTK_IS_OFFSCREEN_WINDOW(window))
     140            window = 0;
     141
     142        GtkWidget *dialog = gtk_message_dialog_new(window ? GTK_WINDOW(window) : 0,
     143                                                    GTK_DIALOG_MODAL,
     144                                                    GTK_MESSAGE_INFO,
     145                                                    GTK_BUTTONS_CLOSE,
     146                                                    "%s is now full screen. Press ESC or f to exit.", uri);
     147        g_signal_connect_swapped(dialog, "response", G_CALLBACK(gtk_widget_destroy), dialog);
     148        g_timeout_add(1500, (GSourceFunc) webViewFullscreenMessageWindowClose, dialog);
     149        gtk_dialog_run(GTK_DIALOG(dialog));
     150    }
     151    return TRUE;
     152}
     153
     154static void hideWidget(GtkWidget* widget, gpointer data)
     155{
     156    if (!GTK_IS_SCROLLED_WINDOW(widget))
     157        gtk_widget_hide(widget);
     158}
     159
     160static void showWidget(GtkWidget* widget, gpointer data)
     161{
     162    if (!GTK_IS_SCROLLED_WINDOW(widget))
     163        gtk_widget_show(widget);
     164}
     165
     166static gboolean webViewEnteringFullScreen(WebKitWebView *webView, GObject *element, GtkWidget* vbox)
     167{
     168    WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
     169    const gchar *uri = webkit_web_frame_get_uri(frame);
     170    GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
     171    if (!gtk_widget_is_toplevel(window) || !GTK_IS_WINDOW(window) || GTK_IS_OFFSCREEN_WINDOW(window))
     172        window = 0;
     173
     174    GtkWidget *dialog = gtk_message_dialog_new(window ? GTK_WINDOW(window) : 0,
     175                                               GTK_DIALOG_MODAL,
     176                                               GTK_MESSAGE_INFO,
     177                                               GTK_BUTTONS_YES_NO,
     178                                               "Allow full screen display of %s ?", uri);
     179    gint result = gtk_dialog_run(GTK_DIALOG(dialog));
     180    if (result == GTK_RESPONSE_YES) {
     181        gtk_container_foreach(GTK_CONTAINER(vbox), (GtkCallback) hideWidget, NULL);
     182        gtk_widget_destroy(GTK_WIDGET(dialog));
     183        return FALSE;
     184    }
     185    gtk_widget_destroy(GTK_WIDGET(dialog));
     186    return TRUE;
     187}
     188
     189static gboolean webViewLeavingFullScreen(WebKitWebView *webView, GObject *element, GtkWidget* vbox)
     190{
     191    GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(webView));
     192    if (gtk_widget_is_toplevel(window) && GTK_IS_WINDOW(window) && !GTK_IS_OFFSCREEN_WINDOW(window))
     193        g_signal_handlers_disconnect_by_func(window, G_CALLBACK(webViewWindowStateEvent), webView);
     194    gtk_container_foreach(GTK_CONTAINER(vbox), (GtkCallback) showWidget, NULL);
     195    return FALSE;
     196}
     197
     198static GtkWidget* createBrowser(GtkWidget* window, GtkWidget* uriEntry, GtkWidget* statusbar, WebKitWebView* webView, GtkWidget* vbox)
    127199{
    128200    GtkWidget *scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
     
    138210    g_signal_connect(webView, "web-view-ready", G_CALLBACK(webViewReadyCb), window);
    139211    g_signal_connect(webView, "close-web-view", G_CALLBACK(closeWebViewCb), window);
     212    g_signal_connect(webView, "entering-fullscreen", G_CALLBACK(webViewEnteringFullScreen), vbox);
     213    g_signal_connect(webView, "leaving-fullscreen", G_CALLBACK(webViewLeavingFullScreen), vbox);
    140214
    141215    return scrolledWindow;
     
    215289    statusbar = createStatusbar(webView);
    216290    gtk_box_pack_start(GTK_BOX(vbox), createToolbar(uriEntry, webView), FALSE, FALSE, 0);
    217     gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView), TRUE, TRUE, 0);
     291    gtk_box_pack_start(GTK_BOX(vbox), createBrowser(window, uriEntry, statusbar, webView, vbox), TRUE, TRUE, 0);
    218292    gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0);
    219293
Note: See TracChangeset for help on using the changeset viewer.