* Screen Capture - a plugin that allows taking screenshots and sending them * to your buddies as inline images. * Copyright (C) 2014, Tomasz Wasilczyk <twasilczyk@pidgin.im> * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #include <gdk/gdkkeysyms.h> #include "gtkwebviewtoolbar.h" #define SCRNCAP_SHOOTING_TIMEOUT 500 #define SCRNCAP_DEFAULT_COLOR "#FFFF00000000" static gboolean is_shooting = FALSE; static guint shooting_timeout = 0; static GtkWidget *current_window = NULL; static gint crop_origin_x, crop_origin_y; static gboolean crop_active; static gint crop_x, crop_y, crop_w, crop_h; static gint draw_origin_x, draw_origin_y; static gboolean draw_active; static GdkRGBA brush_color = {1, 0, 0, 1}; static gint line_width = 2; /****************************************************************************** * libpidgin helper functions ******************************************************************************/ scrncap_conv_set_data(PidginConversation *gtkconv, const gchar *key, g_return_if_fail(gtkconv != NULL); g_object_set_data(G_OBJECT(gtkconv->tab_cont), key, value); scrncap_conv_get_data(PidginConversation *gtkconv, const gchar *key) g_return_val_if_fail(gtkconv != NULL, NULL); return g_object_get_data(G_OBJECT(gtkconv->tab_cont), key); /****************************************************************************** * GdkPixbuf helper functions ******************************************************************************/ scrncap_perform_screenshot(void) root = gdk_get_default_root_window(); gdk_window_get_origin(root, &orig_x, &orig_y); return gdk_pixbuf_get_from_window(root, 0, 0, gdk_window_get_width(root), gdk_window_get_height(root)); scrncap_pixbuf_darken(GdkPixbuf *pixbuf) int i, y, width, height, row_width, n_channels, rowstride, pad; pixels = gdk_pixbuf_get_pixels(pixbuf); width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); n_channels = gdk_pixbuf_get_n_channels(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); row_width = width * n_channels; pad = rowstride - row_width; g_return_if_fail(pad >= 0); for (y = 0; y < height; y++) { for (i = 0; i < row_width; i++, pixels++) scrncap_pixbuf_to_image(GdkPixbuf *pixbuf) PurpleImage *image = NULL; if (!gdk_pixbuf_save_to_buffer(pixbuf, &buffer, &count, "png", purple_debug_error("screencap", "Failed saving an image: %s", image = purple_image_new_take_data((guint8 *)buffer, count); if (purple_image_get_extension(image) == NULL) { purple_debug_error("screencap", "Invalid image format"); /****************************************************************************** ******************************************************************************/ scrncap_drawing_area_btnpress(GtkWidget *draw_area, GdkEventButton *event, draw_origin_x = event->x; draw_origin_y = event->y; scrncap_drawing_area_btnrelease(GtkWidget *draw_area, GdkEvent *event, scrncap_drawing_area_motion(GtkWidget *draw_area, GdkEventButton *event, int redraw_x, redraw_y, redraw_w, redraw_h; cairo_move_to(cr, draw_origin_x, draw_origin_y); cairo_set_line_width(cr, line_width); redraw_x = MIN(draw_origin_x, x) - line_width - 1; redraw_y = MIN(draw_origin_y, y) - line_width - 1; redraw_w = MAX(draw_origin_x, x) - redraw_x + line_width + 1; redraw_h = MAX(draw_origin_y, y) - redraw_y + line_width + 1; gtk_widget_queue_draw_area(draw_area, redraw_x, redraw_y, redraw_w, redraw_h); scrncap_drawing_area_enter(GtkWidget *widget, GdkEvent *event, gdkwindow = gtk_widget_get_window(GTK_WIDGET(widget)); gdk_window_set_cursor(gdkwindow, draw_cursor); scrncap_drawing_area_leave(GtkWidget *widget, GdkEvent *event, gdkwindow = gtk_widget_get_window(GTK_WIDGET(widget)); gdk_window_set_cursor(gdkwindow, NULL); scrncap_draw_window_close(GtkWidget *window, gpointer _unused) if (current_window != window) scrncap_draw_window_paint(GtkWidget *widget, cairo_t *cr, gpointer _surface) cairo_surface_t *surface = _surface; cairo_set_source_surface(cr, surface, 0, 0); scrncap_draw_window_response(GtkDialog *draw_window, gint response_id, PidginWebView *webview = PIDGIN_WEBVIEW(_webview); GdkPixbuf *result = NULL; const gchar *fname_prefix; static guint fname_no = 0; if (response_id == SCRNCAP_RESPONSE_COLOR) if (response_id == GTK_RESPONSE_OK) { cairo_surface_t *surface = g_object_get_data( G_OBJECT(draw_window), "surface"); result = gdk_pixbuf_get_from_surface(surface, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); gtk_widget_destroy(GTK_WIDGET(draw_window)); image = scrncap_pixbuf_to_image(result); /* translators: this is the file name prefix, * keep it lowercase and pure ASCII. * Please avoid "_" character, use "-" instead. */ fname_prefix = _("screenshot-"); fname = g_strdup_printf("%s%u", fname_prefix, ++fname_no); purple_image_set_friendly_filename(image, fname); pidgin_webview_insert_image(webview, image); scrncap_draw_color_selected(GtkColorButton *button, cairo_t *cr) gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(button), &brush_color); gdk_cairo_set_source_rgba(cr, &brush_color); color_str = gdk_rgba_to_string(&brush_color); purple_prefs_set_string("/plugins/gtk/screencap/brush_color", color_str); scrncap_draw_window(PidginWebView *webview, GdkPixbuf *screen) GtkWidget *drawing_area, *box; cairo_surface_t *surface; current_window = pidgin_create_dialog( _("Insert screenshot"), 0, "insert-screenshot", TRUE); draw_window = GTK_DIALOG(current_window); gtk_widget_set_size_request(GTK_WIDGET(draw_window), 400, 300); gtk_window_set_position(GTK_WINDOW(draw_window), GTK_WIN_POS_CENTER); g_signal_connect(G_OBJECT(draw_window), "destroy", G_CALLBACK(scrncap_draw_window_close), NULL); display = gtk_widget_get_display(current_window); draw_cursor = gdk_cursor_new_for_display(display, GDK_PENCIL); g_object_set_data_full(G_OBJECT(draw_window), "draw-cursor", draw_cursor, g_object_unref); width = gdk_pixbuf_get_width(screen); height = gdk_pixbuf_get_height(screen); surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height); cr = cairo_create(surface); g_signal_connect_swapped(G_OBJECT(draw_window), "destroy", G_CALLBACK(cairo_destroy), cr); g_object_set_data_full(G_OBJECT(draw_window), "surface", surface, (GDestroyNotify)cairo_surface_destroy); gdk_cairo_set_source_pixbuf(cr, screen, 0, 0); cairo_rectangle(cr, 0, 0, width, height); drawing_area = gtk_drawing_area_new(); gtk_widget_set_size_request(drawing_area, width, height); g_signal_connect(G_OBJECT(drawing_area), "draw", G_CALLBACK(scrncap_draw_window_paint), surface); gtk_widget_add_events(drawing_area, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(drawing_area), "button-press-event", G_CALLBACK(scrncap_drawing_area_btnpress), NULL); g_signal_connect(G_OBJECT(drawing_area), "button-release-event", G_CALLBACK(scrncap_drawing_area_btnrelease), NULL); g_signal_connect(G_OBJECT(drawing_area), "motion-notify-event", G_CALLBACK(scrncap_drawing_area_motion), cr); g_signal_connect(G_OBJECT(drawing_area), "enter-notify-event", G_CALLBACK(scrncap_drawing_area_enter), draw_cursor); g_signal_connect(G_OBJECT(drawing_area), "leave-notify-event", G_CALLBACK(scrncap_drawing_area_leave), draw_cursor); g_object_set(drawing_area, "halign", GTK_ALIGN_CENTER, "valign", GTK_ALIGN_CENTER, scroll_area = pidgin_make_scrollable(box, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1); g_object_set(G_OBJECT(scroll_area), "expand", TRUE, NULL); gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area( GTK_DIALOG(draw_window))), scroll_area); color_button = gtk_color_button_new(); gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(color_button), g_signal_connect(G_OBJECT(color_button), "color-set", G_CALLBACK(scrncap_draw_color_selected), cr); scrncap_draw_color_selected(GTK_COLOR_BUTTON(color_button), cr); gtk_dialog_add_action_widget(draw_window, color_button, gtk_dialog_add_button(draw_window, _("_Add"), GTK_RESPONSE_OK); gtk_dialog_add_button(draw_window, _("_Cancel"), gtk_dialog_set_default_response(draw_window, GTK_RESPONSE_OK); g_signal_connect(G_OBJECT(draw_window), "response", G_CALLBACK(scrncap_draw_window_response), webview); gtk_widget_show_all(GTK_WIDGET(draw_window)); /****************************************************************************** ******************************************************************************/ scrncap_crop_window_close(GtkWidget *window, gpointer _unused) if (current_window != window) scrncap_crop_window_keypress(GtkWidget *crop_window, GdkEventKey *event, PidginWebView *webview = PIDGIN_WEBVIEW(_webview); guint key = event->keyval; if (key == GDK_KEY_Escape) { gtk_widget_destroy(crop_window); if (key == GDK_KEY_Return) { GdkPixbuf *screenshot, *subscreen, *result; screenshot = g_object_get_data(G_OBJECT(crop_window), subscreen = gdk_pixbuf_new_subpixbuf(screenshot, crop_x, crop_y, crop_w, crop_h); result = gdk_pixbuf_copy(subscreen); g_object_unref(subscreen); gtk_widget_destroy(crop_window); scrncap_draw_window(webview, result); scrncap_crop_window_focusout(GtkWidget *window, GdkEventFocus *event, gtk_widget_destroy(window); scrncap_crop_window_btnpress(GtkWidget *window, GdkEventButton *event, g_return_val_if_fail(!crop_active, TRUE); hint_box = g_object_get_data(G_OBJECT(window), "hint-box"); gtk_widget_destroy(hint_box); g_object_set_data(G_OBJECT(window), "hint-box", NULL); selection = g_object_get_data(G_OBJECT(window), "selection"); cont = g_object_get_data(G_OBJECT(window), "cont"); gtk_fixed_move(cont, GTK_WIDGET(selection), -10, -10); gtk_image_set_from_pixbuf(selection, NULL); gtk_widget_show(GTK_WIDGET(selection)); crop_origin_x = event->x_root; crop_origin_y = event->y_root; scrncap_crop_window_btnrelease(GtkWidget *window, GdkEvent *event, scrncap_crop_window_motion(GtkWidget *window, GdkEventButton *event, GdkPixbuf *crop, *screenshot; g_return_val_if_fail(crop_active, FALSE); selection = g_object_get_data(G_OBJECT(window), "selection"); cont = g_object_get_data(G_OBJECT(window), "cont"); crop_x = MIN(crop_origin_x, event->x_root); crop_y = MIN(crop_origin_y, event->y_root); crop_w = abs(crop_origin_x - event->x_root); crop_h = abs(crop_origin_y - event->y_root); gtk_fixed_move(cont, GTK_WIDGET(selection), crop_x, crop_y); screenshot = g_object_get_data(G_OBJECT(window), "screenshot"); crop = gdk_pixbuf_new_subpixbuf(screenshot, crop_x, crop_y, crop_w, crop_h); gtk_image_set_from_pixbuf(GTK_IMAGE(selection), crop); scrncap_crop_window_realize(GtkWidget *crop_window, gpointer _unused) gdkwindow = gtk_widget_get_window(GTK_WIDGET(crop_window)); display = gdk_window_get_display(gdkwindow); gdk_window_set_events(gdkwindow, gdk_window_get_events(gdkwindow) | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | cursor = gdk_cursor_new_for_display(display, GDK_CROSSHAIR); gdk_window_set_cursor(gdkwindow, cursor); scrncap_do_screenshot_cb(gpointer _webview) PidginWebView *webview = PIDGIN_WEBVIEW(_webview); GdkPixbuf *screenshot, *screenshot_d; GtkImage *image, *selection; GtkRequisition hint_size; screenshot = scrncap_perform_screenshot(); g_return_val_if_fail(screenshot != NULL, G_SOURCE_REMOVE); width = gdk_pixbuf_get_width(screenshot); height = gdk_pixbuf_get_height(screenshot); current_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); crop_window = GTK_WINDOW(current_window); gtk_window_set_decorated(crop_window, FALSE); gtk_window_set_resizable(crop_window, FALSE); gtk_widget_set_size_request(GTK_WIDGET(crop_window), width, height); gtk_window_fullscreen(crop_window); gtk_window_set_keep_above(crop_window, TRUE); g_signal_connect(G_OBJECT(crop_window), "realize", G_CALLBACK(scrncap_crop_window_realize), NULL); g_signal_connect(G_OBJECT(crop_window), "destroy", G_CALLBACK(scrncap_crop_window_close), NULL); g_signal_connect(G_OBJECT(crop_window), "key-press-event", G_CALLBACK(scrncap_crop_window_keypress), webview); g_signal_connect(G_OBJECT(crop_window), "focus-out-event", G_CALLBACK(scrncap_crop_window_focusout), NULL); g_signal_connect(G_OBJECT(crop_window), "button-press-event", G_CALLBACK(scrncap_crop_window_btnpress), NULL); g_signal_connect(G_OBJECT(crop_window), "button-release-event", G_CALLBACK(scrncap_crop_window_btnrelease), NULL); g_signal_connect(G_OBJECT(crop_window), "motion-notify-event", G_CALLBACK(scrncap_crop_window_motion), NULL); g_object_set_data_full(G_OBJECT(crop_window), "screenshot", screenshot, g_object_unref); cont = GTK_FIXED(gtk_fixed_new()); g_object_set_data(G_OBJECT(crop_window), "cont", cont); gtk_container_add(GTK_CONTAINER(crop_window), GTK_WIDGET(cont)); screenshot_d = gdk_pixbuf_copy(screenshot); scrncap_pixbuf_darken(screenshot_d); image = GTK_IMAGE(gtk_image_new_from_pixbuf(screenshot_d)); g_object_unref(screenshot_d); gtk_fixed_put(cont, GTK_WIDGET(image), 0, 0); selection = GTK_IMAGE(gtk_image_new_from_pixbuf(NULL)); gtk_fixed_put(cont, GTK_WIDGET(selection), -10, -10); g_object_set_data(G_OBJECT(crop_window), "selection", selection); hint = gtk_label_new(NULL); hint_msg = g_strdup_printf("<span size='x-large'>%s</span>", _("Select the region to send and press Enter button to confirm " "or press Escape button to cancel")); gtk_label_set_markup(GTK_LABEL(hint), hint_msg); gtk_widget_set_margin_start(hint, 10); gtk_widget_set_margin_end(hint, 10); gtk_widget_set_margin_top(hint, 7); gtk_widget_set_margin_bottom(hint, 7); hint_box = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(hint_box), hint); gtk_widget_get_preferred_size(hint, NULL, &hint_size); gtk_fixed_put(cont, hint_box, width / 2 - hint_size.width / 2 - 10, height / 2 - hint_size.height / 2 - 7); g_object_set_data(G_OBJECT(crop_window), "hint-box", hint_box); gtk_widget_show_all(GTK_WIDGET(crop_window)); gtk_widget_hide(GTK_WIDGET(selection)); scrncap_do_screenshot(GtkAction *action, PidginWebView *webview) gtk_window_present(GTK_WINDOW(current_window)); shooting_timeout = g_timeout_add(SCRNCAP_SHOOTING_TIMEOUT, scrncap_do_screenshot_cb, webview); /****************************************************************************** * PidginConversation setup ******************************************************************************/ scrncap_convwin_switch(GtkNotebook *notebook, GtkWidget *page, gint page_num, PidginConvWindow *win = _win; PidginConversation *gtkconv; gboolean images_supported; gtkconv = pidgin_conv_window_get_active_gtkconv(win); webview = PIDGIN_WEBVIEW(gtkconv->entry); action = g_object_get_data(G_OBJECT(win->menu->menubar), "insert-screenshot-action"); g_return_if_fail(action != NULL); images_supported = pidgin_webview_get_format_functions(webview) & gtk_action_set_sensitive(action, images_supported); scrncap_convwin_menu_cb(GtkAction *action, PidginConvWindow *win) PidginConversation *gtkconv; gtkconv = pidgin_conv_window_get_active_gtkconv(win); webview = PIDGIN_WEBVIEW(gtkconv->entry); scrncap_do_screenshot(action, webview); scrncap_convwin_init(PidginConvWindow *win) PidginConvWindowMenu *menu = win->menu; GtkWidget *conv_submenu, *conv_insert_image; GtkWidget *scrncap_btn_menu; action = g_object_get_data(G_OBJECT(menu->menubar), "insert-screenshot-action"); action = gtk_action_new("InsertScreenshot", _("Insert Screens_hot..."), NULL, PIDGIN_ICON_CAMERA_PHOTO); gtk_action_set_is_important(action, TRUE); g_object_set_data_full(G_OBJECT(menu->menubar), "insert-screenshot-action", action, g_object_unref); g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(scrncap_convwin_menu_cb), win); conv_insert_image = gtk_ui_manager_get_widget(menu->ui, "/Conversation/ConversationMenu/InsertImage"); g_return_if_fail(conv_insert_image != NULL); conv_submenu = gtk_widget_get_parent(conv_insert_image); children = gtk_container_get_children(GTK_CONTAINER(conv_submenu)); pos = g_list_index(children, conv_insert_image); g_warn_if_fail(pos >= 0); scrncap_btn_menu = gtk_action_create_menu_item(action); g_object_set_data(G_OBJECT(menu->menubar), "insert-screenshot-btn", gtk_menu_shell_insert(GTK_MENU_SHELL(conv_submenu), GTK_WIDGET(scrncap_btn_menu), pos); gtk_widget_show(GTK_WIDGET(scrncap_btn_menu)); g_signal_connect_after(G_OBJECT(win->notebook), "switch-page", G_CALLBACK(scrncap_convwin_switch), win); scrncap_convwin_switch(GTK_NOTEBOOK(win->notebook), NULL, 0, win); scrncap_convwin_uninit(PidginConvWindow *win) PidginConvWindowMenu *menu = win->menu; btn = g_object_get_data(G_OBJECT(menu->menubar), "insert-screenshot-btn"); g_object_set_data(G_OBJECT(menu->menubar), "insert-screenshot-btn", NULL); g_object_set_data(G_OBJECT(menu->menubar), "insert-screenshot-action", NULL); g_signal_handlers_disconnect_matched(win->notebook, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, scrncap_convwin_switch, NULL); scrncap_conversation_update(PidginWebView *webview, PidginWebViewButtons buttons, gpointer _action) GtkAction *action = GTK_ACTION(_action); gtk_action_set_sensitive(action, buttons & PIDGIN_WEBVIEW_IMAGE); scrncap_conversation_init(PidginConversation *gtkconv) PidginWebViewToolbar *toolbar; GtkToolItem *scrncap_btn_wide; GtkWidget *scrncap_btn_lean; GtkToolbar *wide_view, *lean_view; GtkMenu *wide_menu = NULL; GList *wide_children, *it; if (scrncap_conv_get_data(gtkconv, "scrncap-btn-wide") != NULL) webview = PIDGIN_WEBVIEW(gtkconv->entry); toolbar = PIDGIN_WEBVIEWTOOLBAR(pidgin_webview_get_toolbar(webview)); g_return_if_fail(toolbar != NULL); wide_view = GTK_TOOLBAR(pidgin_webviewtoolbar_get_wide_view(toolbar)); g_return_if_fail(wide_view != NULL); lean_view = GTK_TOOLBAR(pidgin_webviewtoolbar_get_lean_view(toolbar)); g_return_if_fail(lean_view != NULL); action = gtk_action_new("InsertScreenshot", _("_Screenshot"), _("Insert screenshot"), PIDGIN_ICON_CAMERA_PHOTO); gtk_action_set_is_important(action, TRUE); g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(scrncap_do_screenshot), webview); scrncap_btn_wide = GTK_TOOL_ITEM(gtk_action_create_tool_item(action)); scrncap_conv_set_data(gtkconv, "scrncap-btn-wide", scrncap_btn_wide); for (i = 0; i < gtk_toolbar_get_n_items(wide_view); i++) { GtkToolItem *ref_item = gtk_toolbar_get_nth_item(wide_view, i); action = g_object_get_data(G_OBJECT(ref_item), "action"); if (g_strcmp0(gtk_action_get_name(action), "InsertImage") == 0) { gtk_toolbar_insert(wide_view, scrncap_btn_wide, pos); gtk_widget_show(GTK_WIDGET(scrncap_btn_wide)); for (i = 0; i < gtk_toolbar_get_n_items(lean_view); i++) { GtkToolItem *ref_item = gtk_toolbar_get_nth_item(lean_view, i); menu_name = g_object_get_data(G_OBJECT(ref_item), "menu-name"); if (g_strcmp0(menu_name, "insert") == 0) { wide_menu = g_object_get_data(G_OBJECT(ref_item), "menu"); g_return_if_fail(wide_menu); wide_children = gtk_container_get_children(GTK_CONTAINER(wide_menu)); for (it = wide_children, i = 0; it; it = g_list_next(it), i++) { GtkWidget *child = it->data; action = g_object_get_data(G_OBJECT(child), "action"); if (g_strcmp0(gtk_action_get_name(action), "InsertImage") == 0) { g_list_free(wide_children); g_warn_if_fail(pos >= 0); g_signal_connect_object(G_OBJECT(webview), "allowed-formats-updated", G_CALLBACK(scrncap_conversation_update), action, 0); scrncap_conversation_update(webview, pidgin_webview_get_format_functions(webview), action); scrncap_btn_lean = gtk_action_create_menu_item(action); scrncap_conv_set_data(gtkconv, "scrncap-btn-lean", scrncap_btn_lean); gtk_menu_shell_insert(GTK_MENU_SHELL(wide_menu), GTK_WIDGET(scrncap_btn_lean), pos); gtk_widget_show(GTK_WIDGET(scrncap_btn_lean)); scrncap_conversation_uninit(PidginConversation *gtkconv) GtkWidget *scrncap_btn_wide, *scrncap_btn_lean; scrncap_btn_wide = scrncap_conv_get_data(gtkconv, "scrncap-btn-wide"); if (scrncap_btn_wide == NULL) scrncap_btn_lean = scrncap_conv_get_data(gtkconv, "scrncap-btn-lean"); gtk_widget_destroy(scrncap_btn_wide); gtk_widget_destroy(scrncap_btn_lean); scrncap_conv_set_data(gtkconv, "scrncap-btn-wide", NULL); scrncap_conv_set_data(gtkconv, "scrncap-btn-lean", NULL); /****************************************************************************** ******************************************************************************/ static PidginPluginInfo * plugin_query(GError **error) const gchar * const authors[] = { "Tomasz Wasilczyk <twasilczyk@pidgin.im>", return pidgin_plugin_info_new( "name", N_("Screen Capture"), "version", DISPLAY_VERSION, "category", N_("Utility"), "summary", N_("Send screenshots to your buddies."), "description", N_("Adds an option to send a screenshot as an inline " "image. It works only with protocols that supports " "website", PURPLE_WEBSITE, "abi-version", PURPLE_ABI_VERSION, plugin_load(PurplePlugin *plugin, GError **error) purple_prefs_add_none("/plugins"); purple_prefs_add_none("/plugins/gtk"); purple_prefs_add_none("/plugins/gtk/screencap"); purple_prefs_add_string("/plugins/gtk/screencap/brush_color", color_str = purple_prefs_get_string("/plugins/gtk/screencap/brush_color"); if (color_str && color_str[0]) gdk_rgba_parse(&brush_color, color_str); purple_signal_connect(pidgin_conversations_get_handle(), "conversation-displayed", plugin, PURPLE_CALLBACK(scrncap_conversation_init), NULL); purple_signal_connect(pidgin_conversations_get_handle(), "conversation-window-created", plugin, PURPLE_CALLBACK(scrncap_convwin_init), NULL); it = purple_conversations_get_all(); for (; it; it = g_list_next(it)) { PurpleConversation *conv = it->data; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) scrncap_conversation_init(PIDGIN_CONVERSATION(conv)); it = pidgin_conv_windows_get_list(); for (; it; it = g_list_next(it)) { PidginConvWindow *win = it->data; scrncap_convwin_init(win); plugin_unload(PurplePlugin *plugin, GError **error) if (shooting_timeout > 0) g_source_remove(shooting_timeout); if (current_window != NULL) gtk_widget_destroy(GTK_WIDGET(current_window)); it = purple_conversations_get_all(); for (; it; it = g_list_next(it)) { PurpleConversation *conv = it->data; if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) scrncap_conversation_uninit(PIDGIN_CONVERSATION(conv)); it = pidgin_conv_windows_get_list(); for (; it; it = g_list_next(it)) { PidginConvWindow *win = it->data; scrncap_convwin_uninit(win); PURPLE_PLUGIN_INIT(screencap, plugin_query, plugin_load, plugin_unload);