Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:civ75:fix
gnome-utils
gnome-utils-screenshot-select-area.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gnome-utils-screenshot-select-area.patch of Package gnome-utils
Index: gnome-utils-2.24.1/gnome-screenshot/gnome-screenshot.c =================================================================== --- gnome-utils-2.24.1.orig/gnome-screenshot/gnome-screenshot.c +++ gnome-utils-2.24.1/gnome-screenshot/gnome-screenshot.c @@ -87,6 +87,7 @@ typedef struct int iteration; TestType type; GdkWindow *window; + GdkRectangle *rectangle; } AsyncExistenceJob; static GdkPixbuf *screenshot = NULL; @@ -99,6 +100,7 @@ static gboolean save_immediately = FALSE /* Options */ static gboolean take_window_shot = FALSE; +static gboolean take_area_shot = FALSE; static gboolean include_border = FALSE; static gboolean include_pointer = TRUE; static char *border_effect = NULL; @@ -150,15 +152,20 @@ interactive_dialog_response_cb (GtkDialo } } +#define TARGET_TOGGLE_DESKTOP 0 +#define TARGET_TOGGLE_WINDOW 1 +#define TARGET_TOGGLE_AREA 2 + static void target_toggled_cb (GtkToggleButton *button, gpointer data) { - gboolean window_selected = (GPOINTER_TO_INT (data) == TRUE ? TRUE : FALSE); + int target_toggle = GPOINTER_TO_INT (data); if (gtk_toggle_button_get_active (button)) { - take_window_shot = window_selected; + take_window_shot = (target_toggle == TARGET_TOGGLE_WINDOW); + take_area_shot = (target_toggle == TARGET_TOGGLE_AREA); gtk_widget_set_sensitive (border_check, take_window_shot); gtk_widget_set_sensitive (effect_combo, take_window_shot); @@ -423,11 +430,11 @@ create_screenshot_frame (GtkWidget *ou group = NULL; radio = gtk_radio_button_new_with_mnemonic (group, _("Grab the whole _desktop")); - if (take_window_shot) + if (take_window_shot || take_area_shot) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), FALSE); g_signal_connect (radio, "toggled", G_CALLBACK (target_toggled_cb), - GINT_TO_POINTER (FALSE)); + GINT_TO_POINTER (TARGET_TOGGLE_DESKTOP)); gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0); group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); gtk_widget_show (radio); @@ -439,7 +446,19 @@ create_screenshot_frame (GtkWidget *ou gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); g_signal_connect (radio, "toggled", G_CALLBACK (target_toggled_cb), - GINT_TO_POINTER (TRUE)); + GINT_TO_POINTER (TARGET_TOGGLE_WINDOW)); + gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0); + group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio)); + gtk_widget_show (radio); + + /** Grab area of the desktop **/ + radio = gtk_radio_button_new_with_mnemonic (group, + _("Grab a selected _area")); + if (take_area_shot) + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + g_signal_connect (radio, "toggled", + G_CALLBACK (target_toggled_cb), + GINT_TO_POINTER (TARGET_TOGGLE_AREA)); gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0); gtk_widget_show (radio); @@ -710,13 +729,16 @@ run_dialog (ScreenshotDialog *dialog) } static void -finish_prepare_screenshot (char *initial_uri, GdkWindow *window) +finish_prepare_screenshot (char *initial_uri, GdkWindow *window, GdkRectangle *rectangle) { ScreenshotDialog *dialog; - screenshot = screenshot_get_pixbuf (window, include_pointer, include_border); + /* always disable window border for full-desktop or selected-area screenshots */ + if (!take_window_shot) + screenshot = screenshot_get_pixbuf (window, rectangle, include_pointer, FALSE); + else { + screenshot = screenshot_get_pixbuf (window, rectangle, include_pointer, include_border); - if (take_window_shot) { switch (border_effect[0]) { case 's': /* shadow */ @@ -750,20 +772,27 @@ finish_prepare_screenshot (char *initial run_dialog (dialog); } +static void +async_existence_job_free (AsyncExistenceJob *job) +{ + if (!job) + return; + + g_free (job->base_uris[1]); + g_free (job->base_uris[2]); + g_free (job->rectangle); + g_slice_free (AsyncExistenceJob, job); +} + static gboolean check_file_done (gpointer user_data) { - char *retval; - GdkWindow *window; AsyncExistenceJob *job = user_data; - window = job->window; - retval = job->retval; - g_free (job->base_uris[1]); - g_slice_free (AsyncExistenceJob, job); - - finish_prepare_screenshot (retval, window); - + finish_prepare_screenshot (job->retval, job->window, job->rectangle); + + async_existence_job_free (job); + return FALSE; } @@ -919,6 +948,30 @@ find_current_window (char **window_title return window; } +static GdkRectangle * +find_rectangle (void) +{ + GdkRectangle *rectangle; + + if (!take_area_shot) + return NULL; + + rectangle = g_new0 (GdkRectangle, 1); + if (screenshot_select_area (&rectangle->x, &rectangle->y, + &rectangle->width, &rectangle->height)) + { + g_assert (rectangle->width >= 0); + g_assert (rectangle->height >= 0); + + return rectangle; + } + else + { + g_free (rectangle); + return NULL; + } +} + static void prepare_screenshot (void) { @@ -932,6 +985,16 @@ prepare_screenshot (void) job->iteration = 0; job->type = TEST_LAST_DIR; job->window = find_current_window (&window_title); + job->rectangle = find_rectangle (); + + /* Check if the area selection was cancelled */ + if (job->rectangle && + (job->rectangle->width == 0 || job->rectangle->height == 0)) + { + async_existence_job_free (job); + gtk_main_quit (); + return; + } g_io_scheduler_push_job (try_check_file, job, @@ -1121,6 +1184,7 @@ main (int argc, char *argv[]) GOptionContext *context; GOptionGroup *group; gboolean window_arg = FALSE; + gboolean area_arg = FALSE; gboolean include_border_arg = FALSE; gboolean disable_border_arg = FALSE; gboolean interactive_arg = FALSE; @@ -1129,6 +1193,7 @@ main (int argc, char *argv[]) const GOptionEntry entries[] = { { "window", 'w', 0, G_OPTION_ARG_NONE, &window_arg, N_("Grab a window instead of the entire screen"), NULL }, + { "area", 'a', 0, G_OPTION_ARG_NONE, &area_arg, N_("Grab an area of the screen instead of the entire screen"), NULL }, { "include-border", 'b', 0, G_OPTION_ARG_NONE, &include_border_arg, N_("Include the window border with the screenshot"), NULL }, { "remove-border", 'B', 0, G_OPTION_ARG_NONE, &disable_border_arg, "Remove the window border from the screenshot", NULL }, { "delay", 'd', 0, G_OPTION_ARG_INT, &delay_arg, N_("Take screenshot after specified delay [in seconds]"), N_("seconds") }, @@ -1153,6 +1218,13 @@ main (int argc, char *argv[]) GNOME_PARAM_GOPTION_CONTEXT, context, GNOME_PROGRAM_STANDARD_PROPERTIES, NULL); + + if (window_arg && area_arg) { + g_printerr (_("Conflicting options: --window and --area should not be " + "used at the same time.\n")); + exit (1); + } + gtk_window_set_default_icon_name (SCREENSHOOTER_ICON); screenshooter_init_stock_icons (); @@ -1161,6 +1233,9 @@ main (int argc, char *argv[]) if (window_arg) take_window_shot = TRUE; + if (area_arg) + take_area_shot = TRUE; + if (include_border_arg) include_border = TRUE; Index: gnome-utils-2.24.1/gnome-screenshot/screenshot-utils.c =================================================================== --- gnome-utils-2.24.1.orig/gnome-screenshot/screenshot-utils.c +++ gnome-utils-2.24.1/gnome-screenshot/screenshot-utils.c @@ -253,6 +253,211 @@ screenshot_find_current_window () return current_window; } +static void +select_area_button_press (XKeyEvent *event, + GdkRectangle *rect, + GdkRectangle *draw_rect) +{ + rect->x = event->x_root; + rect->y = event->y_root; + + draw_rect->x = rect->x; + draw_rect->y = rect->y; + draw_rect->width = 0; + draw_rect->height = 0; +} + +static void +select_area_button_release (XKeyEvent *event, + GdkRectangle *rect, + GdkRectangle *draw_rect, + GdkWindow *root, + GC x_gc) +{ + /* remove the old rectangle */ + if (draw_rect->width > 0 && draw_rect->height > 0) + XDrawRectangle (gdk_display, GDK_WINDOW_XID (root), x_gc, + draw_rect->x, draw_rect->y, + draw_rect->width, draw_rect->height); + + rect->width = ABS (rect->x - event->x_root); + rect->height = ABS (rect->y - event->y_root); + + rect->x = MIN (rect->x, event->x_root); + rect->y = MIN (rect->y, event->y_root); +} + +static void +select_area_motion_notify (XKeyEvent *event, + GdkRectangle *rect, + GdkRectangle *draw_rect, + GdkWindow *root, + GC x_gc) +{ + /* FIXME: draw some nice rubberband with cairo if composited */ + + /* remove the old rectangle */ + if (draw_rect->width > 0 && draw_rect->height > 0) + XDrawRectangle (gdk_display, GDK_WINDOW_XID (root), x_gc, + draw_rect->x, draw_rect->y, + draw_rect->width, draw_rect->height); + + draw_rect->width = ABS (rect->x - event->x_root); + draw_rect->height = ABS (rect->y - event->y_root); + + draw_rect->x = MIN (rect->x, event->x_root); + draw_rect->y = MIN (rect->y, event->y_root); + + /* draw the new rectangle */ + if (draw_rect->width > 0 && draw_rect->height > 0) + XDrawRectangle (gdk_display, GDK_WINDOW_XID (root), x_gc, + draw_rect->x, draw_rect->y, + draw_rect->width, draw_rect->height); +} + +typedef struct { + GdkRectangle rect; + GdkRectangle draw_rect; + gboolean button_pressed; + /* only needed because we're using some X primitives to draw the rectangle */ + GdkWindow *root; + GC x_gc; +} select_area_filter_data; + +static GdkFilterReturn +select_area_filter (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer user_data) +{ + select_area_filter_data *data = user_data; + XEvent *xevent = (XEvent *) gdk_xevent; + + switch (xevent->type) + { + case ButtonPress: + if (!data->button_pressed) + { + select_area_button_press (&xevent->xkey, + &data->rect, &data->draw_rect); + data->button_pressed = TRUE; + } + return GDK_FILTER_REMOVE; + case ButtonRelease: + if (data->button_pressed) + { + select_area_button_release (&xevent->xkey, + &data->rect, &data->draw_rect, + data->root, data->x_gc); + gtk_main_quit (); + } + return GDK_FILTER_REMOVE; + case MotionNotify: + if (data->button_pressed) + select_area_motion_notify (&xevent->xkey, + &data->rect, &data->draw_rect, + data->root, data->x_gc); + return GDK_FILTER_REMOVE; + case KeyPress: + if (xevent->xkey.keycode == XKeysymToKeycode (gdk_display, XK_Escape)) + { + data->rect.x = 0; + data->rect.y = 0; + data->rect.width = 0; + data->rect.height = 0; + gtk_main_quit (); + return GDK_FILTER_REMOVE; + } + break; + default: + break; + } + + return GDK_FILTER_CONTINUE; +} + +gboolean +screenshot_select_area (int *px, + int *py, + int *pwidth, + int *pheight) +{ + GdkWindow *root; + GdkCursor *cursor; + select_area_filter_data data; + XGCValues gc_values; + + root = gdk_get_default_root_window (); + cursor = gdk_cursor_new (GDK_CROSSHAIR); + + if (gdk_pointer_grab (root, FALSE, + GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK, + NULL, cursor, + GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) + { + gdk_cursor_unref (cursor); + return FALSE; + } + + if (gdk_keyboard_grab (root, FALSE, GDK_CURRENT_TIME) != GDK_GRAB_SUCCESS) + { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gdk_cursor_unref (cursor); + return FALSE; + } + + gdk_window_add_filter (root, (GdkFilterFunc) select_area_filter, &data); + + gdk_flush (); + + data.rect.x = 0; + data.rect.y = 0; + data.rect.width = 0; + data.rect.height = 0; + data.button_pressed = FALSE; + data.root = root; + + gc_values.function = GXxor; + gc_values.plane_mask = AllPlanes; + gc_values.foreground = WhitePixel (gdk_display, GDK_SCREEN_XNUMBER (gdk_screen_get_default ())); + gc_values.background = BlackPixel (gdk_display, GDK_SCREEN_XNUMBER (gdk_screen_get_default ())); + gc_values.line_width = 0; + gc_values.line_style = LineSolid; + gc_values.fill_style = FillSolid; + gc_values.cap_style = CapButt; + gc_values.join_style = JoinMiter; + gc_values.graphics_exposures = FALSE; + gc_values.clip_x_origin = 0; + gc_values.clip_y_origin = 0; + gc_values.clip_mask = None; + gc_values.subwindow_mode = IncludeInferiors; + + data.x_gc = XCreateGC (gdk_display, + GDK_WINDOW_XID (root), + GCFunction | GCPlaneMask | GCForeground | GCLineWidth | + GCLineStyle | GCCapStyle | GCJoinStyle | + GCGraphicsExposures | GCBackground | GCFillStyle | + GCClipXOrigin | GCClipYOrigin | GCClipMask | + GCSubwindowMode, + &gc_values); + + gtk_main (); + + XFreeGC (gdk_display, data.x_gc); + + gdk_window_remove_filter (root, (GdkFilterFunc) select_area_filter, &data); + + gdk_keyboard_ungrab (GDK_CURRENT_TIME); + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gdk_cursor_unref (cursor); + + *px = data.rect.x; + *py = data.rect.y; + *pwidth = data.rect.width; + *pheight = data.rect.height; + + return TRUE; +} + static Window find_wm_window (Window xid) { @@ -401,9 +606,10 @@ mask_monitors (GdkPixbuf *pixbuf, GdkWin } GdkPixbuf * -screenshot_get_pixbuf (GdkWindow *window, - gboolean include_pointer, - gboolean include_border) +screenshot_get_pixbuf (GdkWindow *window, + GdkRectangle *rectangle, + gboolean include_pointer, + gboolean include_border) { GdkWindow *root; GdkPixbuf *screenshot; @@ -452,6 +658,14 @@ screenshot_get_pixbuf (GdkWindow *window if (y_orig + height > gdk_screen_height ()) height = gdk_screen_height () - y_orig; + + if (rectangle) + { + x_orig = rectangle->x - x_orig; + y_orig = rectangle->y - y_orig; + width = rectangle->width; + height = rectangle->height; + } screenshot = gdk_pixbuf_get_from_drawable (NULL, root, NULL, x_orig, y_orig, 0, 0, @@ -545,7 +759,9 @@ screenshot_get_pixbuf (GdkWindow *window } #endif /* HAVE_X11_EXTENSIONS_SHAPE_H */ - if (include_pointer) + /* if we have a selected area, there were by definition no cursor in the + * screenshot */ + if (include_pointer && !rectangle) { GdkCursor *cursor; GdkPixbuf *cursor_pixbuf; Index: gnome-utils-2.24.1/gnome-screenshot/screenshot-utils.h =================================================================== --- gnome-utils-2.24.1.orig/gnome-screenshot/screenshot-utils.h +++ gnome-utils-2.24.1/gnome-screenshot/screenshot-utils.h @@ -29,7 +29,12 @@ gboolean screenshot_grab_lock void screenshot_release_lock (void); gchar *screenshot_get_window_title (GdkWindow *win); GdkWindow *screenshot_find_current_window (void); +gboolean screenshot_select_area (int *px, + int *py, + int *pwidth, + int *pheight); GdkPixbuf *screenshot_get_pixbuf (GdkWindow *win, + GdkRectangle *rectangle, gboolean include_pointer, gboolean include_border); Index: gnome-utils-2.24.1/po/fr.po =================================================================== --- gnome-utils-2.24.1.orig/po/fr.po +++ gnome-utils-2.24.1/po/fr.po @@ -3276,3 +3276,8 @@ msgstr "La surveillance de fichiers n'es msgid "Gnome-VFS Error.\n" msgstr "Erreur Gnome-VFS.\n" +msgid "Grab a selected _area" +msgstr "Saisir une _zone sélectionnée" + +msgid "Grab an area of the screen instead of the entire screen" +msgstr "Capturer une zone de l'écran plutôt que l'écran"
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor