Xfce Wiki

Sub domains
 
no way to compare when less than two revisions

Differences

This shows you the differences between two versions of the page.


Previous revision
Next revision
midori:tutorial [2014/01/24 22:58] kalikiana
Line 1: Line 1:
 +====== Midori - Tutorial ======
  
 +**This document is licensed under the LGPL 2.1.**
 +
 +===== Writing a new extension =====
 +
 +====== Check out the sources ======
 +
 +<code bash>bzr branch lp:midori</code>
 +
 +To develop and build extensions you need a source tree, typically it is a good idea to use the latest trunk to benefit from the latest and greatest features or bug fixes. So if your extension uncovers a bug you can easily report it and get it fixed.
 +For more details see [[contribute]] which also covers how to make a branch and codying style in detail.
 +
 +====== Add a new extension =====
 +
 +The minimum starting point is a new .vala file in ./extensions/ in the Midori source folder. Let's call it "sandcat.vala" for the course of the tutorial.
 +
 +The code to start with is this:
 +<code vala>
 +namespace Sandcat {
 +    private class Manager : Midori.Extension {
 +
 +    internal Manager () {
 +        GLib.Object (name: _("Furry example extension"),
 +                         description: _("Take care of petting cats"),
 +                         version: "0.1" + Midori.VERSION_SUFFIX,
 +                         authors: "Jane Doe <email@domain.tld>");
 +    }
 +}
 + 
 +public Midori.Extension extension_init () {                                                                                                                    
 +    return new Sandcat.Manager ();
 +}
 +</code>
 +
 +Now let's proceed to run our rather empty extension.
 +
 +<code bash>user@host:~/midori/build$ make
 +user@host:~/midori/build$ ./midori/midori -g -c ~/midoridevel</code>
 +
 +Inside Midori, open the Preferences, go to Extensions, and look for your new extension in the list. Activate and be proud of completing the first part of the tutorial!
 +====== Activating the extension ======
 +
 +A basic principle is that each extension is loaded at first to describe what it does and to be shown in the preferences. At that point it doesn't do anything yet. Let's add basic callbacks to trigger after activation.
 +
 +<code vala>
 +void browser_added (Midori.Browser browser) {
 +    stdout.printf ("a new browser was added, yay\n");
 +}
 +
 +void activated (Midori.App app) {
 +    foreach (var browser in app.get_browsers ())
 +        browser_added (browser);
 +    app.add_browser.connect (browser_added);
 +}
 +
 +void deactivated () {
 +    var app = get_app ();
 +    app.add_browser.disconnect (browser_added);
 +}
 +</code>
 +
 +In your Manager you connect these new callbacks:
 +
 +<code vala>
 +this.activate.connect (activated);
 +this.deactivate.connect (deactivated);
 +</code>
 +
 +You'll see how when activated the extension gets an "app" which is a running Midori instance. It has among other things knowledge of browser windows. It's good practise to not make any assumptions on how many windows are open.
 +
 +====== Working with (web) views =====
 +
 +<code vala>
 +    void tab_added (Midori.Browser browser, Midori.Tab tab) {
 +        var view = tab as Midori.View;
 +        string uri = tab.uri;
 +        string title = tab.title;
 +    }
 +
 +    // in browser_added
 +        foreach (var tab in browser.get_tabs ())
 +                tab_added (browser, tab);
 +        browser.add_tab.connect (tab_added);
 +
 +    // in destroyed
 +        foreach (var tab in browser.get_tabs ())
 +            browser.add_tab_disconnect (tab_added);
 +</code>
 +
 +====== Add a context menu item ======
 +
 +<code vala>
 +    // in tab_added
 +    tab.context_menu.connect (add_menu_items);
 +
 +    void add_menu_items (WebKit.HitTestResult hit_test_result, Midori.ContextAction menu) {
 +        if ((hit_test_result.context & WebKit.HitTestResultContext.SELECTION) == 0)
 +            return;
 +
 +        var action = new Gtk.Action ("NotesCopySnippet", "Copy _snippet to notes", null, null);
 +        action.activate.connect (() => {
 +            stdout.printf ("my menu item rocks\n");
 +        });
 +        menu.add (action);
 +        var submenu = new Midori.ContextAction ("NotesPaste", "Paste N_otes", null, null);
 +        for (int i = 0; i < 10; i++) {
 +            submenu.add (new Gtk.Action ("NotesSnippet%d".format (i), "Snippet #%i".format (i), null, null);
 +        }
 +        menu.add (submenu);
 +    }
 +</code>
 +
 +====== Add an app menu item ======
 +
 +whatever
 +
 +====== Modify resources or webpages loaded ======
 +
 +whatever
 +
 +====== Add a statusbar item ======
 +
 +<code vala>
 +    // in browser_added
 +    var button = new Gtk.Button.with_label ("Click Here!");
 +    browser.statusbar.pack_start (button, false, false, 3);
 +    button.show ();
 +</code>
 +
 +====== Add a panel ======
 +
 +<code vala>
 +// in private class Manager : Midori.Extension
 +GLib.List<Gtk.Widget> widgets; 
 +
 +// in deactivated
 +    foreach (var widget in widgets)
 +        widget.destroy ();
 +
 +// in activated
 +    widgets = new GLib.List<Gtk.Widget> ();
 +
 +// in browser_added
 +    var viewable = new Sidebar ();
 +    viewable.show ();
 +    browser.panel.append_page (viewable);
 +    widgets.append (viewable);
 +</code>
 +
 +Now on to adding a class implementing that panel.
 +
 +<code vala>
 +private class Sidebar : Gtk.VBox, Midori.Viewable {
 +    public unowned string get_stock_id () {
 +        return "a-stock-id";
 +    }
 +
 +    public unowned string get_label () {
 +        return _("Purrfect");
 +    }
 +
 +    public Gtk.Widget get_toolbar () {
 +        return null;
 +    }
 +
 +    public Sidebar () {
 +    }
 +}
 +</code>
 +====== Add a dialog ======
 +
 +whatever
 +
 +====== Add a URL completion ======
 +
 +whatever