~midori/midori/gtk3WebKit2only

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
/*
 Copyright (C) 2013 Christian Dywan <christian@twotoasts.de>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 See the file COPYING for the full license text.
*/

namespace Katze {
    enum MenuPos {
        CURSOR,
        LEFT,
        RIGHT
    }
    extern static void widget_popup (Gtk.Widget? widget, Gtk.Menu menu, Gdk.EventButton? event, MenuPos pos);
}

namespace Midori {
    public class MenuButtonAction : Gtk.Action {
        public Midori.Tab? tab { get; set; }
        public bool menu_on_left_click { get; set; }
        Gtk.ToolButton? toolitem = null;
        public signal string? middle_click_uri ();
        public signal Gtk.Menu? context_menu ();

        public override unowned Gtk.Widget create_tool_item () {
            toolitem = menu_on_left_click ? new Gtk.ToggleToolButton () : new Gtk.ToolButton (null, null);
            toolitem.icon_widget = create_icon (Gtk.IconSize.LARGE_TOOLBAR);
            bind_property ("label", toolitem, "label");
            bind_property ("tooltip", toolitem, "tooltip-text");
            bind_property ("is-important", toolitem, "is-important");
            // Connect to child because ToolItem blocks button-press-event
            toolitem.get_child ().button_press_event.connect ((event)=> {
                // Ctrl+click or middle click
                string? uri = event.button == 2
                 || (event.button == 1 && (bool)(event.state & Gdk.ModifierType.CONTROL_MASK))
                 ? middle_click_uri () : null;
                if (uri != null) {
                    // TODO: Copy all history to the new tab
                    var settings = tab.web_view.get_settings () as Midori.Settings;
                    Signal.emit_by_name (tab, "new-tab", uri, settings.open_tabs_in_the_background);
                    return true;
                }
                Gtk.Menu? menu = event.button == 3 || menu_on_left_click ? context_menu () : null;
                if (menu != null) {
                    Katze.widget_popup (toolitem, menu, event, Katze.MenuPos.LEFT);
                    menu.select_first (true);
                    menu.deactivate.connect (()=>{
                        block_activate ();
                        if (menu_on_left_click)
                            (toolitem as Gtk.ToggleToolButton).active = false;
                        unblock_activate ();
                    });
                    return true;
                }
                return false;
            });
            return toolitem;
        }

    }

    /* Back or forward action, with a submenu
       Since: 0.6.0 */
    public class NavigationAction : MenuButtonAction {
        protected string uri { get; set; }
        Binding uri_binding;

        construct {
            notify["tab"].connect(tab_changed);
        }
        void tab_changed (ParamSpec pspec) {
            uri_binding = tab.bind_property ("uri", this, "uri", 0);
        }

        protected bool can_go_next () {
            /* TODO */
            return false;
        }

        protected void go_next () {
            /* TODO */
        }

        protected void go_next_or_forward () {
            if (tab.web_view.can_go_forward ())
                tab.web_view.go_forward ();
            else
                go_next ();
        }

        protected bool can_go_previous () {
            /* TODO */
            return false;
        }

        protected void go_previous () {
            /* TODO */
        }

        GLib.Icon? scale_if_needed (GLib.Icon? icon) {
            if (icon is Gdk.Pixbuf) {
                var pixbuf = icon as Gdk.Pixbuf;
                int icon_width = 16, icon_height = 16;
                Gtk.icon_size_lookup (Gtk.IconSize.MENU, out icon_width, out icon_height);
                if (pixbuf.width > icon_width || pixbuf.height > icon_height)
                    return pixbuf.scale_simple (icon_width, icon_height, Gdk.InterpType.BILINEAR);
            }
            return icon;
        }

        protected Gtk.Menu? build_menu (List<weak WebKit.BackForwardListItem> items) {
            var menu = new Gtk.Menu ();
            foreach (var item in items) {
                var menuitem = new Gtk.ImageMenuItem.with_label (item.get_title ());
                var icon = new Midori.URI.Icon (item.get_uri ());
                menuitem.image = new Gtk.Image.from_gicon (scale_if_needed (icon), Gtk.IconSize.MENU);
                menuitem.always_show_image = true;
                menuitem.show_all ();
                menuitem.activate.connect (()=>{ tab.web_view.load_uri (item.get_uri ()); });
                menu.append (menuitem);
            }
            return menu;
        }
    }

    public class BackAction : NavigationAction {
        public BackAction () {
            GLib.Object (name: "Back",
                         tooltip: _("Go back to the previous page"),
                         stock_id: Gtk.Stock.GO_BACK,
                         is_important: true);
        }

        construct {
            bind_property ("uri", this, "sensitive", 0,
                (binding, source, ref target)=>{ target = tab.web_view.can_go_back (); return true; });
            activate.connect (()=> { tab.web_view.go_back (); });
            middle_click_uri.connect (()=> { return tab.web_view.get_back_forward_list ().get_back_item ().get_uri (); });
            context_menu.connect (()=> { return build_menu (tab.web_view.get_back_forward_list ().get_back_list_with_limit (10)); });
        }
    }

    public class PreviousAction : NavigationAction {
        public PreviousAction () {
            GLib.Object (name: "Previous",
                         /* i18n: Visit the previous logical page, ie. in a forum or blog */
                         tooltip: _("Go to the previous sub-page"),
                         stock_id: Gtk.Stock.MEDIA_PREVIOUS);
        }

        construct {
            bind_property ("uri", this, "sensitive", 0,
                (binding, source, ref target)=>{ target = can_go_previous (); return true; });
            activate.connect (()=> { go_previous (); });
            context_menu.connect (()=> { return build_menu (tab.web_view.get_back_forward_list ().get_back_list_with_limit (10)); });
        }
    }

    public class ForwardAction : NavigationAction {
        public ForwardAction () {
            GLib.Object (name: "Forward",
                         tooltip: _("Go forward to the next page"),
                         stock_id: Gtk.Stock.GO_FORWARD);
        }

        construct {
            bind_property ("uri", this, "sensitive", 0,
                (binding, source, ref target)=>{ target = tab.web_view.can_go_forward (); return true; });
            activate.connect (()=> { tab.web_view.go_forward (); });
            middle_click_uri.connect (()=> { return tab.web_view.get_back_forward_list ().get_forward_item ().get_uri (); });
            context_menu.connect (()=> { return build_menu (tab.web_view.get_back_forward_list ().get_forward_list_with_limit (10)); });
        }
    }

    public class NextAction : NavigationAction {
        public NextAction () {
            GLib.Object (name: "Next",
                         /* i18n: Visit the following logical page, ie. in a forum or blog */
                         tooltip: _("Go to the next sub-page"),
                         stock_id: Gtk.Stock.MEDIA_NEXT);
        }

        construct {
            bind_property ("uri", this, "sensitive", 0,
                (binding, source, ref target)=>{ target = can_go_next (); return true; });
            activate.connect (()=> { go_next (); });
            context_menu.connect (()=> { return build_menu (tab.web_view.get_back_forward_list ().get_forward_list_with_limit (10)); });
        }
    }

    public class NextForwardAction : NavigationAction {
        public NextForwardAction () {
            GLib.Object (name: "NextForward",
                         label: _("Next or Forward"));
        }

        construct {
            bind_property ("uri", this, "sensitive", 0,
                (binding, source, ref target)=>{ target = (tab.web_view.can_go_forward () || can_go_next ()); return true; });
            bind_property ("uri", this, "stock-id", 0,
                (binding, source, ref target)=>{ target = (can_go_next () ? Gtk.Stock.GO_FORWARD : Gtk.Stock.MEDIA_NEXT); return true; });
            bind_property ("uri", this, "tooltip", 0,
                (binding, source, ref target)=>{ target = (can_go_next () ? _("Go forward to the next page") : _("Go to the next sub-page")); return true; });
            activate.connect (()=> { go_next_or_forward (); });
            context_menu.connect (()=> { return build_menu (tab.web_view.get_back_forward_list ().get_forward_list_with_limit (10)); });
        }
   }

    public class HomepageAction : NavigationAction {
        public HomepageAction () {
            GLib.Object (name: "Homepage",
                         label: _("_Homepage"),
                         tooltip: _("Go to your homepage"),
                         stock_id: Gtk.Stock.HOME);
            activate.connect (()=> { tab.web_view.load_uri ("about:home"); });
            middle_click_uri.connect (()=> { return "about:home"; });
        }
    }

    public class ReloadAction : NavigationAction {
        public ReloadAction () {
            GLib.Object (name: "Reload",
                         tooltip: _("Reload the current page"),
                         stock_id: Gtk.Stock.REFRESH);
            activate.connect (()=> {
                tab.web_view.reload ();
                // tab.web_view.reload_bypass_cache ();
            });
            middle_click_uri.connect (()=> { return tab.uri; });
            // TODO: Update icon/ label, track loading
        }
    }
}