r5409: - add a gtk events plugin
authorStefan Metzmacher <metze@samba.org>
Tue, 15 Feb 2005 11:57:43 +0000 (11:57 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:10:43 +0000 (13:10 -0500)
- this is used in our gtk apps
- make the main() functions of the gtk apps look
  more simular (we need to get rid of the globals
  in gregedit!)

metze

source/gtk/common/gtk-smb.h
source/gtk/common/gtk_events.c [new file with mode: 0644]
source/gtk/config.mk
source/gtk/tools/gepdump.c
source/gtk/tools/gregedit.c
source/gtk/tools/gwcrontab.c
source/gtk/tools/gwsam.c

index cbbd44698f91b88e65d98020734850795917f35a..e85eb5be8580d0254559dc4a327ca85e3b456dfc 100644 (file)
@@ -79,5 +79,8 @@ GtkWidget *gtk_select_domain_dialog_new (struct dcerpc_pipe *sam_pipe);
 GType gtk_select_domain_dialog_get_type (void);
 struct policy_handle gtk_select_domain_dialog_get_handle(GtkSelectDomainDialog *d);
 
+int gtk_event_loop(void);
+struct event_context;
+struct event_context *gtk_event_context(void);
 
 #endif
diff --git a/source/gtk/common/gtk_events.c b/source/gtk/common/gtk_events.c
new file mode 100644 (file)
index 0000000..faa99a7
--- /dev/null
@@ -0,0 +1,369 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   main select loop and event handling
+   
+   plugin for using a gtk application's event loop
+
+   Copyright (C) Stefan Metzmacher 2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "lib/events/events_internal.h"
+
+#include "gtk/common/select.h"
+
+/* as gtk_main() doesn't take a parameter nor return one,
+   we need to have a global event context structure for our
+   gtk-bases tools
+ */
+static struct event_context *gtk_event_context_global;
+
+static int gtk_event_context_destructor(void *ptr)
+{
+       gtk_event_context_global = NULL;
+       return 0;
+}
+
+/*
+  create a gtk_event_context structure.
+*/
+static int gtk_event_context_init(struct event_context *ev, void *private_data)
+{
+       talloc_set_destructor(ev, gtk_event_context_destructor);
+       return 0;
+}
+
+struct gtk_fd_event {
+       BOOL running;
+       BOOL free_after_run;
+       GIOChannel *channel;
+       guint fd_id;
+};
+
+static gboolean gtk_event_fd_handler(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+       struct fd_event *fde = talloc_get_type(data, struct fd_event);
+       struct gtk_fd_event *gtk_fd = talloc_get_type(fde->additional_data,
+                                                     struct gtk_fd_event);
+       int flags = 0;
+
+       if (condition & (G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP))
+               flags |= EVENT_FD_READ;
+       if (condition & G_IO_OUT)
+               flags |= EVENT_FD_WRITE;
+
+       gtk_fd->running = True;
+       fde->handler(fde->event_ctx, fde, flags, fde->private_data);
+       gtk_fd->running = False;
+
+       if (gtk_fd->free_after_run) {
+               talloc_free(fde);
+               return gtk_false();
+       }
+
+       return gtk_true();
+}
+
+/*
+  destroy an fd_event
+*/
+static int gtk_event_fd_destructor(void *ptr)
+{
+       struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
+       struct gtk_fd_event *gtk_fd = talloc_get_type(fde->additional_data,
+                                                     struct gtk_fd_event);
+
+       if (gtk_fd->running) {
+               /* the event is running reject the talloc_free()
+                  as it's done by the gtk_event_timed_handler()
+                */
+               gtk_fd->free_after_run = True;
+               return -1;
+       }
+
+       if (fde->flags) {
+               /* only if any flag is set we have really registered an event */
+               g_source_remove(gtk_fd->fd_id);
+       }
+       g_io_channel_unref(gtk_fd->channel);
+
+       return 0;
+}
+
+/*
+  add a fd based event
+  return NULL on failure (memory allocation error)
+*/
+static struct fd_event *gtk_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+                                        int fd, uint16_t flags,
+                                        event_fd_handler_t handler,
+                                        void *private_data)
+{
+       struct fd_event *fde;
+       struct gtk_fd_event *gtk_fd;
+       GIOChannel *channel;
+       guint fd_id = 0;
+       GIOCondition condition = 0;
+
+       fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
+       if (!fde) return NULL;
+
+       gtk_fd = talloc(fde, struct gtk_fd_event);
+       if (gtk_fd == NULL) {
+               talloc_free(fde);
+               return NULL;
+       }
+
+       fde->event_ctx          = ev;
+       fde->fd                 = fd;
+       fde->flags              = flags;
+       fde->handler            = handler;
+       fde->private_data       = private_data;
+       fde->additional_data    = gtk_fd;
+
+       channel = g_io_channel_unix_new(fde->fd);
+       if (channel == NULL) {
+               talloc_free(fde);
+               return NULL;
+       }
+
+       if (fde->flags & EVENT_FD_READ)
+               condition |= G_IO_IN;
+       if (fde->flags & EVENT_FD_WRITE)
+               condition |= G_IO_OUT;
+
+       if (condition) {
+               /* only register the event when at least one flag is set
+                  as condition == 0 means wait for any event and is not the same
+                  as fde->flags == 0 !
+               */
+               fd_id = g_io_add_watch(channel, condition, gtk_event_fd_handler, fde);
+       }
+
+       gtk_fd->running         = False;
+       gtk_fd->free_after_run  = False;
+       gtk_fd->channel         = channel;
+       gtk_fd->fd_id           = fd_id;
+
+       talloc_set_destructor(fde, gtk_event_fd_destructor);
+
+       return fde;
+}
+
+/*
+  return the fd event flags
+*/
+static uint16_t gtk_event_get_fd_flags(struct fd_event *fde)
+{
+       if (!fde) return 0;
+
+       return fde->flags;
+}
+
+/*
+  set the fd event flags
+*/
+static void gtk_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
+{
+       struct gtk_fd_event *gtk_fd = talloc_get_type(fde->additional_data,
+                                                     struct gtk_fd_event);
+       GIOCondition condition = 0;
+
+       if (!fde) return;
+
+       if (fde->flags == flags) return;
+
+       if (flags & EVENT_FD_READ)
+               condition |= G_IO_IN;
+       if (flags & EVENT_FD_WRITE)
+               condition |= G_IO_OUT;
+
+       /* only register the event when at least one flag is set
+          as condition == 0 means wait for any event and is not the same
+          as fde->flags == 0 !
+       */
+       if (fde->flags) {
+               g_source_remove(gtk_fd->fd_id);
+       }
+       if (condition) {
+               gtk_fd->fd_id = g_io_add_watch(gtk_fd->channel, condition, gtk_event_fd_handler, fde);
+       }
+
+       fde->flags = flags;
+}
+
+struct gtk_timed_event {
+       BOOL running;
+       guint te_id;
+};
+
+static gboolean gtk_event_timed_handler(gpointer data)
+{
+       struct timed_event *te = talloc_get_type(data, struct timed_event);
+       struct gtk_timed_event *gtk_te = talloc_get_type(te->additional_data,
+                                                        struct gtk_timed_event);
+       struct timeval t = timeval_current();
+
+       gtk_te->running = True;
+       te->handler(te->event_ctx, te, t, te->private_data);
+       gtk_te->running = False;
+
+       talloc_free(te);
+
+       /* return FALSE mean this event should be removed */
+       return gtk_false();
+}
+
+/*
+  destroy a timed event
+*/
+static int gtk_event_timed_destructor(void *ptr)
+{
+       struct timed_event *te = talloc_get_type(ptr, struct timed_event);
+       struct gtk_timed_event *gtk_te = talloc_get_type(te->additional_data,
+                                                        struct gtk_timed_event);
+
+       if (gtk_te->running) {
+               /* the event is running reject the talloc_free()
+                  as it's done by the gtk_event_timed_handler()
+                */
+               return -1;
+       }
+
+       g_source_remove(gtk_te->te_id);
+
+       return 0;
+}
+
+/*
+  add a timed event
+  return NULL on failure (memory allocation error)
+*/
+static struct timed_event *gtk_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+                                              struct timeval next_event, 
+                                              event_timed_handler_t handler, 
+                                              void *private_data) 
+{
+       struct timed_event *te;
+       struct gtk_timed_event *gtk_te;
+       struct timeval cur_tv, diff_tv;
+       guint timeout;
+
+       te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
+       if (te == NULL) return NULL;
+
+       gtk_te = talloc(te, struct gtk_timed_event);
+       if (gtk_te == NULL) {
+               talloc_free(te);
+               return NULL;
+       }
+
+       te->event_ctx           = ev;
+       te->next_event          = next_event;
+       te->handler             = handler;
+       te->private_data        = private_data;
+       te->additional_data     = gtk_te;
+
+       cur_tv                  = timeval_current();
+       diff_tv                 = timeval_diff(&next_event, &cur_tv);
+       timeout                 = ((diff_tv.tv_usec+999)/1000)+(diff_tv.tv_sec*1000);
+
+       gtk_te->te_id           = g_timeout_add(timeout, gtk_event_timed_handler, te);
+       gtk_te->running         = False;
+
+       talloc_set_destructor(te, gtk_event_timed_destructor);
+
+       return te;
+}
+
+/*
+  do a single event loop
+*/
+static int gtk_event_loop_once(struct event_context *ev)
+{
+       /*
+        * gtk_main_iteration ()
+        *
+        * gboolean    gtk_main_iteration              (void);
+        *
+        * Runs a single iteration of the mainloop. If no events 
+        * are waiting to be processed GTK+ will block until the
+        * next event is noticed. If you don't want to block look
+        * at gtk_main_iteration_do() or check if any events are
+        * pending with gtk_events_pending() first.
+        * 
+        * Returns :    TRUE if gtk_main_quit() has been called for the innermost mainloop.
+        */
+       gboolean ret;
+
+       ret = gtk_main_iteration();
+       if (ret == gtk_true()) {
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+  return with 0
+*/
+static int gtk_event_loop_wait(struct event_context *ev)
+{
+       /*
+        * gtk_main ()
+        * 
+        * void        gtk_main                        (void);
+        * 
+        * Runs the main loop until gtk_main_quit() is called.
+        * You can nest calls to gtk_main(). In that case
+        * gtk_main_quit() will make the innermost invocation
+        * of the main loop return. 
+        */
+       gtk_main();
+       return 0;
+}
+
+static const struct event_ops gtk_event_ops = {
+       .context_init   = gtk_event_context_init,
+       .add_fd         = gtk_event_add_fd,
+       .get_fd_flags   = gtk_event_get_fd_flags,
+       .set_fd_flags   = gtk_event_set_fd_flags,
+       .add_timed      = gtk_event_add_timed,
+       .loop_once      = gtk_event_loop_once,
+       .loop_wait      = gtk_event_loop_wait,
+};
+
+int gtk_event_loop(void)
+{
+       int ret;
+
+       gtk_event_context_global = event_context_init_ops(NULL, &gtk_event_ops, NULL);
+       if (!gtk_event_context_global) return -1;
+
+       ret = event_loop_wait(gtk_event_context_global);
+
+       talloc_free(gtk_event_context_global);
+
+       return ret;
+}
+
+struct event_context *gtk_event_context(void)
+{
+       return gtk_event_context_global;
+}
index 72040c68820e62bb08a0a6993f3a0912c054e60b..00665839730f27061649b87fedc2a0c7ec12eb45 100644 (file)
@@ -5,7 +5,8 @@
 [SUBSYSTEM::GTKSMB]
 NOPROTO = YES
 INIT_OBJ_FILES = gtk/common/gtk-smb.o 
-ADD_OBJ_FILES = gtk/common/select.o
+ADD_OBJ_FILES = gtk/common/select.o \
+               gtk/common/gtk_events.o
 REQUIRED_SUBSYSTEMS = CHARSET LIBBASIC EXT_LIB_gtk RPC_NDR_SAMR
 # End SUBSYSTEM GTKSMB
 ##############################
index 88cd9ff8b7257aa0b2f7db4e3a8e34dd035157ca..d445dd63cbece5c5449205b63143974b29da4c8c 100644 (file)
@@ -417,15 +417,16 @@ static GtkWidget* create_mainwindow (void)
 }
 
 
-int main(int argc, char **argv)
+ int main(int argc, char **argv)
 {
-       gtk_init(&argc, &argv);
        gepdump_init_subsystems;
        lp_load(dyn_CONFIGFILE,True,False,False);
        load_interfaces();
-       setup_logging("gepdump", True);
+       setup_logging(argv[0], DEBUG_STDERR);
+
+       gtk_init(&argc, &argv);
        mainwin = create_mainwindow();
        gtk_widget_show_all(mainwin);
-       gtk_main();
-       return 0;
+
+       return gtk_event_loop();
 }
index 918ebd69450069ba4886d337be04bcebafa5c388..9d0a87f2a7a643bef824ef22eb5b7bcb99462268 100644 (file)
@@ -660,7 +660,7 @@ gboolean on_key_activate(GtkTreeSelection *selection,
        return TRUE;
 }
 
-static GtkWidget* create_mainwin (void)
+static GtkWidget* create_mainwindow(void)
 {
        GtkWidget *vbox1;
        GtkWidget *menubar;
@@ -955,43 +955,41 @@ static GtkWidget* create_savefilewin (void)
        return savefilewin;
 }
 
+static int gregedit_load_defaults(void)
+{
+       WERROR error = reg_open_local(&registry);
+       if(!W_ERROR_IS_OK(error)) {
+               gtk_show_werror(mainwin, error);
+               return -1;
+       }
+       registry_load_root();
+
+       return 0;
+}
+
  int main(int argc, char *argv[])
 {
-       poptContext pc;
-       WERROR error;
-       int opt;
-       struct poptOption long_options[] = {
-               POPT_AUTOHELP
-               POPT_TABLEEND
-       };
+       int ret;
 
        gregedit_init_subsystems;
-
        lp_load(dyn_CONFIGFILE,True,False,False);
        load_interfaces();
+       setup_logging(argv[0], DEBUG_STDERR);
 
-       gtk_init (&argc, &argv);
        mem_ctx = talloc_init("gregedit");
 
-       pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
+       gtk_init(&argc, &argv);
+       mainwin = create_mainwindow();
+       gtk_widget_show_all(mainwin);
 
-       while((opt = poptGetNextOpt(pc)) != -1) {
-       }
+       ret = gregedit_load_defaults();
+       if (ret != 0) goto failed;
 
-       error = reg_open_local(&registry);
-       if(!W_ERROR_IS_OK(error)) {
-               gtk_show_werror(mainwin, error);
-               return -1;
-       }
-       mainwin = create_mainwin ();
-       registry_load_root();
-
-       gtk_widget_show_all (mainwin);
-
-       gtk_main ();
+       ret = gtk_event_loop();
 
+failed:
        talloc_free(mem_ctx);
-       return 0;
+       return ret;
 }
 
 
index 580bbc2ae3d1ddae70bc3918d6c2f92ca75c7fe7..69ef2d7965b79f2dfc2fa0dc279b4273c70d855c 100644 (file)
@@ -501,11 +501,11 @@ static GtkWidget*create_new_job_dialog (void)
        gwcrontab_init_subsystems;
        lp_load(dyn_CONFIGFILE,True,False,False);
        load_interfaces();
+       setup_logging(argv[0], DEBUG_STDERR);
 
        gtk_init(&argc, &argv);
        mainwin = create_mainwindow();
        gtk_widget_show_all(mainwin);
-       gtk_main();
 
-       return 0;
+       return gtk_event_loop();
 }
index 7d9abde3d3d2b13c242dcbc4ce5286cd79a4ae5e..878440527ead55311237af4b2a6c8f6513241af8 100644 (file)
@@ -420,13 +420,12 @@ create_mainwindow (void)
        gwsam_init_subsystems;
        lp_load(dyn_CONFIGFILE,True,False,False);
        load_interfaces();
-       setup_logging("gwsam", True);
+       setup_logging(argv[0], DEBUG_STDERR);
 
        gtk_init(&argc, &argv);
        mainwin = create_mainwindow();
        connect_sam();
        gtk_widget_show_all(mainwin);
-       gtk_main();
 
-       return 0;
+       return gtk_event_loop();
 }