summaryrefslogtreecommitdiff
path: root/Tools/MiniBrowser/gtk/BrowserWindow.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Tools/MiniBrowser/gtk/BrowserWindow.c
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Tools/MiniBrowser/gtk/BrowserWindow.c')
-rw-r--r--Tools/MiniBrowser/gtk/BrowserWindow.c898
1 files changed, 658 insertions, 240 deletions
diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c
index b8a0d056c..b80157fa2 100644
--- a/Tools/MiniBrowser/gtk/BrowserWindow.c
+++ b/Tools/MiniBrowser/gtk/BrowserWindow.c
@@ -25,23 +25,23 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
+#include "cmakeconfig.h"
+#endif
#include "BrowserWindow.h"
#include "BrowserDownloadsBar.h"
#include "BrowserSearchBar.h"
#include "BrowserSettingsDialog.h"
+#include "BrowserTab.h"
#include <gdk/gdkkeysyms.h>
#include <string.h>
-enum {
- PROP_0,
-
- PROP_VIEW
-};
-
struct _BrowserWindow {
GtkWindow parent;
+ WebKitWebContext *webContext;
+
GtkAccelGroup *accelGroup;
GtkWidget *mainBox;
GtkWidget *toolbar;
@@ -50,18 +50,21 @@ struct _BrowserWindow {
GtkWidget *forwardItem;
GtkWidget *zoomInItem;
GtkWidget *zoomOutItem;
- GtkWidget *statusLabel;
+ GtkWidget *boldItem;
+ GtkWidget *italicItem;
+ GtkWidget *underlineItem;
+ GtkWidget *strikethroughItem;
GtkWidget *settingsDialog;
- WebKitWebView *webView;
+ GtkWidget *notebook;
+ BrowserTab *activeTab;
GtkWidget *downloadsBar;
- BrowserSearchBar *searchBar;
gboolean searchBarVisible;
+ gboolean fullScreenIsEnabled;
GdkPixbuf *favicon;
GtkWidget *reloadOrStopButton;
- GtkWidget *fullScreenMessageLabel;
GtkWindow *parentWindow;
- guint fullScreenMessageLabelId;
guint resetEntryProgressTimeoutId;
+ gchar *sessionFile;
};
struct _BrowserWindowClass {
@@ -69,36 +72,26 @@ struct _BrowserWindowClass {
};
static const char *defaultWindowTitle = "WebKitGTK+ MiniBrowser";
-static const char *miniBrowserAboutScheme = "minibrowser-about";
static const gdouble minimumZoomLevel = 0.5;
static const gdouble maximumZoomLevel = 3;
+static const gdouble defaultZoomLevel = 1;
static const gdouble zoomStep = 1.2;
static gint windowCount = 0;
G_DEFINE_TYPE(BrowserWindow, browser_window, GTK_TYPE_WINDOW)
-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(miniBrowserAboutScheme, uri + strlen ("about"), NULL);
-
- return g_strdup(uri);
-}
-
static char *getExternalURI(const char *uri)
{
- // From the user point of view we support about: prefix.
- if (g_str_has_prefix(uri, miniBrowserAboutScheme))
- return g_strconcat("about", uri + strlen(miniBrowserAboutScheme), NULL);
+ /* From the user point of view we support about: prefix. */
+ if (uri && g_str_has_prefix(uri, BROWSER_ABOUT_SCHEME))
+ return g_strconcat("about", uri + strlen(BROWSER_ABOUT_SCHEME), NULL);
return g_strdup(uri);
}
static void browserWindowSetStatusText(BrowserWindow *window, const char *text)
{
- gtk_label_set_text(GTK_LABEL(window->statusLabel), text);
- gtk_widget_set_visible(window->statusLabel, !!text);
+ browser_tab_set_status_text(window->activeTab, text);
}
static void resetStatusText(GtkWidget *widget, BrowserWindow *window)
@@ -113,20 +106,23 @@ static void activateUriEntryCallback(BrowserWindow *window)
static void reloadOrStopCallback(BrowserWindow *window)
{
- if (webkit_web_view_is_loading(window->webView))
- webkit_web_view_stop_loading(window->webView);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ if (webkit_web_view_is_loading(webView))
+ webkit_web_view_stop_loading(webView);
else
- webkit_web_view_reload(window->webView);
+ webkit_web_view_reload(webView);
}
static void goBackCallback(BrowserWindow *window)
{
- webkit_web_view_go_back(window->webView);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_go_back(webView);
}
static void goForwardCallback(BrowserWindow *window)
{
- webkit_web_view_go_forward(window->webView);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_go_forward(webView);
}
static void settingsCallback(BrowserWindow *window)
@@ -136,7 +132,8 @@ static void settingsCallback(BrowserWindow *window)
return;
}
- window->settingsDialog = browser_settings_dialog_new(webkit_web_view_get_settings(window->webView));
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ window->settingsDialog = browser_settings_dialog_new(webkit_web_view_get_settings(webView));
gtk_window_set_transient_for(GTK_WINDOW(window->settingsDialog), GTK_WINDOW(window));
g_object_add_weak_pointer(G_OBJECT(window->settingsDialog), (gpointer *)&window->settingsDialog);
gtk_widget_show(window->settingsDialog);
@@ -145,14 +142,23 @@ static void settingsCallback(BrowserWindow *window)
static void webViewURIChanged(WebKitWebView *webView, GParamSpec *pspec, BrowserWindow *window)
{
char *externalURI = getExternalURI(webkit_web_view_get_uri(webView));
- gtk_entry_set_text(GTK_ENTRY(window->uriEntry), externalURI);
- g_free(externalURI);
+ if (externalURI) {
+ gtk_entry_set_text(GTK_ENTRY(window->uriEntry), externalURI);
+ g_free(externalURI);
+ } else
+ gtk_entry_set_text(GTK_ENTRY(window->uriEntry), "");
}
static void webViewTitleChanged(WebKitWebView *webView, GParamSpec *pspec, BrowserWindow *window)
{
const char *title = webkit_web_view_get_title(webView);
- gtk_window_set_title(GTK_WINDOW(window), title ? title : defaultWindowTitle);
+ if (!title)
+ title = defaultWindowTitle;
+ char *privateTitle = NULL;
+ if (webkit_web_view_is_ephemeral(webView))
+ privateTitle = g_strdup_printf("[Private] %s", title);
+ gtk_window_set_title(GTK_WINDOW(window), privateTitle ? privateTitle : title);
+ g_free(privateTitle);
}
static gboolean resetEntryProgress(BrowserWindow *window)
@@ -196,7 +202,8 @@ static void browserWindowHistoryItemActivated(BrowserWindow *window, GtkAction *
if (!item)
return;
- webkit_web_view_go_to_back_forward_list_item(window->webView, item);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_go_to_back_forward_list_item(webView, item);
}
static GtkWidget *browserWindowCreateBackForwardMenu(BrowserWindow *window, GList *list)
@@ -230,8 +237,9 @@ static GtkWidget *browserWindowCreateBackForwardMenu(BrowserWindow *window, GLis
static void browserWindowUpdateNavigationActions(BrowserWindow *window, WebKitBackForwardList *backForwadlist)
{
- gtk_widget_set_sensitive(window->backItem, webkit_web_view_can_go_back(window->webView));
- gtk_widget_set_sensitive(window->forwardItem, webkit_web_view_can_go_forward(window->webView));
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ gtk_widget_set_sensitive(window->backItem, webkit_web_view_can_go_back(webView));
+ gtk_widget_set_sensitive(window->forwardItem, webkit_web_view_can_go_forward(webView));
GList *list = g_list_reverse(webkit_back_forward_list_get_back_list_with_limit(backForwadlist, 10));
gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(window->backItem),
@@ -249,24 +257,22 @@ static void backForwadlistChanged(WebKitBackForwardList *backForwadlist, WebKitB
browserWindowUpdateNavigationActions(window, backForwadlist);
}
-static void geolocationRequestDialogCallback(GtkDialog *dialog, gint response, WebKitPermissionRequest *request)
+static void webViewClose(WebKitWebView *webView, BrowserWindow *window)
{
- switch (response) {
- case GTK_RESPONSE_YES:
- webkit_permission_request_allow(request);
- break;
- default:
- webkit_permission_request_deny(request);
- break;
+ int tabsCount = gtk_notebook_get_n_pages(GTK_NOTEBOOK(window->notebook));
+ if (tabsCount == 1) {
+ gtk_widget_destroy(GTK_WIDGET(window));
+ return;
}
- gtk_widget_destroy(GTK_WIDGET(dialog));
- g_object_unref(request);
-}
-
-static void webViewClose(WebKitWebView *webView, BrowserWindow *window)
-{
- gtk_widget_destroy(GTK_WIDGET(window));
+ int i;
+ for (i = 0; i < tabsCount; ++i) {
+ BrowserTab *tab = (BrowserTab *)gtk_notebook_get_nth_page(GTK_NOTEBOOK(window->notebook), i);
+ if (browser_tab_get_web_view(tab) == webView) {
+ gtk_widget_destroy(GTK_WIDGET(tab));
+ return;
+ }
+ }
}
static void webViewRunAsModal(WebKitWebView *webView, BrowserWindow *window)
@@ -297,65 +303,33 @@ static void webViewReadyToShow(WebKitWebView *webView, BrowserWindow *window)
gtk_widget_show(GTK_WIDGET(window));
}
-static gboolean fullScreenMessageTimeoutCallback(BrowserWindow *window)
+static GtkWidget *webViewCreate(WebKitWebView *webView, WebKitNavigationAction *navigation, BrowserWindow *window)
{
- gtk_widget_hide(window->fullScreenMessageLabel);
- window->fullScreenMessageLabelId = 0;
- return FALSE;
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(webView));
+ webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
+
+ GtkWidget *newWindow = browser_window_new(GTK_WINDOW(window), window->webContext);
+ browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView);
+ g_signal_connect(newWebView, "ready-to-show", G_CALLBACK(webViewReadyToShow), newWindow);
+ g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(webViewRunAsModal), newWindow);
+ g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), newWindow);
+ return GTK_WIDGET(newWebView);
}
static gboolean webViewEnterFullScreen(WebKitWebView *webView, BrowserWindow *window)
{
- gchar *titleOrURI = g_strdup(webkit_web_view_get_title(window->webView));
- if (!titleOrURI)
- titleOrURI = getExternalURI(webkit_web_view_get_uri(window->webView));
- gchar *message = g_strdup_printf("%s is now full screen. Press ESC or f to exit.", titleOrURI);
- gtk_label_set_text(GTK_LABEL(window->fullScreenMessageLabel), message);
- g_free(titleOrURI);
- g_free(message);
-
- gtk_widget_show(window->fullScreenMessageLabel);
-
- window->fullScreenMessageLabelId = g_timeout_add_seconds(2, (GSourceFunc)fullScreenMessageTimeoutCallback, window);
- g_source_set_name_by_id(window->fullScreenMessageLabelId, "[WebKit] fullScreenMessageTimeoutCallback");
gtk_widget_hide(window->toolbar);
- window->searchBarVisible = gtk_widget_get_visible(GTK_WIDGET(window->searchBar));
- browser_search_bar_close(window->searchBar);
-
+ browser_tab_enter_fullscreen(window->activeTab);
return FALSE;
}
static gboolean webViewLeaveFullScreen(WebKitWebView *webView, BrowserWindow *window)
{
- if (window->fullScreenMessageLabelId) {
- g_source_remove(window->fullScreenMessageLabelId);
- window->fullScreenMessageLabelId = 0;
- }
- gtk_widget_hide(window->fullScreenMessageLabel);
+ browser_tab_leave_fullscreen(window->activeTab);
gtk_widget_show(window->toolbar);
- if (window->searchBarVisible) {
- // Opening the search bar steals the focus. Usually, we want
- // this but not when coming back from fullscreen.
- GtkWidget *focusWidget = gtk_window_get_focus(GTK_WINDOW(window));
- browser_search_bar_open(window->searchBar);
- gtk_window_set_focus(GTK_WINDOW(window), focusWidget);
- }
-
return FALSE;
}
-static GtkWidget *webViewCreate(WebKitWebView *webView, BrowserWindow *window)
-{
- WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(webView));
- webkit_web_view_set_settings(newWebView, webkit_web_view_get_settings(webView));
-
- GtkWidget *newWindow = browser_window_new(newWebView, GTK_WINDOW(window));
- g_signal_connect(newWebView, "ready-to-show", G_CALLBACK(webViewReadyToShow), newWindow);
- g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(webViewRunAsModal), newWindow);
- g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), newWindow);
- return GTK_WIDGET(newWebView);
-}
-
static gboolean webViewLoadFailed(WebKitWebView *webView, WebKitLoadEvent loadEvent, const char *failingURI, GError *error, BrowserWindow *window)
{
gtk_entry_set_progress_fraction(GTK_ENTRY(window->uriEntry), 0.);
@@ -364,57 +338,28 @@ static gboolean webViewLoadFailed(WebKitWebView *webView, WebKitLoadEvent loadEv
static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision *decision, WebKitPolicyDecisionType decisionType, BrowserWindow *window)
{
- switch (decisionType) {
- case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: {
- WebKitNavigationPolicyDecision *navigationDecision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
- if (webkit_navigation_policy_decision_get_navigation_type(navigationDecision) != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
- || webkit_navigation_policy_decision_get_mouse_button(navigationDecision) != GDK_BUTTON_MIDDLE)
- return FALSE;
-
- // Opening a new window if link clicked with the middle button.
- WebKitWebView *newWebView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(webkit_web_view_get_context(webView)));
- GtkWidget *newWindow = browser_window_new(newWebView, GTK_WINDOW(window));
- webkit_web_view_load_request(newWebView, webkit_navigation_policy_decision_get_request(navigationDecision));
- gtk_widget_show(newWindow);
-
- webkit_policy_decision_ignore(decision);
- return TRUE;
- }
- case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: {
- 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;
- }
- case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
- default:
+ if (decisionType != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION)
return FALSE;
- }
-}
-static gboolean webViewDecidePermissionRequest(WebKitWebView *webView, WebKitPermissionRequest *request, BrowserWindow *window)
-{
- if (!WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(request))
+ WebKitNavigationAction *navigationAction = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(decision));
+ if (webkit_navigation_action_get_navigation_type(navigationAction) != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED
+ || webkit_navigation_action_get_mouse_button(navigationAction) != GDK_BUTTON_MIDDLE)
return FALSE;
- GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_YES_NO,
- "Geolocation request");
+ /* Multiple tabs are not allowed in editor mode. */
+ if (webkit_web_view_is_editable(webView))
+ return FALSE;
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "Allow geolocation request?");
- g_signal_connect(dialog, "response", G_CALLBACK(geolocationRequestDialogCallback), g_object_ref(request));
- gtk_widget_show(dialog);
+ /* Opening a new tab if link clicked with the middle button. */
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_view_get_context(webView),
+ "settings", webkit_web_view_get_settings(webView),
+ "user-content-manager", webkit_web_view_get_user_content_manager(webView),
+ NULL));
+ browser_window_append_view(window, newWebView);
+ webkit_web_view_load_request(newWebView, webkit_navigation_action_get_request(navigationAction));
+ webkit_policy_decision_ignore(decision);
return TRUE;
}
@@ -429,16 +374,53 @@ static void webViewMouseTargetChanged(WebKitWebView *webView, WebKitHitTestResul
static gboolean browserWindowCanZoomIn(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) * zoomStep;
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(webView) * zoomStep;
return zoomLevel < maximumZoomLevel;
}
static gboolean browserWindowCanZoomOut(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) / zoomStep;
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(webView) / zoomStep;
return zoomLevel > minimumZoomLevel;
}
+static gboolean browserWindowZoomIn(BrowserWindow *window)
+{
+ if (browserWindowCanZoomIn(window)) {
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(webView) * zoomStep;
+ webkit_web_view_set_zoom_level(webView, zoomLevel);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean browserWindowZoomOut(BrowserWindow *window)
+{
+ if (browserWindowCanZoomOut(window)) {
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ gdouble zoomLevel = webkit_web_view_get_zoom_level(webView) / zoomStep;
+ webkit_web_view_set_zoom_level(webView, zoomLevel);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean scrollEventCallback(WebKitWebView *webView, const GdkEventScroll *event, BrowserWindow *window)
+{
+ GdkModifierType mod = gtk_accelerator_get_default_mod_mask();
+
+ if ((event->state & mod) != GDK_CONTROL_MASK)
+ return FALSE;
+
+ if (event->delta_y < 0)
+ return browserWindowZoomIn(window);
+
+ return browserWindowZoomOut(window);
+}
+
static void browserWindowUpdateZoomActions(BrowserWindow *window)
{
gtk_widget_set_sensitive(window->zoomInItem, browserWindowCanZoomIn(window));
@@ -459,10 +441,10 @@ static void updateUriEntryIcon(BrowserWindow *window)
gtk_entry_set_icon_from_stock(entry, GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_NEW);
}
-static void faviconChanged(GObject *object, GParamSpec *paramSpec, BrowserWindow *window)
+static void faviconChanged(WebKitWebView *webView, GParamSpec *paramSpec, BrowserWindow *window)
{
GdkPixbuf *favicon = NULL;
- cairo_surface_t *surface = webkit_web_view_get_favicon(window->webView);
+ cairo_surface_t *surface = webkit_web_view_get_favicon(webView);
if (surface) {
int width = cairo_image_surface_get_width(surface);
@@ -477,32 +459,194 @@ static void faviconChanged(GObject *object, GParamSpec *paramSpec, BrowserWindow
updateUriEntryIcon(window);
}
-static void webViewIsLoadingChanged(GObject *object, GParamSpec *paramSpec, BrowserWindow *window)
+static void webViewIsLoadingChanged(WebKitWebView *webView, GParamSpec *paramSpec, BrowserWindow *window)
{
- gboolean isLoading = webkit_web_view_is_loading(window->webView);
+ gboolean isLoading = webkit_web_view_is_loading(webView);
gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(window->reloadOrStopButton), isLoading ? GTK_STOCK_STOP : GTK_STOCK_REFRESH);
}
static void zoomInCallback(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) * zoomStep;
- webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ browserWindowZoomIn(window);
}
static void zoomOutCallback(BrowserWindow *window)
{
- gdouble zoomLevel = webkit_web_view_get_zoom_level(window->webView) / zoomStep;
- webkit_web_view_set_zoom_level(window->webView, zoomLevel);
+ browserWindowZoomOut(window);
+}
+
+static void defaultZoomCallback(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_set_zoom_level(webView, defaultZoomLevel);
}
static void searchCallback(BrowserWindow *window)
{
- browser_search_bar_open(window->searchBar);
+ browser_tab_start_search(window->activeTab);
+}
+
+static void newTabCallback(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ if (webkit_web_view_is_editable(webView))
+ return;
+
+ browser_window_append_view(window, WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_view_get_context(webView),
+ "settings", webkit_web_view_get_settings(webView),
+ "user-content-manager", webkit_web_view_get_user_content_manager(webView),
+ NULL)));
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), -1);
+}
+
+static void toggleWebInspector(BrowserWindow *window)
+{
+ browser_tab_toggle_inspector(window->activeTab);
+}
+
+static void openPrivateWindow(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ WebKitWebView *newWebView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_view_get_context(webView),
+ "settings", webkit_web_view_get_settings(webView),
+ "user-content-manager", webkit_web_view_get_user_content_manager(webView),
+ "is-ephemeral", TRUE,
+ NULL));
+ GtkWidget *newWindow = browser_window_new(GTK_WINDOW(window), window->webContext);
+ browser_window_append_view(BROWSER_WINDOW(newWindow), newWebView);
+ gtk_widget_show(GTK_WIDGET(newWindow));
+}
+
+static void reloadPage(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_reload(webView);
+}
+
+static void reloadPageIgnoringCache(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_reload_bypass_cache(webView);
+}
+
+static void stopPageLoad(BrowserWindow *window)
+{
+ browser_tab_stop_search(window->activeTab);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ if (webkit_web_view_is_loading(webView))
+ webkit_web_view_stop_loading(webView);
+}
+
+static void loadHomePage(BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_load_uri(webView, BROWSER_DEFAULT_URL);
+}
+
+static gboolean toggleFullScreen(BrowserWindow *window, gpointer user_data)
+{
+ if (!window->fullScreenIsEnabled) {
+ gtk_window_fullscreen(GTK_WINDOW(window));
+ gtk_widget_hide(window->toolbar);
+ window->fullScreenIsEnabled = TRUE;
+ } else {
+ gtk_window_unfullscreen(GTK_WINDOW(window));
+ gtk_widget_show(window->toolbar);
+ window->fullScreenIsEnabled = FALSE;
+ }
+ return TRUE;
+}
+
+static void webKitPrintOperationFailedCallback(WebKitPrintOperation *printOperation, GError *error)
+{
+ g_warning("Print failed: '%s'", error->message);
+}
+
+static gboolean printPage(BrowserWindow *window, gpointer user_data)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ WebKitPrintOperation *printOperation = webkit_print_operation_new(webView);
+
+ g_signal_connect(printOperation, "failed", G_CALLBACK(webKitPrintOperationFailedCallback), NULL);
+ webkit_print_operation_run_dialog(printOperation, GTK_WINDOW(window));
+ g_object_unref(printOperation);
+
+ return TRUE;
+}
+
+static void editingCommandCallback(GtkWidget *widget, BrowserWindow *window)
+{
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_execute_editing_command(webView, gtk_widget_get_name(widget));
+}
+
+static void insertImageCommandCallback(GtkWidget *widget, BrowserWindow *window)
+{
+ GtkWidget *fileChooser = gtk_file_chooser_dialog_new("Insert Image", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
+ "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
+
+ GtkFileFilter *filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "Images");
+ gtk_file_filter_add_pixbuf_formats(filter);
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fileChooser), filter);
+
+ if (gtk_dialog_run(GTK_DIALOG(fileChooser)) == GTK_RESPONSE_ACCEPT) {
+ char *uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(fileChooser));
+ if (uri) {
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_execute_editing_command_with_argument(webView, WEBKIT_EDITING_COMMAND_INSERT_IMAGE, uri);
+ g_free(uri);
+ }
+ }
+
+ gtk_widget_destroy(fileChooser);
+}
+
+static void insertLinkCommandCallback(GtkWidget *widget, BrowserWindow *window)
+{
+ GtkWidget *dialog = gtk_dialog_new_with_buttons("Insert Link", GTK_WINDOW(window), GTK_DIALOG_MODAL, "Insert", GTK_RESPONSE_ACCEPT, NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
+ GtkWidget *entry = gtk_entry_new();
+ gtk_entry_set_placeholder_text(GTK_ENTRY(entry), "URL");
+ gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
+ gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
+ gtk_widget_show(entry);
+
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+ const char *url = gtk_entry_get_text(GTK_ENTRY(entry));
+ if (url && *url) {
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_execute_editing_command_with_argument(webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, url);
+ }
+ }
+
+ gtk_widget_destroy(dialog);
+}
+
+static void browserWindowEditingCommandToggleButtonSetActive(BrowserWindow *window, GtkWidget *button, gboolean active)
+{
+ g_signal_handlers_block_by_func(button, G_CALLBACK(editingCommandCallback), window);
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button), active);
+ g_signal_handlers_unblock_by_func(button, G_CALLBACK(editingCommandCallback), window);
+}
+
+static void typingAttributesChanged(WebKitEditorState *editorState, GParamSpec *spec, BrowserWindow *window)
+{
+ unsigned typingAttributes = webkit_editor_state_get_typing_attributes(editorState);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->boldItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->italicItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->underlineItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ browserWindowEditingCommandToggleButtonSetActive(window, window->strikethroughItem, typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
}
static void browserWindowFinalize(GObject *gObject)
{
BrowserWindow *window = BROWSER_WINDOW(gObject);
+
+ g_signal_handlers_disconnect_matched(window->webContext, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
+
if (window->favicon) {
g_object_unref(window->favicon);
window->favicon = NULL;
@@ -513,42 +657,207 @@ static void browserWindowFinalize(GObject *gObject)
window->accelGroup = NULL;
}
- if (window->fullScreenMessageLabelId)
- g_source_remove(window->fullScreenMessageLabelId);
-
if (window->resetEntryProgressTimeoutId)
g_source_remove(window->resetEntryProgressTimeoutId);
+ g_free(window->sessionFile);
+
G_OBJECT_CLASS(browser_window_parent_class)->finalize(gObject);
if (g_atomic_int_dec_and_test(&windowCount))
gtk_main_quit();
}
-static void browserWindowGetProperty(GObject *object, guint propId, GValue *value, GParamSpec *pspec)
+static void browserWindowSetupEditorToolbar(BrowserWindow *window)
{
- BrowserWindow *window = BROWSER_WINDOW(object);
+ GtkWidget *toolbar = gtk_toolbar_new();
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
- switch (propId) {
- case PROP_VIEW:
- g_value_set_object(value, browser_window_get_view(window));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
- }
+ GtkToolItem *item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_BOLD);
+ window->boldItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Bold");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_ITALIC);
+ window->italicItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Italic");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_UNDERLINE);
+ window->underlineItem = GTK_WIDGET(item);
+ gtk_widget_set_name(GTK_WIDGET(item), "Underline");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_STRIKETHROUGH);
+ gtk_widget_set_name(GTK_WIDGET(item), "Strikethrough");
+ window->strikethroughItem = GTK_WIDGET(item);
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_CUT);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_CUT);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_COPY);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_COPY);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_PASTE);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_PASTE);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_UNDO);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
+ gtk_widget_set_name(GTK_WIDGET(item), WEBKIT_EDITING_COMMAND_REDO);
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(NULL, GTK_STOCK_JUSTIFY_LEFT);
+ GSList *justifyRadioGroup = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(item));
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyLeft");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(justifyRadioGroup, GTK_STOCK_JUSTIFY_CENTER);
+ justifyRadioGroup = gtk_radio_tool_button_get_group(GTK_RADIO_TOOL_BUTTON(item));
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyCenter");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_radio_tool_button_new_from_stock(justifyRadioGroup, GTK_STOCK_JUSTIFY_RIGHT);
+ gtk_widget_set_name(GTK_WIDGET(item), "JustifyRight");
+ g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_INDENT);
+ gtk_widget_set_name(GTK_WIDGET(item), "Indent");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_UNINDENT);
+ gtk_widget_set_name(GTK_WIDGET(item), "Outdent");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(editingCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_separator_tool_item_new();
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new(NULL, NULL);
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "insert-image");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(insertImageCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new(NULL, NULL);
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "insert-link");
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(insertLinkCommandCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ gtk_box_pack_start(GTK_BOX(window->mainBox), toolbar, FALSE, FALSE, 0);
+ gtk_box_reorder_child(GTK_BOX(window->mainBox), toolbar, 1);
+ gtk_widget_show(toolbar);
}
-static void browserWindowSetProperty(GObject *object, guint propId, const GValue *value, GParamSpec *pspec)
+static void browserWindowSwitchTab(GtkNotebook *notebook, BrowserTab *tab, guint tabIndex, BrowserWindow *window)
{
- BrowserWindow* window = BROWSER_WINDOW(object);
+ if (window->activeTab == tab)
+ return;
- switch (propId) {
- case PROP_VIEW:
- window->webView = g_value_get_object(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
+ if (window->activeTab) {
+ browser_tab_set_status_text(window->activeTab, NULL);
+ g_clear_object(&window->favicon);
+
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ g_signal_handlers_disconnect_by_data(webView, window);
+
+ /* We always want close to be connected even for not active tabs */
+ g_signal_connect(webView, "close", G_CALLBACK(webViewClose), window);
+
+ WebKitBackForwardList *backForwadlist = webkit_web_view_get_back_forward_list(webView);
+ g_signal_handlers_disconnect_by_data(backForwadlist, window);
+ }
+
+ window->activeTab = tab;
+
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ if (webkit_web_view_is_editable(webView)) {
+ browserWindowSetupEditorToolbar(window);
+ g_signal_connect(webkit_web_view_get_editor_state(webView), "notify::typing-attributes", G_CALLBACK(typingAttributesChanged), window);
}
+ webViewURIChanged(webView, NULL, window);
+ webViewTitleChanged(webView, NULL, window);
+ webViewIsLoadingChanged(webView, NULL, window);
+ faviconChanged(webView, NULL, window);
+ browserWindowUpdateZoomActions(window);
+ if (webkit_web_view_is_loading(webView))
+ webViewLoadProgressChanged(webView, NULL, window);
+
+ g_signal_connect(webView, "notify::uri", G_CALLBACK(webViewURIChanged), window);
+ g_signal_connect(webView, "notify::estimated-load-progress", G_CALLBACK(webViewLoadProgressChanged), window);
+ g_signal_connect(webView, "notify::title", G_CALLBACK(webViewTitleChanged), window);
+ g_signal_connect(webView, "notify::is-loading", G_CALLBACK(webViewIsLoadingChanged), window);
+ g_signal_connect(webView, "create", G_CALLBACK(webViewCreate), window);
+ g_signal_connect(webView, "close", G_CALLBACK(webViewClose), window);
+ g_signal_connect(webView, "load-failed", G_CALLBACK(webViewLoadFailed), window);
+ g_signal_connect(webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), window);
+ g_signal_connect(webView, "mouse-target-changed", G_CALLBACK(webViewMouseTargetChanged), window);
+ g_signal_connect(webView, "notify::zoom-level", G_CALLBACK(webViewZoomLevelChanged), window);
+ g_signal_connect(webView, "notify::favicon", G_CALLBACK(faviconChanged), window);
+ g_signal_connect(webView, "enter-fullscreen", G_CALLBACK(webViewEnterFullScreen), window);
+ g_signal_connect(webView, "leave-fullscreen", G_CALLBACK(webViewLeaveFullScreen), window);
+ g_signal_connect(webView, "scroll-event", G_CALLBACK(scrollEventCallback), window);
+
+ WebKitBackForwardList *backForwadlist = webkit_web_view_get_back_forward_list(webView);
+ browserWindowUpdateNavigationActions(window, backForwadlist);
+ g_signal_connect(backForwadlist, "changed", G_CALLBACK(backForwadlistChanged), window);
+}
+
+static void browserWindowTabAddedOrRemoved(GtkNotebook *notebook, BrowserTab *tab, guint tabIndex, BrowserWindow *window)
+{
+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(window->notebook), gtk_notebook_get_n_pages(notebook) > 1);
}
static void browser_window_init(BrowserWindow *window)
@@ -567,6 +876,64 @@ static void browser_window_init(BrowserWindow *window)
window->accelGroup = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), window->accelGroup);
+ /* Global accelerators */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_I, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleWebInspector), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F12, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleWebInspector), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_P, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(openPrivateWindow), window, NULL));
+
+ /* Reload page */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F5, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPage), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_R, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPage), window, NULL));
+
+ /* Reload page ignoring cache */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F5, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPageIgnoringCache), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_R, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(reloadPageIgnoringCache), window, NULL));
+
+ /* Stop page load */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F6, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(stopPageLoad), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Escape, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(stopPageLoad), window, NULL));
+
+ /* Load home page */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Home, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(loadHomePage), window, NULL));
+
+ /* Zoom in, zoom out and default zoom*/
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_equal, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomInCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_Add, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomInCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_minus, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomOutCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_Subtract, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(zoomOutCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_0, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(defaultZoomCallback), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_KP_0, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(defaultZoomCallback), window, NULL));
+
+ /* Toggle fullscreen */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_F11, 0, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(toggleFullScreen), window, NULL));
+
+ /* Quit */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_Q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(gtk_widget_destroy), window, NULL));
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_W, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(gtk_widget_destroy), window, NULL));
+
+ /* Print */
+ gtk_accel_group_connect(window->accelGroup, GDK_KEY_P, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
+ g_cclosure_new_swap(G_CALLBACK(printPage), window, NULL));
+
GtkWidget *toolbar = gtk_toolbar_new();
window->toolbar = toolbar;
gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
@@ -609,6 +976,18 @@ static void browser_window_init(BrowserWindow *window)
gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", window->accelGroup, GDK_KEY_F, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_widget_show(GTK_WIDGET(item));
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_HOME);
+ g_signal_connect_swapped(item, "clicked", G_CALLBACK(loadHomePage), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", window->accelGroup, GDK_KEY_Home, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ item = gtk_tool_button_new(gtk_image_new_from_icon_name("tab-new", GTK_ICON_SIZE_SMALL_TOOLBAR), NULL);
+ g_signal_connect_swapped(item, "clicked", G_CALLBACK(newTabCallback), window);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
+ gtk_widget_add_accelerator(GTK_WIDGET(item), "clicked", window->accelGroup, GDK_KEY_T, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+ gtk_widget_show_all(GTK_WIDGET(item));
+
item = gtk_tool_item_new();
gtk_tool_item_set_expand(item, TRUE);
gtk_container_add(GTK_CONTAINER(item), window->uriEntry);
@@ -628,60 +1007,44 @@ static void browser_window_init(BrowserWindow *window)
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
gtk_widget_show(toolbar);
+ window->notebook = gtk_notebook_new();
+ g_signal_connect(window->notebook, "switch-page", G_CALLBACK(browserWindowSwitchTab), window);
+ g_signal_connect(window->notebook, "page-added", G_CALLBACK(browserWindowTabAddedOrRemoved), window);
+ g_signal_connect(window->notebook, "page-removed", G_CALLBACK(browserWindowTabAddedOrRemoved), window);
+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(window->notebook), FALSE);
+ gtk_notebook_set_show_border(GTK_NOTEBOOK(window->notebook), FALSE);
+ gtk_box_pack_start(GTK_BOX(window->mainBox), window->notebook, TRUE, TRUE, 0);
+ gtk_widget_show(window->notebook);
+
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
}
static void browserWindowConstructed(GObject *gObject)
{
- BrowserWindow *window = BROWSER_WINDOW(gObject);
-
- browserWindowUpdateZoomActions(window);
-
- g_signal_connect(window->webView, "notify::uri", G_CALLBACK(webViewURIChanged), window);
- g_signal_connect(window->webView, "notify::estimated-load-progress", G_CALLBACK(webViewLoadProgressChanged), window);
- g_signal_connect(window->webView, "notify::title", G_CALLBACK(webViewTitleChanged), window);
- g_signal_connect(window->webView, "create", G_CALLBACK(webViewCreate), window);
- g_signal_connect(window->webView, "load-failed", G_CALLBACK(webViewLoadFailed), window);
- g_signal_connect(window->webView, "decide-policy", G_CALLBACK(webViewDecidePolicy), window);
- g_signal_connect(window->webView, "permission-request", G_CALLBACK(webViewDecidePermissionRequest), window);
- g_signal_connect(window->webView, "mouse-target-changed", G_CALLBACK(webViewMouseTargetChanged), window);
- g_signal_connect(window->webView, "notify::zoom-level", G_CALLBACK(webViewZoomLevelChanged), window);
- g_signal_connect(window->webView, "notify::favicon", G_CALLBACK(faviconChanged), window);
- g_signal_connect(window->webView, "enter-fullscreen", G_CALLBACK(webViewEnterFullScreen), window);
- g_signal_connect(window->webView, "leave-fullscreen", G_CALLBACK(webViewLeaveFullScreen), window);
- g_signal_connect(window->webView, "notify::is-loading", G_CALLBACK(webViewIsLoadingChanged), window);
-
- g_signal_connect(webkit_web_view_get_context(window->webView), "download-started", G_CALLBACK(downloadStarted), window);
-
- window->searchBar = BROWSER_SEARCH_BAR(browser_search_bar_new(window->webView));
- browser_search_bar_add_accelerators(window->searchBar, window->accelGroup);
- gtk_box_pack_start(GTK_BOX(window->mainBox), GTK_WIDGET(window->searchBar), FALSE, FALSE, 0);
-
- WebKitBackForwardList *backForwadlist = webkit_web_view_get_back_forward_list(window->webView);
- g_signal_connect(backForwadlist, "changed", G_CALLBACK(backForwadlistChanged), window);
-
- GtkWidget *overlay = gtk_overlay_new();
- gtk_box_pack_start(GTK_BOX(window->mainBox), overlay, TRUE, TRUE, 0);
- gtk_widget_show(overlay);
+ G_OBJECT_CLASS(browser_window_parent_class)->constructed(gObject);
+}
- window->statusLabel = gtk_label_new(NULL);
- gtk_widget_set_halign(window->statusLabel, GTK_ALIGN_START);
- gtk_widget_set_valign(window->statusLabel, GTK_ALIGN_END);
- gtk_widget_set_margin_left(window->statusLabel, 1);
- gtk_widget_set_margin_right(window->statusLabel, 1);
- gtk_widget_set_margin_top(window->statusLabel, 1);
- gtk_widget_set_margin_bottom(window->statusLabel, 1);
- gtk_overlay_add_overlay(GTK_OVERLAY(overlay), window->statusLabel);
+static void browserWindowSaveSession(BrowserWindow *window)
+{
+ if (!window->sessionFile)
+ return;
- gtk_container_add(GTK_CONTAINER(overlay), GTK_WIDGET(window->webView));
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ WebKitWebViewSessionState *state = webkit_web_view_get_session_state(webView);
+ GBytes *bytes = webkit_web_view_session_state_serialize(state);
+ webkit_web_view_session_state_unref(state);
+ g_file_set_contents(window->sessionFile, g_bytes_get_data(bytes, NULL), g_bytes_get_size(bytes), NULL);
+ g_bytes_unref(bytes);
+}
- window->fullScreenMessageLabel = gtk_label_new(NULL);
- gtk_widget_set_halign(window->fullScreenMessageLabel, GTK_ALIGN_CENTER);
- gtk_widget_set_valign(window->fullScreenMessageLabel, GTK_ALIGN_CENTER);
- gtk_widget_set_no_show_all(window->fullScreenMessageLabel, TRUE);
- gtk_overlay_add_overlay(GTK_OVERLAY(overlay), window->fullScreenMessageLabel);
- gtk_widget_show(GTK_WIDGET(window->webView));
+static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event)
+{
+ BrowserWindow *window = BROWSER_WINDOW(widget);
+ browserWindowSaveSession(window);
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ webkit_web_view_try_close(webView);
+ return TRUE;
}
static void browser_window_class_init(BrowserWindowClass *klass)
@@ -689,27 +1052,22 @@ static void browser_window_class_init(BrowserWindowClass *klass)
GObjectClass *gobjectClass = G_OBJECT_CLASS(klass);
gobjectClass->constructed = browserWindowConstructed;
- gobjectClass->get_property = browserWindowGetProperty;
- gobjectClass->set_property = browserWindowSetProperty;
gobjectClass->finalize = browserWindowFinalize;
- g_object_class_install_property(gobjectClass,
- PROP_VIEW,
- g_param_spec_object("view",
- "View",
- "The web view of this window",
- WEBKIT_TYPE_WEB_VIEW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass);
+ widgetClass->delete_event = browserWindowDeleteEvent;
}
-// Public API.
-GtkWidget *browser_window_new(WebKitWebView *view, GtkWindow *parent)
+/* Public API. */
+GtkWidget *browser_window_new(GtkWindow *parent, WebKitWebContext *webContext)
{
- g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(view), 0);
+ g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(webContext), NULL);
BrowserWindow *window = BROWSER_WINDOW(g_object_new(BROWSER_TYPE_WINDOW,
- "type", GTK_WINDOW_TOPLEVEL, "view", view, NULL));
+ "type", GTK_WINDOW_TOPLEVEL, NULL));
+ window->webContext = webContext;
+ g_signal_connect(window->webContext, "download-started", G_CALLBACK(downloadStarted), window);
if (parent) {
window->parentWindow = parent;
g_object_add_weak_pointer(G_OBJECT(parent), (gpointer *)&window->parentWindow);
@@ -718,11 +1076,28 @@ GtkWidget *browser_window_new(WebKitWebView *view, GtkWindow *parent)
return GTK_WIDGET(window);
}
-WebKitWebView *browser_window_get_view(BrowserWindow *window)
+WebKitWebContext *browser_window_get_web_context(BrowserWindow *window)
+{
+ g_return_val_if_fail(BROWSER_IS_WINDOW(window), NULL);
+
+ return window->webContext;
+}
+
+void browser_window_append_view(BrowserWindow *window, WebKitWebView *webView)
{
- g_return_val_if_fail(BROWSER_IS_WINDOW(window), 0);
+ g_return_if_fail(BROWSER_IS_WINDOW(window));
+ g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
- return window->webView;
+ if (window->activeTab && webkit_web_view_is_editable(browser_tab_get_web_view(window->activeTab))) {
+ g_warning("Only one tab is allowed in editable mode");
+ return;
+ }
+
+ GtkWidget *tab = browser_tab_new(webView);
+ browser_tab_add_accelerators(BROWSER_TAB(tab), window->accelGroup);
+ gtk_notebook_append_page(GTK_NOTEBOOK(window->notebook), tab, browser_tab_get_title_widget(BROWSER_TAB(tab)));
+ gtk_container_child_set(GTK_CONTAINER(window->notebook), tab, "tab-expand", TRUE, NULL);
+ gtk_widget_show(tab);
}
void browser_window_load_uri(BrowserWindow *window, const char *uri)
@@ -730,12 +1105,55 @@ void browser_window_load_uri(BrowserWindow *window, const char *uri)
g_return_if_fail(BROWSER_IS_WINDOW(window));
g_return_if_fail(uri);
- if (!g_str_has_prefix(uri, "javascript:")) {
- char *internalURI = getInternalURI(uri);
- webkit_web_view_load_uri(window->webView, internalURI);
- g_free(internalURI);
- return;
+ browser_tab_load_uri(window->activeTab, uri);
+}
+
+void browser_window_load_session(BrowserWindow *window, const char *sessionFile)
+{
+ g_return_if_fail(BROWSER_IS_WINDOW(window));
+ g_return_if_fail(sessionFile);
+
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ window->sessionFile = g_strdup(sessionFile);
+ gchar *data = NULL;
+ gsize dataLength;
+ if (g_file_get_contents(sessionFile, &data, &dataLength, NULL)) {
+ GBytes *bytes = g_bytes_new_take(data, dataLength);
+ WebKitWebViewSessionState *state = webkit_web_view_session_state_new(bytes);
+ g_bytes_unref(bytes);
+
+ if (state) {
+ webkit_web_view_restore_session_state(webView, state);
+ webkit_web_view_session_state_unref(state);
+ }
}
- webkit_web_view_run_javascript(window->webView, strstr(uri, "javascript:"), NULL, NULL, NULL);
+ WebKitBackForwardList *bfList = webkit_web_view_get_back_forward_list(webView);
+ WebKitBackForwardListItem *item = webkit_back_forward_list_get_current_item(bfList);
+ if (item)
+ webkit_web_view_go_to_back_forward_list_item(webView, item);
+ else
+ webkit_web_view_load_uri(webView, BROWSER_DEFAULT_URL);
+
+}
+
+void browser_window_set_background_color(BrowserWindow *window, GdkRGBA *rgba)
+{
+ g_return_if_fail(BROWSER_IS_WINDOW(window));
+ g_return_if_fail(rgba);
+
+ WebKitWebView *webView = browser_tab_get_web_view(window->activeTab);
+ GdkRGBA viewRGBA;
+ webkit_web_view_get_background_color(webView, &viewRGBA);
+ if (gdk_rgba_equal(rgba, &viewRGBA))
+ return;
+
+ GdkVisual *rgbaVisual = gdk_screen_get_rgba_visual(gtk_window_get_screen(GTK_WINDOW(window)));
+ if (!rgbaVisual)
+ return;
+
+ gtk_widget_set_visual(GTK_WIDGET(window), rgbaVisual);
+ gtk_widget_set_app_paintable(GTK_WIDGET(window), TRUE);
+
+ webkit_web_view_set_background_color(webView, rgba);
}