/***************** Electirc Eyes ***********************/ /* This software is Copyright (C) 1998 but The Rasterman (Carsten Haitzler). */ /* This software falls under the GNU Public License. Please read the COPYING */ /* file for more information */ /*****************************************************************************/ #include #include #include #include #include #include #include "globals.h" static void ee_grab_draw_selection(void); static void ee_grab_out_window(GtkWidget *widget, gpointer data); static void ee_grab_in_window(GtkWidget *widget, gpointer data); static void ee_grab_hide(GtkWidget *widget, gpointer data); static void ee_grab_time_changed(GtkObject *widget, gpointer data); static void ee_grab_window(GtkWidget *widget, gpointer data); static void ee_grab_delay(GtkObject *widget, gpointer data); static void ee_grab_cancel(GtkWidget *widget, gpointer data); static void * AtomGet(Display *disp, Window win, Atom to_get, Atom type, int *size); static void ee_grab_make_winlist(void); static gint stack_member = 0; static gint stack_count = 0; static GList *window_stack = NULL; static gint hide = 0; static gint wtime = 5; static gchar show_list = 0, show_edit = 0; static void ee_grab_draw_selection(void) { Display *disp; Window win, root, chld; GC gc; XGCValues gcv; int rx, ry, dd; unsigned int w, h, d; gint i; GList *gl; disp = GDK_DISPLAY(); gl = g_list_nth(window_stack, stack_member); if (!gl) return; win = (Window)gl->data; XGetGeometry(disp, win, &root, &dd, &dd, &w, &h, &d, &d); XTranslateCoordinates(disp, win, root, 0, 0, &rx, &ry, &chld); XGrabServer(disp); gcv.function = GXxor; gcv.foreground = WhitePixel(disp, DefaultScreen(disp)); if (gcv.foreground == 0) gcv.foreground = 1; gcv.subwindow_mode = IncludeInferiors; gc = XCreateGC(disp, root, GCFunction | GCForeground | GCSubwindowMode, &gcv); for (i = 0; i < 16; i++) { XFillRectangle(disp, root, gc, rx, ry, w, h); XSync(disp, False); usleep(20000); } XFreeGC(disp, gc); XUngrabServer(disp); } static void * AtomGet(Display *disp, Window win, Atom to_get, Atom type, int *size) { unsigned char *retval; Atom type_ret; unsigned long bytes_after, num_ret; int format_ret; long length; void *data; retval = NULL; length = 0x7fffffff; XGetWindowProperty(disp, win, to_get, 0, length, False, type, &type_ret, &format_ret, &num_ret, &bytes_after, &retval); if ((retval) && (num_ret > 0) && (format_ret > 0)) { data = g_malloc(num_ret * (format_ret >> 3)); if (data) memcpy(data, retval, num_ret * (format_ret >> 3)); XFree(retval); *size = num_ret * (format_ret >> 3); return data; } return NULL; } static void ee_grab_make_winlist(void) { unsigned int w, h, d, pw, ph, px, py, count; Display *disp; Window win, dwin, par, *lst, root; GList *gl; int x, y; gint i; Atom a; void *data; stack_member = 0; disp = GDK_DISPLAY(); gl = g_list_nth(window_stack, stack_member); if (!gl) return; win = (Window)gl->data; XGetGeometry(disp, win, &root, &x, &y, &w, &h, &d, &d); if (win == root) { ee_grab_draw_selection(); return; } do { do { px = x; py = y; pw = w; ph = h; XQueryTree(disp, win, &dwin, &par, &lst, &count); if (count > 0) XFree(lst); win = par; XGetGeometry(disp, win, &root, &x, &y, &w, &h, &d, &d); window_stack = g_list_append(window_stack, (gpointer)win); stack_member++; } while ((pw == w) && (ph == h) && (px == 0) && (py == 0) && (par != GDK_ROOT_WINDOW())); } while (win != root); stack_count = stack_member + 1; a = XInternAtom(disp, "WM_STATE", False); for (i = 0; i < stack_count; i++) { gl = g_list_nth(window_stack, i); if (!gl) return; win = (Window)gl->data; data = AtomGet(disp, win, a, a, &x); if (data) { g_free(data); stack_member = i; i = stack_count; } } ee_grab_draw_selection(); } static void ee_grab_out_window(GtkWidget *widget, gpointer data) { stack_member++; if (stack_member >= stack_count) stack_member = stack_count - 1; ee_grab_draw_selection(); widget = NULL; data = NULL; } static void ee_grab_in_window(GtkWidget *widget, gpointer data) { stack_member--; if (stack_member < 0) stack_member = 0; ee_grab_draw_selection(); widget = NULL; data = NULL; } static void ee_grab_hide(GtkWidget *widget, gpointer data) { if (hide) hide = 0; else hide = 1; widget = NULL; data = NULL; } void ee_grab_select_window(void) { Display *disp; Window pwin, nwin, win, rwin; XEvent ev; int d; unsigned int mask; Cursor c; disp = GDK_DISPLAY(); win = GDK_ROOT_WINDOW(); XSelectInput(disp, win, ButtonReleaseMask); c = XCreateFontCursor(disp, XC_question_arrow); XGrabPointer(disp, win, True, ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, c, CurrentTime); XFreeCursor(disp, c); XMaskEvent(disp, ButtonReleaseMask, &ev); XUngrabPointer(disp, CurrentTime); nwin = 1; while (nwin) { pwin = win; XQueryPointer(disp, win, &rwin, &win, &d, &d, &d, &d, &mask); nwin = win; } win = pwin; if (window_stack) g_list_free(window_stack); window_stack = NULL; window_stack = g_list_append(window_stack, (gpointer)win); stack_member = 0; } static void ee_grab_time_changed(GtkObject *widget, gpointer data) { wtime = (gint)GTK_ADJUSTMENT(widget)->value; data = NULL; } static void ee_grab_window(GtkWidget *widget, gpointer data) { GdkImlibImage *im; gint w, h; Display *disp; GList *gl; Window win; GdkWindow *gwin; if (widget) gtk_widget_destroy((GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "widget")); disp = GDK_DISPLAY(); gl = g_list_nth(window_stack, stack_member); if (!gl) return; win = (Window)gl->data; if (hide) { if ((image_display) && (GTK_WIDGET_VISIBLE(image_display))) gtk_widget_hide(image_display); if ((file_selector) && (GTK_WIDGET_VISIBLE(file_selector))) gtk_widget_hide(file_selector); if ((image_list) && (GTK_WIDGET_VISIBLE(image_list))) { show_list = 1; gtk_widget_hide(image_list); } if ((edit_window) && (GTK_WIDGET_VISIBLE(edit_window))) { show_edit = 1; gtk_widget_hide(edit_window); } if ((main_menu) && (GTK_WIDGET_VISIBLE(main_menu))) gtk_widget_hide(main_menu); } while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); gwin = gdk_window_foreign_new(win); gdk_window_get_size(gwin, &w, &h); im = gdk_imlib_create_image_from_drawable(gwin, NULL, 0, 0, w, h); ee_image_set_filename(image_display, "DisplayGrab.ppm"); ee_image_set_image(image_display, im); ee_image_set_filename(image_display, "DisplayGrab.ppm"); if (hide) { gtk_widget_show(image_display); if (show_list) gtk_widget_show(image_list); if (show_edit) gtk_widget_show(edit_window); } widget = NULL; data = NULL; } static void ee_grab_delay(GtkObject *widget, gpointer data) { gtk_widget_destroy(GTK_WIDGET(data)); if (hide) { if ((image_display) && (GTK_WIDGET_VISIBLE(image_display))) gtk_widget_hide(image_display); if ((file_selector) && (GTK_WIDGET_VISIBLE(file_selector))) gtk_widget_hide(file_selector); if ((image_list) && (GTK_WIDGET_VISIBLE(image_list))) { show_list = 1; gtk_widget_hide(image_list); } if ((edit_window) && (GTK_WIDGET_VISIBLE(edit_window))) { show_edit = 1; gtk_widget_hide(edit_window); } if ((main_menu) && (GTK_WIDGET_VISIBLE(main_menu))) gtk_widget_hide(main_menu); } while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); sleep(wtime); ee_grab_window(NULL, NULL); widget = NULL; } static void ee_grab_cancel(GtkWidget *widget, gpointer data) { gtk_widget_destroy(GTK_WIDGET(data)); widget = NULL; } GtkWidget * ee_grab_new(void) { GtkWidget *w, *t, *e, *l, *b, *h; GtkAdjustment *adj; w = gnome_dialog_new(_("Grab Options"), GNOME_STOCK_BUTTON_OK, GNOME_STOCK_BUTTON_CANCEL, NULL); gtk_widget_realize(w); t = gtk_table_new(4, 3, FALSE); gtk_widget_show(t); gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(w)->vbox), t, TRUE, TRUE, 5); gtk_table_set_row_spacings(GTK_TABLE(t), 4); gtk_table_set_col_spacings(GTK_TABLE(t), 4); l = gtk_label_new(_("Number of seconds to wait:")); gtk_widget_show(l); gtk_table_attach_defaults(GTK_TABLE(t), l, 0, 1, 0, 1); adj = GTK_ADJUSTMENT(gtk_adjustment_new(5.0, 0.0, 99.0, 1.0, 1.0, 1.0)); gtk_signal_connect(GTK_OBJECT(adj), "value_changed", GTK_SIGNAL_FUNC(ee_grab_time_changed), NULL); e = gtk_spin_button_new(adj, 1.0, 0); gtk_widget_show(e); gtk_table_attach_defaults(GTK_TABLE(t), e, 1, 3, 0, 1); b = gtk_check_button_new_with_label(_("Hide EE windows")); gtk_widget_show(b); gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(ee_grab_hide), NULL); gtk_table_attach_defaults(GTK_TABLE(t), b, 0, 1, 1, 2); l = gtk_label_new(_("Selected window hierachy depth:")); gtk_widget_show(l); gtk_table_attach_defaults(GTK_TABLE(t), l, 0, 1, 2, 3); b = gtk_button_new(); l = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); gtk_widget_show(l); gtk_container_add(GTK_CONTAINER(b), l); gtk_widget_show(b); gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(ee_grab_in_window), NULL); gtk_table_attach_defaults(GTK_TABLE(t), b, 1, 2, 2, 3); b = gtk_button_new(); l = gtk_arrow_new(GTK_ARROW_UP, GTK_SHADOW_OUT); gtk_widget_show(l); gtk_container_add(GTK_CONTAINER(b), l); gtk_widget_show(b); gtk_signal_connect(GTK_OBJECT(b), "clicked", GTK_SIGNAL_FUNC(ee_grab_out_window), NULL); gtk_table_attach_defaults(GTK_TABLE(t), b, 2, 3, 2, 3); gtk_hbutton_box_set_spacing_default(4); h = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(h), GTK_BUTTONBOX_SPREAD); gtk_widget_show(h); gtk_table_attach_defaults(GTK_TABLE(t), h, 0, 3, 3, 4); gtk_object_set_data(GTK_OBJECT(w), "widget", w); gnome_dialog_button_connect(GNOME_DIALOG(w), 0, GTK_SIGNAL_FUNC(ee_grab_delay), w); gnome_dialog_button_connect(GNOME_DIALOG(w), 1, GTK_SIGNAL_FUNC(ee_grab_cancel), w); wtime = 5; ee_grab_make_winlist(); return w; }