2 * (c) 2001 Michal Krause <michal@krause.cz>
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"
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"
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");
44 wmcliphist_exit(gint code
)
46 begin_func("wmcliphist_exit");
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
)
61 Window mainwin
, iw
, p
, dummy1
, *dummy2
, w
;
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
);
79 w
= XCreateSimpleWindow(d
, p
, 0, 0, 1, 1, 0, 0, 0);
80 XReparentWindow(d
, mainwin
, w
, 0, 0);
82 gtk_widget_show(foobox
);
83 wmHints
= XGetWMHints(d
, mainwin
);
85 wmHints
= XAllocWMHints();
86 wmHints
->flags
|= IconWindowHint
;
87 wmHints
->icon_window
= iw
;
88 XSetWMHints(d
, mainwin
, wmHints
);
90 XReparentWindow(d
, mainwin
, p
, 0, 0);
100 main(int argc
, char **argv
)
108 gboolean dump_only
= FALSE
;
111 debug_init_nothreads();
115 /* load configuration */
116 if ((res
= rcconfig_get(rcconfig_get_name("rc"))) != 0) {
117 fprintf(stderr
, "~/.wmcliphistrc parse error (%d)\n", res
);
121 /* parse command line */
122 while ((arg
= argv
[i
])) {
124 if (*(arg
+ 1) == 'h')
126 else if (*(arg
+ 1) == 'n') {
129 fprintf(stderr
, "Missing value of -n\n");
132 num_items_to_keep
= atol(argv
[i
]);
133 } else if (*(arg
+ 1) == 'c') {
136 fprintf(stderr
, "Missing value of -c\n");
139 memset(locked_color_str
, 0, 32);
140 strncpy(locked_color_str
, argv
[i
], 31);
141 } else if (*(arg
+ 1) == 'i') {
144 fprintf(stderr
, "Missing value of -i\n");
147 icon_number
= atoi(argv
[i
]);
148 if (icon_number
< 0 || icon_number
> 2) {
149 fprintf(stderr
, "Invalid value of -i\n");
152 } else if (*(arg
+ 1) == 's') {
155 fprintf(stderr
, "Missing value of -s\n");
158 icon_size
= atoi(argv
[i
]);
159 if (icon_size
!= 60 && icon_size
!= 40
163 fprintf(stderr
, "Invalid value of -s\n");
166 if (icon_size
== 0) {
169 } else if (*(arg
+ 1) == 'd') {
172 fprintf(stderr
, "Invalid option -%c\n", *(arg
+ 1));
176 fprintf(stderr
, "Invalid option %s\n", arg
);
182 signal(SIGCHLD
, SIG_IGN
);
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
);
195 /* create icon_mask */
196 if (icon_size
== 60) {
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
);
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";
208 icon_file
= "ico_60x60_white.png";
210 } else if (icon_size
== 40) {
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
);
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";
222 icon_file
= "ico_40x40_white.png";
224 } else if (icon_size
== 30) {
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
);
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";
236 icon_file
= "ico_30x30_white.png";
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
);
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
),
277 G_CALLBACK(menu_app_item_click
),
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
),
284 G_CALLBACK(menu_app_item_click
),
287 gtk_widget_show_all(menu_app
);
290 list_node
= action_list
;
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(
298 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist
),
300 action
->submenu
= gtk_menu_new();
301 gtk_menu_item_set_submenu(
302 GTK_MENU_ITEM(action
->menu_item
),
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
);
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
;
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) {
330 sprintf(msg_str
, "Invalid color string: '%s'.\n"
331 "Falling back to default (red).",
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) {
355 } else if (errno
!= E_OPEN
) {
357 fprintf(stderr
, "cannot load history (%d)\n", errno
);
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
),
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
),
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
),
401 G_CALLBACK(selection_handle
),
404 g_signal_connect(G_OBJECT(dock_app
),
406 G_CALLBACK(wmcliphist_exit
),