|
@@ -1,7 +1,7 @@
|
1
|
1
|
/*
|
2
|
2
|
* StarDict terminal UI
|
3
|
3
|
*
|
4
|
|
- * Copyright (c) 2013 - 2016, Přemysl Janouch <p@janouch.name>
|
|
4
|
+ * Copyright (c) 2013 - 2018, Přemysl Janouch <p@janouch.name>
|
5
|
5
|
*
|
6
|
6
|
* Permission to use, copy, modify, and/or distribute this software for any
|
7
|
7
|
* purpose with or without fee is hereby granted.
|
|
@@ -43,10 +43,6 @@
|
43
|
43
|
#include "stardict.h"
|
44
|
44
|
#include "utils.h"
|
45
|
45
|
|
46
|
|
-#ifdef WITH_GTK
|
47
|
|
-#include <gtk/gtk.h>
|
48
|
|
-#endif // WITH_GTK
|
49
|
|
-
|
50
|
46
|
#define CTRL_KEY(x) ((x) - 'A' + 1)
|
51
|
47
|
|
52
|
48
|
#define TOP_BAR_CUTOFF 2 ///< How many lines are reserved on top
|
|
@@ -213,6 +209,7 @@ struct application
|
213
|
209
|
guint center_search : 1; ///< Whether to center the search
|
214
|
210
|
guint underline_last : 1; ///< Underline the last definition
|
215
|
211
|
guint hl_prefix : 1; ///< Highlight the common prefix
|
|
212
|
+ guint watch_x11_sel : 1; ///< Requested X11 selection watcher
|
216
|
213
|
|
217
|
214
|
guint32 top_position; ///< Index of the topmost dict. entry
|
218
|
215
|
guint top_offset; ///< Offset into the top entry
|
|
@@ -226,10 +223,6 @@ struct application
|
226
|
223
|
|
227
|
224
|
gfloat division; ///< Position of the division column
|
228
|
225
|
|
229
|
|
- guint selection_timer; ///< Selection watcher timeout timer
|
230
|
|
- gint selection_interval; ///< Selection watcher timer interval
|
231
|
|
- gchar * selection_contents; ///< Selection contents
|
232
|
|
-
|
233
|
226
|
struct attrs attrs[ATTRIBUTE_COUNT];
|
234
|
227
|
};
|
235
|
228
|
|
|
@@ -398,18 +391,6 @@ app_reload_view (Application *self)
|
398
|
391
|
g_object_unref (iterator);
|
399
|
392
|
}
|
400
|
393
|
|
401
|
|
-#ifdef WITH_GTK
|
402
|
|
-static gboolean on_selection_timer (gpointer data);
|
403
|
|
-
|
404
|
|
-static void
|
405
|
|
-rearm_selection_watcher (Application *self)
|
406
|
|
-{
|
407
|
|
- if (self->selection_interval > 0)
|
408
|
|
- self->selection_timer = g_timeout_add
|
409
|
|
- (self->selection_interval, on_selection_timer, self);
|
410
|
|
-}
|
411
|
|
-#endif // WITH_GTK
|
412
|
|
-
|
413
|
394
|
/// Load configuration for a color using a subset of git config colors.
|
414
|
395
|
static void
|
415
|
396
|
app_load_color (Application *self, GKeyFile *kf, const gchar *name, int id)
|
|
@@ -468,14 +449,8 @@ app_load_config_values (Application *self, GKeyFile *kf)
|
468
|
449
|
app_load_bool (kf, "underline-last", self->underline_last);
|
469
|
450
|
self->hl_prefix =
|
470
|
451
|
app_load_bool (kf, "hl-common-prefix", self->hl_prefix);
|
471
|
|
-
|
472
|
|
- guint64 timer;
|
473
|
|
- const gchar *watch_selection = "watch-selection";
|
474
|
|
- if (app_load_bool (kf, watch_selection, FALSE))
|
475
|
|
- self->selection_interval = 500;
|
476
|
|
- else if ((timer = g_key_file_get_uint64
|
477
|
|
- (kf, "Settings", watch_selection, NULL)) && timer <= G_MAXINT)
|
478
|
|
- self->selection_interval = timer;
|
|
452
|
+ self->watch_x11_sel =
|
|
453
|
+ app_load_bool (kf, "watch-selection", self->watch_x11_sel);
|
479
|
454
|
|
480
|
455
|
#define XX(name, config, fg_, bg_, attrs_) \
|
481
|
456
|
app_load_color (self, kf, config, ATTRIBUTE_ ## name);
|
|
@@ -613,9 +588,6 @@ static void
|
613
|
588
|
app_init (Application *self, char **filenames)
|
614
|
589
|
{
|
615
|
590
|
self->loop = NULL;
|
616
|
|
- self->selection_interval = -1;
|
617
|
|
- self->selection_timer = 0;
|
618
|
|
- self->selection_contents = NULL;
|
619
|
591
|
|
620
|
592
|
self->tk = NULL;
|
621
|
593
|
self->tk_timer = 0;
|
|
@@ -624,6 +596,7 @@ app_init (Application *self, char **filenames)
|
624
|
596
|
self->center_search = TRUE;
|
625
|
597
|
self->underline_last = TRUE;
|
626
|
598
|
self->hl_prefix = TRUE;
|
|
599
|
+ self->watch_x11_sel = FALSE;
|
627
|
600
|
|
628
|
601
|
self->top_position = 0;
|
629
|
602
|
self->top_offset = 0;
|
|
@@ -660,18 +633,7 @@ app_init (Application *self, char **filenames)
|
660
|
633
|
exit (EXIT_FAILURE);
|
661
|
634
|
}
|
662
|
635
|
|
663
|
|
- // Now we have settings for the clipboard watcher, we can arm the timer
|
664
|
|
-#ifdef WITH_GTK
|
665
|
|
- if (gtk_init_check (0, NULL))
|
666
|
|
- {
|
667
|
|
- // So that we set the input only when it actually changes
|
668
|
|
- GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
|
669
|
|
- self->selection_contents = gtk_clipboard_wait_for_text (clipboard);
|
670
|
|
- rearm_selection_watcher (self);
|
671
|
|
- }
|
672
|
|
- else
|
673
|
|
-#endif // WITH_GTK
|
674
|
|
- self->loop = g_main_loop_new (NULL, FALSE);
|
|
636
|
+ self->loop = g_main_loop_new (NULL, FALSE);
|
675
|
637
|
|
676
|
638
|
// Dictionaries given on the command line override the configuration
|
677
|
639
|
if (*filenames)
|
|
@@ -744,10 +706,6 @@ app_destroy (Application *self)
|
744
|
706
|
if (self->tk_timer)
|
745
|
707
|
g_source_remove (self->tk_timer);
|
746
|
708
|
|
747
|
|
- if (self->selection_timer)
|
748
|
|
- g_source_remove (self->selection_timer);
|
749
|
|
- g_free (self->selection_contents);
|
750
|
|
-
|
751
|
709
|
g_ptr_array_free (self->entries, TRUE);
|
752
|
710
|
g_free (self->search_label);
|
753
|
711
|
g_array_free (self->input, TRUE);
|
|
@@ -760,24 +718,14 @@ app_destroy (Application *self)
|
760
|
718
|
static void
|
761
|
719
|
app_run (Application *self)
|
762
|
720
|
{
|
763
|
|
- if (self->loop)
|
764
|
|
- g_main_loop_run (self->loop);
|
765
|
|
-#ifdef WITH_GTK
|
766
|
|
- else
|
767
|
|
- gtk_main ();
|
768
|
|
-#endif // WITH_GTK
|
|
721
|
+ g_main_loop_run (self->loop);
|
769
|
722
|
}
|
770
|
723
|
|
771
|
724
|
/// Quit the main event dispatch loop.
|
772
|
725
|
static void
|
773
|
726
|
app_quit (Application *self)
|
774
|
727
|
{
|
775
|
|
- if (self->loop)
|
776
|
|
- g_main_loop_quit (self->loop);
|
777
|
|
-#ifdef WITH_GTK
|
778
|
|
- else
|
779
|
|
- gtk_main_quit ();
|
780
|
|
-#endif // WITH_GTK
|
|
728
|
+ g_main_loop_quit (self->loop);
|
781
|
729
|
}
|
782
|
730
|
|
783
|
731
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
@@ -1023,7 +971,7 @@ app_show_help (Application *self)
|
1023
|
971
|
{
|
1024
|
972
|
PROJECT_NAME " " PROJECT_VERSION,
|
1025
|
973
|
_("Terminal UI for StarDict dictionaries"),
|
1026
|
|
- "Copyright (c) 2013 - 2016, Přemysl Janouch",
|
|
974
|
+ "Copyright (c) 2013 - 2018, Přemysl Janouch",
|
1027
|
975
|
"",
|
1028
|
976
|
_("Type to search")
|
1029
|
977
|
};
|
|
@@ -1835,6 +1783,215 @@ install_winch_handler (void)
|
1835
|
1783
|
sigaction (SIGWINCH, &act, &oldact);
|
1836
|
1784
|
}
|
1837
|
1785
|
|
|
1786
|
+// --- X11 selection watcher ---------------------------------------------------
|
|
1787
|
+
|
|
1788
|
+#ifdef WITH_X11
|
|
1789
|
+
|
|
1790
|
+#include <xcb/xcb.h>
|
|
1791
|
+#include <xcb/xfixes.h>
|
|
1792
|
+
|
|
1793
|
+/// Data relating to one entry within the dictionary.
|
|
1794
|
+typedef struct selection_watch SelectionWatch;
|
|
1795
|
+
|
|
1796
|
+struct selection_watch
|
|
1797
|
+{
|
|
1798
|
+ Application *app;
|
|
1799
|
+ xcb_connection_t *X;
|
|
1800
|
+ const xcb_query_extension_reply_t *xfixes;
|
|
1801
|
+
|
|
1802
|
+ guint watch; ///< X11 connection watcher
|
|
1803
|
+ xcb_window_t wid; ///< Withdrawn communications window
|
|
1804
|
+ xcb_atom_t atom_utf8_string; ///< UTF8_STRING
|
|
1805
|
+ xcb_timestamp_t in_progress; ///< Timestamp of last processed event
|
|
1806
|
+};
|
|
1807
|
+
|
|
1808
|
+static gboolean
|
|
1809
|
+is_xcb_ok (xcb_connection_t *X)
|
|
1810
|
+{
|
|
1811
|
+ int xcb_error = xcb_connection_has_error (X);
|
|
1812
|
+ if (xcb_error)
|
|
1813
|
+ {
|
|
1814
|
+ g_warning (_("X11 connection failed (error code %d)"), xcb_error);
|
|
1815
|
+ return FALSE;
|
|
1816
|
+ }
|
|
1817
|
+ return TRUE;
|
|
1818
|
+}
|
|
1819
|
+
|
|
1820
|
+static xcb_atom_t
|
|
1821
|
+resolve_atom (xcb_connection_t *X, const char *atom)
|
|
1822
|
+{
|
|
1823
|
+ xcb_intern_atom_reply_t *iar = xcb_intern_atom_reply (X,
|
|
1824
|
+ xcb_intern_atom (X, false, strlen (atom), atom), NULL);
|
|
1825
|
+ xcb_atom_t result = iar ? iar->atom : XCB_NONE;
|
|
1826
|
+ free (iar);
|
|
1827
|
+ return result;
|
|
1828
|
+}
|
|
1829
|
+
|
|
1830
|
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
1831
|
+
|
|
1832
|
+static void
|
|
1833
|
+app_set_input (Application *self, const gchar *text, gsize text_len);
|
|
1834
|
+
|
|
1835
|
+static void
|
|
1836
|
+on_selection_text_received (SelectionWatch *self, const gchar *text);
|
|
1837
|
+
|
|
1838
|
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
1839
|
+
|
|
1840
|
+static gboolean
|
|
1841
|
+read_utf8_property (SelectionWatch *self, xcb_window_t wid, xcb_atom_t property,
|
|
1842
|
+ GString *buf)
|
|
1843
|
+{
|
|
1844
|
+ guint32 offset = 0;
|
|
1845
|
+ gboolean loop = TRUE, ok = TRUE;
|
|
1846
|
+ while (ok && loop)
|
|
1847
|
+ {
|
|
1848
|
+ xcb_get_property_reply_t *gpr = xcb_get_property_reply (self->X,
|
|
1849
|
+ xcb_get_property (self->X, FALSE /* delete */, wid,
|
|
1850
|
+ property, XCB_GET_PROPERTY_TYPE_ANY, offset, 0x7fff), NULL);
|
|
1851
|
+
|
|
1852
|
+ if (!gpr || gpr->type != self->atom_utf8_string || gpr->format != 8)
|
|
1853
|
+ ok = FALSE;
|
|
1854
|
+ else
|
|
1855
|
+ {
|
|
1856
|
+ int len = xcb_get_property_value_length (gpr);
|
|
1857
|
+ g_string_append_len (buf, xcb_get_property_value (gpr), len);
|
|
1858
|
+ offset += len >> 2;
|
|
1859
|
+ loop = gpr->bytes_after > 0;
|
|
1860
|
+ }
|
|
1861
|
+
|
|
1862
|
+ free (gpr);
|
|
1863
|
+ }
|
|
1864
|
+ return ok;
|
|
1865
|
+}
|
|
1866
|
+
|
|
1867
|
+static void
|
|
1868
|
+process_x11_event (SelectionWatch *self, xcb_generic_event_t *event)
|
|
1869
|
+{
|
|
1870
|
+ xcb_generic_error_t *err = NULL;
|
|
1871
|
+ int event_code = event->response_type & 0x7f;
|
|
1872
|
+ if (event_code == 0)
|
|
1873
|
+ {
|
|
1874
|
+ err = (xcb_generic_error_t *) event;
|
|
1875
|
+ g_warning (_("X11 request error (%d, major %d, minor %d)"),
|
|
1876
|
+ err->error_code, err->major_code, err->minor_code);
|
|
1877
|
+ }
|
|
1878
|
+ else if (event_code ==
|
|
1879
|
+ self->xfixes->first_event + XCB_XFIXES_SELECTION_NOTIFY)
|
|
1880
|
+ {
|
|
1881
|
+ xcb_xfixes_selection_notify_event_t *e =
|
|
1882
|
+ (xcb_xfixes_selection_notify_event_t *) event;
|
|
1883
|
+
|
|
1884
|
+ // Not checking whether we should give up when this interrupts our
|
|
1885
|
+ // current retrieval attempt--the timeout solves this
|
|
1886
|
+ if (e->owner == XCB_NONE)
|
|
1887
|
+ return;
|
|
1888
|
+
|
|
1889
|
+ // Don't try to process two things at once. Each request gets a few
|
|
1890
|
+ // seconds to finish, then we move on, hoping that a property race
|
|
1891
|
+ // doesn't commence. Ideally we'd set up a separate queue for these
|
|
1892
|
+ // skipped requests and process them later.
|
|
1893
|
+ if (self->in_progress != 0 && e->timestamp - self->in_progress < 5000)
|
|
1894
|
+ return;
|
|
1895
|
+
|
|
1896
|
+ // ICCCM says we should ensure the named property doesn't exist
|
|
1897
|
+ (void) xcb_delete_property (self->X, self->wid, XCB_ATOM_PRIMARY);
|
|
1898
|
+
|
|
1899
|
+ (void) xcb_convert_selection (self->X, self->wid, e->selection,
|
|
1900
|
+ self->atom_utf8_string, XCB_ATOM_PRIMARY, e->timestamp);
|
|
1901
|
+ self->in_progress = e->timestamp;
|
|
1902
|
+ }
|
|
1903
|
+ else if (event_code == XCB_SELECTION_NOTIFY)
|
|
1904
|
+ {
|
|
1905
|
+ xcb_selection_notify_event_t *e =
|
|
1906
|
+ (xcb_selection_notify_event_t *) event;
|
|
1907
|
+ if (e->time != self->in_progress)
|
|
1908
|
+ return;
|
|
1909
|
+
|
|
1910
|
+ self->in_progress = 0;
|
|
1911
|
+ if (e->property == XCB_ATOM_NONE)
|
|
1912
|
+ return;
|
|
1913
|
+
|
|
1914
|
+ GString *buf = g_string_new (NULL);
|
|
1915
|
+ if (read_utf8_property (self, e->requestor, e->property, buf))
|
|
1916
|
+ on_selection_text_received (self, buf->str);
|
|
1917
|
+ g_string_free (buf, TRUE);
|
|
1918
|
+
|
|
1919
|
+ (void) xcb_delete_property (self->X, self->wid, e->property);
|
|
1920
|
+ }
|
|
1921
|
+}
|
|
1922
|
+
|
|
1923
|
+static gboolean
|
|
1924
|
+process_x11 (G_GNUC_UNUSED GIOChannel *source,
|
|
1925
|
+ G_GNUC_UNUSED GIOCondition condition, gpointer data)
|
|
1926
|
+{
|
|
1927
|
+ SelectionWatch *self = data;
|
|
1928
|
+
|
|
1929
|
+ xcb_generic_event_t *event;
|
|
1930
|
+ while ((event = xcb_poll_for_event (self->X)))
|
|
1931
|
+ {
|
|
1932
|
+ process_x11_event (self, event);
|
|
1933
|
+ free (event);
|
|
1934
|
+ }
|
|
1935
|
+ (void) xcb_flush (self->X);
|
|
1936
|
+ return is_xcb_ok (self->X);
|
|
1937
|
+}
|
|
1938
|
+
|
|
1939
|
+static void
|
|
1940
|
+selection_watch_init (SelectionWatch *self, Application *app)
|
|
1941
|
+{
|
|
1942
|
+ memset (self, 0, sizeof *self);
|
|
1943
|
+ if (!app->watch_x11_sel)
|
|
1944
|
+ return;
|
|
1945
|
+ self->app = app;
|
|
1946
|
+
|
|
1947
|
+ int which_screen = -1;
|
|
1948
|
+ self->X = xcb_connect (NULL, &which_screen);
|
|
1949
|
+ if (!is_xcb_ok (self->X))
|
|
1950
|
+ return;
|
|
1951
|
+
|
|
1952
|
+ // Most modern applications support this, though an XCB_ATOM_STRING
|
|
1953
|
+ // fallback might be good to add (COMPOUND_TEXT is complex)
|
|
1954
|
+ g_return_if_fail
|
|
1955
|
+ ((self->atom_utf8_string = resolve_atom (self->X, "UTF8_STRING")));
|
|
1956
|
+
|
|
1957
|
+ self->xfixes = xcb_get_extension_data (self->X, &xcb_xfixes_id);
|
|
1958
|
+ g_return_if_fail (self->xfixes->present);
|
|
1959
|
+
|
|
1960
|
+ (void) xcb_xfixes_query_version_unchecked (self->X,
|
|
1961
|
+ XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
|
|
1962
|
+
|
|
1963
|
+ const xcb_setup_t *setup = xcb_get_setup (self->X);
|
|
1964
|
+ xcb_screen_iterator_t setup_iter = xcb_setup_roots_iterator (setup);
|
|
1965
|
+ while (which_screen--)
|
|
1966
|
+ xcb_screen_next (&setup_iter);
|
|
1967
|
+
|
|
1968
|
+ xcb_screen_t *screen = setup_iter.data;
|
|
1969
|
+ self->wid = xcb_generate_id (self->X);
|
|
1970
|
+ (void) xcb_create_window (self->X, screen->root_depth, self->wid,
|
|
1971
|
+ screen->root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
1972
|
+ screen->root_visual, 0, NULL);
|
|
1973
|
+
|
|
1974
|
+ (void) xcb_xfixes_select_selection_input (self->X, self->wid,
|
|
1975
|
+ XCB_ATOM_PRIMARY, XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
|
|
1976
|
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
|
|
1977
|
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE);
|
|
1978
|
+
|
|
1979
|
+ (void) xcb_flush (self->X);
|
|
1980
|
+ self->watch = g_io_add_watch (g_io_channel_unix_new
|
|
1981
|
+ (xcb_get_file_descriptor (self->X)), G_IO_IN, process_x11, self);
|
|
1982
|
+}
|
|
1983
|
+
|
|
1984
|
+static void
|
|
1985
|
+selection_watch_destroy (SelectionWatch *self)
|
|
1986
|
+{
|
|
1987
|
+ if (self->X)
|
|
1988
|
+ xcb_disconnect (self->X);
|
|
1989
|
+ if (self->watch)
|
|
1990
|
+ g_source_remove (self->watch);
|
|
1991
|
+}
|
|
1992
|
+
|
|
1993
|
+#endif // WITH_X11
|
|
1994
|
+
|
1838
|
1995
|
// --- Initialisation, event handling ------------------------------------------
|
1839
|
1996
|
|
1840
|
1997
|
static gboolean on_stdin_input_timeout (gpointer data);
|
|
@@ -1903,7 +2060,7 @@ on_terminated (gpointer user_data)
|
1903
|
2060
|
return TRUE;
|
1904
|
2061
|
}
|
1905
|
2062
|
|
1906
|
|
-#ifdef WITH_GTK
|
|
2063
|
+#ifdef WITH_X11
|
1907
|
2064
|
static void
|
1908
|
2065
|
app_set_input (Application *self, const gchar *text, gsize text_len)
|
1909
|
2066
|
{
|
|
@@ -1935,47 +2092,19 @@ app_set_input (Application *self, const gchar *text, gsize text_len)
|
1935
|
2092
|
}
|
1936
|
2093
|
|
1937
|
2094
|
static void
|
1938
|
|
-on_selection_text_received (G_GNUC_UNUSED GtkClipboard *clipboard,
|
1939
|
|
- const gchar *text, gpointer data)
|
1940
|
|
-{
|
1941
|
|
- Application *app = data;
|
1942
|
|
- rearm_selection_watcher (app);
|
1943
|
|
-
|
1944
|
|
- if (text)
|
1945
|
|
- {
|
1946
|
|
- // Strip ASCII whitespace: this is compatible with UTF-8
|
1947
|
|
- while (g_ascii_isspace (*text))
|
1948
|
|
- text++;
|
1949
|
|
- gsize text_len = strlen (text);
|
1950
|
|
- while (text_len && g_ascii_isspace (text[text_len - 1]))
|
1951
|
|
- text_len--;
|
1952
|
|
-
|
1953
|
|
- if (app->selection_contents &&
|
1954
|
|
- !strncmp (app->selection_contents, text, text_len))
|
1955
|
|
- return;
|
1956
|
|
-
|
1957
|
|
- g_free (app->selection_contents);
|
1958
|
|
- app->selection_contents = g_strndup (text, text_len);
|
1959
|
|
- app_set_input (app, text, text_len);
|
1960
|
|
- }
|
1961
|
|
- else if (app->selection_contents)
|
1962
|
|
- {
|
1963
|
|
- g_free (app->selection_contents);
|
1964
|
|
- app->selection_contents = NULL;
|
1965
|
|
- }
|
1966
|
|
-}
|
1967
|
|
-
|
1968
|
|
-static gboolean
|
1969
|
|
-on_selection_timer (gpointer data)
|
|
2095
|
+on_selection_text_received (SelectionWatch *self, const gchar *text)
|
1970
|
2096
|
{
|
1971
|
|
- Application *app = data;
|
1972
|
|
- GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
|
1973
|
|
- gtk_clipboard_request_text (clipboard, on_selection_text_received, app);
|
|
2097
|
+ // Strip ASCII whitespace: this is compatible with UTF-8
|
|
2098
|
+ while (g_ascii_isspace (*text))
|
|
2099
|
+ text++;
|
|
2100
|
+ gsize text_len = strlen (text);
|
|
2101
|
+ while (text_len && g_ascii_isspace (text[text_len - 1]))
|
|
2102
|
+ text_len--;
|
1974
|
2103
|
|
1975
|
|
- app->selection_timer = 0;
|
1976
|
|
- return FALSE;
|
|
2104
|
+ if (text_len)
|
|
2105
|
+ app_set_input (self->app, text, text_len);
|
1977
|
2106
|
}
|
1978
|
|
-#endif // WITH_GTK
|
|
2107
|
+#endif // WITH_X11
|
1979
|
2108
|
|
1980
|
2109
|
static void
|
1981
|
2110
|
log_handler_curses (Application *self, const gchar *message)
|
|
@@ -2091,7 +2220,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
2091
|
2220
|
// g_unix_signal_add() cannot handle SIGWINCH
|
2092
|
2221
|
install_winch_handler ();
|
2093
|
2222
|
|
2094
|
|
- // GtkClipboard can internally issue some rather disruptive warnings
|
|
2223
|
+ // Avoid disruptive warnings
|
2095
|
2224
|
g_log_set_default_handler (log_handler, &app);
|
2096
|
2225
|
|
2097
|
2226
|
// Message loop
|
|
@@ -2102,8 +2231,17 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
2102
|
2231
|
guint watch_winch = g_io_add_watch (g_io_channel_unix_new (g_winch_pipe[0]),
|
2103
|
2232
|
G_IO_IN, process_winch_input, &app);
|
2104
|
2233
|
|
|
2234
|
+#ifdef WITH_X11
|
|
2235
|
+ SelectionWatch sw;
|
|
2236
|
+ selection_watch_init (&sw, &app);
|
|
2237
|
+#endif // WITH_X11
|
|
2238
|
+
|
2105
|
2239
|
app_run (&app);
|
2106
|
2240
|
|
|
2241
|
+#ifdef WITH_X11
|
|
2242
|
+ selection_watch_destroy (&sw);
|
|
2243
|
+#endif // WITH_X11
|
|
2244
|
+
|
2107
|
2245
|
g_source_remove (watch_term);
|
2108
|
2246
|
g_source_remove (watch_int);
|
2109
|
2247
|
g_source_remove (watch_stdin);
|