1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  *  Copyright © 2018 Purism SPC
4  *  Copyright © 2018 Adrien Plazas <kekun.plazas@laposte.net>
5  *
6  *  This file is part of Epiphany.
7  *
8  *  Epiphany is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  Epiphany is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with Epiphany.  If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "ephy-action-bar-start.h"
23 
24 #include "ephy-desktop-utils.h"
25 #include "ephy-embed.h"
26 #include "ephy-embed-container.h"
27 #include "ephy-embed-prefs.h"
28 #include "ephy-embed-utils.h"
29 #include "ephy-favicon-helpers.h"
30 #include "ephy-file-helpers.h"
31 #include "ephy-gui.h"
32 #include "ephy-settings.h"
33 #include "ephy-shell.h"
34 #include "ephy-window.h"
35 
36 /* Translators: tooltip for the refresh button */
37 static const char *REFRESH_BUTTON_TOOLTIP = N_("Reload the current page");
38 
39 struct _EphyActionBarStart {
40   GtkBox parent_instance;
41 
42   GtkWidget *navigation_box;
43   GtkWidget *navigation_back;
44   GtkWidget *navigation_forward;
45   GtkWidget *combined_stop_reload_button;
46   GtkWidget *combined_stop_reload_image;
47   GtkWidget *homepage_button;
48   GtkWidget *new_tab_button;
49   GtkWidget *placeholder;
50 
51   guint navigation_buttons_menu_timeout;
52 };
53 
54 G_DEFINE_TYPE (EphyActionBarStart, ephy_action_bar_start, GTK_TYPE_BOX)
55 
56 typedef enum {
57   EPHY_NAVIGATION_HISTORY_DIRECTION_BACK,
58   EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD
59 } EphyNavigationHistoryDirection;
60 
61 typedef enum {
62   WEBKIT_HISTORY_BACKWARD,
63   WEBKIT_HISTORY_FORWARD
64 } WebKitHistoryType;
65 
66 typedef struct {
67   GtkWidget *button;
68   EphyWindow *window;
69   EphyNavigationHistoryDirection direction;
70   GdkEventButton *event;
71 } PopupData;
72 
73 #define MAX_LABEL_LENGTH 48
74 #define HISTORY_ITEM_DATA_KEY "history-item-data-key"
75 
76 static gboolean
item_enter_notify_event_cb(GtkWidget * widget,GdkEvent * event,EphyWebView * view)77 item_enter_notify_event_cb (GtkWidget   *widget,
78                             GdkEvent    *event,
79                             EphyWebView *view)
80 {
81   char *text;
82 
83   text = g_object_get_data (G_OBJECT (widget), "link-message");
84   ephy_web_view_set_link_message (view, text);
85 
86   return GDK_EVENT_PROPAGATE;
87 }
88 
89 static gboolean
item_leave_notify_event_cb(GtkWidget * widget,GdkEvent * event,EphyWebView * view)90 item_leave_notify_event_cb (GtkWidget   *widget,
91                             GdkEvent    *event,
92                             EphyWebView *view)
93 {
94   ephy_web_view_set_link_message (view, NULL);
95   return GDK_EVENT_PROPAGATE;
96 }
97 
98 static void
icon_loaded_cb(GObject * source,GAsyncResult * result,GtkWidget * image)99 icon_loaded_cb (GObject      *source,
100                 GAsyncResult *result,
101                 GtkWidget    *image)
102 {
103   WebKitFaviconDatabase *database = WEBKIT_FAVICON_DATABASE (source);
104   GdkPixbuf *favicon = NULL;
105   cairo_surface_t *icon_surface = webkit_favicon_database_get_favicon_finish (database, result, NULL);
106 
107   if (icon_surface) {
108     gint scale = gtk_widget_get_scale_factor (image);
109 
110     favicon = ephy_pixbuf_get_from_surface_scaled (icon_surface, FAVICON_SIZE * scale, FAVICON_SIZE * scale);
111     cairo_surface_destroy (icon_surface);
112   }
113 
114   if (favicon)
115     gtk_image_set_from_gicon (GTK_IMAGE (image), G_ICON (favicon), GTK_ICON_SIZE_MENU);
116 
117   g_object_unref (image);
118 }
119 
120 static GtkWidget *
new_history_menu_item(EphyWebView * view,const char * origtext,const char * address)121 new_history_menu_item (EphyWebView *view,
122                        const char  *origtext,
123                        const char  *address)
124 {
125   GtkWidget *menu_item;
126   GtkWidget *box;
127   GtkWidget *image;
128   GtkWidget *label;
129   WebKitFaviconDatabase *database;
130   EphyEmbedShell *shell = ephy_embed_shell_get_default ();
131 
132   g_assert (address != NULL && origtext != NULL);
133 
134   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
135 
136   image = gtk_image_new ();
137   gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
138 
139   label = gtk_label_new (origtext);
140   gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
141   gtk_label_set_max_width_chars (GTK_LABEL (label), MAX_LABEL_LENGTH);
142   gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
143   gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 6);
144 
145   menu_item = gtk_menu_item_new ();
146   gtk_container_add (GTK_CONTAINER (menu_item), box);
147 
148   database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (shell));
149   webkit_favicon_database_get_favicon (database, address,
150                                        NULL,
151                                        (GAsyncReadyCallback)icon_loaded_cb,
152                                        g_object_ref (image));
153 
154   g_object_set_data_full (G_OBJECT (menu_item), "link-message", g_strdup (address), (GDestroyNotify)g_free);
155 
156   g_signal_connect (menu_item, "enter-notify-event",
157                     G_CALLBACK (item_enter_notify_event_cb), view);
158   g_signal_connect (menu_item, "leave-notify-event",
159                     G_CALLBACK (item_leave_notify_event_cb), view);
160 
161   gtk_widget_show_all (menu_item);
162 
163   return menu_item;
164 }
165 
166 static void
middle_click_handle_on_history_menu_item(EphyEmbed * embed,WebKitBackForwardListItem * item)167 middle_click_handle_on_history_menu_item (EphyEmbed                 *embed,
168                                           WebKitBackForwardListItem *item)
169 {
170   EphyEmbed *new_embed = NULL;
171   const gchar *url;
172 
173   new_embed = ephy_shell_new_tab (ephy_shell_get_default (),
174                                   EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (embed))),
175                                   embed,
176                                   0);
177   g_assert (new_embed != NULL);
178 
179   /* Load the new URL */
180   url = webkit_back_forward_list_item_get_original_uri (item);
181   ephy_web_view_load_url (ephy_embed_get_web_view (new_embed), url);
182 }
183 
184 static gboolean
navigation_menu_item_pressed_cb(GtkWidget * menuitem,GdkEvent * event,gpointer user_data)185 navigation_menu_item_pressed_cb (GtkWidget *menuitem,
186                                  GdkEvent  *event,
187                                  gpointer   user_data)
188 {
189   EphyWindow *window = EPHY_WINDOW (user_data);
190   WebKitBackForwardListItem *item;
191   EphyEmbed *embed;
192 
193   embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
194 
195   item = (WebKitBackForwardListItem *)g_object_get_data (G_OBJECT (menuitem), HISTORY_ITEM_DATA_KEY);
196 
197   if (((GdkEventButton *)event)->button == GDK_BUTTON_MIDDLE) {
198     middle_click_handle_on_history_menu_item (embed, item);
199   } else {
200     WebKitWebView *web_view;
201 
202     web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
203     webkit_web_view_go_to_back_forward_list_item (web_view, item);
204   }
205 
206   return GDK_EVENT_STOP;
207 }
208 
209 static GList *
construct_webkit_history_list(WebKitWebView * web_view,WebKitHistoryType hist_type,int limit)210 construct_webkit_history_list (WebKitWebView     *web_view,
211                                WebKitHistoryType  hist_type,
212                                int                limit)
213 {
214   WebKitBackForwardList *back_forward_list;
215 
216   back_forward_list = webkit_web_view_get_back_forward_list (web_view);
217   return hist_type == WEBKIT_HISTORY_FORWARD ?
218          g_list_reverse (webkit_back_forward_list_get_forward_list_with_limit (back_forward_list, limit)) :
219          webkit_back_forward_list_get_back_list_with_limit (back_forward_list, limit);
220 }
221 
222 static GtkWidget *
build_dropdown_menu(EphyWindow * window,EphyNavigationHistoryDirection direction)223 build_dropdown_menu (EphyWindow                     *window,
224                      EphyNavigationHistoryDirection  direction)
225 {
226   GtkMenuShell *menu;
227   EphyEmbed *embed;
228   GList *list, *l;
229   WebKitWebView *web_view;
230 
231   embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
232   g_assert (embed != NULL);
233 
234   menu = GTK_MENU_SHELL (gtk_menu_new ());
235 
236   web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
237 
238   if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK)
239     list = construct_webkit_history_list (web_view,
240                                           WEBKIT_HISTORY_BACKWARD, 10);
241   else
242     list = construct_webkit_history_list (web_view,
243                                           WEBKIT_HISTORY_FORWARD, 10);
244 
245   for (l = list; l != NULL; l = l->next) {
246     GtkWidget *item;
247     WebKitBackForwardListItem *hitem;
248     const char *uri;
249     char *title;
250 
251     hitem = (WebKitBackForwardListItem *)l->data;
252     uri = webkit_back_forward_list_item_get_uri (hitem);
253     title = g_strdup (webkit_back_forward_list_item_get_title (hitem));
254 
255     if (title == NULL || g_strstrip (title)[0] == '\0')
256       item = new_history_menu_item (EPHY_WEB_VIEW (web_view), uri, uri);
257     else
258       item = new_history_menu_item (EPHY_WEB_VIEW (web_view), title, uri);
259 
260     g_free (title);
261 
262     g_object_set_data_full (G_OBJECT (item), HISTORY_ITEM_DATA_KEY,
263                             g_object_ref (hitem), g_object_unref);
264 
265     g_signal_connect (item, "button-release-event",
266                       G_CALLBACK (navigation_menu_item_pressed_cb), window);
267 
268     gtk_menu_shell_append (menu, item);
269     gtk_widget_show_all (item);
270   }
271 
272   g_list_free (list);
273 
274   return GTK_WIDGET (menu);
275 }
276 
277 static void
popup_history_menu(GtkWidget * widget,EphyWindow * window,EphyNavigationHistoryDirection direction,GdkEventButton * event)278 popup_history_menu (GtkWidget                      *widget,
279                     EphyWindow                     *window,
280                     EphyNavigationHistoryDirection  direction,
281                     GdkEventButton                 *event)
282 {
283   GtkWidget *menu;
284 
285   menu = build_dropdown_menu (window, direction);
286   gtk_menu_popup_at_widget (GTK_MENU (menu),
287                             widget,
288                             GDK_GRAVITY_SOUTH_WEST,
289                             GDK_GRAVITY_NORTH_WEST,
290                             (GdkEvent *)event);
291 }
292 
293 static gboolean
menu_timeout_cb(PopupData * data)294 menu_timeout_cb (PopupData *data)
295 {
296   if (data != NULL && data->window)
297     popup_history_menu (data->button, data->window, data->direction, data->event);
298 
299   return G_SOURCE_REMOVE;
300 }
301 
302 static gboolean
navigation_button_press_event_cb(GtkButton * button,GdkEvent * event,gpointer user_data)303 navigation_button_press_event_cb (GtkButton *button,
304                                   GdkEvent  *event,
305                                   gpointer   user_data)
306 {
307   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
308   EphyNavigationHistoryDirection direction;
309   PopupData *data;
310   gboolean is_back = FALSE;
311 
312   is_back = (GTK_WIDGET (button) == action_bar_start->navigation_back);
313 
314   direction = is_back ? EPHY_NAVIGATION_HISTORY_DIRECTION_BACK
315                       : EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD;
316 
317   switch (((GdkEventButton *)event)->button) {
318     case GDK_BUTTON_SECONDARY:
319       popup_history_menu (GTK_WIDGET (button), EPHY_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW)),
320                           direction, (GdkEventButton *)event);
321       return GDK_EVENT_STOP;
322     case GDK_BUTTON_MIDDLE:
323       /* If a desktop-wide middle-click titlebar action is enabled, we want to
324        * prevent that action from occurring because we handle middle click in
325        * navigation_button_release_event_cb().
326        */
327       return GDK_EVENT_STOP;
328     default:
329       break;
330   }
331 
332   data = g_new (PopupData, 1);
333   data->button = GTK_WIDGET (button);
334   data->window = EPHY_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW));
335   data->direction = direction;
336   data->event = (GdkEventButton *)event;
337 
338   action_bar_start->navigation_buttons_menu_timeout = g_timeout_add_full (G_PRIORITY_DEFAULT, 500,
339                                                                           (GSourceFunc)menu_timeout_cb,
340                                                                           data,
341                                                                           (GDestroyNotify)g_free);
342   g_source_set_name_by_id (action_bar_start->navigation_buttons_menu_timeout, "[epiphany] menu_timeout_cb");
343 
344   return GDK_EVENT_PROPAGATE;
345 }
346 
347 static gboolean
navigation_button_release_event_cb(GtkButton * button,GdkEvent * event,gpointer user_data)348 navigation_button_release_event_cb (GtkButton *button,
349                                     GdkEvent  *event,
350                                     gpointer   user_data)
351 {
352   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
353   GActionGroup *action_group;
354   GAction *action;
355   EphyNavigationHistoryDirection direction;
356   gboolean is_back = FALSE;
357   gboolean open_in_new_tab = FALSE;
358   gboolean open_in_current_tab = FALSE;
359   GdkEventType type = GDK_NOTHING;
360   guint state = 0, button_val = (guint) - 1, keyval = (guint) - 1;
361 
362   ephy_gui_get_current_event (&type, &state, &button_val, &keyval);
363   is_back = (GTK_WIDGET (button) == action_bar_start->navigation_back);
364 
365   g_clear_handle_id (&action_bar_start->navigation_buttons_menu_timeout, g_source_remove);
366 
367   action_group = gtk_widget_get_action_group (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW), "toolbar");
368 
369   direction = is_back ? EPHY_NAVIGATION_HISTORY_DIRECTION_BACK
370                       : EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD;
371 
372   open_in_new_tab = (((GdkEventButton *)event)->button == GDK_BUTTON_MIDDLE) || (state == GDK_CONTROL_MASK);
373   open_in_current_tab = ((GdkEventButton *)event)->button == GDK_BUTTON_PRIMARY;
374 
375   if (open_in_new_tab) {
376     if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK) {
377       action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
378                                            "navigation-back-new-tab");
379       g_action_activate (action, NULL);
380     } else if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD) {
381       action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
382                                            "navigation-forward-new-tab");
383       g_action_activate (action, NULL);
384     }
385 
386     /* Don't propagate the event to avoid other middle-click actions. */
387     return GDK_EVENT_STOP;
388   }
389 
390   if (open_in_current_tab) {
391     if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_BACK) {
392       action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
393                                            "navigation-back");
394       g_action_activate (action, NULL);
395     } else if (direction == EPHY_NAVIGATION_HISTORY_DIRECTION_FORWARD) {
396       action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
397                                            "navigation-forward");
398       g_action_activate (action, NULL);
399     }
400 
401     /* Propagate the event to allow the button to correctly reset its internal
402      * state. */
403     return GDK_EVENT_PROPAGATE;
404   }
405 
406   /* Propagate other unhandled events. */
407   return GDK_EVENT_PROPAGATE;
408 }
409 
410 static gboolean
homepage_button_release_event_cb(GtkButton * button,GdkEvent * event,gpointer user_data)411 homepage_button_release_event_cb (GtkButton *button,
412                                   GdkEvent  *event,
413                                   gpointer   user_data)
414 {
415   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
416   GActionGroup *action_group;
417   GAction *action;
418 
419   action_group = gtk_widget_get_action_group (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW), "toolbar");
420 
421   switch (((GdkEventButton *)event)->button) {
422     case GDK_BUTTON_MIDDLE:
423       action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "homepage-new-tab");
424       g_action_activate (action, NULL);
425       return GDK_EVENT_STOP;
426     default:
427       break;
428   }
429 
430   return GDK_EVENT_PROPAGATE;
431 }
432 
433 static gboolean
new_tab_button_release_event_cb(GtkButton * button,GdkEvent * event,gpointer user_data)434 new_tab_button_release_event_cb (GtkButton *button,
435                                  GdkEvent  *event,
436                                  gpointer   user_data)
437 {
438   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
439   GActionGroup *action_group;
440   GAction *action;
441 
442   action_group = gtk_widget_get_action_group (gtk_widget_get_ancestor (GTK_WIDGET (action_bar_start), EPHY_TYPE_WINDOW), "toolbar");
443 
444   switch (((GdkEventButton *)event)->button) {
445     case GDK_BUTTON_MIDDLE:
446       action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "new-tab-from-clipboard");
447       g_action_activate (action, NULL);
448       return GDK_EVENT_STOP;
449     default:
450       break;
451   }
452 
453   return GDK_EVENT_PROPAGATE;
454 }
455 
456 static gboolean
navigation_leave_notify_event_cb(GtkButton * button,GdkEvent * event,gpointer user_data)457 navigation_leave_notify_event_cb (GtkButton *button,
458                                   GdkEvent  *event,
459                                   gpointer   user_data)
460 {
461   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (user_data);
462 
463   g_clear_handle_id (&action_bar_start->navigation_buttons_menu_timeout, g_source_remove);
464 
465   return GDK_EVENT_PROPAGATE;
466 }
467 
468 static void
homepage_url_changed(GSettings * settings,const char * key,GtkWidget * button)469 homepage_url_changed (GSettings  *settings,
470                       const char *key,
471                       GtkWidget  *button)
472 {
473   char *setting;
474   gboolean show_button;
475 
476   setting = g_settings_get_string (settings, key);
477   if (setting && setting[0])
478     show_button = g_strcmp0 (setting, "about:blank") != 0;
479   else
480     show_button = is_desktop_pantheon ();
481 
482   gtk_widget_set_visible (button, show_button);
483   g_free (setting);
484 }
485 
486 static void
ephy_action_bar_start_dispose(GObject * object)487 ephy_action_bar_start_dispose (GObject *object)
488 {
489   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (object);
490 
491   g_clear_handle_id (&action_bar_start->navigation_buttons_menu_timeout, g_source_remove);
492 
493   G_OBJECT_CLASS (ephy_action_bar_start_parent_class)->dispose (object);
494 }
495 
496 static void
update_new_tab_button_visibility(EphyActionBarStart * action_bar_start)497 update_new_tab_button_visibility (EphyActionBarStart *action_bar_start)
498 {
499   EphyEmbedShell *embed_shell;
500 
501   embed_shell = ephy_embed_shell_get_default ();
502 
503   gtk_widget_set_visible (action_bar_start->new_tab_button,
504                           (ephy_embed_shell_get_mode (embed_shell) != EPHY_EMBED_SHELL_MODE_APPLICATION) &&
505                           !is_desktop_pantheon ());
506 }
507 
508 static void
ephy_action_bar_start_constructed(GObject * object)509 ephy_action_bar_start_constructed (GObject *object)
510 {
511   EphyActionBarStart *action_bar_start = EPHY_ACTION_BAR_START (object);
512   EphyEmbedShell *embed_shell;
513 
514   G_OBJECT_CLASS (ephy_action_bar_start_parent_class)->constructed (object);
515 
516   gtk_widget_init_template (GTK_WIDGET (action_bar_start));
517 
518   /* Back */
519   g_signal_connect (action_bar_start->navigation_back, "button-press-event",
520                     G_CALLBACK (navigation_button_press_event_cb), action_bar_start);
521   g_signal_connect (action_bar_start->navigation_back, "button-release-event",
522                     G_CALLBACK (navigation_button_release_event_cb), action_bar_start);
523   g_signal_connect (action_bar_start->navigation_back, "leave-notify-event",
524                     G_CALLBACK (navigation_leave_notify_event_cb), action_bar_start);
525 
526   /* Forward */
527   g_signal_connect (action_bar_start->navigation_forward, "button-press-event",
528                     G_CALLBACK (navigation_button_press_event_cb), action_bar_start);
529   g_signal_connect (action_bar_start->navigation_forward, "button-release-event",
530                     G_CALLBACK (navigation_button_release_event_cb), action_bar_start);
531   g_signal_connect (action_bar_start->navigation_forward, "leave-notify-event",
532                     G_CALLBACK (navigation_leave_notify_event_cb), action_bar_start);
533 
534   /* Combined_stop_reload */
535   gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button, _(REFRESH_BUTTON_TOOLTIP));
536 
537   /* Homepage */
538   embed_shell = ephy_embed_shell_get_default ();
539   if (ephy_embed_shell_get_mode (embed_shell) != EPHY_EMBED_SHELL_MODE_APPLICATION) {
540     homepage_url_changed (EPHY_SETTINGS_MAIN, EPHY_PREFS_HOMEPAGE_URL, action_bar_start->homepage_button);
541     g_signal_connect_object (EPHY_SETTINGS_MAIN,
542                              "changed::" EPHY_PREFS_HOMEPAGE_URL,
543                              G_CALLBACK (homepage_url_changed),
544                              action_bar_start->homepage_button,
545                              0);
546   } else {
547     gtk_widget_set_visible (action_bar_start->homepage_button, FALSE);
548   }
549   g_signal_connect (action_bar_start->homepage_button, "button-release-event",
550                     G_CALLBACK (homepage_button_release_event_cb), action_bar_start);
551 
552   /* New Tab Button */
553   update_new_tab_button_visibility (action_bar_start);
554 
555   g_signal_connect (action_bar_start->new_tab_button, "button-release-event",
556                     G_CALLBACK (new_tab_button_release_event_cb), action_bar_start);
557 
558   if (is_desktop_pantheon ()) {
559     gtk_button_set_image (GTK_BUTTON (action_bar_start->navigation_back),
560                           gtk_image_new_from_icon_name ("go-previous-symbolic",
561                                                         get_icon_size ()));
562     gtk_button_set_image (GTK_BUTTON (action_bar_start->navigation_forward),
563                           gtk_image_new_from_icon_name ("go-next-symbolic",
564                                                         get_icon_size ()));
565     gtk_button_set_image (GTK_BUTTON (action_bar_start->homepage_button),
566                           gtk_image_new_from_icon_name ("go-home-symbolic",
567                                                         get_icon_size ()));
568   }
569 
570   if (ephy_profile_dir_is_web_application ()) {
571     GtkWidget *navigation_box = ephy_action_bar_start_get_navigation_box (action_bar_start);
572 
573     g_settings_bind (EPHY_SETTINGS_WEB_APP, EPHY_PREFS_WEB_APP_SHOW_NAVIGATION_BUTTONS, navigation_box, "visible", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN);
574   }
575 }
576 
577 static void
ephy_action_bar_start_class_init(EphyActionBarStartClass * klass)578 ephy_action_bar_start_class_init (EphyActionBarStartClass *klass)
579 {
580   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
581   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
582 
583   gobject_class->dispose = ephy_action_bar_start_dispose;
584   gobject_class->constructed = ephy_action_bar_start_constructed;
585 
586   gtk_widget_class_set_template_from_resource (widget_class,
587                                                "/org/gnome/epiphany/gtk/action-bar-start.ui");
588 
589   gtk_widget_class_bind_template_child (widget_class,
590                                         EphyActionBarStart,
591                                         navigation_box);
592   gtk_widget_class_bind_template_child (widget_class,
593                                         EphyActionBarStart,
594                                         navigation_back);
595   gtk_widget_class_bind_template_child (widget_class,
596                                         EphyActionBarStart,
597                                         navigation_forward);
598   gtk_widget_class_bind_template_child (widget_class,
599                                         EphyActionBarStart,
600                                         combined_stop_reload_button);
601   gtk_widget_class_bind_template_child (widget_class,
602                                         EphyActionBarStart,
603                                         combined_stop_reload_image);
604   gtk_widget_class_bind_template_child (widget_class,
605                                         EphyActionBarStart,
606                                         homepage_button);
607   gtk_widget_class_bind_template_child (widget_class,
608                                         EphyActionBarStart,
609                                         new_tab_button);
610   gtk_widget_class_bind_template_child (widget_class,
611                                         EphyActionBarStart,
612                                         placeholder);
613 }
614 
615 static void
ephy_action_bar_start_init(EphyActionBarStart * action_bar_start)616 ephy_action_bar_start_init (EphyActionBarStart *action_bar_start)
617 {
618 }
619 
620 EphyActionBarStart *
ephy_action_bar_start_new(void)621 ephy_action_bar_start_new (void)
622 {
623   return g_object_new (EPHY_TYPE_ACTION_BAR_START,
624                        NULL);
625 }
626 
627 GtkWidget *
ephy_action_bar_start_get_navigation_box(EphyActionBarStart * action_bar_start)628 ephy_action_bar_start_get_navigation_box (EphyActionBarStart *action_bar_start)
629 {
630   return action_bar_start->navigation_box;
631 }
632 
633 void
ephy_action_bar_start_change_combined_stop_reload_state(EphyActionBarStart * action_bar_start,gboolean loading)634 ephy_action_bar_start_change_combined_stop_reload_state (EphyActionBarStart *action_bar_start,
635                                                          gboolean            loading)
636 {
637   if (loading) {
638     gtk_image_set_from_icon_name (GTK_IMAGE (action_bar_start->combined_stop_reload_image),
639                                   "process-stop-symbolic",
640                                   get_icon_size ());
641     /* Translators: tooltip for the stop button */
642     gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button,
643                                  _("Stop loading the current page"));
644   } else {
645     gtk_image_set_from_icon_name (GTK_IMAGE (action_bar_start->combined_stop_reload_image),
646                                   "view-refresh-symbolic",
647                                   get_icon_size ());
648     gtk_widget_set_tooltip_text (action_bar_start->combined_stop_reload_button,
649                                  _(REFRESH_BUTTON_TOOLTIP));
650   }
651 }
652 
653 GtkWidget *
ephy_action_bar_start_get_placeholder(EphyActionBarStart * action_bar_start)654 ephy_action_bar_start_get_placeholder (EphyActionBarStart *action_bar_start)
655 {
656   return action_bar_start->placeholder;
657 }
658 
659 void
ephy_action_bar_start_set_adaptive_mode(EphyActionBarStart * action_bar,EphyAdaptiveMode adaptive_mode)660 ephy_action_bar_start_set_adaptive_mode (EphyActionBarStart *action_bar,
661                                          EphyAdaptiveMode    adaptive_mode)
662 {
663   GValue val = G_VALUE_INIT;
664 
665   g_value_init (&val, G_TYPE_INT);
666 
667   gtk_widget_set_visible (action_bar->new_tab_button, adaptive_mode == EPHY_ADAPTIVE_MODE_NORMAL);
668   gtk_widget_set_visible (action_bar->combined_stop_reload_button, adaptive_mode == EPHY_ADAPTIVE_MODE_NORMAL);
669 
670   if (adaptive_mode == EPHY_ADAPTIVE_MODE_NARROW)
671     g_value_set_int (&val, 42);
672   else
673     g_value_set_int (&val, -1);
674 
675   g_object_set_property (G_OBJECT (action_bar->navigation_back), "width-request", &val);
676   g_object_set_property (G_OBJECT (action_bar->navigation_forward), "width-request", &val);
677 
678   g_value_unset (&val);
679 }
680