aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-04-11 21:32:20 +1200
committerArslaan Pathan <[email protected]>2026-04-11 21:32:20 +1200
commit94a741c456b73ac44615406ad55069ee9d02d77f (patch)
treedfc94a5403dcd84781c0332239d6ac0290f73f05
parent082ffb7c0e1985e2f0e5165b130dd0a809bd83df (diff)
downloadcinnamon-browser-94a741c456b73ac44615406ad55069ee9d02d77f.tar.xz
cinnamon-browser-94a741c456b73ac44615406ad55069ee9d02d77f.zip
Favicons, yay!
finally, i might daily drive cinnamon now!
-rw-r--r--Makefile4
-rw-r--r--config.def.h27
-rw-r--r--main.c47
3 files changed, 70 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 37b0149..1bbb302 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
# Copyright (c) 2026 Arslaan Pathan
# This software is licensed under the ARPL. See LICENSE for details.
CC = clang
-CFLAGS = -std=gnu17 `pkg-config --cflags webkit2gtk-4.1 gtk+-3.0` -Wno-deprecated-declarations
-LIBS = `pkg-config --libs webkit2gtk-4.1 gtk+-3.0`
+CFLAGS = -std=gnu17 `pkg-config --cflags webkit2gtk-4.1 gtk+-3.0 gdk-pixbuf-2.0` -Wno-deprecated-declarations
+LIBS = `pkg-config --libs webkit2gtk-4.1 gtk+-3.0 gdk-pixbuf-2.0`
TARGET = cinnamon
SRC = main.c
PREFIX = /usr/local
diff --git a/config.def.h b/config.def.h
index 12eeaaa..afc1693 100644
--- a/config.def.h
+++ b/config.def.h
@@ -28,8 +28,11 @@ extern void inject_hint_mode(Cinnamon* cinnamon, void (*callback)(Cinnamon*, cha
/* if the last tab is closed, don't quit, just make a fresh one */
#define NO_QUIT_ON_CLOSE_LAST_TAB
/* hide the tab bar, unless a keybind or command shows it */
-#define HIDE_TAB_BAR
+/* #define HIDE_TAB_BAR */
#define USERAGENT "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/605.1.15 (KHTML, like Gecko) cinnamon/1.0 (git.arslaancodes.com/cinnamon-browser.git) Safari/605.1.15"
+/* show favicon AND title */
+#define TABS_SHOW_FAVICON
+#define TABS_SHOW_TITLE
/* Keybind definitions */
/* we use the _kbd prefix here just because, idk, good practice to keep keybinds isolated? in practice use whatever the hell you want as long as it doesnt interfere with builtin functions */
@@ -126,6 +129,20 @@ static void _kbd_follow(Cinnamon* cinnamon, void* arg) {
inject_hint_mode(cinnamon, &_conf_hint_callback);
}
+static void _kbd_next_tab(Cinnamon* cinnamon, void* arg) {
+ int current = gtk_notebook_get_current_page(GTK_NOTEBOOK(cinnamon->notebook));
+ int n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(cinnamon->notebook));
+ int next = (current + 1) % n_pages;
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(cinnamon->notebook), next);
+}
+
+static void _kbd_prev_tab(Cinnamon* cinnamon, void* arg) {
+ int current = gtk_notebook_get_current_page(GTK_NOTEBOOK(cinnamon->notebook));
+ int n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(cinnamon->notebook));
+ int prev = (current - 1 + n_pages) % n_pages;
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(cinnamon->notebook), prev);
+}
+
static const Keybind keybinds[] = {
{ "t", &_kbd_tabopen, NULL },
{ "d", &_kbd_tabclose, NULL },
@@ -139,6 +156,8 @@ static const Keybind keybinds[] = {
{ "l", &_kbd_scroll, "right" },
{ "r", &_kbd_reload, NULL },
{ "f", &_kbd_follow, NULL },
+ { "<S-j>", &_kbd_next_tab, NULL },
+ { "<S-k>", &_kbd_prev_tab, NULL },
{ "<S-h>", &_kbd_back, NULL },
{ "<S-l>", &_kbd_forward, NULL },
{ "<S-r>", &_kbd_hardreload, NULL },
@@ -202,12 +221,18 @@ static void _cmd_forward(Cinnamon* cinnamon, const char* args) {
webkit_web_view_go_forward(WEBKIT_WEB_VIEW(webview));
}
+static void _cmd_quit(Cinnamon* cinnamon, const char* args) {
+ gtk_main_quit();
+}
+
static const Command commands[] = {
{ "open", &_cmd_open },
{ "reload", &_cmd_reload },
{ "hard_reload", &_cmd_hardreload },
{ "back", &_cmd_back },
{ "forward", &_cmd_forward },
+ { "q", &_cmd_quit },
+ { "quit", &_cmd_quit },
};
diff --git a/main.c b/main.c
index 313cb1d..a902461 100644
--- a/main.c
+++ b/main.c
@@ -4,6 +4,8 @@ This software is licensed under the ARPL. See LICENSE for details.
*/
#include <webkit2/webkit2.h>
#include <gtk/gtk.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
#include <stdio.h>
/* forward declare BEFORE including config.h so that config.h can reference them */
@@ -61,13 +63,43 @@ static void parse_keybind(const char *key, guint *keyval, GdkModifierType *mods)
*keyval = gdk_keyval_from_name(name);
}
-static void on_title_changed(WebKitWebView *webview, GParamSpec *pspec, GtkNotebook *notebook) {
- const char *title = webkit_web_view_get_title(webview);
+static void on_title_changed(WebKitWebView* webview, GParamSpec* pspec, GtkNotebook* notebook) {
+ const char* title = webkit_web_view_get_title(webview);
int page = gtk_notebook_page_num(notebook, GTK_WIDGET(webview));
- gtk_notebook_set_tab_label_text(notebook, GTK_WIDGET(webview), title ? title : "New Tab");
+
+ GtkWidget* hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
+
+#ifdef TABS_SHOW_FAVICON
+ cairo_surface_t* favicon = webkit_web_view_get_favicon(webview);
+ if (favicon) {
+ int w = cairo_image_surface_get_width(favicon);
+ int h = cairo_image_surface_get_height(favicon);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_get_from_surface(favicon, 0, 0, w, h);
+ if (pixbuf) {
+ GdkPixbuf* scaled = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR);
+ GtkWidget* image = gtk_image_new_from_pixbuf(scaled);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+ g_object_unref(scaled);
+ g_object_unref(pixbuf);
+ }
+ }
+#endif
+
+#ifdef TABS_SHOW_TITLE
+ GtkWidget* label = gtk_label_new(title ? title : "New Tab");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+#endif
+
+ gtk_widget_show_all(hbox);
+ gtk_notebook_set_tab_label(notebook, GTK_WIDGET(webview), hbox);
}
-static gboolean on_cmdbar_activate(GtkEntry *entry, gpointer data) {
+static void on_favicon_changed(WebKitWebView* webview, GParamSpec* pspec, GtkNotebook* notebook) {
+ on_title_changed(webview, pspec, notebook);
+}
+
+static gboolean on_cmdbar_activate(GtkEntry* entry, gpointer data) {
Cinnamon* cinnamon = (Cinnamon*)data;
const char *input = gtk_entry_get_text(entry);
@@ -187,8 +219,9 @@ void set_mode(Cinnamon* cinnamon, int new_mode) {
void tabopen(Cinnamon* cinnamon) {
GtkWidget *webview = webkit_web_view_new_with_context(cinnamon->web_context);
- gtk_notebook_append_page(GTK_NOTEBOOK(cinnamon->notebook), webview, gtk_label_new("New Tab"));
+ gtk_notebook_append_page(GTK_NOTEBOOK(cinnamon->notebook), webview, gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4));
g_signal_connect(webview, "notify::title", G_CALLBACK(on_title_changed), cinnamon->notebook);
+ g_signal_connect(webview, "notify::favicon", G_CALLBACK(on_favicon_changed), cinnamon->notebook);
/* HOMEPAGE and USERAGENT defined in config.h */
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webview), g_object_new(WEBKIT_TYPE_SETTINGS, "user-agent", USERAGENT, NULL));
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), HOMEPAGE);
@@ -250,6 +283,7 @@ int main(int argc, char *argv[]) {
gtk_container_add(GTK_CONTAINER(cinnamon.window), vbox);
cinnamon.notebook = gtk_notebook_new();
+ gtk_notebook_set_scrollable(GTK_NOTEBOOK(cinnamon.notebook), TRUE);
// gtk_container_add(GTK_CONTAINER(cinnamon.window), cinnamon.notebook);
gtk_box_pack_start(GTK_BOX(vbox), cinnamon.notebook, TRUE, TRUE, 0);
@@ -259,6 +293,9 @@ int main(int argc, char *argv[]) {
WebKitCookieManager *cookie_manager = webkit_web_context_get_cookie_manager(cinnamon.web_context);
webkit_cookie_manager_set_persistent_storage(cookie_manager, g_build_filename(g_get_user_data_dir(), "cinnamon", "cookies.sqlite", NULL), WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
+ /* favicon db */
+ webkit_web_context_set_favicon_database_directory(cinnamon.web_context, g_build_filename(g_get_user_cache_dir(), "cinnamon", "favicons", NULL));
+
/* Create initial tab */
tabopen(&cinnamon);