Commit | Line | Data |
---|---|---|
872870b2 | 1 | /* Function for handling the GLib event loop. |
95df8112 | 2 | |
acaf905b | 3 | Copyright (C) 2009-2012 Free Software Foundation, Inc. |
872870b2 JD |
4 | |
5 | This file is part of GNU Emacs. | |
6 | ||
7 | GNU Emacs is free software: you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation, either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | GNU Emacs is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
0949d2b6 | 18 | along with GNU Emacs. If not, see <http§://www.gnu.org/licenses/>. */ |
872870b2 | 19 | |
08a494a3 | 20 | #include <config.h> |
872870b2 | 21 | |
aefd87e1 PE |
22 | #include <setjmp.h> |
23 | #include "xgselect.h" | |
24 | ||
0949d2b6 | 25 | #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) |
aefd87e1 | 26 | |
872870b2 JD |
27 | #include <glib.h> |
28 | #include <errno.h> | |
29 | #include <setjmp.h> | |
b2f4d39f | 30 | #include "xterm.h" |
872870b2 JD |
31 | |
32 | static GPollFD *gfds; | |
0065d054 | 33 | static ptrdiff_t gfds_size; |
872870b2 JD |
34 | |
35 | int | |
e5447b22 JB |
36 | xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, |
37 | EMACS_TIME *timeout) | |
872870b2 JD |
38 | { |
39 | SELECT_TYPE all_rfds, all_wfds; | |
40 | EMACS_TIME tmo, *tmop = timeout; | |
41 | ||
b0572523 | 42 | GMainContext *context; |
872870b2 JD |
43 | int have_wfds = wfds != NULL; |
44 | int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0; | |
97107e2e | 45 | int i, nfds, fds_lim, tmo_in_millisec; |
872870b2 | 46 | |
b2f4d39f | 47 | if (!x_in_use) |
b0572523 PE |
48 | return select (max_fds, rfds, wfds, efds, timeout); |
49 | ||
872870b2 JD |
50 | if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds)); |
51 | else FD_ZERO (&all_rfds); | |
52 | if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds)); | |
53 | else FD_ZERO (&all_wfds); | |
54 | ||
55 | /* Update event sources in GLib. */ | |
b0572523 | 56 | context = g_main_context_default (); |
872870b2 JD |
57 | g_main_context_pending (context); |
58 | ||
59 | do { | |
41729b81 | 60 | if (n_gfds > gfds_size) |
872870b2 | 61 | { |
872870b2 | 62 | xfree (gfds); |
0065d054 PE |
63 | gfds = xpalloc (0, &gfds_size, n_gfds - gfds_size, INT_MAX, |
64 | sizeof *gfds); | |
872870b2 JD |
65 | } |
66 | ||
67 | n_gfds = g_main_context_query (context, | |
68 | G_PRIORITY_LOW, | |
69 | &tmo_in_millisec, | |
70 | gfds, | |
71 | gfds_size); | |
72 | } while (n_gfds > gfds_size); | |
73 | ||
41729b81 | 74 | for (i = 0; i < n_gfds; ++i) |
872870b2 JD |
75 | { |
76 | if (gfds[i].events & G_IO_IN) | |
77 | { | |
78 | FD_SET (gfds[i].fd, &all_rfds); | |
79 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | |
80 | } | |
81 | if (gfds[i].events & G_IO_OUT) | |
82 | { | |
83 | FD_SET (gfds[i].fd, &all_wfds); | |
84 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | |
85 | have_wfds = 1; | |
86 | } | |
87 | } | |
88 | ||
89 | if (tmo_in_millisec >= 0) | |
90 | { | |
91 | EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000, | |
92 | 1000 * (tmo_in_millisec % 1000)); | |
93 | if (!timeout) our_tmo = 1; | |
94 | else | |
95 | { | |
96 | EMACS_TIME difference; | |
41729b81 | 97 | |
872870b2 JD |
98 | EMACS_SUB_TIME (difference, tmo, *timeout); |
99 | if (EMACS_TIME_NEG_P (difference)) our_tmo = 1; | |
100 | } | |
101 | ||
102 | if (our_tmo) tmop = &tmo; | |
103 | } | |
104 | ||
97107e2e PE |
105 | fds_lim = max_fds + 1; |
106 | nfds = select (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop); | |
872870b2 JD |
107 | |
108 | if (nfds < 0) | |
109 | retval = nfds; | |
41729b81 | 110 | else if (nfds > 0) |
872870b2 | 111 | { |
97107e2e | 112 | for (i = 0; i < fds_lim; ++i) |
872870b2 JD |
113 | { |
114 | if (FD_ISSET (i, &all_rfds)) | |
115 | { | |
116 | if (rfds && FD_ISSET (i, rfds)) ++retval; | |
117 | else ++our_fds; | |
118 | } | |
42d3022b J |
119 | else if (rfds) |
120 | FD_CLR (i, rfds); | |
121 | ||
872870b2 JD |
122 | if (have_wfds && FD_ISSET (i, &all_wfds)) |
123 | { | |
124 | if (wfds && FD_ISSET (i, wfds)) ++retval; | |
125 | else ++our_fds; | |
126 | } | |
42d3022b J |
127 | else if (wfds) |
128 | FD_CLR (i, wfds); | |
129 | ||
872870b2 JD |
130 | if (efds && FD_ISSET (i, efds)) |
131 | ++retval; | |
132 | } | |
133 | } | |
134 | ||
135 | if (our_fds > 0 || (nfds == 0 && our_tmo)) | |
136 | { | |
41729b81 | 137 | |
872870b2 JD |
138 | /* If Gtk+ is in use eventually gtk_main_iteration will be called, |
139 | unless retval is zero. */ | |
140 | #ifdef USE_GTK | |
141 | if (retval == 0) | |
142 | #endif | |
143 | while (g_main_context_pending (context)) | |
144 | g_main_context_dispatch (context); | |
145 | ||
146 | /* To not have to recalculate timeout, return like this. */ | |
41729b81 | 147 | if (retval == 0) |
872870b2 JD |
148 | { |
149 | retval = -1; | |
150 | errno = EINTR; | |
151 | } | |
152 | } | |
153 | ||
154 | return retval; | |
155 | } | |
0949d2b6 | 156 | #endif /* USE_GTK || HAVE_GCONF || HAVE_GSETTINGS */ |
872870b2 JD |
157 | |
158 | void | |
971de7fb | 159 | xgselect_initialize (void) |
872870b2 | 160 | { |
0949d2b6 | 161 | #if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) |
872870b2 JD |
162 | gfds_size = 128; |
163 | gfds = xmalloc (sizeof (*gfds)*gfds_size); | |
0949d2b6 | 164 | #endif |
872870b2 | 165 | } |