Changeset 196062 in webkit


Ignore:
Timestamp:
Feb 3, 2016 3:04:33 AM (8 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] Reduce IPC traffic due to view state changes
https://bugs.webkit.org/show_bug.cgi?id=153745

Reviewed by Sergio Villar Senin.

Very often view state changes happen one after another in a very
short period of time, even in the same run loop iteration. For
example, when you switch to the web view window, the view is
focused and the active window flag changes as well. In that case
we are sending two messages to the web process and the page
updates its status according to the new flags in two steps. So, we
could group all state changes happening in the same run loop
iteration and notify about them all in the next iteration. This
also prevents unnecessary changes of state when we quickly go back
to a previous state, for example in focus follows mouse
configurations if you move the mouse outside the window and then
inside the window again quickly.

  • UIProcess/API/gtk/WebKitWebViewBase.cpp:

(_WebKitWebViewBasePrivate::_WebKitWebViewBasePrivate): Use
VirewState::Flags to keep the web view state instead of
boolean, and also to keep the flags that need to be updated. Use a
timer to update web view state flags.
(_WebKitWebViewBasePrivate::updateViewStateTimerFired): Call
WebPageProxy::viewStateDidChange() and reset the flags that need
to be updated.
(webkitWebViewBaseScheduleUpdateViewState): Update the flags that
need to be updated and schedule the timer if it's not active.
(toplevelWindowFocusInEvent): Use the flags and schedule an update.
(toplevelWindowFocusOutEvent): Ditto.
(toplevelWindowStateEvent): Also mark the view as hidden when minimized.
(webkitWebViewBaseSetToplevelOnScreenWindow): Connect to
window-state-event instead of deprecated visibility-notify-event.
(webkitWebViewBaseMap): Use the flags and schedule an update.
(webkitWebViewBaseUnmap): Ditto.
(webkitWebViewBaseSetFocus): Ditto.
(webkitWebViewBaseIsInWindowActive): Use the flags.
(webkitWebViewBaseIsFocused): Ditto
(webkitWebViewBaseIsVisible): Ditto.
(webkitWebViewBaseIsInWindow): Removed this since it was unused.

  • UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r196059 r196062  
     12016-02-03  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Reduce IPC traffic due to view state changes
     4        https://bugs.webkit.org/show_bug.cgi?id=153745
     5
     6        Reviewed by Sergio Villar Senin.
     7
     8        Very often view state changes happen one after another in a very
     9        short period of time, even in the same run loop iteration. For
     10        example, when you switch to the web view window, the view is
     11        focused and the active window flag changes as well. In that case
     12        we are sending two messages to the web process and the page
     13        updates its status according to the new flags in two steps. So, we
     14        could group all state changes happening in the same run loop
     15        iteration and notify about them all in the next iteration. This
     16        also prevents unnecessary changes of state when we quickly go back
     17        to a previous state, for example in focus follows mouse
     18        configurations if you move the mouse outside the window and then
     19        inside the window again quickly.
     20
     21        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
     22        (_WebKitWebViewBasePrivate::_WebKitWebViewBasePrivate): Use
     23        VirewState::Flags to keep the web view state instead of
     24        boolean, and also to keep the flags that need to be updated. Use a
     25        timer to update web view state flags.
     26        (_WebKitWebViewBasePrivate::updateViewStateTimerFired): Call
     27        WebPageProxy::viewStateDidChange() and reset the flags that need
     28        to be updated.
     29        (webkitWebViewBaseScheduleUpdateViewState): Update the flags that
     30        need to be updated and schedule the timer if it's not active.
     31        (toplevelWindowFocusInEvent): Use the flags and schedule an update.
     32        (toplevelWindowFocusOutEvent): Ditto.
     33        (toplevelWindowStateEvent): Also mark the view as hidden when minimized.
     34        (webkitWebViewBaseSetToplevelOnScreenWindow): Connect to
     35        window-state-event instead of deprecated visibility-notify-event.
     36        (webkitWebViewBaseMap): Use the flags and schedule an update.
     37        (webkitWebViewBaseUnmap): Ditto.
     38        (webkitWebViewBaseSetFocus): Ditto.
     39        (webkitWebViewBaseIsInWindowActive): Use the flags.
     40        (webkitWebViewBaseIsFocused): Ditto
     41        (webkitWebViewBaseIsVisible): Ditto.
     42        (webkitWebViewBaseIsInWindow): Removed this since it was unused.
     43        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
     44
    1452016-02-03  Carlos Garcia Campos  <cgarcia@igalia.com>
    246
  • trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp

    r194846 r196062  
    149149
    150150struct _WebKitWebViewBasePrivate {
     151    _WebKitWebViewBasePrivate()
     152        : updateViewStateTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::updateViewStateTimerFired)
    151153#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
    152     _WebKitWebViewBasePrivate()
    153         : clearRedirectedWindowSoonTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::clearRedirectedWindowSoonTimerFired)
     154        , clearRedirectedWindowSoonTimer(RunLoop::main(), this, &_WebKitWebViewBasePrivate::clearRedirectedWindowSoonTimerFired)
     155#endif
    154156    {
    155157    }
    156158
     159    void updateViewStateTimerFired()
     160    {
     161        if (!pageProxy)
     162            return;
     163        pageProxy->viewStateDidChange(viewStateFlagsToUpdate);
     164        viewStateFlagsToUpdate = ViewState::NoFlags;
     165    }
     166
     167#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
    157168    void clearRedirectedWindowSoonTimerFired()
    158169    {
     
    183194    unsigned long toplevelFocusInEventID;
    184195    unsigned long toplevelFocusOutEventID;
    185     unsigned long toplevelVisibilityEventID;
     196    unsigned long toplevelWindowStateEventID;
    186197
    187198    // View State.
    188     bool isInWindowActive : 1;
    189     bool isFocused : 1;
    190     bool isVisible : 1;
    191     bool isWindowVisible : 1;
     199    ViewState::Flags viewState;
     200    ViewState::Flags viewStateFlagsToUpdate;
     201    RunLoop::Timer<WebKitWebViewBasePrivate> updateViewStateTimer;
    192202
    193203    WebKitWebViewBaseDownloadRequestHandler downloadHandler;
     
    217227WEBKIT_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
    218228
     229static void webkitWebViewBaseScheduleUpdateViewState(WebKitWebViewBase* webViewBase, ViewState::Flags flagsToUpdate)
     230{
     231    WebKitWebViewBasePrivate* priv = webViewBase->priv;
     232    priv->viewStateFlagsToUpdate |= flagsToUpdate;
     233    if (priv->updateViewStateTimer.isActive())
     234        return;
     235
     236    priv->updateViewStateTimer.startOneShot(0);
     237}
     238
    219239static gboolean toplevelWindowFocusInEvent(GtkWidget*, GdkEventFocus*, WebKitWebViewBase* webViewBase)
    220240{
    221241    WebKitWebViewBasePrivate* priv = webViewBase->priv;
    222     if (!priv->isInWindowActive) {
    223         priv->isInWindowActive = true;
    224         priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
    225     }
     242    if (priv->viewState & ViewState::WindowIsActive)
     243        return FALSE;
     244
     245    priv->viewState |= ViewState::WindowIsActive;
     246    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::WindowIsActive);
    226247
    227248    return FALSE;
     
    231252{
    232253    WebKitWebViewBasePrivate* priv = webViewBase->priv;
    233     if (priv->isInWindowActive) {
    234         priv->isInWindowActive = false;
    235         priv->pageProxy->viewStateDidChange(ViewState::WindowIsActive);
    236     }
     254    if (!(priv->viewState & ViewState::WindowIsActive))
     255        return FALSE;
     256
     257    priv->viewState &= ~ViewState::WindowIsActive;
     258    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::WindowIsActive);
    237259
    238260    return FALSE;
    239261}
    240262
    241 static gboolean toplevelWindowVisibilityEvent(GtkWidget*, GdkEventVisibility* visibilityEvent, WebKitWebViewBase* webViewBase)
    242 {
    243     WebKitWebViewBasePrivate* priv = webViewBase->priv;
    244     bool isWindowVisible = visibilityEvent->state != GDK_VISIBILITY_FULLY_OBSCURED;
    245     if (priv->isWindowVisible != isWindowVisible) {
    246         priv->isWindowVisible = isWindowVisible;
    247         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
    248     }
     263static gboolean toplevelWindowStateEvent(GtkWidget*, GdkEventWindowState* event, WebKitWebViewBase* webViewBase)
     264{
     265    WebKitWebViewBasePrivate* priv = webViewBase->priv;
     266    if (!(event->changed_mask & GDK_WINDOW_STATE_ICONIFIED))
     267        return FALSE;
     268
     269    bool visible = !(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED);
     270    if ((visible && priv->viewState & ViewState::IsVisible) || (!visible && !(priv->viewState & ViewState::IsVisible)))
     271        return FALSE;
     272
     273    if (visible)
     274        priv->viewState |= ViewState::IsVisible;
     275    else
     276        priv->viewState &= ~ViewState::IsVisible;
     277    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
    249278
    250279    return FALSE;
     
    265294        priv->toplevelFocusOutEventID = 0;
    266295    }
    267     if (priv->toplevelVisibilityEventID) {
    268         g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelVisibilityEventID);
    269         priv->toplevelVisibilityEventID = 0;
     296    if (priv->toplevelWindowStateEventID) {
     297        g_signal_handler_disconnect(priv->toplevelOnScreenWindow, priv->toplevelWindowStateEventID);
     298        priv->toplevelWindowStateEventID = 0;
    270299    }
    271300
    272301    priv->toplevelOnScreenWindow = window;
    273     priv->pageProxy->viewStateDidChange(ViewState::IsInWindow);
     302    if (!(priv->viewState & ViewState::IsInWindow)) {
     303        priv->viewState |= ViewState::IsInWindow;
     304        webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsInWindow);
     305    }
    274306    if (!priv->toplevelOnScreenWindow)
    275307        return;
     
    281313        g_signal_connect(priv->toplevelOnScreenWindow, "focus-out-event",
    282314                         G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
    283     priv->toplevelVisibilityEventID =
    284         g_signal_connect(priv->toplevelOnScreenWindow, "visibility-notify-event",
    285                          G_CALLBACK(toplevelWindowVisibilityEvent), webViewBase);
     315    priv->toplevelWindowStateEventID =
     316        g_signal_connect(priv->toplevelOnScreenWindow, "window-state-event", G_CALLBACK(toplevelWindowStateEvent), webViewBase);
    286317}
    287318
     
    640671    WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
    641672    WebKitWebViewBasePrivate* priv = webViewBase->priv;
    642     if (!priv->isVisible) {
    643         priv->isVisible = true;
    644         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
    645     }
     673    if (priv->viewState & ViewState::IsVisible)
     674        return;
     675
     676    priv->viewState |= ViewState::IsVisible;
     677    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
    646678}
    647679
     
    650682    GTK_WIDGET_CLASS(webkit_web_view_base_parent_class)->unmap(widget);
    651683
    652     WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
    653     if (priv->isVisible) {
    654         priv->isVisible = false;
    655         priv->pageProxy->viewStateDidChange(ViewState::IsVisible);
    656     }
     684    WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
     685    WebKitWebViewBasePrivate* priv = webViewBase->priv;
     686    if (!(priv->viewState & ViewState::IsVisible))
     687        return;
     688
     689    priv->viewState &= ~ViewState::IsVisible;
     690    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
    657691}
    658692
     
    13011335{
    13021336    WebKitWebViewBasePrivate* priv = webViewBase->priv;
    1303     if (priv->isFocused == focused)
    1304         return;
    1305 
    1306     unsigned viewStateFlags = ViewState::IsFocused;
    1307     priv->isFocused = focused;
    1308 
    1309     // If the view has received the focus and the window is not active
    1310     // mark the current window as active now. This can happen if the
    1311     // toplevel window is a GTK_WINDOW_POPUP and the focus has been
    1312     // set programatically like WebKitTestRunner does, because POPUP
    1313     // can't be focused.
    1314     if (priv->isFocused && !priv->isInWindowActive) {
    1315         priv->isInWindowActive = true;
    1316         viewStateFlags |= ViewState::WindowIsActive;
    1317     }
    1318     priv->pageProxy->viewStateDidChange(viewStateFlags);
     1337    if ((focused && priv->viewState & ViewState::IsFocused) || (!focused && !(priv->viewState & ViewState::IsFocused)))
     1338        return;
     1339
     1340    ViewState::Flags flagsToUpdate = ViewState::IsFocused;
     1341    if (focused) {
     1342        priv->viewState |= ViewState::IsFocused;
     1343
     1344        // If the view has received the focus and the window is not active
     1345        // mark the current window as active now. This can happen if the
     1346        // toplevel window is a GTK_WINDOW_POPUP and the focus has been
     1347        // set programatically like WebKitTestRunner does, because POPUP
     1348        // can't be focused.
     1349        if (!(priv->viewState & ViewState::WindowIsActive)) {
     1350            priv->viewState |= ViewState::WindowIsActive;
     1351            flagsToUpdate |= ViewState::WindowIsActive;
     1352        }
     1353    } else
     1354        priv->viewState &= ~ViewState::IsFocused;
     1355
     1356    webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
    13191357}
    13201358
    13211359bool webkitWebViewBaseIsInWindowActive(WebKitWebViewBase* webViewBase)
    13221360{
    1323     return webViewBase->priv->isInWindowActive;
     1361    return webViewBase->priv->viewState & ViewState::WindowIsActive;
    13241362}
    13251363
    13261364bool webkitWebViewBaseIsFocused(WebKitWebViewBase* webViewBase)
    13271365{
    1328     return webViewBase->priv->isFocused;
     1366    return webViewBase->priv->viewState & ViewState::IsFocused;
    13291367}
    13301368
    13311369bool webkitWebViewBaseIsVisible(WebKitWebViewBase* webViewBase)
    13321370{
    1333     return webViewBase->priv->isVisible;
     1371    return webViewBase->priv->viewState & ViewState::IsVisible;
    13341372}
    13351373
    13361374bool webkitWebViewBaseIsInWindow(WebKitWebViewBase* webViewBase)
    13371375{
    1338     return webViewBase->priv->toplevelOnScreenWindow;
    1339 }
    1340 
    1341 bool webkitWebViewBaseIsWindowVisible(WebKitWebViewBase* webViewBase)
    1342 {
    1343     return webViewBase->priv->isWindowVisible;
     1376    return webViewBase->priv->viewState & ViewState::IsInWindow;
    13441377}
    13451378
  • trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h

    r191340 r196062  
    6161bool webkitWebViewBaseIsVisible(WebKitWebViewBase*);
    6262bool webkitWebViewBaseIsInWindow(WebKitWebViewBase*);
    63 bool webkitWebViewBaseIsWindowVisible(WebKitWebViewBase*);
    6463
    6564typedef void (*WebKitWebViewBaseDownloadRequestHandler) (WebKitWebViewBase*, WebKit::DownloadProxy*);
Note: See TracChangeset for help on using the changeset viewer.