diff options
Diffstat (limited to 'Tools/MiniBrowser/gtk/BrowserTab.c')
-rw-r--r-- | Tools/MiniBrowser/gtk/BrowserTab.c | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/Tools/MiniBrowser/gtk/BrowserTab.c b/Tools/MiniBrowser/gtk/BrowserTab.c new file mode 100644 index 000000000..a6b2ea42e --- /dev/null +++ b/Tools/MiniBrowser/gtk/BrowserTab.c @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2016 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE) +#include "cmakeconfig.h" +#endif +#include "BrowserTab.h" + +#include "BrowserSearchBar.h" +#include "BrowserWindow.h" +#include <string.h> + +enum { + PROP_0, + + PROP_VIEW +}; + +struct _BrowserTab { + GtkBox parent; + + WebKitWebView *webView; + BrowserSearchBar *searchBar; + GtkWidget *statusLabel; + gboolean wasSearchingWhenEnteredFullscreen; + gboolean inspectorIsVisible; + GtkWidget *fullScreenMessageLabel; + guint fullScreenMessageLabelId; + + /* Tab Title */ + GtkWidget *titleBox; + GtkWidget *titleLabel; + GtkWidget *titleSpinner; + GtkWidget *titleCloseButton; +}; + +struct _BrowserTabClass { + GtkBoxClass parent; +}; + +G_DEFINE_TYPE(BrowserTab, browser_tab, GTK_TYPE_BOX) + +static void titleChanged(WebKitWebView *webView, GParamSpec *pspec, BrowserTab *tab) +{ + const char *title = webkit_web_view_get_title(webView); + if (title && *title) + gtk_label_set_text(GTK_LABEL(tab->titleLabel), title); +} + +static void isLoadingChanged(WebKitWebView *webView, GParamSpec *paramSpec, BrowserTab *tab) +{ + if (webkit_web_view_is_loading(webView)) { + gtk_spinner_start(GTK_SPINNER(tab->titleSpinner)); + gtk_widget_show(tab->titleSpinner); + } else { + gtk_spinner_stop(GTK_SPINNER(tab->titleSpinner)); + gtk_widget_hide(tab->titleSpinner); + } +} + +static gboolean decidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, BrowserTab *tab) +{ + if (decisionType != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) + return FALSE; + + WebKitResponsePolicyDecision *responseDecision = WEBKIT_RESPONSE_POLICY_DECISION(decision); + if (webkit_response_policy_decision_is_mime_type_supported(responseDecision)) + return FALSE; + + WebKitWebResource *mainResource = webkit_web_view_get_main_resource(webView); + WebKitURIRequest *request = webkit_response_policy_decision_get_request(responseDecision); + const char *requestURI = webkit_uri_request_get_uri(request); + if (g_strcmp0(webkit_web_resource_get_uri(mainResource), requestURI)) + return FALSE; + + webkit_policy_decision_download(decision); + return TRUE; +} + +static void removeChildIfInfoBar(GtkWidget *child, GtkContainer *tab) +{ + if (GTK_IS_INFO_BAR(child)) + gtk_container_remove(tab, child); +} + +static void loadChanged(WebKitWebView *webView, WebKitLoadEvent loadEvent, BrowserTab *tab) +{ + if (loadEvent != WEBKIT_LOAD_STARTED) + return; + + gtk_container_foreach(GTK_CONTAINER(tab), (GtkCallback)removeChildIfInfoBar, tab); +} + +static GtkWidget *createInfoBarQuestionMessage(const char *title, const char *text) +{ + GtkWidget *dialog = gtk_info_bar_new_with_buttons("No", GTK_RESPONSE_NO, "Yes", GTK_RESPONSE_YES, NULL); + gtk_info_bar_set_message_type(GTK_INFO_BAR(dialog), GTK_MESSAGE_QUESTION); + + GtkWidget *contentBox = gtk_info_bar_get_content_area(GTK_INFO_BAR(dialog)); + gtk_orientable_set_orientation(GTK_ORIENTABLE(contentBox), GTK_ORIENTATION_VERTICAL); + gtk_box_set_spacing(GTK_BOX(contentBox), 0); + + GtkWidget *label = gtk_label_new(NULL); + gchar *markup = g_strdup_printf("<span size='xx-large' weight='bold'>%s</span>", title); + gtk_label_set_markup(GTK_LABEL(label), markup); + g_free(markup); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5); + gtk_box_pack_start(GTK_BOX(contentBox), label, FALSE, FALSE, 2); + gtk_widget_show(label); + + label = gtk_label_new(text); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + gtk_misc_set_alignment(GTK_MISC(label), 0., 0.5); + gtk_box_pack_start(GTK_BOX(contentBox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + return dialog; +} + +static void tlsErrorsDialogResponse(GtkWidget *dialog, gint response, BrowserTab *tab) +{ + if (response == GTK_RESPONSE_YES) { + const char *failingURI = (const char *)g_object_get_data(G_OBJECT(dialog), "failingURI"); + GTlsCertificate *certificate = (GTlsCertificate *)g_object_get_data(G_OBJECT(dialog), "certificate"); + SoupURI *uri = soup_uri_new(failingURI); + webkit_web_context_allow_tls_certificate_for_host(webkit_web_view_get_context(tab->webView), certificate, uri->host); + soup_uri_free(uri); + webkit_web_view_load_uri(tab->webView, failingURI); + } + gtk_widget_destroy(dialog); +} + +static gboolean loadFailedWithTLSerrors(WebKitWebView *webView, const char *failingURI, GTlsCertificate *certificate, GTlsCertificateFlags errors, BrowserTab *tab) +{ + gchar *text = g_strdup_printf("Failed to load %s: Do you want to continue ignoring the TLS errors?", failingURI); + GtkWidget *dialog = createInfoBarQuestionMessage("Invalid TLS Certificate", text); + g_free(text); + g_object_set_data_full(G_OBJECT(dialog), "failingURI", g_strdup(failingURI), g_free); + g_object_set_data_full(G_OBJECT(dialog), "certificate", g_object_ref(certificate), g_object_unref); + + g_signal_connect(dialog, "response", G_CALLBACK(tlsErrorsDialogResponse), tab); + + gtk_box_pack_start(GTK_BOX(tab), dialog, FALSE, FALSE, 0); + gtk_box_reorder_child(GTK_BOX(tab), dialog, 0); + gtk_widget_show(dialog); + + return TRUE; +} + +static void permissionRequestDialogResponse(GtkWidget *dialog, gint response, WebKitPermissionRequest *request) +{ + switch (response) { + case GTK_RESPONSE_YES: + webkit_permission_request_allow(request); + break; + default: + webkit_permission_request_deny(request); + break; + } + + gtk_widget_destroy(dialog); + g_object_unref(request); +} + +static gboolean decidePermissionRequest(WebKitWebView *webView, WebKitPermissionRequest *request, BrowserTab *tab) +{ + const gchar *title = NULL; + gchar *text = NULL; + + if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request)) { + title = "Geolocation request"; + text = g_strdup("Allow geolocation request?"); + } else if (WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request)) { + title = "Notification request"; + text = g_strdup("Allow notifications request?"); + } else if (WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) { + title = "UserMedia request"; + gboolean is_for_audio_device = webkit_user_media_permission_is_for_audio_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request)); + gboolean is_for_video_device = webkit_user_media_permission_is_for_video_device(WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request)); + const char *mediaType = NULL; + if (is_for_audio_device) { + if (is_for_video_device) + mediaType = "audio/video"; + else + mediaType = "audio"; + } else if (is_for_video_device) + mediaType = "video"; + text = g_strdup_printf("Allow access to %s device?", mediaType); + } else if (WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request)) { + title = "Media plugin missing request"; + text = g_strdup_printf("The media backend was unable to find a plugin to play the requested media:\n%s.\nAllow to search and install the missing plugin?", + webkit_install_missing_media_plugins_permission_request_get_description(WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request))); + } else + return FALSE; + + GtkWidget *dialog = createInfoBarQuestionMessage(title, text); + g_free(text); + g_signal_connect(dialog, "response", G_CALLBACK(permissionRequestDialogResponse), g_object_ref(request)); + + gtk_box_pack_start(GTK_BOX(tab), dialog, FALSE, FALSE, 0); + gtk_box_reorder_child(GTK_BOX(tab), dialog, 0); + gtk_widget_show(dialog); + + return TRUE; +} + +#if GTK_CHECK_VERSION(3, 12, 0) +static void colorChooserRGBAChanged(GtkColorChooser *colorChooser, GParamSpec *paramSpec, WebKitColorChooserRequest *request) +{ + GdkRGBA rgba; + gtk_color_chooser_get_rgba(colorChooser, &rgba); + webkit_color_chooser_request_set_rgba(request, &rgba); +} + +static void popoverColorClosed(GtkWidget *popover, WebKitColorChooserRequest *request) +{ + webkit_color_chooser_request_finish(request); +} + +static void colorChooserRequestFinished(WebKitColorChooserRequest *request, GtkWidget *popover) +{ + g_object_unref(request); + gtk_widget_destroy(popover); +} + +static gboolean runColorChooserCallback(WebKitWebView *webView, WebKitColorChooserRequest *request, BrowserTab *tab) +{ + GtkWidget *popover = gtk_popover_new(GTK_WIDGET(webView)); + + GdkRectangle rectangle; + webkit_color_chooser_request_get_element_rectangle(request, &rectangle); + gtk_popover_set_pointing_to(GTK_POPOVER(popover), &rectangle); + + GtkWidget *colorChooser = gtk_color_chooser_widget_new(); + GdkRGBA rgba; + webkit_color_chooser_request_get_rgba(request, &rgba); + gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(colorChooser), &rgba); + g_signal_connect(colorChooser, "notify::rgba", G_CALLBACK(colorChooserRGBAChanged), request); + gtk_container_add(GTK_CONTAINER(popover), colorChooser); + gtk_widget_show(colorChooser); + + g_object_ref(request); + g_signal_connect_object(popover, "hide", G_CALLBACK(popoverColorClosed), request, 0); + g_signal_connect_object(request, "finished", G_CALLBACK(colorChooserRequestFinished), popover, 0); + + gtk_widget_show(popover); + + return TRUE; +} +#endif /* GTK_CHECK_VERSION(3, 12, 0) */ + +static gboolean inspectorOpenedInWindow(WebKitWebInspector *inspector, BrowserTab *tab) +{ + tab->inspectorIsVisible = TRUE; + return FALSE; +} + +static gboolean inspectorClosed(WebKitWebInspector *inspector, BrowserTab *tab) +{ + tab->inspectorIsVisible = FALSE; + return FALSE; +} + +static void browserTabSetProperty(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + BrowserTab *tab = BROWSER_TAB(object); + + switch (propId) { + case PROP_VIEW: + tab->webView = g_value_get_object(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + } +} + +static void browserTabFinalize(GObject *gObject) +{ + BrowserTab *tab = BROWSER_TAB(gObject); + + if (tab->fullScreenMessageLabelId) + g_source_remove(tab->fullScreenMessageLabelId); + + G_OBJECT_CLASS(browser_tab_parent_class)->finalize(gObject); +} + +static void browser_tab_init(BrowserTab *tab) +{ + gtk_orientable_set_orientation(GTK_ORIENTABLE(tab), GTK_ORIENTATION_VERTICAL); +} + +static void browserTabConstructed(GObject *gObject) +{ + BrowserTab *tab = BROWSER_TAB(gObject); + + G_OBJECT_CLASS(browser_tab_parent_class)->constructed(gObject); + + tab->searchBar = BROWSER_SEARCH_BAR(browser_search_bar_new(tab->webView)); + gtk_box_pack_start(GTK_BOX(tab), GTK_WIDGET(tab->searchBar), FALSE, FALSE, 0); + + GtkWidget *overlay = gtk_overlay_new(); + gtk_box_pack_start(GTK_BOX(tab), overlay, TRUE, TRUE, 0); + gtk_widget_show(overlay); + + tab->statusLabel = gtk_label_new(NULL); + gtk_widget_set_halign(tab->statusLabel, GTK_ALIGN_START); + gtk_widget_set_valign(tab->statusLabel, GTK_ALIGN_END); + gtk_widget_set_margin_left(tab->statusLabel, 1); + gtk_widget_set_margin_right(tab->statusLabel, 1); + gtk_widget_set_margin_top(tab->statusLabel, 1); + gtk_widget_set_margin_bottom(tab->statusLabel, 1); + gtk_overlay_add_overlay(GTK_OVERLAY(overlay), tab->statusLabel); + + tab->fullScreenMessageLabel = gtk_label_new(NULL); + gtk_widget_set_halign(tab->fullScreenMessageLabel, GTK_ALIGN_CENTER); + gtk_widget_set_valign(tab->fullScreenMessageLabel, GTK_ALIGN_CENTER); + gtk_widget_set_no_show_all(tab->fullScreenMessageLabel, TRUE); + gtk_overlay_add_overlay(GTK_OVERLAY(overlay), tab->fullScreenMessageLabel); + + gtk_container_add(GTK_CONTAINER(overlay), GTK_WIDGET(tab->webView)); + gtk_widget_show(GTK_WIDGET(tab->webView)); + + tab->titleBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4); + + GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); + gtk_widget_set_halign(hbox, GTK_ALIGN_CENTER); + + tab->titleSpinner = gtk_spinner_new(); + gtk_box_pack_start(GTK_BOX(hbox), tab->titleSpinner, FALSE, FALSE, 0); + + tab->titleLabel = gtk_label_new(NULL); + gtk_label_set_ellipsize(GTK_LABEL(tab->titleLabel), PANGO_ELLIPSIZE_END); + gtk_label_set_single_line_mode(GTK_LABEL(tab->titleLabel), TRUE); + gtk_misc_set_padding(GTK_MISC(tab->titleLabel), 0, 0); + gtk_box_pack_start(GTK_BOX(hbox), tab->titleLabel, FALSE, FALSE, 0); + gtk_widget_show(tab->titleLabel); + + gtk_box_pack_start(GTK_BOX(tab->titleBox), hbox, TRUE, TRUE, 0); + gtk_widget_show(hbox); + + tab->titleCloseButton = gtk_button_new(); + g_signal_connect_swapped(tab->titleCloseButton, "clicked", G_CALLBACK(gtk_widget_destroy), tab); + gtk_button_set_relief(GTK_BUTTON(tab->titleCloseButton), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click(GTK_BUTTON(tab->titleCloseButton), FALSE); + + GtkWidget *image = gtk_image_new_from_icon_name("window-close-symbolic", GTK_ICON_SIZE_MENU); + gtk_container_add(GTK_CONTAINER(tab->titleCloseButton), image); + gtk_widget_show(image); + + gtk_box_pack_start(GTK_BOX(tab->titleBox), tab->titleCloseButton, FALSE, FALSE, 0); + gtk_widget_show(tab->titleCloseButton); + + g_signal_connect(tab->webView, "notify::title", G_CALLBACK(titleChanged), tab); + g_signal_connect(tab->webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), tab); + g_signal_connect(tab->webView, "decide-policy", G_CALLBACK(decidePolicy), tab); + g_signal_connect(tab->webView, "load-changed", G_CALLBACK(loadChanged), tab); + g_signal_connect(tab->webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSerrors), tab); + g_signal_connect(tab->webView, "permission-request", G_CALLBACK(decidePermissionRequest), tab); +#if GTK_CHECK_VERSION(3, 12, 0) + g_signal_connect(tab->webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), tab); +#endif + + WebKitWebInspector *inspector = webkit_web_view_get_inspector(tab->webView); + g_signal_connect(inspector, "open-window", G_CALLBACK(inspectorOpenedInWindow), tab); + g_signal_connect(inspector, "closed", G_CALLBACK(inspectorClosed), tab); + + if (webkit_web_view_is_editable(tab->webView)) + webkit_web_view_load_html(tab->webView, "<html></html>", "file:///"); +} + +static void browser_tab_class_init(BrowserTabClass *klass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + gobjectClass->constructed = browserTabConstructed; + gobjectClass->set_property = browserTabSetProperty; + gobjectClass->finalize = browserTabFinalize; + + g_object_class_install_property( + gobjectClass, + PROP_VIEW, + g_param_spec_object( + "view", + "View", + "The web view of this tab", + WEBKIT_TYPE_WEB_VIEW, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +static char *getInternalURI(const char *uri) +{ + /* Internally we use minibrowser-about: as about: prefix is ignored by WebKit. */ + if (g_str_has_prefix(uri, "about:") && !g_str_equal(uri, "about:blank")) + return g_strconcat(BROWSER_ABOUT_SCHEME, uri + strlen ("about"), NULL); + + return g_strdup(uri); +} + +/* Public API. */ +GtkWidget *browser_tab_new(WebKitWebView *view) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(view), NULL); + + return GTK_WIDGET(g_object_new(BROWSER_TYPE_TAB, "view", view, NULL)); +} + +WebKitWebView *browser_tab_get_web_view(BrowserTab *tab) +{ + g_return_val_if_fail(BROWSER_IS_TAB(tab), NULL); + + return tab->webView; +} + +void browser_tab_load_uri(BrowserTab *tab, const char *uri) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + g_return_if_fail(uri); + + if (!g_str_has_prefix(uri, "javascript:")) { + char *internalURI = getInternalURI(uri); + webkit_web_view_load_uri(tab->webView, internalURI); + g_free(internalURI); + return; + } + + webkit_web_view_run_javascript(tab->webView, strstr(uri, "javascript:"), NULL, NULL, NULL); +} + +GtkWidget *browser_tab_get_title_widget(BrowserTab *tab) +{ + g_return_val_if_fail(BROWSER_IS_TAB(tab), NULL); + + return tab->titleBox; +} + +void browser_tab_set_status_text(BrowserTab *tab, const char *text) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + gtk_label_set_text(GTK_LABEL(tab->statusLabel), text); + gtk_widget_set_visible(tab->statusLabel, !!text); +} + +void browser_tab_toggle_inspector(BrowserTab *tab) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + WebKitWebInspector *inspector = webkit_web_view_get_inspector(tab->webView); + if (!tab->inspectorIsVisible) { + webkit_web_inspector_show(inspector); + tab->inspectorIsVisible = TRUE; + } else + webkit_web_inspector_close(inspector); +} + +void browser_tab_start_search(BrowserTab *tab) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + if (!gtk_widget_get_visible(GTK_WIDGET(tab->searchBar))) + browser_search_bar_open(tab->searchBar); +} + +void browser_tab_stop_search(BrowserTab *tab) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + if (gtk_widget_get_visible(GTK_WIDGET(tab->searchBar))) + browser_search_bar_close(tab->searchBar); +} + +void browser_tab_add_accelerators(BrowserTab *tab, GtkAccelGroup *accelGroup) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + g_return_if_fail(GTK_IS_ACCEL_GROUP(accelGroup)); + + browser_search_bar_add_accelerators(tab->searchBar, accelGroup); +} + +static gboolean fullScreenMessageTimeoutCallback(BrowserTab *tab) +{ + gtk_widget_hide(tab->fullScreenMessageLabel); + tab->fullScreenMessageLabelId = 0; + return FALSE; +} + +void browser_tab_enter_fullscreen(BrowserTab *tab) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + const gchar *titleOrURI = webkit_web_view_get_title(tab->webView); + if (!titleOrURI || !titleOrURI[0]) + titleOrURI = webkit_web_view_get_uri(tab->webView); + + gchar *message = g_strdup_printf("%s is now full screen. Press ESC or f to exit.", titleOrURI); + gtk_label_set_text(GTK_LABEL(tab->fullScreenMessageLabel), message); + g_free(message); + + gtk_widget_show(tab->fullScreenMessageLabel); + + tab->fullScreenMessageLabelId = g_timeout_add_seconds(2, (GSourceFunc)fullScreenMessageTimeoutCallback, tab); + g_source_set_name_by_id(tab->fullScreenMessageLabelId, "[WebKit] fullScreenMessageTimeoutCallback"); + + tab->wasSearchingWhenEnteredFullscreen = gtk_widget_get_visible(GTK_WIDGET(tab->searchBar)); + browser_tab_stop_search(tab); +} + +void browser_tab_leave_fullscreen(BrowserTab *tab) +{ + g_return_if_fail(BROWSER_IS_TAB(tab)); + + if (tab->fullScreenMessageLabelId) { + g_source_remove(tab->fullScreenMessageLabelId); + tab->fullScreenMessageLabelId = 0; + } + + gtk_widget_hide(tab->fullScreenMessageLabel); + + if (tab->wasSearchingWhenEnteredFullscreen) { + /* Opening the search bar steals the focus. Usually, we want + * this but not when coming back from fullscreen. + */ + GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(tab))); + GtkWidget *focusWidget = gtk_window_get_focus(window); + browser_tab_start_search(tab); + gtk_window_set_focus(window, focusWidget); + } +} |