[gromit: 7/13] Import of gromit history



commit 08b1f35177d43484f9f7e41acace929162eb5231
Author: Simon Budig <simon budig de>
Date:   Sun Aug 26 16:07:00 2001 +0200

    Import of gromit history

 ChangeLog       |    5 --
 Makefile        |    3 -
 README          |   50 +++++++++-------
 gromit.c        |  180 +++++++++++++++++++++++++++++++++++++++++--------------
 gromitconf      |   26 --------
 propertywatch.c |  136 -----------------------------------------
 sawfish-config  |    9 +++
 7 files changed, 172 insertions(+), 237 deletions(-)
---
diff --git a/Makefile b/Makefile
index 0613232..4fe7115 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,4 @@
 all: gromit
 
-propertywatch: propertywatch.c
-	gcc -o propertywatch propertywatch.c `gtk-config --libs --cflags`
-
 gromit: gromit.c
 	gcc -o gromit gromit.c `gtk-config --libs --cflags`
diff --git a/README b/README
index 24e7a18..06525fd 100644
--- a/README
+++ b/README
@@ -12,8 +12,8 @@ on the screen, ignoring any window-borders.
 
 Gromit is a first implementation of this program.
 
-The main usage problem of gromit is its activation. You need a special
-command to make gromit grab the mouse, since you typically want to use
+The main usage problem of Gromit is its activation. You need a special
+command to make Gromit grab the mouse, since you typically want to use
 the program you are demonstrating and highlighting something is a short
 interruption of your workflow. It should work *always*, regardless of
 the currently focused window. X11 does not have an easy way to make a
@@ -21,8 +21,8 @@ program sensible for all events of a certain kind. You have to iterate
 over all windows and tell X that you are interested in the events of
 this window. However, this does not affect windows opened later, so you
 have to reiterate this permanently. At this point I decided to use
-another way: You can invoke gromit with various arguments to control an
-already running gromit (see below).  Configure your favourite
+another way: You can invoke Gromit with various arguments to control an
+already running Gromit (see below).  Configure your favourite
 windowmanager to invoke these commands on your favourite
 key-combination. I included a script that reconfigures the
 sawfish-windowmanager. (If you are interested: Internally this is done
@@ -35,29 +35,32 @@ possible to erase something with the other end of the (Wacom) pen.
 
 Usage:
   gromit --quit
-      will cause the main gromit process to quit (or "-q")
+      will cause the main Gromit process to quit (or "-q")
   gromit --toggle
       will toggle the grabbing of the cursor (or "-t")
+  gromit --visibility
+      will toggle the visibility of the window (or "-v")
   gromit --clear
       will clear the screen (or "-c")
 
-If activated gromit prevents you from using other programs with the
+If activated Gromit prevents you from using other programs with the
 mouse. You can press the button and paint on the screen. Key presses
 will still reach the currently active window but it may be difficult
 to change the window-focus without mouse... 
-The next "gromit --toggle" will deactivate gromit and you can use your
+The next "gromit --toggle" will deactivate Gromit and you can use your
 programs as usual - only the painted regions will be obscured.
 
 I included the (shell-)script "sawfish-config". If you are using the
 sawfish-windowmanager you can simply start this script. The "Pause"-Key
 will be bound to the (de)activation, the "Break"-Key (probably
-Shift+Pause) will clear the screen. If you have config-files for other
-window-managers I'd be happy to include them. Please send them to me.
+Shift+Pause) will clear the screen, "Control-Pause" will toccle the
+visibility of Gromit. If you have config-files for other window-managers
+I'd be happy to include them. Please send them to me.
 
 
 Building:
 
-Gromit is small and lightwight. It needs Gtk to build and the Makefile
+Gromit is small and lightwight. It needs GTK+ to build and the Makefile
 is straightforward. No need for autoconf/automake yet  :-)
 Simply type "make" and copy the resulting binary to a convenient place.
 Stripping the binary can reduce its size. I just tested it on
@@ -67,9 +70,9 @@ Linux/XFree86, reports from other platforms are welcome.
 Configuration:
 
 Gromit is configurable via the file ".gromit" in your Homedirectory.
-### not yet, currently it tries to open "gromitconf" in the current directory
 Here you can specify which Device/Button/Modifier combination invokes
-which tool. Example:
+which tool. See the file "gromitconf" distributed with this program for
+an example. An overview on the syntax:
 
      # Comments can be either # Shell-Style or
      /* C-Style. */
@@ -123,15 +126,20 @@ The descision, which tool to use follows a simple policy:
 
 Problems:
 
-Gromit may drastically slow down your X-Server. It makes heavily use of
-the shape extension, which is quite expensive if you paint a complex
-pattern on screen. Especially terminal-programs tend to scroll
-incredibly slow if something is painted over their window. There is
-nothing I can do about this.
-
-Gromit may disable DnD, since this interferes with the special Selection-Code.
-Unfortunately I have no better idea for the (de)activation of Gromit.
-Hopefully I can find a way to work around this.
+Gromit may drastically slow down your X-Server, especially when you draw
+very thin lines. It makes heavily use of the shape extension, which is
+quite expensive if you paint a complex pattern on screen. Especially
+terminal-programs tend to scroll incredibly slow if something is painted
+over their window. There is nothing I can do about this.
+
+Gromit partially disables DnD, since it lays a transparent window across
+the whole screen and everything gets "dropped" to this (invisible)
+window. Gromit tries to minimize this effect: When you clear the screen
+the shaped window will be hidden. It will be resurrected, when you want
+to paint something again. However: The window does not hide, if you
+erase everything with the eraser tool, you have to clear the screen
+explicitely with the "gromit --clear" command or hide Gromit with
+"gromit --visibility".
 
 This Program is distributed under the Gnu General Public License. See
 the file COPYING for details.
diff --git a/gromit.c b/gromit.c
index 1e101f1..119cc5e 100644
--- a/gromit.c
+++ b/gromit.c
@@ -21,6 +21,7 @@
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 
+#include <errno.h>
 #include <fcntl.h>
 
 #include "paint_cursor.xbm"
@@ -34,7 +35,9 @@
 				    GDK_BUTTON_PRESS_MASK | \
 				    GDK_BUTTON_MOTION_MASK \
 				    /* | GDK_POINTER_MOTION_HINT_MASK */ )
-
+ 
+/* #define GROMIT_WINDOW_EVENTS ( GDK_PROPERTY_CHANGE_MASK ) */
+#define GROMIT_WINDOW_EVENTS ( 0 )
 
 /* Atoms used to control Gromit */
 #define GA_CONTROL    gdk_atom_intern ("Gromit/control", FALSE)
@@ -43,8 +46,10 @@
 #define GA_ACTIVATE   gdk_atom_intern ("Gromit/activate", FALSE)
 #define GA_DEACTIVATE gdk_atom_intern ("Gromit/deactivate", FALSE)
 #define GA_TOGGLE     gdk_atom_intern ("Gromit/toggle", FALSE)
+#define GA_VISIBILITY gdk_atom_intern ("Gromit/visibility", FALSE)
 #define GA_CLEAR      gdk_atom_intern ("Gromit/clear", FALSE)
 
+
 typedef enum
 {
    GROMIT_PEN,
@@ -103,9 +108,15 @@ typedef struct
    guint	height;
    guint	hard_grab;
    guint	client;
+   guint	painted;
+   guint	hidden;
 } GromitData;
 
 
+/* I need a prototype...  */
+void gromit_release_grab (GromitData *data);
+void gromit_aquire_grab (GromitData *data);
+
 GromitPaintContext *
 gromit_paint_context_new (GromitData *data, GromitPaintType type,
 			  GdkColor *fg_color, guint width)
@@ -180,56 +191,115 @@ gromit_paint_context_free (GromitPaintContext *context)
 
 
 void
-gromit_toggle_grab (GromitData *data)
+gromit_hide_window (GromitData *data)
+{
+   if (!data->hidden)
+   {
+      if (data->hard_grab)
+	 data->hidden = 2;
+      else
+	 data->hidden = 1;
+      gromit_release_grab (data);
+      gtk_widget_hide (data->win);
+   }
+}
+
+
+void
+gromit_show_window (GromitData *data)
+{
+   gint oldstatus = data->hidden;
+
+   if (data->hidden)
+   {
+      gtk_widget_show (data->win);
+      data->hidden = 0;
+      if (oldstatus == 2)
+	 gromit_aquire_grab (data);
+   }
+   gdk_window_raise (data->win->window);
+}
+
+
+void
+gromit_toggle_visibility (GromitData *data)
+{
+   if (data->hidden)
+      gromit_show_window (data);
+   else
+      gromit_hide_window (data);
+}
+
+
+void
+gromit_release_grab (GromitData *data)
 {
    if (data->hard_grab)
    {
       data->hard_grab = 0;
-      /* gtk_grab_remove (gtk_grab_get_current ()); */
-      g_printerr ("Ungrabbing pointer\n");
       gdk_pointer_ungrab (GDK_CURRENT_TIME);
-      /* gdk_pointer_grab (data->area->window, FALSE, GDK_POINTER_MOTION_MASK,
-                      0, NULL, GDK_CURRENT_TIME); */
-   } else {
-      int foo;
-      /* gtk_grab_add (data->area); */
-      g_printerr ("Grabbing pointer: ");
-      foo = gdk_pointer_grab (data->area->window, FALSE,
-	    GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK |
-	    GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK,
-	    0, NULL /* data->paint_cursor */, GDK_CURRENT_TIME);
-      switch (foo) {
+   }
+   if (!data->painted)
+      gromit_hide_window (data);
+}
+
+
+void
+gromit_aquire_grab (GromitData *data)
+{
+   int result;
+
+   gromit_show_window (data);
+   if (!data->hard_grab)
+   {
+
+      result = gdk_pointer_grab (data->area->window, FALSE,
+	       GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK |
+	       GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK,
+	       0, NULL /* data->paint_cursor */, GDK_CURRENT_TIME);
+      switch (result) {
        	 case Success:
 	    data->hard_grab = 1;
-	    g_printerr ("Success\n");
 	    break;
 	 case GrabNotViewable:
-	    g_printerr ("GrabNotViewable\n");
+	    g_printerr ("Grabbing Pointer failed: %s\n", "GrabNotViewable");
 	    break;
 	 case AlreadyGrabbed:
-	    g_printerr ("AlreadyGrabbed\n");
+	    g_printerr ("Grabbing Pointer failed: %s\n", "AlreadyGrabbed");
 	    break;
 	 case GrabFrozen:
-	    g_printerr ("GrabFrozen\n");
+	    g_printerr ("Grabbing Pointer failed: %s\n", "GrabFrozen");
 	    break;
 	 case GrabInvalidTime:
-	    g_printerr ("GrabInvalidTime\n");
+	    g_printerr ("Grabbing Pointer failed: %s\n", "GrabInvalidTime");
 	    break;
 	 default:
-	    g_printerr ("Huh?\n");
+	    g_printerr ("Grabbing Pointer failed: %s\n", "Unknown error");
       }
-      gdk_window_raise (data->win->window);
    }
 }
 
 
 void
+gromit_toggle_grab (GromitData *data)
+{
+   if (data->hard_grab)
+      gromit_release_grab (data);
+   else
+      gromit_aquire_grab (data);
+}
+
+
+void
 gromit_clear_screen (GromitData *data)
 {
    gdk_gc_set_foreground (data->shape_gc, data->transparent);
    gdk_draw_rectangle (data->shape, data->shape_gc, 1,
 		       0, 0, data->width, data->height);
    gtk_widget_shape_combine_mask (data->win, data->shape, 0,0);
+   if (!data->hard_grab)
+      gromit_hide_window (data);
+   data->painted = 0;
 }
 
 
@@ -248,7 +318,6 @@ reshape (gpointer user_data)
 	 data->delayed = 0;
       }
    }
-
    return 1;
 }
 
@@ -363,11 +432,12 @@ gromit_draw_line (GromitData *data, gint x1, gint y1,
    if (data->cur_context->paint_gc)
       gtk_widget_draw (data->area, &rect);
    
+   data->painted = 1;
 }
 
 
 /*
- * Event-Handlers that perform the drawing
+ * Event-Handlers to perform the drawing
  */
 
 gboolean
@@ -377,7 +447,6 @@ proximity_in (GtkWidget *win, GdkEventProximity *ev, gpointer user_data)
    gint x, y;
    GdkModifierType state;
    
-   g_printerr ("proximity_in\n");
    gdk_window_get_pointer (data->win->window, &x, &y, &state);
    gromit_select_tool (data, ev->deviceid, state);
    return 0;
@@ -389,7 +458,6 @@ proximity_out (GtkWidget *win, GdkEventProximity *ev, gpointer user_data)
 {
    GromitData *data = (GromitData *) user_data;
    
-   g_printerr ("proximity_out\n");
    data->cur_context = data->default_pen;
 
    if (data->cur_context->type == GROMIT_ERASER)
@@ -407,7 +475,6 @@ paint (GtkWidget *win, GdkEventButton *ev, gpointer user_data)
 {
    GromitData *data = (GromitData *) user_data;
    
-   g_printerr ("Button %d\n", ev->button);
    /* See GdkModifierType. Am I fixing a Gtk misbehaviour???  */
    ev->state |= 1 << (ev->button + 7); 
    if (ev->state != data->state || ev->deviceid != data->deviceid)
@@ -467,7 +534,6 @@ paintto (GtkWidget *win, GdkEventMotion *ev, gpointer user_data)
       g_free (coords);
    } else {
       if (ev->is_hint) {
-	 g_printerr ("Hint\n");
 	 gdk_input_window_get_pointer (ev->window, ev->deviceid,
 				       NULL, NULL, NULL, NULL, NULL, NULL);
       }
@@ -499,16 +565,6 @@ quiet_print_handler (const gchar *string)
 }
 
 
-guint
-event_key_snoop (GtkWidget *grab_widget,
-		 GdkEventKey *event,
-		 gpointer func_data)
-{
-   g_printerr ("Got Key!\n");
-   return 0;
-}
-
-
 gboolean
 event_configure (GtkWidget *widget,
 		 GdkEventExpose *event,
@@ -555,6 +611,8 @@ event_selection_get (GtkWidget          *widget,
 
    if (selection_data->target == GA_TOGGLE)
       gromit_toggle_grab (data);
+   else if (selection_data->target == GA_VISIBILITY)
+      gromit_toggle_visibility (data);
    else if (selection_data->target == GA_CLEAR)
       gromit_clear_screen (data);
    else if (selection_data->target == GA_QUIT)
@@ -662,6 +720,7 @@ gint parse_config (GromitData *data) {
    GromitPaintContext *context_template=NULL;
    GScanner *scanner;
    GTokenType token;
+   gchar *filename;
    int file;
 
    gchar *name, *copy;
@@ -672,7 +731,18 @@ gint parse_config (GromitData *data) {
 
    guint buttons, modifier;
 
+   filename = g_strjoin (G_DIR_SEPARATOR_S, g_get_home_dir(), ".gromit", NULL);
+   file = open (filename, O_RDONLY);
+
+   if (file < 0)
+   {
+      g_printerr ("Could not open %s: %s\n", filename, g_strerror (errno));
+      g_free (filename);
+      return;
+   }
+
    scanner = g_scanner_new (NULL);
+   scanner->input_name = filename;
    scanner->config->case_sensitive = 0;
    scanner->config->scan_octal = 0;
    scanner->config->identifier_2_string = 0;
@@ -700,7 +770,6 @@ gint parse_config (GromitData *data) {
    g_scanner_set_scope (scanner, 0);
    scanner->config->scope_0_fallback = 0;
 
-   file = open ("./gromitconf", O_RDONLY);
    g_scanner_input_file (scanner, file);
    
    token = g_scanner_get_next_token (scanner);
@@ -828,6 +897,7 @@ gint parse_config (GromitData *data) {
    }
    g_scanner_destroy (scanner);
    close (file);
+   g_free (filename);
 
    g_printerr ("\n-----------------------------\n");
    g_hash_table_foreach (data->tool_config, parse_print_help, NULL);
@@ -850,15 +920,19 @@ setup_input_devices ()
    while (tmp_list)
    {
       GdkDeviceInfo *info = (GdkDeviceInfo *) tmp_list->data;
-      if (strstr (info->name, "raser"))  /* Guess "Eraser"-Type devices */
-	 gdk_input_set_source (info->deviceid, GDK_SOURCE_ERASER);
 
-      g_printerr ("Enabling No. %d: \"%s\" (Type: %d)\n",
-		  info->deviceid, info->name, info->source);
+      /* Guess "Eraser"-Type devices */
+      if (strstr (info->name, "raser") ||
+	  strstr (info->name, "RASER")) 
+	 gdk_input_set_source (info->deviceid, GDK_SOURCE_ERASER);
 
+      /* Dont touch the "SWITCH"-Device - this seems to confuse GDK */
       if (! strstr (info->name, "SWITCH"))
-	 /* Dont touch the "SWITCH"-Device - this seems to confuse Gtk+ */
+      {
+	 g_printerr ("Enabling No. %d: \"%s\" (Type: %d)\n",
+		     info->deviceid, info->name, info->source);
 	 gdk_input_set_mode (info->deviceid, GDK_MODE_SCREEN);
+      }
 
       tmp_list = tmp_list->next;
    }
@@ -877,6 +951,8 @@ setup_client_app (GromitData *data)
    gtk_widget_set_usize (GTK_WIDGET (data->win), data->width, data->height);
    gtk_widget_set_uposition (GTK_WIDGET (data->win), 0, 0);
 
+   gtk_widget_set_events (data->win, GROMIT_WINDOW_EVENTS);
+
    gtk_signal_connect (GTK_OBJECT (data->win), "delete-event", 
 		       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
    gtk_signal_connect (GTK_OBJECT (data->win), "destroy", 
@@ -893,6 +969,7 @@ void
 setup_main_app (GromitData *data)
 {
    GdkPixmap *cursor_src, *cursor_mask;
+   Window xwin;
 
    /* COLORMAP */
    data->cm = gdk_colormap_get_system ();
@@ -971,7 +1048,12 @@ setup_main_app (GromitData *data)
 
    gtk_widget_shape_combine_mask (data->win, data->shape, 0,0);
 
-   gtk_widget_show_all (data->win);
+   gtk_widget_show_all (data->area);
+
+   gtk_widget_realize (data->win);
+
+   data->painted = 0;
+   gromit_hide_window (data);
 
    data->timeout_id = gtk_timeout_add (20, reshape, data);
    data->modified = 0;
@@ -979,6 +1061,7 @@ setup_main_app (GromitData *data)
    data->default_pen = gromit_paint_context_new (data, GROMIT_PEN, data->red, 7);
    data->default_eraser = gromit_paint_context_new (data, GROMIT_ERASER, data->red, 75);
 
+
    /*
     * Parse Config file
     */
@@ -994,7 +1077,8 @@ setup_main_app (GromitData *data)
    gtk_selection_add_target (data->win, GA_CONTROL, GA_ACTIVATE, 2);
    gtk_selection_add_target (data->win, GA_CONTROL, GA_DEACTIVATE, 3);
    gtk_selection_add_target (data->win, GA_CONTROL, GA_TOGGLE, 4);
-   gtk_selection_add_target (data->win, GA_CONTROL, GA_CLEAR, 5);
+   gtk_selection_add_target (data->win, GA_CONTROL, GA_VISIBILITY, 5);
+   gtk_selection_add_target (data->win, GA_CONTROL, GA_CLEAR, 6);
 
    setup_input_devices ();
 }
@@ -1018,6 +1102,9 @@ main_client (int argc, char **argv, GromitData *data)
       if (strcmp (arg, "-t") == 0 ||
 	  strcmp (arg, "--toggle") == 0)
 	 action = GA_TOGGLE;
+      else if (strcmp (arg, "-v") == 0 ||
+	       strcmp (arg, "--visibility") == 0)
+	 action = GA_VISIBILITY;
       else if (strcmp (arg, "-q") == 0 ||
 	       strcmp (arg, "--quit") == 0)
 	 action = GA_QUIT;
@@ -1058,6 +1145,7 @@ main (int argc, char **argv)
 
    if (data->client)
       return main_client (argc, argv, data);
+   data->client = FALSE;
 
    /* Main application */
    setup_main_app (data);
diff --git a/sawfish-config b/sawfish-config
index 2eb56ed..69c5118 100755
--- a/sawfish-config
+++ b/sawfish-config
@@ -23,7 +23,16 @@ sawfish-client -- >/dev/null <<ENDOFSAWFISHCONFIG
    (system "cd \"$LOCATION\" ; ./gromit --clear &")
 )
 
+(defun gromit-toggle-visibility ()
+   (interactive)
+   (ungrab-pointer)
+   (ungrab-keyboard)
+   (sync-server)
+   (system "cd \"$LOCATION\" ; ./gromit --visibility &")
+)
+
 (bind-keys global-keymap "Pause" 'gromit-toggle-grab)
+(bind-keys global-keymap "C-Pause" 'gromit-toggle-visibility)
 (bind-keys global-keymap "Break" 'gromit-clear-screen)
 
 ENDOFSAWFISHCONFIG



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]