No issues found
1 /*
2 * e-focus-tracker.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "e-focus-tracker.h"
27
28 #include <glib/gi18n-lib.h>
29
30 #include <misc/e-selectable.h>
31
32 #define E_FOCUS_TRACKER_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_FOCUS_TRACKER, EFocusTrackerPrivate))
35
36 struct _EFocusTrackerPrivate {
37 GtkWidget *focus; /* not referenced */
38 GtkWindow *window;
39
40 GtkAction *cut_clipboard;
41 GtkAction *copy_clipboard;
42 GtkAction *paste_clipboard;
43 GtkAction *delete_selection;
44 GtkAction *select_all;
45 };
46
47 enum {
48 PROP_0,
49 PROP_FOCUS,
50 PROP_WINDOW,
51 PROP_CUT_CLIPBOARD_ACTION,
52 PROP_COPY_CLIPBOARD_ACTION,
53 PROP_PASTE_CLIPBOARD_ACTION,
54 PROP_DELETE_SELECTION_ACTION,
55 PROP_SELECT_ALL_ACTION
56 };
57
58 G_DEFINE_TYPE (
59 EFocusTracker,
60 e_focus_tracker,
61 G_TYPE_OBJECT)
62
63 static void
64 focus_tracker_disable_actions (EFocusTracker *focus_tracker)
65 {
66 GtkAction *action;
67
68 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
69 if (action != NULL)
70 gtk_action_set_sensitive (action, FALSE);
71
72 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
73 if (action != NULL)
74 gtk_action_set_sensitive (action, FALSE);
75
76 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
77 if (action != NULL)
78 gtk_action_set_sensitive (action, FALSE);
79
80 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
81 if (action != NULL)
82 gtk_action_set_sensitive (action, FALSE);
83
84 action = e_focus_tracker_get_select_all_action (focus_tracker);
85 if (action != NULL)
86 gtk_action_set_sensitive (action, FALSE);
87 }
88
89 static void
90 focus_tracker_editable_update_actions (EFocusTracker *focus_tracker,
91 GtkEditable *editable,
92 GdkAtom *targets,
93 gint n_targets)
94 {
95 GtkAction *action;
96 gboolean can_edit_text;
97 gboolean clipboard_has_text;
98 gboolean text_is_selected;
99 gboolean sensitive;
100
101 can_edit_text =
102 gtk_editable_get_editable (editable);
103
104 clipboard_has_text = (targets != NULL) &&
105 gtk_targets_include_text (targets, n_targets);
106
107 text_is_selected =
108 gtk_editable_get_selection_bounds (editable, NULL, NULL);
109
110 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
111 if (action != NULL) {
112 sensitive = can_edit_text && text_is_selected;
113 gtk_action_set_sensitive (action, sensitive);
114 gtk_action_set_tooltip (action, _("Cut the selection"));
115 }
116
117 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
118 if (action != NULL) {
119 sensitive = text_is_selected;
120 gtk_action_set_sensitive (action, sensitive);
121 gtk_action_set_tooltip (action, _("Copy the selection"));
122 }
123
124 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
125 if (action != NULL) {
126 sensitive = can_edit_text && clipboard_has_text;
127 gtk_action_set_sensitive (action, sensitive);
128 gtk_action_set_tooltip (action, _("Paste the clipboard"));
129 }
130
131 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
132 if (action != NULL) {
133 sensitive = can_edit_text && text_is_selected;
134 gtk_action_set_sensitive (action, sensitive);
135 gtk_action_set_tooltip (action, _("Delete the selection"));
136 }
137
138 action = e_focus_tracker_get_select_all_action (focus_tracker);
139 if (action != NULL) {
140 sensitive = TRUE; /* always enabled */
141 gtk_action_set_sensitive (action, sensitive);
142 gtk_action_set_tooltip (action, _("Select all text"));
143 }
144 }
145
146 static void
147 focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker,
148 ESelectable *selectable,
149 GdkAtom *targets,
150 gint n_targets)
151 {
152 ESelectableInterface *interface;
153 GtkAction *action;
154
155 interface = E_SELECTABLE_GET_INTERFACE (selectable);
156
157 e_selectable_update_actions (
158 selectable, focus_tracker, targets, n_targets);
159
160 /* Disable actions for which the corresponding method is not
161 * implemented. This allows update_actions() implementations
162 * to simply skip the actions they don't support, which in turn
163 * allows us to add new actions without disturbing the existing
164 * ESelectable implementations. */
165
166 action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
167 if (action != NULL && interface->cut_clipboard == NULL)
168 gtk_action_set_sensitive (action, FALSE);
169
170 action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
171 if (action != NULL && interface->copy_clipboard == NULL)
172 gtk_action_set_sensitive (action, FALSE);
173
174 action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
175 if (action != NULL && interface->paste_clipboard == NULL)
176 gtk_action_set_sensitive (action, FALSE);
177
178 action = e_focus_tracker_get_delete_selection_action (focus_tracker);
179 if (action != NULL && interface->delete_selection == NULL)
180 gtk_action_set_sensitive (action, FALSE);
181
182 action = e_focus_tracker_get_select_all_action (focus_tracker);
183 if (action != NULL && interface->select_all == NULL)
184 gtk_action_set_sensitive (action, FALSE);
185 }
186
187 static void
188 focus_tracker_targets_received_cb (GtkClipboard *clipboard,
189 GdkAtom *targets,
190 gint n_targets,
191 EFocusTracker *focus_tracker)
192 {
193 GtkWidget *focus;
194
195 focus = e_focus_tracker_get_focus (focus_tracker);
196
197 if (focus == NULL)
198 focus_tracker_disable_actions (focus_tracker);
199
200 else if (GTK_IS_EDITABLE (focus))
201 focus_tracker_editable_update_actions (
202 focus_tracker, GTK_EDITABLE (focus),
203 targets, n_targets);
204
205 else if (E_IS_SELECTABLE (focus))
206 focus_tracker_selectable_update_actions (
207 focus_tracker, E_SELECTABLE (focus),
208 targets, n_targets);
209
210 g_object_unref (focus_tracker);
211 }
212
213 static void
214 focus_tracker_set_focus_cb (GtkWindow *window,
215 GtkWidget *focus,
216 EFocusTracker *focus_tracker)
217 {
218 while (focus != NULL) {
219 if (GTK_IS_EDITABLE (focus))
220 break;
221
222 if (E_IS_SELECTABLE (focus))
223 break;
224
225 focus = gtk_widget_get_parent (focus);
226 }
227
228 if (focus == focus_tracker->priv->focus)
229 return;
230
231 focus_tracker->priv->focus = focus;
232 g_object_notify (G_OBJECT (focus_tracker), "focus");
233
234 e_focus_tracker_update_actions (focus_tracker);
235 }
236
237 static void
238 focus_tracker_set_window (EFocusTracker *focus_tracker,
239 GtkWindow *window)
240 {
241 g_return_if_fail (GTK_IS_WINDOW (window));
242 g_return_if_fail (focus_tracker->priv->window == NULL);
243
244 focus_tracker->priv->window = g_object_ref (window);
245
246 g_signal_connect (
247 window, "set-focus",
248 G_CALLBACK (focus_tracker_set_focus_cb), focus_tracker);
249 }
250
251 static void
252 focus_tracker_set_property (GObject *object,
253 guint property_id,
254 const GValue *value,
255 GParamSpec *pspec)
256 {
257 switch (property_id) {
258 case PROP_WINDOW:
259 focus_tracker_set_window (
260 E_FOCUS_TRACKER (object),
261 g_value_get_object (value));
262 return;
263
264 case PROP_CUT_CLIPBOARD_ACTION:
265 e_focus_tracker_set_cut_clipboard_action (
266 E_FOCUS_TRACKER (object),
267 g_value_get_object (value));
268 return;
269
270 case PROP_COPY_CLIPBOARD_ACTION:
271 e_focus_tracker_set_copy_clipboard_action (
272 E_FOCUS_TRACKER (object),
273 g_value_get_object (value));
274 return;
275
276 case PROP_PASTE_CLIPBOARD_ACTION:
277 e_focus_tracker_set_paste_clipboard_action (
278 E_FOCUS_TRACKER (object),
279 g_value_get_object (value));
280 return;
281
282 case PROP_DELETE_SELECTION_ACTION:
283 e_focus_tracker_set_delete_selection_action (
284 E_FOCUS_TRACKER (object),
285 g_value_get_object (value));
286 return;
287
288 case PROP_SELECT_ALL_ACTION:
289 e_focus_tracker_set_select_all_action (
290 E_FOCUS_TRACKER (object),
291 g_value_get_object (value));
292 return;
293 }
294
295 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
296 }
297
298 static void
299 focus_tracker_get_property (GObject *object,
300 guint property_id,
301 GValue *value,
302 GParamSpec *pspec)
303 {
304 switch (property_id) {
305 case PROP_FOCUS:
306 g_value_set_object (
307 value,
308 e_focus_tracker_get_focus (
309 E_FOCUS_TRACKER (object)));
310 return;
311
312 case PROP_WINDOW:
313 g_value_set_object (
314 value,
315 e_focus_tracker_get_window (
316 E_FOCUS_TRACKER (object)));
317 return;
318
319 case PROP_CUT_CLIPBOARD_ACTION:
320 g_value_set_object (
321 value,
322 e_focus_tracker_get_cut_clipboard_action (
323 E_FOCUS_TRACKER (object)));
324 return;
325
326 case PROP_COPY_CLIPBOARD_ACTION:
327 g_value_set_object (
328 value,
329 e_focus_tracker_get_copy_clipboard_action (
330 E_FOCUS_TRACKER (object)));
331 return;
332
333 case PROP_PASTE_CLIPBOARD_ACTION:
334 g_value_set_object (
335 value,
336 e_focus_tracker_get_paste_clipboard_action (
337 E_FOCUS_TRACKER (object)));
338 return;
339
340 case PROP_DELETE_SELECTION_ACTION:
341 g_value_set_object (
342 value,
343 e_focus_tracker_get_delete_selection_action (
344 E_FOCUS_TRACKER (object)));
345 return;
346
347 case PROP_SELECT_ALL_ACTION:
348 g_value_set_object (
349 value,
350 e_focus_tracker_get_select_all_action (
351 E_FOCUS_TRACKER (object)));
352 return;
353 }
354
355 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
356 }
357
358 static void
359 focus_tracker_dispose (GObject *object)
360 {
361 EFocusTrackerPrivate *priv;
362
363 priv = E_FOCUS_TRACKER_GET_PRIVATE (object);
364
365 g_signal_handlers_disconnect_matched (
366 gtk_clipboard_get (GDK_SELECTION_PRIMARY),
367 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
368
369 g_signal_handlers_disconnect_matched (
370 gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
371 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object);
372
373 if (priv->window != NULL) {
374 g_signal_handlers_disconnect_matched (
375 priv->window, G_SIGNAL_MATCH_DATA,
376 0, 0, NULL, NULL, object);
377 g_object_unref (priv->window);
378 priv->window = NULL;
379 }
380
381 if (priv->cut_clipboard != NULL) {
382 g_signal_handlers_disconnect_matched (
383 priv->cut_clipboard, G_SIGNAL_MATCH_DATA,
384 0, 0, NULL, NULL, object);
385 g_object_unref (priv->cut_clipboard);
386 priv->cut_clipboard = NULL;
387 }
388
389 if (priv->copy_clipboard != NULL) {
390 g_signal_handlers_disconnect_matched (
391 priv->copy_clipboard, G_SIGNAL_MATCH_DATA,
392 0, 0, NULL, NULL, object);
393 g_object_unref (priv->copy_clipboard);
394 priv->copy_clipboard = NULL;
395 }
396
397 if (priv->paste_clipboard != NULL) {
398 g_signal_handlers_disconnect_matched (
399 priv->paste_clipboard, G_SIGNAL_MATCH_DATA,
400 0, 0, NULL, NULL, object);
401 g_object_unref (priv->paste_clipboard);
402 priv->paste_clipboard = NULL;
403 }
404
405 if (priv->delete_selection != NULL) {
406 g_signal_handlers_disconnect_matched (
407 priv->delete_selection, G_SIGNAL_MATCH_DATA,
408 0, 0, NULL, NULL, object);
409 g_object_unref (priv->delete_selection);
410 priv->delete_selection = NULL;
411 }
412
413 if (priv->select_all != NULL) {
414 g_signal_handlers_disconnect_matched (
415 priv->select_all, G_SIGNAL_MATCH_DATA,
416 0, 0, NULL, NULL, object);
417 g_object_unref (priv->select_all);
418 priv->select_all = NULL;
419 }
420
421 /* Chain up to parent's dispose() method. */
422 G_OBJECT_CLASS (e_focus_tracker_parent_class)->dispose (object);
423 }
424
425 static void
426 focus_tracker_constructed (GObject *object)
427 {
428 GtkClipboard *clipboard;
429
430 /* Listen for "owner-change" signals from the primary selection
431 * clipboard to learn when text selections change in GtkEditable
432 * widgets. It's a bit of an overkill, but I don't know of any
433 * other notification mechanism. */
434
435 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
436
437 g_signal_connect_swapped (
438 clipboard, "owner-change",
439 G_CALLBACK (e_focus_tracker_update_actions), object);
440
441 /* Listen for "owner-change" signals from the default clipboard
442 * so we can update the paste action when the user cuts or copies
443 * something. This is how GEdit does it. */
444
445 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
446
447 g_signal_connect_swapped (
448 clipboard, "owner-change",
449 G_CALLBACK (e_focus_tracker_update_actions), object);
450
451 /* Chain up to parent's constructed() method. */
452 G_OBJECT_CLASS (e_focus_tracker_parent_class)->constructed (object);
453 }
454
455 static void
456 e_focus_tracker_class_init (EFocusTrackerClass *class)
457 {
458 GObjectClass *object_class;
459
460 g_type_class_add_private (class, sizeof (EFocusTrackerPrivate));
461
462 object_class = G_OBJECT_CLASS (class);
463 object_class->set_property = focus_tracker_set_property;
464 object_class->get_property = focus_tracker_get_property;
465 object_class->dispose = focus_tracker_dispose;
466 object_class->constructed = focus_tracker_constructed;
467
468 g_object_class_install_property (
469 object_class,
470 PROP_FOCUS,
471 g_param_spec_object (
472 "focus",
473 "Focus",
474 NULL,
475 GTK_TYPE_WIDGET,
476 G_PARAM_READABLE));
477
478 g_object_class_install_property (
479 object_class,
480 PROP_WINDOW,
481 g_param_spec_object (
482 "window",
483 "Window",
484 NULL,
485 GTK_TYPE_WINDOW,
486 G_PARAM_READWRITE |
487 G_PARAM_CONSTRUCT_ONLY));
488
489 g_object_class_install_property (
490 object_class,
491 PROP_CUT_CLIPBOARD_ACTION,
492 g_param_spec_object (
493 "cut-clipboard-action",
494 "Cut Clipboard Action",
495 NULL,
496 GTK_TYPE_ACTION,
497 G_PARAM_READWRITE));
498
499 g_object_class_install_property (
500 object_class,
501 PROP_COPY_CLIPBOARD_ACTION,
502 g_param_spec_object (
503 "copy-clipboard-action",
504 "Copy Clipboard Action",
505 NULL,
506 GTK_TYPE_ACTION,
507 G_PARAM_READWRITE));
508
509 g_object_class_install_property (
510 object_class,
511 PROP_PASTE_CLIPBOARD_ACTION,
512 g_param_spec_object (
513 "paste-clipboard-action",
514 "Paste Clipboard Action",
515 NULL,
516 GTK_TYPE_ACTION,
517 G_PARAM_READWRITE));
518
519 g_object_class_install_property (
520 object_class,
521 PROP_DELETE_SELECTION_ACTION,
522 g_param_spec_object (
523 "delete-selection-action",
524 "Delete Selection Action",
525 NULL,
526 GTK_TYPE_ACTION,
527 G_PARAM_READWRITE));
528
529 g_object_class_install_property (
530 object_class,
531 PROP_SELECT_ALL_ACTION,
532 g_param_spec_object (
533 "select-all-action",
534 "Select All Action",
535 NULL,
536 GTK_TYPE_ACTION,
537 G_PARAM_READWRITE));
538 }
539
540 static void
541 e_focus_tracker_init (EFocusTracker *focus_tracker)
542 {
543 GtkAction *action;
544
545 focus_tracker->priv = E_FOCUS_TRACKER_GET_PRIVATE (focus_tracker);
546
547 /* Define dummy actions. These will most likely be overridden,
548 * but for cases where they're not it ensures ESelectable objects
549 * will always get a valid GtkAction when they ask us for one. */
550
551 action = gtk_action_new (
552 "cut-clipboard", NULL,
553 _("Cut the selection"), GTK_STOCK_CUT);
554 focus_tracker->priv->cut_clipboard = action;
555
556 action = gtk_action_new (
557 "copy-clipboard", NULL,
558 _("Copy the selection"), GTK_STOCK_COPY);
559 focus_tracker->priv->copy_clipboard = action;
560
561 action = gtk_action_new (
562 "paste-clipboard", NULL,
563 _("Paste the clipboard"), GTK_STOCK_PASTE);
564 focus_tracker->priv->paste_clipboard = action;
565
566 action = gtk_action_new (
567 "delete-selection", NULL,
568 _("Delete the selection"), GTK_STOCK_DELETE);
569 focus_tracker->priv->delete_selection = action;
570
571 action = gtk_action_new (
572 "select-all", NULL,
573 _("Select all text"), GTK_STOCK_SELECT_ALL);
574 focus_tracker->priv->select_all = action;
575 }
576
577 EFocusTracker *
578 e_focus_tracker_new (GtkWindow *window)
579 {
580 g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
581
582 return g_object_new (E_TYPE_FOCUS_TRACKER, "window", window, NULL);
583 }
584
585 GtkWidget *
586 e_focus_tracker_get_focus (EFocusTracker *focus_tracker)
587 {
588 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
589
590 return focus_tracker->priv->focus;
591 }
592
593 GtkWindow *
594 e_focus_tracker_get_window (EFocusTracker *focus_tracker)
595 {
596 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
597
598 return focus_tracker->priv->window;
599 }
600
601 GtkAction *
602 e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker)
603 {
604 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
605
606 return focus_tracker->priv->cut_clipboard;
607 }
608
609 void
610 e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker,
611 GtkAction *cut_clipboard)
612 {
613 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
614
615 if (cut_clipboard != NULL) {
616 g_return_if_fail (GTK_IS_ACTION (cut_clipboard));
617 g_object_ref (cut_clipboard);
618 }
619
620 if (focus_tracker->priv->cut_clipboard != NULL) {
621 g_signal_handlers_disconnect_matched (
622 focus_tracker->priv->cut_clipboard,
623 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
624 focus_tracker);
625 g_object_unref (focus_tracker->priv->cut_clipboard);
626 }
627
628 focus_tracker->priv->cut_clipboard = cut_clipboard;
629
630 if (cut_clipboard != NULL)
631 g_signal_connect_swapped (
632 cut_clipboard, "activate",
633 G_CALLBACK (e_focus_tracker_cut_clipboard),
634 focus_tracker);
635
636 g_object_notify (G_OBJECT (focus_tracker), "cut-clipboard-action");
637 }
638
639 GtkAction *
640 e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker)
641 {
642 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
643
644 return focus_tracker->priv->copy_clipboard;
645 }
646
647 void
648 e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker,
649 GtkAction *copy_clipboard)
650 {
651 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
652
653 if (copy_clipboard != NULL) {
654 g_return_if_fail (GTK_IS_ACTION (copy_clipboard));
655 g_object_ref (copy_clipboard);
656 }
657
658 if (focus_tracker->priv->copy_clipboard != NULL) {
659 g_signal_handlers_disconnect_matched (
660 focus_tracker->priv->copy_clipboard,
661 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
662 focus_tracker);
663 g_object_unref (focus_tracker->priv->copy_clipboard);
664 }
665
666 focus_tracker->priv->copy_clipboard = copy_clipboard;
667
668 if (copy_clipboard != NULL)
669 g_signal_connect_swapped (
670 copy_clipboard, "activate",
671 G_CALLBACK (e_focus_tracker_copy_clipboard),
672 focus_tracker);
673
674 g_object_notify (G_OBJECT (focus_tracker), "copy-clipboard-action");
675 }
676
677 GtkAction *
678 e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker)
679 {
680 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
681
682 return focus_tracker->priv->paste_clipboard;
683 }
684
685 void
686 e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker,
687 GtkAction *paste_clipboard)
688 {
689 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
690
691 if (paste_clipboard != NULL) {
692 g_return_if_fail (GTK_IS_ACTION (paste_clipboard));
693 g_object_ref (paste_clipboard);
694 }
695
696 if (focus_tracker->priv->paste_clipboard != NULL) {
697 g_signal_handlers_disconnect_matched (
698 focus_tracker->priv->paste_clipboard,
699 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
700 focus_tracker);
701 g_object_unref (focus_tracker->priv->paste_clipboard);
702 }
703
704 focus_tracker->priv->paste_clipboard = paste_clipboard;
705
706 if (paste_clipboard != NULL)
707 g_signal_connect_swapped (
708 paste_clipboard, "activate",
709 G_CALLBACK (e_focus_tracker_paste_clipboard),
710 focus_tracker);
711
712 g_object_notify (G_OBJECT (focus_tracker), "paste-clipboard-action");
713 }
714
715 GtkAction *
716 e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker)
717 {
718 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
719
720 return focus_tracker->priv->delete_selection;
721 }
722
723 void
724 e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker,
725 GtkAction *delete_selection)
726 {
727 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
728
729 if (delete_selection != NULL) {
730 g_return_if_fail (GTK_IS_ACTION (delete_selection));
731 g_object_ref (delete_selection);
732 }
733
734 if (focus_tracker->priv->delete_selection != NULL) {
735 g_signal_handlers_disconnect_matched (
736 focus_tracker->priv->delete_selection,
737 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
738 focus_tracker);
739 g_object_unref (focus_tracker->priv->delete_selection);
740 }
741
742 focus_tracker->priv->delete_selection = delete_selection;
743
744 if (delete_selection != NULL)
745 g_signal_connect_swapped (
746 delete_selection, "activate",
747 G_CALLBACK (e_focus_tracker_delete_selection),
748 focus_tracker);
749
750 g_object_notify (G_OBJECT (focus_tracker), "delete-selection-action");
751 }
752
753 GtkAction *
754 e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker)
755 {
756 g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL);
757
758 return focus_tracker->priv->select_all;
759 }
760
761 void
762 e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker,
763 GtkAction *select_all)
764 {
765 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
766
767 if (select_all != NULL) {
768 g_return_if_fail (GTK_IS_ACTION (select_all));
769 g_object_ref (select_all);
770 }
771
772 if (focus_tracker->priv->select_all != NULL) {
773 g_signal_handlers_disconnect_matched (
774 focus_tracker->priv->select_all,
775 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL,
776 focus_tracker);
777 g_object_unref (focus_tracker->priv->select_all);
778 }
779
780 focus_tracker->priv->select_all = select_all;
781
782 if (select_all != NULL)
783 g_signal_connect_swapped (
784 select_all, "activate",
785 G_CALLBACK (e_focus_tracker_select_all),
786 focus_tracker);
787
788 g_object_notify (G_OBJECT (focus_tracker), "select-all-action");
789 }
790
791 void
792 e_focus_tracker_update_actions (EFocusTracker *focus_tracker)
793 {
794 GtkClipboard *clipboard;
795
796 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
797
798 /* Request clipboard targets asynchronously. */
799
800 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
801
802 gtk_clipboard_request_targets (
803 clipboard, (GtkClipboardTargetsReceivedFunc)
804 focus_tracker_targets_received_cb,
805 g_object_ref (focus_tracker));
806 }
807
808 void
809 e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker)
810 {
811 GtkWidget *focus;
812
813 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
814
815 focus = e_focus_tracker_get_focus (focus_tracker);
816
817 if (GTK_IS_EDITABLE (focus))
818 gtk_editable_cut_clipboard (GTK_EDITABLE (focus));
819
820 else if (E_IS_SELECTABLE (focus))
821 e_selectable_cut_clipboard (E_SELECTABLE (focus));
822 }
823
824 void
825 e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker)
826 {
827 GtkWidget *focus;
828
829 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
830
831 focus = e_focus_tracker_get_focus (focus_tracker);
832
833 if (GTK_IS_EDITABLE (focus))
834 gtk_editable_copy_clipboard (GTK_EDITABLE (focus));
835
836 else if (E_IS_SELECTABLE (focus))
837 e_selectable_copy_clipboard (E_SELECTABLE (focus));
838 }
839
840 void
841 e_focus_tracker_paste_clipboard (EFocusTracker *focus_tracker)
842 {
843 GtkWidget *focus;
844
845 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
846
847 focus = e_focus_tracker_get_focus (focus_tracker);
848
849 if (GTK_IS_EDITABLE (focus))
850 gtk_editable_paste_clipboard (GTK_EDITABLE (focus));
851
852 else if (E_IS_SELECTABLE (focus))
853 e_selectable_paste_clipboard (E_SELECTABLE (focus));
854 }
855
856 void
857 e_focus_tracker_delete_selection (EFocusTracker *focus_tracker)
858 {
859 GtkWidget *focus;
860
861 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
862
863 focus = e_focus_tracker_get_focus (focus_tracker);
864
865 if (GTK_IS_EDITABLE (focus))
866 gtk_editable_delete_selection (GTK_EDITABLE (focus));
867
868 else if (E_IS_SELECTABLE (focus))
869 e_selectable_delete_selection (E_SELECTABLE (focus));
870 }
871
872 void
873 e_focus_tracker_select_all (EFocusTracker *focus_tracker)
874 {
875 GtkWidget *focus;
876
877 g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker));
878
879 focus = e_focus_tracker_get_focus (focus_tracker);
880
881 if (GTK_IS_EDITABLE (focus))
882 gtk_editable_select_region (GTK_EDITABLE (focus), 0, -1);
883
884 else if (E_IS_SELECTABLE (focus))
885 e_selectable_select_all (E_SELECTABLE (focus));
886 }