summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Dywan <christian@twotoasts.de>2018-08-22 01:07:25 +0200
committerGitHub <noreply@github.com>2018-08-22 01:07:25 +0200
commit57fa97773fc1f708fe572e8ed9fd9bf7a2c8f740 (patch)
treee91b68b392f514105ac17a4e070bad138746d0da
parentb363061ac6406e6b7f99cec1809531719d015aa5 (diff)
downloadmidori-git-57fa97773fc1f708fe572e8ed9fd9bf7a2c8f740.tar.gz
Implement speed dial based on recent history (#15)
![screenshot from 2018-08-18 20-45-09](https://user-images.githubusercontent.com/1204189/44302400-03a58a80-a328-11e8-8c4f-88be485e7920.png) The speed dial is implemented as an "internal" scheme handler, which won't require special-casing on the UX side except using "internal:speed-dial" as a default URI in Midori.Tab and recognizing it as "empty" in Midori.Urlbar. All items are populated automatically from the history and use favicons.
-rw-r--r--core/app.vala99
-rw-r--r--core/tab.vala4
-rw-r--r--core/urlbar.vala4
-rw-r--r--data/about.css50
-rw-r--r--data/speed-dial.html24
-rw-r--r--gresource.xml1
6 files changed, 163 insertions, 19 deletions
diff --git a/core/app.vala b/core/app.vala
index 1fdd4d48..2c0e3b35 100644
--- a/core/app.vala
+++ b/core/app.vala
@@ -60,22 +60,17 @@ namespace Midori {
Gtk.Window.set_default_icon_name (Config.PROJECT_NAME);
var context = WebKit.WebContext.get_default ();
+ context.register_uri_scheme ("internal", (request) => {
+ request.ref ();
+ internal_scheme.begin (request);
+ });
+ context.register_uri_scheme ("favicon", (request) => {
+ request.ref ();
+ favicon_scheme.begin (request);
+ });
context.register_uri_scheme ("stock", (request) => {
- string icon_name = request.get_path ().substring (1, -1);
- int icon_size = 48;
- Gtk.icon_size_lookup ((Gtk.IconSize)Gtk.IconSize.DIALOG, out icon_size, null);
- try {
- var icon = Gtk.IconTheme.get_default ().load_icon (icon_name, icon_size, Gtk.IconLookupFlags.FORCE_SYMBOLIC);
- var output = new MemoryOutputStream (null, realloc, free);
- icon.save_to_stream (output, "png");
- output.close ();
- uint8[] data = output.steal_data ();
- data.length = (int)output.get_data_size ();
- var stream = new MemoryInputStream.from_data (data, free);
- request.finish (stream, -1, null);
- } catch (Error error) {
- critical ("Failed to load icon %s: %s", icon_name, error.message);
- }
+ request.ref ();
+ stock_scheme.begin (request);
});
context.register_uri_scheme ("res", (request) => {
try {
@@ -83,6 +78,7 @@ namespace Midori {
ResourceLookupFlags.NONE);
request.finish (stream, -1, null);
} catch (Error error) {
+ request.finish_error (error);
critical ("Failed to load resource %s: %s", request.get_uri (), error.message);
}
});
@@ -119,6 +115,79 @@ namespace Midori {
}
}
+ async void internal_scheme (WebKit.URISchemeRequest request) {
+ try {
+ var shortcuts = yield HistoryDatabase.get_default ().query (null, 9);
+ string content = "";
+ uint index = 0;
+ foreach (var shortcut in shortcuts) {
+ index++;
+ content += """
+ <div class="shortcut">
+ <a href="%s" accesskey="%u">
+ <img src="%s" />
+ <span class="title">%s</span>
+ </a>
+ </div>""".printf (shortcut.uri, index, "favicon:///" + shortcut.uri, shortcut.title);
+ }
+ string stylesheet = (string)resources_lookup_data ("/data/about.css",
+ ResourceLookupFlags.NONE).get_data ();
+ string html = ((string)resources_lookup_data ("/data/speed-dial.html",
+ ResourceLookupFlags.NONE).get_data ())
+ .replace ("{title}", _("Speed Dial"))
+ .replace ("{icon}", "view-grid")
+ .replace ("{content}", content)
+ .replace ("{stylesheet}", stylesheet);
+ var stream = new MemoryInputStream.from_data (html.data, free);
+ request.finish (stream, html.length, "text/html");
+ } catch (Error error) {
+ request.finish_error (error);
+ critical ("Failed to render %s: %s", request.get_uri (), error.message);
+ }
+ request.unref ();
+ }
+
+ void request_finish_pixbuf (WebKit.URISchemeRequest request, Gdk.Pixbuf pixbuf) throws Error {
+ var output = new MemoryOutputStream (null, realloc, free);
+ pixbuf.save_to_stream (output, "png");
+ output.close ();
+ uint8[] data = output.steal_data ();
+ data.length = (int)output.get_data_size ();
+ var stream = new MemoryInputStream.from_data (data, free);
+ request.finish (stream, -1, null);
+ }
+
+ async void favicon_scheme (WebKit.URISchemeRequest request) {
+ string page_uri = request.get_path ().substring (1, -1);
+ try {
+ var database = WebKit.WebContext.get_default ().get_favicon_database ();
+ var surface = yield database.get_favicon (page_uri, null);
+ if (surface != null) {
+ var image = (Cairo.ImageSurface)surface;
+ var icon = Gdk.pixbuf_get_from_surface (image, 0, 0, image.get_width (), image.get_height ());
+ request_finish_pixbuf (request, icon);
+ }
+ } catch (Error error) {
+ request.finish_error (error);
+ debug ("Failed to render favicon for %s: %s", page_uri, error.message);
+ }
+ request.unref ();
+ }
+
+ async void stock_scheme (WebKit.URISchemeRequest request) {
+ string icon_name = request.get_path ().substring (1, -1);
+ int icon_size = 48;
+ Gtk.icon_size_lookup ((Gtk.IconSize)Gtk.IconSize.DIALOG, out icon_size, null);
+ try {
+ var icon = Gtk.IconTheme.get_default ().load_icon (icon_name, icon_size, Gtk.IconLookupFlags.FORCE_SYMBOLIC);
+ request_finish_pixbuf (request, icon);
+ } catch (Error error) {
+ request.finish_error (error);
+ critical ("Failed to load icon %s: %s", icon_name, error.message);
+ }
+ request.unref ();
+ }
+
void win_new_activated (Action action, Variant? parameter) {
var browser = incognito
? new Browser.incognito (this)
diff --git a/core/tab.vala b/core/tab.vala
index ef8916e7..1592e719 100644
--- a/core/tab.vala
+++ b/core/tab.vala
@@ -55,7 +55,7 @@ namespace Midori {
get_settings ().enable_developer_extras = true;
if (pinned) {
- load_uri (uri ?? "about:blank");
+ load_uri (uri ?? "internal:speed-dial");
Plugins.get_default ().plug (this);
} else {
load_uri_delayed.begin (uri, title);
@@ -63,7 +63,7 @@ namespace Midori {
}
async void load_uri_delayed (string? uri, string? title) {
- display_uri = uri ?? "about:blank";
+ display_uri = uri ?? "internal:speed-dial";
display_title = title ?? display_uri;
item = new DatabaseItem (display_uri, display_title, 0);
diff --git a/core/urlbar.vala b/core/urlbar.vala
index 8cba903a..7f54cb88 100644
--- a/core/urlbar.vala
+++ b/core/urlbar.vala
@@ -35,7 +35,7 @@ namespace Midori {
}
primary_icon_activatable = !blank;
} }
- bool blank { get { return uri == "about:blank"; } }
+ bool blank { get { return uri == "about:blank" || uri == "internal:speed-dial"; } }
[GtkChild]
Gtk.Popover? suggestions;
@@ -164,7 +164,7 @@ namespace Midori {
complete ();
return true;
case Gdk.Key.Escape:
- text = uri;
+ text = blank ? "" : uri;
// Propagate to allow Escape to stop loading
return false;
}
diff --git a/data/about.css b/data/about.css
index a346ef09..ab1d85ff 100644
--- a/data/about.css
+++ b/data/about.css
@@ -71,3 +71,53 @@ button {
font-size: 14pt;
text-align: right;
}
+
+#grid {
+ margin: auto auto;
+}
+
+.shortcut {
+ width: 27%;
+ max-width: 32%;
+ height: 30%;
+ margin: 1%;
+ display: inline-table;
+ box-sizing: border-box;
+ overflow: hidden;
+}
+
+.shortcut a {
+ width: 100%;
+ height: 100%;
+ display: block;
+ text-decoration: none;
+}
+
+.shortcut a img {
+ width: 50%;
+ height: 50%;
+ margin: auto;
+ margin-bottom: .5em;
+ display: block;
+ border-radius: 12px;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12),
+ 0 1px 2px rgba(0,0,0,0.24);
+}
+
+.shortcut a:hover img {
+ box-shadow: 0 3px 5px rgba(0,0,0,0.24),
+ 0 3px 4px rgba(0,0,0,0.48);
+}
+
+.shortcut a .title {
+ width: 90%;
+ color: #222222;
+ text-align: center;
+ text-overflow: ellipsis;
+ word-wrap: nowrap;
+ max-height: 2em;
+ line-height: 1em;
+ overflow: hidden;
+ display: block;
+ font-size: 70%;
+}
diff --git a/data/speed-dial.html b/data/speed-dial.html
new file mode 100644
index 00000000..c1e89d36
--- /dev/null
+++ b/data/speed-dial.html
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2018 Christian Dywan <christian@twotoats.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.
+-->
+<html>
+ <head>
+ <title>{title}</title>
+ <link ref="shortcut icon" href="stock:///{icon}" />
+ <style type="text/css">
+ {stylesheet}
+ </style>
+ </head>
+ <body>
+ <div id="grid">
+ {content}
+ </div>
+ </body>
+</html>
diff --git a/gresource.xml b/gresource.xml
index 0aaa1b4e..86a438ed 100644
--- a/gresource.xml
+++ b/gresource.xml
@@ -13,6 +13,7 @@
<gresource prefix="/">
<file compressed="true">data/about.css</file>
<file compressed="true">data/error.html</file>
+ <file compressed="true">data/speed-dial.html</file>
<file compressed="true">data/gtk3.css</file>
<file compressed="true">data/logo-shade.svg</file>
<file compressed="true">data/history/Create.sql</file>