#include <gtk/gtk.h>
#include <webkit/webkit.h>
+#include <pthread.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
-#include <pthread.h>
-static GtkWidget* main_window;
-static GtkWidget* uri_entry;
-static GtkStatusbar* main_statusbar;
+static GtkWidget* main_window;
static WebKitWebView* web_view;
-static gchar* main_title;
-static gint load_progress;
-static guint status_context_id;
-static gchar* uri = NULL;
-static gboolean verbose = FALSE;
+static gchar* uri = NULL;
+static gchar* fifodir = NULL;
+static gint mechmode = 0;
+static char fifopath[64];
static GOptionEntry entries[] =
{
- { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri, "Uri to load", NULL },
- { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL },
- { NULL }
+ { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri, "Uri to load", NULL },
+ { "fifo-dir", 'd', 0, G_OPTION_ARG_STRING, &fifodir, "Directory to place FIFOs", NULL },
+ { "mechmode", 'm', 0, G_OPTION_ARG_INT, &mechmode, "Enable output suitable for machine processing", NULL },
+ { NULL }
};
-
-static void
-activate_uri_entry_cb (GtkWidget* entry, gpointer data)
+struct command
{
- const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
- g_assert (uri);
- webkit_web_view_load_uri (web_view, uri);
-}
+ char command[256];
+ void (*func)(WebKitWebView*);
+};
-static void update_title (GtkWindow* window)
-{
- GString* string = g_string_new (main_title);
- g_string_append (string, " - Uzbl browser");
- if (load_progress < 100)
- g_string_append_printf (string, " (%d%%)", load_progress);
- gchar* title = g_string_free (string, FALSE);
- gtk_window_set_title (window, title);
- g_free (title);
-}
+static struct command *commands;
+static int numcmds = 0;
-static void
-link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data)
+static GtkWidget* create_browser ()
{
- /* underflow is allowed */
- gtk_statusbar_pop (main_statusbar, status_context_id);
- if (link)
- gtk_statusbar_push (main_statusbar, status_context_id, link);
-}
+ GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
-static void
-title_change_cb (WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data)
-{
- if (main_title)
- g_free (main_title);
- main_title = g_strdup (title);
- update_title (GTK_WINDOW (main_window));
-}
+ web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
+ gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));
-static void
-progress_change_cb (WebKitWebView* page, gint progress, gpointer data)
-{
- load_progress = progress;
- update_title (GTK_WINDOW (main_window));
+ return scrolled_window;
}
-static void
-load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data)
+static GtkWidget* create_window ()
{
- const gchar* uri = webkit_web_frame_get_uri(frame);
- if (uri)
- gtk_entry_set_text (GTK_ENTRY (uri_entry), uri);
+ GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
+ gtk_widget_set_name (window, "Uzbl Browser");
+ g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ return window;
}
-static void
-destroy_cb (GtkWidget* widget, gpointer data)
+static void parse_command(char *command)
{
- gtk_main_quit ();
+ int i = 0;
+ bool done = false;
+
+ for (i = 0; i < numcmds && !done; i++)
+ {
+ if (!strcmp(command, commands[i].command))
+ {
+ commands[i].func(web_view);
+ done = true;
+ }
+ }
+
+ if(!done)
+ {
+ if (!strncmp("http://", command, 7))
+ {
+ printf("Loading URI \"%s\"\n", command);
+ uri = command;
+ webkit_web_view_load_uri (web_view, uri);
+ }
+ else
+ {
+ printf("Unhandled command \"%s\"\n", command);
+ }
+ }
}
-static void
-go_back_cb (GtkWidget* widget, gpointer data)
-{
- webkit_web_view_go_back (web_view);
+static void *control_fifo()
+{
+ if (fifodir) {
+ sprintf(fifopath, "%s/uzbl_%d", fifodir, getpid());
+ } else {
+ sprintf(fifopath, "/tmp/uzbl_%d", getpid());
+ }
+
+ if (mkfifo (fifopath, 0666) == -1) {
+ printf("Possible error creating fifo\n");
+ }
+
+ if (mechmode) {
+ printf("%s\n", fifopath);
+ } else {
+ printf ("Opened control fifo in %s\n", fifopath);
+ }
+
+ while (true)
+ {
+ FILE *fifo = fopen(fifopath, "r");
+ if (!fifo) {
+ printf("Could not open %s for reading\n", fifopath);
+ return NULL;
+ }
+
+ char buffer[256];
+ memset(buffer, 0, sizeof(buffer));
+ while (!feof(fifo) && fgets(buffer, sizeof(buffer), fifo)) {
+ if (strcmp(buffer, "\n")) {
+ buffer[strlen(buffer)-1] = '\0'; // Remove newline
+ parse_command(buffer);
+ }
+ }
+ }
+
+ return NULL;
}
-static void
-go_forward_cb (GtkWidget* widget, gpointer data)
+static void add_command (char* cmdstr, void* function)
{
- webkit_web_view_go_forward (web_view);
+ struct command commands[numcmds];
+ printf(" Defining string\n");
+ strncpy(commands[numcmds].command, cmdstr, strlen(cmdstr));
+ printf(" Adding function\n");
+ commands[numcmds].func = function;
+ printf(" Incrementing count\n");
+ numcmds++;
+ printf(" Done\n");
}
-static GtkWidget*
-create_browser ()
+static bool setup_gtk(int argc, char* argv[])
{
- GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_init (&argc, &argv);
- web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
- gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view));
+ GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), create_browser (), TRUE, TRUE, 0);
- g_signal_connect (G_OBJECT (web_view), "title-changed", G_CALLBACK (title_change_cb), web_view);
- g_signal_connect (G_OBJECT (web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), web_view);
- g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (load_commit_cb), web_view);
- g_signal_connect (G_OBJECT (web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), web_view);
+ main_window = create_window ();
+ gtk_container_add (GTK_CONTAINER (main_window), vbox);
+ GError *error = NULL;
- return scrolled_window;
-}
+ GOptionContext* context = g_option_context_new ("- The Usable Browser, controlled entirely through a FIFO");
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+ g_option_context_parse (context, &argc, &argv, &error);
-static GtkWidget* create_statusbar ()
-{
- main_statusbar = GTK_STATUSBAR (gtk_statusbar_new ());
- status_context_id = gtk_statusbar_get_context_id (main_statusbar, "Link Hover");
+ if (uri) {
+ webkit_web_view_load_uri (web_view, uri);
+ } else {
+ webkit_web_view_load_uri (web_view, "http://www.google.com");
+ }
- return (GtkWidget*)main_statusbar;
-}
-
-static GtkWidget* create_window ()
-{
- GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
- gtk_widget_set_name (window, "Uzbl browser");
- g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy_cb), NULL);
+ gtk_widget_grab_focus (GTK_WIDGET (web_view));
+ gtk_widget_show_all (main_window);
- return window;
+ return true;
}
-
-static bool parse_command(char *command)
+static bool setup_commands()
{
- bool output;
- output = true;
-
- if(strcmp(command, "forward") == 0)
- {
- printf("Going forward\n");
- webkit_web_view_go_forward (web_view);
- }
- else if(strcmp(command, "back") == 0)
- {
- printf("Going back\n");
- webkit_web_view_go_back (web_view);
- }
- else if(strncmp("http://", command, 7) == 0)
- {
- printf("Loading URI \"%s\"\n", command);
- uri = command;
- webkit_web_view_load_uri (web_view, uri);
- }
- else
- {
- output = false;
- }
-
- return output;
+ printf("Adding back\n");
+ add_command("back", &webkit_web_view_go_back);
+ printf("Adding forward\n");
+ add_command("forward", &webkit_web_view_go_forward);
+ printf("Done\n");
+ return true;
}
-static void control_fifo()
+static bool setup_threading()
{
- char *cmd = (char *)malloc(1024);
- int num, fd;
- char *fifoname = "/tmp/uzbl";
+ pthread_t control_thread;
+ pthread_create(&control_thread, NULL, control_fifo, NULL);
- umask(0);
- mknod(fifoname, S_IFIFO | 0666 , 0); /* Do some stuff to work with multiple instances later foo-$PID or something */
- printf("Opened control fifo in %s\n", fifoname);
-
- while (true)
- {
- fd = open(fifoname, O_RDONLY);
- while (num > 0)
- {
- if ((num = read(fd, cmd, 300)) == -1)
- perror("read");
- else
- {
- cmd[num] = '\0';
- if(! parse_command(cmd))
- printf("Unknown command \"%s\".\n", cmd);
- }
- }
- num = 1;
- }
- printf("Oops, this code should never be run.\n");
+ return true;
}
int main (int argc, char* argv[])
{
- gtk_init (&argc, &argv);
-
- if (!g_thread_supported ())
- g_thread_init (NULL);
-
- GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), create_browser (), TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), create_statusbar (), FALSE, FALSE, 0);
-
- main_window = create_window ();
- gtk_container_add (GTK_CONTAINER (main_window), vbox);
- GError *error = NULL;
-
- GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
- g_option_context_add_main_entries (context, entries, NULL);
- g_option_context_add_group (context, gtk_get_option_group (TRUE));
- g_option_context_parse (context, &argc, &argv, &error);
-
- char *uri = "http://www.google.com";
- if(argc == 2)
- uri = argv[1];
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
- webkit_web_view_load_uri (web_view, uri);
+ setup_gtk (argc, argv);
+ setup_commands ();
+ setup_threading ();
+ gtk_main ();
- gtk_widget_grab_focus (GTK_WIDGET (web_view));
- gtk_widget_show_all (main_window);
+ /*pthread_join (control_thread, NULL); For some reason it doesn't terminate upon the browser closing when this is enabled. */
- pthread_t control_thread;
- int ret;
+ printf ("Shutting down...\n");
- ret = pthread_create(&control_thread, NULL, control_fifo, (void*) NULL);
- gtk_main ();
+ // Remove FIFO
+ unlink (fifopath);
- pthread_join(control_thread, NULL);
- return 0;
+ return 0;
}