#include #include #include #include #include #include #include #include #include #include #define DATA_PATH "data" typedef struct _E_Band E_Band; void _eg_band_show(); void _eg_band_hide(); void _eg_band_resize(int w, int h); void _eg_band_move(int x, int y); void _eg_init(); static int _eg_event_mouse_move_cb(void *data, int type, void *event); static int _eg_event_mouse_up_cb(void *data, int type, void *event); /* initial coords of region to grab */ int grab_x, grab_y; /* the rubber band object */ static E_Band *band = NULL; /* mouse move event */ static Ecore_Event_Handler *event_mouse_move = NULL; /* mouse button up event */ static Ecore_Event_Handler *event_mouse_up = NULL; /* input window that us used to get X events */ static Ecore_X_Window input_window; /* rubber band structure */ struct _E_Band { /* gui components */ Ecore_Evas *ee; Evas *evas; Evas_Object *edj; }; /** * Grab a part of the screen and return as an Evas object */ Evas_Object *_eg_screen_area_grab(int x, int y, int w, int h) { Imlib_Image im; Evas_Object *ob; imlib_context_set_display(ecore_x_display_get()); imlib_context_set_drawable(RootWindow(ecore_x_display_get(),0)); imlib_context_set_visual( DefaultVisual(ecore_x_display_get(), DefaultScreen(ecore_x_display_get() ) )); im = imlib_create_image_from_drawable(0, x,y,w,h,0); imlib_context_set_image(im); imlib_image_set_format("argb"); ob = evas_object_image_add(band->evas); evas_object_image_size_set(ob, w, h); evas_object_image_data_copy_set(ob, imlib_image_get_data_for_reading_only()); evas_object_image_fill_set(ob, 0, 0, w, h); evas_object_resize(ob, w, h); evas_object_image_alpha_set(ob, 0); imlib_free_image(); return ob; } /** * Show rubber band */ void _eg_band_show() { /* create rubber band if it doesnt exist */ if (!band) { /* allocate memory, create Ecore_Evas, create Edje object */ band = calloc(1, sizeof(E_Band)); band->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 0, 0); band->evas = ecore_evas_get(band->ee); /* check if we have composite, if we do, use translucency */ if (ecore_x_composite_query() && ecore_x_screen_is_composited(0)) { ecore_evas_alpha_set(band->ee, 1); } else { /* we dont have composite, use shaped windows */ ecore_evas_shaped_set(band->ee, 1); } band->edj = evas_object_image_add(band->evas); evas_object_image_file_set(band->edj, "data/images/rect.png", NULL); evas_object_image_border_set(band->edj, 3, 3, 3, 3); evas_object_move(band->edj, 0, 0); /* if we dont put these here, Evas messes up */ evas_object_resize(band->edj, 50, 50); evas_object_image_fill_set(band->edj, 0, 0, 50, 50); /* let the window manager ignore this window, and make it borderless */ ecore_evas_override_set(band->ee, 1); ecore_evas_borderless_set(band->ee, 1); } ecore_evas_show(band->ee); evas_object_show(band->edj); } /** * Hide rubber band */ void _eg_band_hide() { if (!band) return; ecore_evas_hide(band->ee); } /** * Resize rubber band */ void _eg_band_resize(int w, int h) { if (!band) return; ecore_evas_resize(band->ee, w, h); /* this is also the same problem with Evas as above */ if (w >= 6 && h >= 6) { evas_object_resize(band->edj, w, h); evas_object_image_fill_set(band->edj, 0, 0, w, h); } _eg_band_show(); } /** * Move the rubber band */ void _eg_band_move(int x, int y) { if (!band) return; ecore_evas_move(band->ee, x, y); } /** * Start the selection of a region to grab */ void _eg_grab_region_start() { int px, py; int sw, sh; /* attach callbacks to mouse movement and click so * we can resize the rubber band and hide it on a click */ event_mouse_move = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_MOVE, _eg_event_mouse_move_cb, NULL); event_mouse_up = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_UP, _eg_event_mouse_up_cb, NULL); /* get our desktop's width and height */ ecore_x_window_geometry_get(0, NULL, NULL, &sw, &sh); /* set up our input window to grab X events */ input_window = ecore_x_window_input_new(0, 0, 0, sw, sh); ecore_x_window_show(input_window); /* get our mouse cursor's curret x and y coords */ ecore_x_pointer_xy_get(input_window, &px, &py); /* set initial grabbing coords */ grab_x = px; grab_y = py; /* show the rubber band */ _eg_band_show(); /* move the rubber band */ _eg_band_move(grab_x, grab_y); } /** * End the selection of a region */ void _eg_grab_region_end() { int x, y, w, h; Evas_Object *shot; /* detach the events we added to move movement and click */ ecore_event_handler_del(event_mouse_move); ecore_event_handler_del(event_mouse_up); /* hide and delete our input window */ ecore_x_window_hide(input_window); ecore_x_window_delete_request_send(input_window); /* get the proper coords */ ecore_evas_geometry_get(band->ee, &x, &y, &w, &h); /* hide the rubber band */ _eg_band_hide(); /* grab and save the shot to disk */ shot = _eg_screen_area_grab(x, y, w, h); if (!evas_object_image_save(shot, "/tmp/egrab_tmp.jpg", NULL, NULL)) { fprintf(stderr, "WARNING: Could not save screenshot to disk!\n"); } evas_object_del(shot); /* quit the application */ ecore_main_loop_quit(); } /** * Called when a region grab is in progress and the mouse is moving */ static int _eg_event_mouse_move_cb(void *data, int type, void *event) { int w, h; Ecore_X_Event_Mouse_Move *ev = event; w = ev->root.x - grab_x; h = ev->root.y - grab_y; /* figure out how to move the band */ if (w < 0 && h < 0) { int x, y; ecore_x_pointer_xy_get(input_window, &x, &y); _eg_band_move(x, y); _eg_band_resize(-w, -h); } else if (w < 0 && h > 0) { int x, y; ecore_x_pointer_xy_get(input_window, &x, &y); _eg_band_move(x, grab_y); _eg_band_resize(-w, h); } else if (w > 0 && h < 0) { int x, y; ecore_x_pointer_xy_get(input_window, &x, &y); _eg_band_move(grab_x, y); _eg_band_resize(w, -h); } else { _eg_band_resize(w, h); } return 1; } /** * Called when a region grab is in progress and the mouse button is depressed */ static int _eg_event_mouse_up_cb(void *data, int type, void *event) { _eg_grab_region_end(); return 1; } /** * Initialize Ecore_X with proper display * FIXME: This is segfaulting. Cant call ecore_x_window_root_list if not * init'ed. */ void _eg_init() { Ecore_X_Window *roots; int screens, i; char *dispstr, *subdisp; char newdisp[255]; roots = ecore_x_window_root_list(&screens); dispstr = DisplayString(ecore_x_display_get()); subdisp = strdup(dispstr); for (i = 0; i < screens; i++) { dispstr = strchr(subdisp, ':'); if (dispstr) { dispstr = strchr(dispstr, '.'); if (NULL != dispstr) *dispstr = '\0'; } snprintf(newdisp, sizeof(newdisp), "%s.%d", subdisp, i); ecore_x_init(newdisp); } } int main(char *argc, char **argv) { ecore_init(); ecore_evas_init(); ecore_x_init(NULL); edje_init(); _eg_grab_region_start(); ecore_main_loop_begin(); edje_shutdown(); ecore_x_shutdown(); ecore_evas_shutdown(); ecore_shutdown(); return 0; }