From 035a3451587e420b7538f939905cf77cdc5611dd Mon Sep 17 00:00:00 2001 From: fenze Date: Tue, 10 May 2022 23:47:17 +0200 Subject: [PATCH] Add support for xatom search action --- config.h | 12 +++--- keyconf.h | 6 ++- makefile | 4 +- rose.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++------ rose.h | 18 +++++++++ window.c | 36 +++++++++++++++-- window.h | 3 +- 7 files changed, 170 insertions(+), 26 deletions(-) diff --git a/config.h b/config.h index bbb8019..03682dd 100644 --- a/config.h +++ b/config.h @@ -8,9 +8,11 @@ static const char *homepage = "https://duckduckgo.com"; #define MODKEY GDK_CONTROL_MASK static Key keys[] = { - { MODKEY, GDK_KEY_h, goback }, - { MODKEY, GDK_KEY_l, goforward }, - { MODKEY, GDK_KEY_y, copy_url }, - { MODKEY, GDK_KEY_p, paste_url }, - { 0, GDK_KEY_F11, fullscreen } + { MODKEY, GDK_KEY_h, goback }, + { MODKEY, GDK_KEY_l, goforward }, + { MODKEY, GDK_KEY_y, copy_url }, + { MODKEY, GDK_KEY_p, paste_url }, + { 0, GDK_KEY_F11, fullscreen }, + { MODKEY|SHIFT, GDK_KEY_i, inspector }, + { MODKEY, GDK_KEY_e, search } }; diff --git a/keyconf.h b/keyconf.h index afa8c7f..948a9b9 100644 --- a/keyconf.h +++ b/keyconf.h @@ -3,7 +3,7 @@ #include #include -#define NONE 4 +#define SHIFT GDK_SHIFT_MASK typedef struct { unsigned modkey; @@ -16,5 +16,7 @@ enum { goforward, copy_url, paste_url, - fullscreen + fullscreen, + inspector, + search }; diff --git a/makefile b/makefile index d179080..cbce5d9 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ CC = clang -CFLAGS = `pkg-config --cflags gtk4 webkit2gtk-5.0` -LIBS = `pkg-config --libs gtk4 webkit2gtk-5.0` +CFLAGS = `pkg-config --cflags gtk4 webkit2gtk-5.0 x11` +LIBS = `pkg-config --libs gtk4 webkit2gtk-5.0 x11` all: ${CC} -fPIC -g -O3 -o rose *.c $(CFLAGS) $(LIBS) diff --git a/rose.c b/rose.c index 9898830..bf16d7a 100644 --- a/rose.c +++ b/rose.c @@ -1,26 +1,116 @@ #include "rose.h" -#include "config.h" -#include "webview.h" -#include "window.h" -#include -#include + +#define MSGBUFSZ 8 +#define LENGTH(x) (sizeof(x) / sizeof(x[0])) + +guint xid; + +void +sigchld(int unused) +{ + if (signal(SIGCHLD, sigchld) == SIG_ERR) { + puts("Can't install SIGCHLD handler"); + exit(1); + } + while (waitpid(-1, NULL, WNOHANG) > 0) + ; +} + +void +setatom(int a, const char *v) +{ + XChangeProperty(dpy, xid, + atoms[a], atoms[AtomUTF8], 8, PropModeReplace, + (unsigned char *)v, strlen(v) + 1); + XSync(dpy, False); +} + +static gboolean +readsock(GIOChannel *s, GIOCondition ioc, gpointer unused) +{ + static char msg[MSGBUFSZ]; + GError *gerr = NULL; + gsize msgsz; + + if (g_io_channel_read_chars(s, msg, sizeof(msg), &msgsz, &gerr) != + G_IO_STATUS_NORMAL) { + if (gerr) { + fprintf(stderr, "surf: error reading socket: %s\n", + gerr->message); + g_error_free(gerr); + } + return TRUE; + } + + if (msgsz < 2) { + fprintf(stderr, "surf: message too short: %lu\n", msgsz); + return TRUE; + } + + return TRUE; +} + +const char * +getatom(int a) +{ + static char buf[BUFSIZ]; + Atom adummy; + int idummy; + unsigned long ldummy; + unsigned char *p = NULL; + + XSync(dpy, False); + XGetWindowProperty(dpy, xid, + atoms[a], 0L, BUFSIZ, False, atoms[AtomUTF8], + &adummy, &idummy, &ldummy, &ldummy, &p); + if (p) + strncpy(buf, (char *)p, LENGTH(buf) - 1); + else + buf[0] = '\0'; + XFree(p); + + return buf; +} + +static void setup() +{ + GIOChannel *gchanin; + + sigchld(0); + + if (!(dpy = XOpenDisplay(NULL))) { + puts("Can't open default display"); + exit(1); + } + + atoms[AtomFind] = XInternAtom(dpy, "_ROSE_FIND", False); + atoms[AtomGo] = XInternAtom(dpy, "_ROSE_GO", False); + atoms[AtomUri] = XInternAtom(dpy, "_ROSE_URI", False); + atoms[AtomUTF8] = XInternAtom(dpy, "UTF8_STRING", False); + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, spair) < 0) { + fputs("Unable to create sockets\n", stderr); + spair[0] = spair[1] = -1; + } else { + gchanin = g_io_channel_unix_new(spair[0]); + g_io_channel_set_encoding(gchanin, NULL, NULL); + g_io_channel_set_flags(gchanin, g_io_channel_get_flags(gchanin) + | G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_close_on_unref(gchanin, TRUE); + g_io_add_watch(gchanin, G_IO_IN, readsock, NULL); + } +} static void run(GtkApplication *app) { RoseWindow *window = rose_window_new(app); - GtkWidget *webview = rose_webview_new(); if (dark_mode) { g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", true, NULL); - GdkRGBA color = { 0, 0, 0, 1 }; - webkit_web_view_get_background_color(WEBKIT_WEB_VIEW(webview), &color); } - rose_window_set_webview(window, webview); - rose_window_show(window); - - if (homepage) - rose_webview_load_url(WEBKIT_WEB_VIEW(webview), homepage); + xid = rose_window_show(app, window); + setatom(AtomUri, homepage); } int main(int argc, char **argv) @@ -30,6 +120,7 @@ int main(int argc, char **argv) argv++; argc--; } + setup(); GtkApplication *app = gtk_application_new("org.gtk.rose", G_APPLICATION_NON_UNIQUE); g_signal_connect(app, "activate", G_CALLBACK(run), NULL); g_application_run(G_APPLICATION(app), argc, argv); diff --git a/rose.h b/rose.h index 03b9e77..8f29f0b 100644 --- a/rose.h +++ b/rose.h @@ -1,4 +1,22 @@ #pragma once +#include "window.h" +#include "webview.h" +#include "config.h" + #include +#include +#include +#include +#include +#include +#include +#include #include +#include + +enum { AtomFind, AtomGo, AtomUri, AtomUTF8, AtomLast }; +static Atom atoms[AtomLast]; +static Display *dpy; +const char* getatom(int a); +static int spair[2]; diff --git a/window.c b/window.c index 4e35a3c..5979071 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,5 @@ #include "window.h" +#include "rose.h" /* #include "gestures.h" */ #include "config.h" #include "webview.h" @@ -8,6 +9,7 @@ struct _RoseWindow { GtkApplicationWindow parent_instance; + guint xid; GtkWindow *window; WebKitWebView *webview; GHashTable *action_groups; @@ -66,6 +68,26 @@ static gboolean key_press_callback(RoseWindow *window, else gtk_window_fullscreen(GTK_WINDOW(window->window)); break; + case inspector: + puts("wqf"); + break; + case search: { + int id = fork(); + if (id == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + close(spair[0]); + close(spair[1]); + setsid(); + char* argument_list[] = {"/bin/sh", "-c", "surf-open", NULL}; + execvp("/bin/sh", argument_list); + perror(" failed"); + exit(1); + } else { + wait(&id); + webkit_web_view_load_uri(window->webview, getatom(AtomGo)); + } + } } } } @@ -93,11 +115,17 @@ static void rose_window_init(RoseWindow *window) window->window = GTK_WINDOW(gtk_window_new()); } -void rose_window_show(RoseWindow *window) +guint rose_window_show(GtkApplication *app, RoseWindow *window) { - GtkWidget *w = gtk_window_new(); + GtkWidget *w = gtk_application_window_new(app); window->window = GTK_WINDOW(w); - gtk_window_set_child(GTK_WINDOW(w), GTK_WIDGET(window->webview)); + GtkWidget *webview = rose_webview_new(); + window->webview = WEBKIT_WEB_VIEW(webview); + + if (homepage) + rose_webview_load_url(WEBKIT_WEB_VIEW(webview), homepage); + + gtk_window_set_child(GTK_WINDOW(w), GTK_WIDGET(webview)); /* Keyboard shortcuts */ GtkEventController *controller; @@ -106,6 +134,8 @@ void rose_window_show(RoseWindow *window) gtk_widget_add_controller(GTK_WIDGET(w), controller); gtk_widget_show(w); + + return gdk_x11_surface_get_xid(gtk_native_get_surface(GTK_NATIVE(w))); } void rose_window_set_webview(RoseWindow *window, GtkWidget *webview) diff --git a/window.h b/window.h index 7e42018..a238a2a 100644 --- a/window.h +++ b/window.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "webview.h" G_BEGIN_DECLS @@ -10,7 +11,7 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(RoseWindow, rose_window, ROSE, WINDOW, GtkApplicationWindow) RoseWindow* rose_window_new(); -void rose_window_show(RoseWindow *window); +guint rose_window_show(GtkApplication *app, RoseWindow *window); gboolean rose_window_close(RoseWindow *window); void rose_window_set_webview(RoseWindow *window, GtkWidget *webview);