Mercurial > pidgin
comparison console/plugins/gntclipboard.c @ 15750:0eb7846f9e7e
Add a gntclipboard. You can select text in a textview with the mouse, and paste it in an entry with ctrl-v (or rebind GntEntry's clipboard-paste).
If you use the s.so WM, pressing alt-shift-c ("toggle-clipboard") will toggle display of the clipboard contents in a possibly easy-to-copy-with-the-x-mouse window.
This includes a plugin which interacts with the X selection, which is not built by default.
author | Richard Nelson <wabz@pidgin.im> |
---|---|
date | Fri, 02 Mar 2007 01:48:11 +0000 |
parents | |
children | 8afc77eb6c1f |
comparison
equal
deleted
inserted
replaced
15749:f403bc58ba07 | 15750:0eb7846f9e7e |
---|---|
1 /** | |
2 * @file gntclipboard.c | |
3 * | |
4 * Copyright (C) 2007 Richard Nelson <wabz@whatsbeef.net> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 */ | |
20 | |
21 | |
22 #include "internal.h" | |
23 #include <glib.h> | |
24 | |
25 #define PLUGIN_STATIC_NAME "GntClipboard" | |
26 | |
27 #ifdef HAVE_X11 | |
28 #include <X11/Xlib.h> | |
29 #include <X11/Xutil.h> | |
30 #include <X11/Xatom.h> | |
31 #endif | |
32 | |
33 #include <glib.h> | |
34 | |
35 #include <plugin.h> | |
36 #include <version.h> | |
37 #include <debug.h> | |
38 #include <gntwm.h> | |
39 | |
40 #include <gntplugin.h> | |
41 | |
42 static gboolean stop = FALSE; | |
43 | |
44 static gulong sig_handle; | |
45 | |
46 static gpointer * | |
47 set_clip(gchar *string) | |
48 { | |
49 #ifdef HAVE_X11 | |
50 Window w; | |
51 XEvent e, respond; | |
52 XSelectionRequestEvent *req; | |
53 const char *ids; | |
54 Display *dpy = XOpenDisplay(NULL); | |
55 | |
56 if (!dpy) | |
57 return NULL; | |
58 ids = getenv("WINDOWID"); | |
59 if (ids == NULL) | |
60 return NULL; | |
61 w = atoi(ids); | |
62 XSetSelectionOwner(dpy, XA_PRIMARY, w, CurrentTime); | |
63 XFlush(dpy); | |
64 XSelectInput(dpy, w, StructureNotifyMask); | |
65 while (!stop) { | |
66 XNextEvent(dpy, &e); | |
67 req = &e.xselectionrequest; | |
68 if (e.type == SelectionRequest) { | |
69 XChangeProperty(dpy, | |
70 req->requestor, | |
71 req->property, | |
72 XA_STRING, | |
73 8, PropModeReplace, | |
74 (unsigned char *)string, | |
75 strlen(string)); | |
76 respond.xselection.property = req->property; | |
77 respond.xselection.type = SelectionNotify; | |
78 respond.xselection.display = req->display; | |
79 respond.xselection.requestor = req->requestor; | |
80 respond.xselection.selection = req->selection; | |
81 respond.xselection.target= req->target; | |
82 respond.xselection.time = req->time; | |
83 XSendEvent(dpy, req->requestor, 0, 0, &respond); | |
84 XFlush (dpy); | |
85 } else if (e.type == SelectionClear) { | |
86 return NULL; | |
87 } | |
88 } | |
89 #endif | |
90 return NULL; | |
91 } | |
92 | |
93 static void | |
94 clipboard_changed(GntWM *wm, gchar *string) | |
95 { | |
96 #ifdef HAVE_X11 | |
97 static GThread *thread = NULL; | |
98 if (thread) { | |
99 stop = TRUE; | |
100 thread = g_thread_join(thread); | |
101 } | |
102 g_thread_create((GThreadFunc)set_clip, string, TRUE, NULL); | |
103 #endif | |
104 } | |
105 | |
106 static gboolean | |
107 plugin_load(GaimPlugin *plugin) | |
108 { | |
109 if (!XOpenDisplay(NULL)) | |
110 gaim_debug_warning("gntclipboard", "Couldn't find X display\n"); | |
111 if (!getenv("WINDOWID")) | |
112 gaim_debug_warning("gntclipboard", "Couldn't find window\n"); | |
113 sig_handle = g_signal_connect(G_OBJECT(gnt_get_clipboard()), "clipboard_changed", G_CALLBACK(clipboard_changed), NULL); | |
114 return TRUE; | |
115 } | |
116 | |
117 static gboolean | |
118 plugin_unload(GaimPlugin *plugin) | |
119 { | |
120 g_signal_handler_disconnect(G_OBJECT(gnt_get_clipboard()), sig_handle); | |
121 return TRUE; | |
122 } | |
123 | |
124 static GaimPluginInfo info = | |
125 { | |
126 GAIM_PLUGIN_MAGIC, | |
127 GAIM_MAJOR_VERSION, | |
128 GAIM_MINOR_VERSION, | |
129 GAIM_PLUGIN_STANDARD, | |
130 GAIM_GNT_PLUGIN_TYPE, | |
131 0, | |
132 NULL, | |
133 GAIM_PRIORITY_DEFAULT, | |
134 "gntclipboard", | |
135 N_("GntClipboard"), | |
136 VERSION, | |
137 N_("Clipboard plugin"), | |
138 N_("When the gnt clipboard contents change, " | |
139 "the contents are made available to X, if possible."), | |
140 "Richard Nelson <wabz@whatsbeef.net>", | |
141 "http://gaim.sourceforge.net", | |
142 plugin_load, | |
143 plugin_unload, | |
144 NULL, | |
145 NULL, | |
146 NULL, | |
147 NULL, | |
148 NULL | |
149 }; | |
150 | |
151 static void | |
152 init_plugin(GaimPlugin *plugin) | |
153 { | |
154 g_thread_init(NULL); | |
155 } | |
156 | |
157 GAIM_INIT_PLUGIN(PLUGIN_STATIC_NAME, init_plugin, info) |