2 * (c) 2001 Michal Krause <michal@krause.cz>
5 #include "wmcliphist.h"
7 #define WMCLIPHIST_VERSION "2.1"
15 begin_func("print_help");
17 fprintf(stderr
, "Usage: wmcliphist [options]\n\n"
18 "wmcliphist is small dock applet for Window Maker which "
19 "keeps X clipboard history\n\n");
20 fprintf(stderr
, "-h show this help\n"
22 "-n <num> set number of items to keep (default 10)\n"
23 "-c color set color for locked items (default is red)\n"
24 "-s <size> choose wmcliphist icon size:\n"
26 " 16 = tiny 16x16 px icon\n"
27 " 30 = icon suitable for 32px dock/slit\n"
28 " 40 = icon suitable for 48px dock/slit\n"
29 " 60 = icon suitable for 64px dock/slit (default)\n");
30 fprintf(stderr
, "-i <num> choose wmcliphist icon antialiasing:\n"
31 " 0 = for mid tones background (default)\n"
32 " 1 = for dark background\n"
33 " 2 = for light background\n");
34 fprintf(stderr
, "-d dumps clipboard history to stdout"
35 " in pseudo XML format (no escaping etc.)\n");
36 fprintf(stderr
, "-b <type> choose clipboard to manage\n"
37 " PRIMARY = select copies, middle click pastes (default)\n"
38 " SECONDARY = not used\n"
39 " CLIPBOARD = Ctrl+C copies, Ctrl+V pastes\n\n");
45 wmcliphist_exit(gint code
)
47 begin_func("wmcliphist_exit");
52 /* gtk3 dockapp code based on wmpasman by Brad Jorsch
53 * <anomie@users.sourceforge.net>
54 * http://sourceforge.net/projects/wmpasman */
56 GtkWidget
*foo_create_main_icon_window(GtkWidget
*mw
, unsigned int s
)
62 Window mainwin
, iw
, p
, dummy1
, *dummy2
, w
;
65 display
= gdk_display_get_default();
66 foobox
= gtk_window_new(GTK_WINDOW_POPUP
);
68 gtk_window_set_wmclass(GTK_WINDOW(mw
), g_get_prgname(), "DockApp");
69 gtk_widget_set_size_request(foobox
, s
, s
);
71 gtk_widget_realize(mw
);
72 gtk_widget_realize(foobox
);
74 d
= GDK_DISPLAY_XDISPLAY(display
);
75 mainwin
= GDK_WINDOW_XID(gtk_widget_get_window(mw
));
76 iw
= GDK_WINDOW_XID(gtk_widget_get_window(foobox
));
77 XQueryTree(d
, mainwin
, &dummy1
, &p
, &dummy2
, &dummy3
);
80 w
= XCreateSimpleWindow(d
, p
, 0, 0, 1, 1, 0, 0, 0);
81 XReparentWindow(d
, mainwin
, w
, 0, 0);
83 gtk_widget_show(foobox
);
84 wmHints
= XGetWMHints(d
, mainwin
);
86 wmHints
= XAllocWMHints();
87 wmHints
->flags
|= IconWindowHint
;
88 wmHints
->icon_window
= iw
;
89 XSetWMHints(d
, mainwin
, wmHints
);
91 XReparentWindow(d
, mainwin
, p
, 0, 0);
101 main(int argc
, char **argv
)
109 gboolean dump_only
= FALSE
;
112 debug_init_nothreads();
116 /* load configuration */
117 if ((res
= rcconfig_get(rcconfig_get_name("rc"))) != 0) {
118 fprintf(stderr
, "~/.wmcliphistrc parse error (%d)\n", res
);
122 /* parse command line */
123 while ((arg
= argv
[i
])) {
125 if (*(arg
+ 1) == 'h')
127 else if (*(arg
+ 1) == 'n') {
130 fprintf(stderr
, "Missing value of -n\n");
133 num_items_to_keep
= atol(argv
[i
]);
134 } else if (*(arg
+ 1) == 'c') {
137 fprintf(stderr
, "Missing value of -c\n");
140 memset(locked_color_str
, 0, 32);
141 strncpy(locked_color_str
, argv
[i
], 31);
142 } else if (*(arg
+ 1) == 'i') {
145 fprintf(stderr
, "Missing value of -i\n");
148 icon_number
= atoi(argv
[i
]);
149 if (icon_number
< 0 || icon_number
> 2) {
150 fprintf(stderr
, "Invalid value of -i\n");
153 } else if (*(arg
+ 1) == 's') {
156 fprintf(stderr
, "Missing value of -s\n");
159 icon_size
= atoi(argv
[i
]);
160 if (icon_size
!= 60 && icon_size
!= 40
164 fprintf(stderr
, "Invalid value of -s\n");
167 if (icon_size
== 0) {
170 } else if (*(arg
+ 1) == 'd') {
172 } else if (*(arg
+ 1) == 'v') {
173 printf("wmcliphist "WMCLIPHIST_VERSION
"\n");
175 } else if (*(arg
+ 1) == 'b') {
178 fprintf(stderr
, "Missing value of -b\n");
181 memset(clipboard_str
, 0, 32);
182 strncpy(clipboard_str
, argv
[i
], 31);
184 fprintf(stderr
, "Invalid option -%c\n", *(arg
+ 1));
188 fprintf(stderr
, "Invalid option %s\n", arg
);
194 signal(SIGCHLD
, SIG_IGN
);
197 gtk_init(&argc
, &argv
);
200 /* create main window */
201 main_window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
203 /* creat dock icon */
204 dock_app
= foo_create_main_icon_window(main_window
, icon_size
);
207 /* create icon_mask */
208 if (icon_size
== 60) {
210 if (icon_number
== 0) {
211 icon_file
= "ico_60x60_gray.png";
212 } else if (icon_number
== 1) {
213 icon_file
= "ico_60x60_black.png";
215 icon_file
= "ico_60x60_white.png";
217 } else if (icon_size
== 40) {
220 if (icon_number
== 0) {
221 icon_file
= "ico_40x40_gray.png";
222 } else if (icon_number
== 1) {
223 icon_file
= "ico_40x40_black.png";
225 icon_file
= "ico_40x40_white.png";
227 } else if (icon_size
== 30) {
230 if (icon_number
== 0) {
231 icon_file
= "ico_30x30_gray.png";
232 } else if (icon_number
== 1) {
233 icon_file
= "ico_30x30_black.png";
235 icon_file
= "ico_30x30_white.png";
240 icon_file
= "ico_16x16.png";
243 icon_file
= g_strconcat(DATADIR
"/", icon_file
, NULL
);
244 pixmap
= gtk_image_new_from_file(icon_file
);
245 gtk_widget_show(pixmap
);
246 gtk_container_add(GTK_CONTAINER(dock_app
), pixmap
);
250 /* create clipboard history menu */
251 menu_hist
= gtk_menu_new();
252 menu_title
= gtk_menu_item_new();
253 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist
), menu_title
);
254 gtk_widget_show(menu_title
);
255 gtk_widget_show(menu_hist
);
258 /* create application menu */
259 menu_app
= gtk_menu_new();
261 menu_app_clip_lock
= gtk_check_menu_item_new_with_label("Clipboard lock");
262 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app
), menu_app_clip_lock
);
264 menu_app_clip_ignore
= gtk_check_menu_item_new_with_label("Clipboard ignore");
265 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app
), menu_app_clip_ignore
);
267 menu_app_save
= gtk_menu_item_new_with_label("Save history");
268 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app
), menu_app_save
);
269 g_signal_connect(G_OBJECT(menu_app_save
),
271 G_CALLBACK(menu_app_item_click
),
274 menu_app_exit
= gtk_menu_item_new_with_label("Exit");
275 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app
), menu_app_exit
);
276 g_signal_connect(G_OBJECT(menu_app_exit
),
278 G_CALLBACK(menu_app_item_click
),
281 gtk_widget_show_all(menu_app
);
284 list_node
= action_list
;
286 ACTION
*action
= list_node
->data
;
288 if (action
->action
== ACT_SUBMENU
&&
289 strcmp(action
->command
, "-") != 0) {
290 action
->menu_item
= gtk_menu_item_new_with_label(
292 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist
),
294 action
->submenu
= gtk_menu_new();
295 gtk_menu_item_set_submenu(
296 GTK_MENU_ITEM(action
->menu_item
),
298 menu_title
= gtk_menu_item_new();
299 gtk_menu_shell_append(GTK_MENU_SHELL(action
->submenu
), menu_title
);
300 gtk_widget_show(menu_title
);
301 gtk_widget_show(action
->menu_item
);
302 gtk_widget_show(action
->submenu
);
305 if (action
->action
== ACT_SUBMENU
&&
306 strcmp(action
->command
, "-") == 0) {
307 printf("'%s'\n", action
->command
);
308 action
->submenu
= menu_hist
;
310 list_node
= list_node
->next
;
313 GtkWidget
*separator
;
315 separator
= gtk_menu_item_new();
316 gtk_widget_show(separator
);
317 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_hist
), separator
, 1);
320 /* prepare colors and styles */
321 if (gdk_rgba_parse(&locked_color
, locked_color_str
) == FALSE
) {
324 sprintf(msg_str
, "Invalid color string: '%s'.\n"
325 "Falling back to default (red).",
327 show_message(msg_str
, "Warning", "OK", NULL
, NULL
);
328 strcpy(locked_color_str
, DEF_LOCKED_COLOR
);
329 gdk_rgba_parse(&locked_color
, locked_color_str
);
333 if (strcmp(clipboard_str
, "PRIMARY") == 0) {
334 clipboard
= GDK_SELECTION_PRIMARY
;
335 } else if (strcmp(clipboard_str
, "SECONDARY") == 0) {
336 clipboard
= GDK_SELECTION_SECONDARY
;
337 } else if (strcmp(clipboard_str
, "CLIPBOARD") == 0) {
338 clipboard
= GDK_SELECTION_CLIPBOARD
;
342 sprintf(msg_str
, "Invalid clipboard string: '%s'.\n"
343 "Falling back to default ("
347 show_message(msg_str
, "Warning", "OK", NULL
, NULL
);
348 clipboard
= DEF_CLIPBOARD
;
351 /* load previously saved history */
352 if (history_load(dump_only
) != 0) {
353 if (errno
== E_TOO_MUCH
) {
354 if (show_message("Number of items to keep (-n switch or "
355 "keep directive in ~/.wmcliphistrc)\n"
356 "is lower than actual number of items "
357 "in history file.\nSome items from "
358 "history will be lost. May I continue?",
359 "Warning", "Yes", "No", NULL
) == 1) {
363 } else if (errno
!= E_OPEN
) {
365 fprintf(stderr
, "cannot load history (%d)\n", errno
);
376 cairo_region_t
*region
;
377 cairo_surface_t
*surface
;
379 /* connect signal for menu popup */
380 gtk_widget_add_events(dock_app
, GDK_BUTTON_PRESS_MASK
);
381 g_signal_connect(G_OBJECT(dock_app
),
383 G_CALLBACK(button_press
),
384 G_OBJECT(menu_hist
));
386 surface
= cairo_image_surface_create_from_png(icon_file
);
387 region
= gdk_cairo_region_create_from_surface(surface
);
388 gdk_window_shape_combine_region(gtk_widget_get_window(dock_app
),
395 /* run clipboard monitor */
396 g_signal_connect(G_OBJECT(main_window
),
397 "selection_received",
398 G_CALLBACK(my_get_xselection
),
400 g_timeout_add(250, time_conv_select
, NULL
);
403 /* run autosave timer */
404 if (autosave_period
> 0)
405 g_timeout_add(autosave_period
* 1000, history_autosave
, NULL
);
408 /* setup everything for supplying selection to other apps */
409 gtk_selection_add_target(dock_app
,
411 GDK_SELECTION_TYPE_STRING
,
414 g_signal_connect(G_OBJECT(dock_app
),
416 G_CALLBACK(selection_handle
),
419 g_signal_connect(G_OBJECT(dock_app
),
421 G_CALLBACK(wmcliphist_exit
),