metacity-mag.c

Go to the documentation of this file.
00001 /* Hack for use instead of xmag */
00002 
00003 /* 
00004  * Copyright (C) 2002 Red Hat Inc.
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019  * 02111-1307, USA.
00020  */
00021 
00022 #define _GNU_SOURCE
00023 #define _XOPEN_SOURCE 600 /* C99 -- for rint() */
00024 
00025 #include <gtk/gtk.h>
00026 #include <gdk/gdkx.h>
00027 #include <gdk/gdkkeysyms.h>
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 
00032 static GtkWidget *grab_widget = NULL;
00033 static GtkWidget *display_window = NULL;
00034 static int last_grab_x = 0;
00035 static int last_grab_y = 0;
00036 static int last_grab_width = 150;
00037 static int last_grab_height = 150;
00038 static GtkAllocation last_grab_allocation;
00039 static double width_factor = 4.0;
00040 static double height_factor = 4.0;
00041 static GdkInterpType interp_mode = GDK_INTERP_NEAREST;
00042 static guint regrab_idle_id = 0;
00043 
00044 static GdkPixbuf*
00045 get_pixbuf (void)
00046 {
00047   GdkPixbuf *screenshot;
00048   GdkPixbuf *magnified;
00049 
00050 #if 0
00051   g_print ("Size %d x %d\n",
00052            last_grab_width, last_grab_height);
00053 #endif
00054   
00055   screenshot = gdk_pixbuf_get_from_drawable (NULL, gdk_get_default_root_window (),
00056                                              NULL,
00057                                              last_grab_x, last_grab_y, 0, 0,
00058                                              last_grab_width, last_grab_height);
00059 
00060   if (screenshot == NULL)
00061     {
00062       g_printerr ("Screenshot failed\n");
00063       exit (1);
00064     }
00065 
00066   magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor,
00067                                        last_grab_height * height_factor,
00068                                        interp_mode);
00069 
00070 
00071   g_object_unref (G_OBJECT (screenshot));
00072 
00073   return magnified;
00074 }
00075 
00076 static gboolean
00077 regrab_idle (GtkWidget *image)
00078 {
00079   GdkPixbuf *magnified;
00080   
00081   if (image->allocation.width != last_grab_allocation.width ||
00082       image->allocation.height != last_grab_allocation.height)
00083     {
00084       last_grab_width = rint (image->allocation.width / width_factor);
00085       last_grab_height = rint (image->allocation.height / height_factor);
00086       last_grab_allocation = image->allocation;
00087       
00088       magnified = get_pixbuf ();
00089 
00090       gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified);
00091 
00092       g_object_unref (G_OBJECT (magnified));
00093     }
00094 
00095   regrab_idle_id = 0;
00096   
00097   return FALSE;
00098 }
00099 
00100 static void
00101 image_resized (GtkWidget *image)
00102 {
00103   if (regrab_idle_id == 0)
00104     regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle,
00105                                       image, NULL);
00106 }
00107 
00108 static void
00109 grab_area_at_mouse (GtkWidget *invisible,
00110                     int        x_root,
00111                     int        y_root)
00112 {
00113   GdkPixbuf *magnified;
00114   int width, height;
00115   GtkWidget *widget;
00116   
00117   width = last_grab_width;
00118   height = last_grab_height;
00119 
00120   last_grab_x = x_root;
00121   last_grab_y = y_root;
00122   last_grab_width = width;
00123   last_grab_height = height;
00124   
00125   magnified = get_pixbuf ();
00126   
00127   display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
00128   gtk_window_set_default_size (GTK_WINDOW (display_window),
00129                                last_grab_width, last_grab_height);
00130   widget = gtk_image_new_from_pixbuf (magnified);
00131   gtk_widget_set_size_request (widget, 40, 40);
00132   gtk_container_add (GTK_CONTAINER (display_window), widget);
00133   g_object_unref (G_OBJECT (magnified));
00134 
00135   g_object_add_weak_pointer (G_OBJECT (display_window),
00136                              (gpointer) &display_window);
00137 
00138   g_signal_connect (G_OBJECT (display_window), "destroy",
00139                     G_CALLBACK (gtk_main_quit), NULL);
00140 
00141   g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL);
00142   
00143   gtk_widget_show_all (display_window);
00144 }
00145 
00146 static void
00147 shutdown_grab (void)
00148 {
00149   gdk_keyboard_ungrab (gtk_get_current_event_time ());
00150   gdk_pointer_ungrab (gtk_get_current_event_time ());
00151   gtk_grab_remove (grab_widget);
00152 }
00153 
00154 static void
00155 mouse_motion (GtkWidget      *invisible,
00156               GdkEventMotion *event,
00157               gpointer        data)
00158 {
00159   
00160 }
00161 
00162 static gboolean
00163 mouse_release (GtkWidget      *invisible,
00164                GdkEventButton *event,
00165                gpointer        data)
00166 {
00167   if (event->button != 1)
00168     return FALSE;
00169 
00170   grab_area_at_mouse (invisible, event->x_root, event->y_root);
00171 
00172   shutdown_grab ();
00173   
00174   gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00175                                  GTK_SIGNAL_FUNC (mouse_motion), NULL);
00176   gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00177                                  GTK_SIGNAL_FUNC (mouse_release), NULL);
00178 
00179   return TRUE;
00180 }
00181 
00182 /* Helper Functions */
00183 
00184 static gboolean mouse_press (GtkWidget      *invisible,
00185                              GdkEventButton *event,
00186                              gpointer        data);
00187 
00188 static gboolean
00189 key_press (GtkWidget   *invisible,
00190            GdkEventKey *event,
00191            gpointer     data)
00192 {  
00193   if (event->keyval == GDK_Escape)
00194     {
00195       shutdown_grab ();
00196 
00197       gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00198                                      GTK_SIGNAL_FUNC (mouse_press),
00199                                      NULL);
00200       gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00201                                      GTK_SIGNAL_FUNC (key_press),
00202                                      NULL);
00203       
00204       return TRUE;
00205     }
00206 
00207   return FALSE;
00208 }
00209 
00210 static gboolean
00211 mouse_press (GtkWidget      *invisible,
00212              GdkEventButton *event,
00213              gpointer        data)
00214 {  
00215   if (event->type == GDK_BUTTON_PRESS &&
00216       event->button == 1)
00217     {
00218       g_signal_connect (invisible, "motion_notify_event",
00219                         G_CALLBACK (mouse_motion), NULL);
00220       g_signal_connect (invisible, "button_release_event",
00221                         G_CALLBACK (mouse_release), NULL);
00222       gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00223                                      GTK_SIGNAL_FUNC (mouse_press),
00224                                      NULL);
00225       gtk_signal_disconnect_by_func (GTK_OBJECT (invisible),
00226                                      GTK_SIGNAL_FUNC (key_press),
00227                                      NULL);
00228       return TRUE;
00229     }
00230 
00231   return FALSE;
00232 }
00233 
00234 static void
00235 begin_area_grab (void)
00236 {
00237   if (grab_widget == NULL)
00238     {
00239       grab_widget = gtk_invisible_new ();
00240 
00241       gtk_widget_add_events (grab_widget,
00242                              GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
00243       
00244       gtk_widget_show (grab_widget);
00245     }
00246 
00247   if (gdk_keyboard_grab (grab_widget->window,
00248                          FALSE,
00249                          gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
00250     {
00251       g_warning ("Failed to grab keyboard to do eyedropper");
00252       return;
00253     }
00254   
00255   if (gdk_pointer_grab (grab_widget->window,
00256                         FALSE,
00257                         GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
00258                         NULL,
00259                         NULL,
00260                         gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
00261     {
00262       gdk_keyboard_ungrab (GDK_CURRENT_TIME);
00263       g_warning ("Failed to grab pointer to do eyedropper");
00264       return;
00265     }
00266 
00267   gtk_grab_add (grab_widget);
00268   
00269   g_signal_connect (grab_widget, "button_press_event",
00270                     G_CALLBACK (mouse_press), NULL);
00271   g_signal_connect (grab_widget, "key_press_event",
00272                     G_CALLBACK (key_press), NULL);
00273 }
00274 
00275 int
00276 main (int argc, char **argv)
00277 {
00278   gtk_init (&argc, &argv);
00279 
00280   begin_area_grab ();
00281   
00282   gtk_main ();
00283   
00284   return 0;
00285 }

Generated on Sat Aug 23 22:04:18 2008 for metacity by  doxygen 1.5.5