wmcliphist: Replace xpm icons with png.
[dockapps.git] / wmcliphist / wmcliphist.c
blobe167f6b5261add468357a0eee66324d80d760060
1 /*
2 * (c) 2001 Michal Krause <michal@krause.cz>
3 */
5 #include "wmcliphist.h"
7 #include "icon/ico_60x60_mask.xbm"
8 #include "icon/ico_40x40_mask.xbm"
9 #include "icon/ico_30x30_mask.xbm"
10 #include "icon/ico_16x16_mask.xbm"
13 * print some help
15 void
16 print_help()
18 begin_func("print_help");
20 fprintf(stderr, "Usage: wmcliphist [options]\n\n"
21 "wmcliphist is small dock applet for Window Maker which "
22 "keeps X clipboard history\n\n");
23 fprintf(stderr, "-h show this help\n"
24 "-n <num> set number of items to keep (default 10)\n"
25 "-c color set color for locked items (default is red)\n"
26 "-s <size> choose wmcliphist icon size:\n"
27 " 0 = no icon\n"
28 " 16 = tiny 16x16 px icon\n"
29 " 30 = icon suitable for 32px dock/slit\n"
30 " 40 = icon suitable for 48px dock/slit\n"
31 " 60 = icon suitable for 64px dock/slit (default)\n");
32 fprintf(stderr, "-i <num> choose wmcliphist icon antialiasing:\n"
33 " 0 = for mid tones background (default)\n"
34 " 1 = for dark background\n"
35 " 2 = for light background\n");
36 fprintf(stderr, "-d dumps clipboard history to stdout"
37 " in pseudo XML format (no escaping etc.)\n\n");
39 exit(1);
40 return_void();
43 static void
44 wmcliphist_exit(gint code)
46 begin_func("wmcliphist_exit");
47 exit(code);
48 return_void();
51 /* gtk3 dockapp code based on wmpasman by Brad Jorsch
52 * <anomie@users.sourceforge.net>
53 * http://sourceforge.net/projects/wmpasman */
55 GtkWidget *foo_create_main_icon_window(GtkWidget *mw, unsigned int s)
57 Display *d;
58 GdkDisplay *display;
59 GtkWidget *foobox;
60 unsigned int dummy3;
61 Window mainwin, iw, p, dummy1, *dummy2, w;
62 XWMHints *wmHints;
64 display = gdk_display_get_default();
65 foobox = gtk_window_new(GTK_WINDOW_POPUP);
67 gtk_window_set_wmclass(GTK_WINDOW(mw), g_get_prgname(), "DockApp");
68 gtk_widget_set_size_request(foobox, s, s);
70 gtk_widget_realize(mw);
71 gtk_widget_realize(foobox);
73 d = GDK_DISPLAY_XDISPLAY(display);
74 mainwin = GDK_WINDOW_XID(gtk_widget_get_window(mw));
75 iw = GDK_WINDOW_XID(gtk_widget_get_window(foobox));
76 XQueryTree(d, mainwin, &dummy1, &p, &dummy2, &dummy3);
77 if (dummy2)
78 XFree(dummy2);
79 w = XCreateSimpleWindow(d, p, 0, 0, 1, 1, 0, 0, 0);
80 XReparentWindow(d, mainwin, w, 0, 0);
81 gtk_widget_show(mw);
82 gtk_widget_show(foobox);
83 wmHints = XGetWMHints(d, mainwin);
84 if (!wmHints)
85 wmHints = XAllocWMHints();
86 wmHints->flags |= IconWindowHint;
87 wmHints->icon_window = iw;
88 XSetWMHints(d, mainwin, wmHints);
89 XFree(wmHints);
90 XReparentWindow(d, mainwin, p, 0, 0);
91 XDestroyWindow(d, w);
93 return foobox;
97 * main func
99 int
100 main(int argc, char **argv)
102 gint i = 1, res;
103 gchar *arg;
104 gchar *icon_file;
105 GList *list_node;
106 int icon_number = 0;
107 int icon_size = 60;
108 gboolean dump_only = FALSE;
110 #ifdef FNCALL_DEBUG
111 debug_init_nothreads();
112 #endif
113 begin_func("main");
115 /* load configuration */
116 if ((res = rcconfig_get(rcconfig_get_name("rc"))) != 0) {
117 fprintf(stderr, "~/.wmcliphistrc parse error (%d)\n", res);
118 return_val(1);
121 /* parse command line */
122 while ((arg = argv[i])) {
123 if (*arg == '-') {
124 if (*(arg + 1) == 'h')
125 print_help();
126 else if (*(arg + 1) == 'n') {
127 i++;
128 if (!argv[i]) {
129 fprintf(stderr, "Missing value of -n\n");
130 print_help();
132 num_items_to_keep = atol(argv[i]);
133 } else if (*(arg + 1) == 'c') {
134 i++;
135 if (!argv[i]) {
136 fprintf(stderr, "Missing value of -c\n");
137 print_help();
139 memset(locked_color_str, 0, 32);
140 strncpy(locked_color_str, argv[i], 31);
141 } else if (*(arg + 1) == 'i') {
142 i++;
143 if (!argv[i]) {
144 fprintf(stderr, "Missing value of -i\n");
145 print_help();
147 icon_number = atoi(argv[i]);
148 if (icon_number < 0 || icon_number > 2) {
149 fprintf(stderr, "Invalid value of -i\n");
150 print_help();
152 } else if (*(arg + 1) == 's') {
153 i++;
154 if (!argv[i]) {
155 fprintf(stderr, "Missing value of -s\n");
156 print_help();
158 icon_size = atoi(argv[i]);
159 if (icon_size != 60 && icon_size != 40
160 && icon_size != 30
161 && icon_size != 16
162 && icon_size != 0) {
163 fprintf(stderr, "Invalid value of -s\n");
164 print_help();
166 if (icon_size == 0) {
167 icon_size = 1;
169 } else if (*(arg + 1) == 'd') {
170 dump_only = TRUE;
171 } else {
172 fprintf(stderr, "Invalid option -%c\n", *(arg + 1));
173 print_help();
175 } else {
176 fprintf(stderr, "Invalid option %s\n", arg);
177 print_help();
179 i++;
182 signal(SIGCHLD, SIG_IGN);
184 /* initialize Gtk */
185 gtk_init(&argc, &argv);
188 /* create main window */
189 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
191 /* creat dock icon */
192 dock_app = foo_create_main_icon_window(main_window, icon_size);
194 if (icon_size) {
195 /* create icon_mask */
196 if (icon_size == 60) {
197 /* 60x60 icon */
198 icon_mask = gdk_bitmap_create_from_data(gtk_widget_get_window(main_window),
199 (gchar *) ico_60x60_mask_bits,
200 ico_60x60_mask_width,
201 ico_60x60_mask_height);
202 /* create icon */
203 if (icon_number == 0) {
204 icon_file = "ico_60x60_gray.png";
205 } else if (icon_number == 1) {
206 icon_file = "ico_60x60_black.png";
207 } else {
208 icon_file = "ico_60x60_white.png";
210 } else if (icon_size == 40) {
211 /* 40x40 icon */
212 icon_mask = gdk_bitmap_create_from_data(gtk_widget_get_window(main_window),
213 (gchar *) ico_40x40_mask_bits,
214 ico_40x40_mask_width,
215 ico_40x40_mask_height);
216 /* create icon */
217 if (icon_number == 0) {
218 icon_file = "ico_40x40_gray.png";
219 } else if (icon_number == 1) {
220 icon_file = "ico_40x40_black.png";
221 } else {
222 icon_file = "ico_40x40_white.png";
224 } else if (icon_size == 30) {
225 /* 30x30 icon */
226 icon_mask = gdk_bitmap_create_from_data(gtk_widget_get_window(main_window),
227 (gchar *) ico_30x30_mask_bits,
228 ico_30x30_mask_width,
229 ico_30x30_mask_height);
230 /* create icon */
231 if (icon_number == 0) {
232 icon_file = "ico_30x30_gray.png";
233 } else if (icon_number == 1) {
234 icon_file = "ico_30x30_black.png";
235 } else {
236 icon_file = "ico_30x30_white.png";
238 } else {
239 /* 16x16 icon */
240 icon_mask = gdk_bitmap_create_from_data(gtk_widget_get_window(main_window),
241 (gchar *) ico_16x16_mask_bits,
242 ico_16x16_mask_width,
243 ico_16x16_mask_height);
244 /* create icon */
245 icon_file = "ico_16x16.png";
248 icon_file = g_strconcat(DATADIR"/", icon_file, NULL);
249 pixmap = gtk_image_new_from_file(icon_file);
250 gtk_widget_show(pixmap);
251 gtk_container_add(GTK_CONTAINER(dock_app), pixmap);
255 /* create clipboard history menu */
256 menu_hist = gtk_menu_new();
257 gtk_menu_set_title(GTK_MENU(menu_hist), "Clipboard history");
258 menu_title = gtk_tearoff_menu_item_new();
259 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist), menu_title);
260 gtk_widget_show(menu_title);
261 gtk_widget_show(menu_hist);
264 /* create application menu */
265 menu_app = gtk_menu_new();
267 menu_app_clip_lock = gtk_check_menu_item_new_with_label("Clipboard lock");
268 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_lock);
270 menu_app_clip_ignore = gtk_check_menu_item_new_with_label("Clipboard ignore");
271 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_ignore);
273 menu_app_save = gtk_menu_item_new_with_label("Save history");
274 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_save);
275 g_signal_connect(G_OBJECT(menu_app_save),
276 "activate",
277 G_CALLBACK(menu_app_item_click),
278 GINT_TO_POINTER(0));
280 menu_app_exit = gtk_menu_item_new_with_label("Exit");
281 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_exit);
282 g_signal_connect(G_OBJECT(menu_app_exit),
283 "activate",
284 G_CALLBACK(menu_app_item_click),
285 GINT_TO_POINTER(1));
287 gtk_widget_show_all(menu_app);
290 list_node = action_list;
291 while (list_node) {
292 ACTION *action = list_node->data;
294 if (action->action == ACT_SUBMENU &&
295 strcmp(action->command, "-") != 0) {
296 action->menu_item = gtk_menu_item_new_with_label(
297 action->command);
298 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist),
299 action->menu_item);
300 action->submenu = gtk_menu_new();
301 gtk_menu_item_set_submenu(
302 GTK_MENU_ITEM(action->menu_item),
303 action->submenu);
304 menu_title = gtk_tearoff_menu_item_new();
305 gtk_menu_shell_append(GTK_MENU_SHELL(action->submenu), menu_title);
306 gtk_widget_show(menu_title);
307 gtk_widget_show(action->menu_item);
308 gtk_widget_show(action->submenu);
309 submenu_count++;
311 if (action->action == ACT_SUBMENU &&
312 strcmp(action->command, "-") == 0) {
313 printf("'%s'\n", action->command);
314 action->submenu = menu_hist;
316 list_node = list_node->next;
318 if (submenu_count) {
319 GtkWidget *separator;
321 separator = gtk_menu_item_new();
322 gtk_widget_show(separator);
323 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_hist), separator, 1);
326 /* prepare colors and styles */
327 if (gdk_color_parse(locked_color_str, &locked_color) == 0) {
328 char msg_str[128];
330 sprintf(msg_str, "Invalid color string: '%s'.\n"
331 "Falling back to default (red).",
332 locked_color_str);
333 show_message(msg_str, "Warning", "OK", NULL, NULL);
334 strcpy(locked_color_str, DEF_LOCKED_COLOR);
335 gdk_color_parse(locked_color_str, &locked_color);
337 style_normal = gtk_style_copy(gtk_widget_get_style(menu_hist));
338 style_locked = gtk_style_copy(gtk_widget_get_style(menu_hist));
339 style_locked->fg[GTK_STATE_NORMAL] = locked_color;
340 style_locked->fg[GTK_STATE_PRELIGHT] = locked_color;
343 /* load previously saved history */
344 if (history_load(dump_only) != 0) {
345 if (errno == E_TOO_MUCH) {
346 if (show_message("Number of items to keep (-n switch or "
347 "keep directive in ~/.wmcliphistrc)\n"
348 "is lower than actual number of items "
349 "in history file.\nSome items from "
350 "history will be lost. May I continue?",
351 "Warning", "Yes", "No", NULL) == 1) {
352 rcconfig_free();
353 exit(1);
355 } else if (errno != E_OPEN) {
356 rcconfig_free();
357 fprintf(stderr, "cannot load history (%d)\n", errno);
358 exit(1);
361 if (dump_only) {
362 rcconfig_free();
363 exit(1);
367 if (icon_size) {
368 /* connect signal for menu popup */
369 gtk_widget_add_events(dock_app, GDK_BUTTON_PRESS_MASK);
370 g_signal_connect(G_OBJECT(dock_app),
371 "event",
372 G_CALLBACK(button_press),
373 G_OBJECT(menu_hist));
375 gdk_window_shape_combine_mask(gtk_widget_get_window(main_window), icon_mask, 0, 0);
376 gdk_window_shape_combine_mask(gtk_widget_get_window(dock_app), icon_mask, 0, 0);
380 /* run clipboard monitor */
381 g_signal_connect(G_OBJECT(main_window),
382 "selection_received",
383 G_CALLBACK(my_get_xselection),
384 NULL);
385 g_timeout_add(250, time_conv_select, NULL);
388 /* run autosave timer */
389 if (autosave_period > 0)
390 g_timeout_add(autosave_period * 1000, history_autosave, NULL);
393 /* setup everything for supplying selection to other apps */
394 gtk_selection_add_target(dock_app,
395 GDK_SELECTION_PRIMARY,
396 GDK_SELECTION_TYPE_STRING,
399 g_signal_connect(G_OBJECT(dock_app),
400 "selection_get",
401 G_CALLBACK(selection_handle),
402 NULL);
404 g_signal_connect(G_OBJECT(dock_app),
405 "destroy",
406 G_CALLBACK(wmcliphist_exit),
407 NULL);
410 hotkeys_init();
412 gtk_main();
414 return_val(0);