Mercurial > emacs
comparison src/gtkutil.c @ 106186:9b6f45dd8386
Use a select wrapper around the GLib event loop, thus taking into account GLib
timeouts and event sources. This simplifies Gtk+-code a lot, and is needed
for handling GConf death/restart.
* xterm.c: #include xgselect.h.
(x_initialize): Call xgselect_initialize.
* xsettings.c (something_changedCB): C++ comments => C comments.
(init_gconf): Do not deal with any GLib file descriptors, xg_select
does that now.
* gtkutil.c (xg_timer, xg_process_timeouts, xg_start_timer)
(xg_stop_timer, menu_grab_callback_cnt, menu_grab_callback)
(scroll_bar_button_cb): Remove.
(create_menus): C++ comments => C comments. Don't bind grab-notify
event.
(xg_create_scroll_bar): Don't bind button-press-event and
button-release-event.
* process.c: Include xgselect.h if defined (USE_GTK) ||
defined (HAVE_GCONF).
(wait_reading_process_output): Call xg_select for the same condition.
* xgselect.c (xg_select): New function to better integrate with
GLib/Gtk event handling. Needed if GConf daemon dies/restarts.
* xgselect.h: New file, declare xg_select, xgselect_initialize.
* Makefile.in (XOBJ): Add xgselect.o.
author | Jan Djärv <jan.h.d@swipnet.se> |
---|---|
date | Sat, 21 Nov 2009 15:28:59 +0000 |
parents | 0ea716305b13 |
children | 471e6932ea09 |
comparison
equal
deleted
inserted
replaced
106185:f2cea199b0c4 | 106186:9b6f45dd8386 |
---|---|
27 #include "lisp.h" | 27 #include "lisp.h" |
28 #include "xterm.h" | 28 #include "xterm.h" |
29 #include "blockinput.h" | 29 #include "blockinput.h" |
30 #include "syssignal.h" | 30 #include "syssignal.h" |
31 #include "window.h" | 31 #include "window.h" |
32 #include "atimer.h" | |
33 #include "gtkutil.h" | 32 #include "gtkutil.h" |
34 #include "termhooks.h" | 33 #include "termhooks.h" |
35 #include "keyboard.h" | 34 #include "keyboard.h" |
36 #include "charset.h" | 35 #include "charset.h" |
37 #include "coding.h" | 36 #include "coding.h" |
179 | 178 |
180 | 179 |
181 /*********************************************************************** | 180 /*********************************************************************** |
182 Utility functions | 181 Utility functions |
183 ***********************************************************************/ | 182 ***********************************************************************/ |
184 /* The timer for scroll bar repetition and menu bar timeouts. | |
185 NULL if no timer is started. */ | |
186 static struct atimer *xg_timer; | |
187 | |
188 | |
189 /* The next two variables and functions are taken from lwlib. */ | 183 /* The next two variables and functions are taken from lwlib. */ |
190 static widget_value *widget_value_free_list; | 184 static widget_value *widget_value_free_list; |
191 static int malloc_cpt; | 185 static int malloc_cpt; |
192 | 186 |
193 /* Allocate a widget_value structure, either by taking one from the | 187 /* Allocate a widget_value structure, either by taking one from the |
422 on widgets in GTK. So we must set the cursor for all GDK windows. | 416 on widgets in GTK. So we must set the cursor for all GDK windows. |
423 Ditto for menus. */ | 417 Ditto for menus. */ |
424 | 418 |
425 for ( ; children; children = g_list_next (children)) | 419 for ( ; children; children = g_list_next (children)) |
426 gdk_window_set_cursor (GDK_WINDOW (children->data), cursor); | 420 gdk_window_set_cursor (GDK_WINDOW (children->data), cursor); |
427 } | |
428 | |
429 /* Timer function called when a timeout occurs for xg_timer. | |
430 This function processes all GTK events in a recursive event loop. | |
431 This is done because GTK timer events are not seen by Emacs event | |
432 detection, Emacs only looks for X events. When a scroll bar has the | |
433 pointer (detected by button press/release events below) an Emacs | |
434 timer is started, and this function can then check if the GTK timer | |
435 has expired by calling the GTK event loop. | |
436 Also, when a menu is active, it has a small timeout before it | |
437 pops down the sub menu under it. */ | |
438 | |
439 static void | |
440 xg_process_timeouts (timer) | |
441 struct atimer *timer; | |
442 { | |
443 BLOCK_INPUT; | |
444 /* Ideally we would like to just handle timer events, like the Xt version | |
445 of this does in xterm.c, but there is no such feature in GTK. */ | |
446 while (gtk_events_pending ()) | |
447 gtk_main_iteration (); | |
448 UNBLOCK_INPUT; | |
449 } | |
450 | |
451 /* Start the xg_timer with an interval of 0.1 seconds, if not already started. | |
452 xg_process_timeouts is called when the timer expires. The timer | |
453 started is continuous, i.e. runs until xg_stop_timer is called. */ | |
454 | |
455 static void | |
456 xg_start_timer () | |
457 { | |
458 if (! xg_timer) | |
459 { | |
460 EMACS_TIME interval; | |
461 EMACS_SET_SECS_USECS (interval, 0, 100000); | |
462 xg_timer = start_atimer (ATIMER_CONTINUOUS, | |
463 interval, | |
464 xg_process_timeouts, | |
465 0); | |
466 } | |
467 } | |
468 | |
469 /* Stop the xg_timer if started. */ | |
470 | |
471 static void | |
472 xg_stop_timer () | |
473 { | |
474 if (xg_timer) | |
475 { | |
476 cancel_atimer (xg_timer); | |
477 xg_timer = 0; | |
478 } | |
479 } | 421 } |
480 | 422 |
481 /* Insert NODE into linked LIST. */ | 423 /* Insert NODE into linked LIST. */ |
482 | 424 |
483 static void | 425 static void |
1893 gpointer client_data; | 1835 gpointer client_data; |
1894 { | 1836 { |
1895 unref_cl_data ((xg_menu_cb_data*) client_data); | 1837 unref_cl_data ((xg_menu_cb_data*) client_data); |
1896 } | 1838 } |
1897 | 1839 |
1898 /* Callback called when a menu does a grab or ungrab. That means the | |
1899 menu has been activated or deactivated. | |
1900 Used to start a timer so the small timeout the menus in GTK uses before | |
1901 popping down a menu is seen by Emacs (see xg_process_timeouts above). | |
1902 W is the widget that does the grab (not used). | |
1903 UNGRAB_P is TRUE if this is an ungrab, FALSE if it is a grab. | |
1904 CLIENT_DATA is NULL (not used). */ | |
1905 | |
1906 /* Keep track of total number of grabs. */ | |
1907 static int menu_grab_callback_cnt; | |
1908 | |
1909 static void | |
1910 menu_grab_callback (GtkWidget *widget, | |
1911 gboolean ungrab_p, | |
1912 gpointer client_data) | |
1913 { | |
1914 if (ungrab_p) menu_grab_callback_cnt--; | |
1915 else menu_grab_callback_cnt++; | |
1916 | |
1917 if (menu_grab_callback_cnt > 0 && ! xg_timer) xg_start_timer (); | |
1918 else if (menu_grab_callback_cnt == 0 && xg_timer) xg_stop_timer (); | |
1919 } | |
1920 | |
1921 /* Make a GTK widget that contains both UTF8_LABEL and UTF8_KEY (both | 1840 /* Make a GTK widget that contains both UTF8_LABEL and UTF8_KEY (both |
1922 must be non-NULL) and can be inserted into a menu item. | 1841 must be non-NULL) and can be inserted into a menu item. |
1923 | 1842 |
1924 Returns the GtkHBox. */ | 1843 Returns the GtkHBox. */ |
1925 | 1844 |
2230 NULL); | 2149 NULL); |
2231 } | 2150 } |
2232 else | 2151 else |
2233 { | 2152 { |
2234 wmenu = gtk_menu_bar_new (); | 2153 wmenu = gtk_menu_bar_new (); |
2235 // Set width of menu bar to a small value so it doesn't enlarge | 2154 /* Set width of menu bar to a small value so it doesn't enlarge |
2236 // a small initial frame size. The width will be set to the | 2155 a small initial frame size. The width will be set to the |
2237 // width of the frame later on when it is added to a container. | 2156 width of the frame later on when it is added to a container. |
2238 // height -1: Natural height. | 2157 height -1: Natural height. */ |
2239 gtk_widget_set_size_request (wmenu, 1, -1); | 2158 gtk_widget_set_size_request (wmenu, 1, -1); |
2240 } | 2159 } |
2241 | 2160 |
2242 /* Put cl_data on the top menu for easier access. */ | 2161 /* Put cl_data on the top menu for easier access. */ |
2243 cl_data = make_cl_data (cl_data, f, highlight_cb); | 2162 cl_data = make_cl_data (cl_data, f, highlight_cb); |
2249 gtk_widget_set_name (wmenu, name); | 2168 gtk_widget_set_name (wmenu, name); |
2250 | 2169 |
2251 if (deactivate_cb) | 2170 if (deactivate_cb) |
2252 g_signal_connect (G_OBJECT (wmenu), | 2171 g_signal_connect (G_OBJECT (wmenu), |
2253 "selection-done", deactivate_cb, 0); | 2172 "selection-done", deactivate_cb, 0); |
2254 | |
2255 g_signal_connect (G_OBJECT (wmenu), | |
2256 "grab-notify", G_CALLBACK (menu_grab_callback), 0); | |
2257 } | 2173 } |
2258 | 2174 |
2259 if (! menu_bar_p && add_tearoff_p) | 2175 if (! menu_bar_p && add_tearoff_p) |
2260 { | 2176 { |
2261 GtkWidget *tearoff = gtk_tearoff_menu_item_new (); | 2177 GtkWidget *tearoff = gtk_tearoff_menu_item_new (); |
3175 p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA); | 3091 p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA); |
3176 xfree (p); | 3092 xfree (p); |
3177 xg_remove_widget_from_map (id); | 3093 xg_remove_widget_from_map (id); |
3178 } | 3094 } |
3179 | 3095 |
3180 /* Callback for button press/release events. Used to start timer so that | |
3181 the scroll bar repetition timer in GTK gets handled. | |
3182 Also, sets bar->dragging to Qnil when dragging (button release) is done. | |
3183 WIDGET is the scroll bar widget the event is for (not used). | |
3184 EVENT contains the event. | |
3185 USER_DATA points to the struct scrollbar structure. | |
3186 | |
3187 Returns FALSE to tell GTK that it shall continue propagate the event | |
3188 to widgets. */ | |
3189 | |
3190 static gboolean | |
3191 scroll_bar_button_cb (widget, event, user_data) | |
3192 GtkWidget *widget; | |
3193 GdkEventButton *event; | |
3194 gpointer user_data; | |
3195 { | |
3196 if (event->type == GDK_BUTTON_PRESS && ! xg_timer) | |
3197 xg_start_timer (); | |
3198 else if (event->type == GDK_BUTTON_RELEASE) | |
3199 { | |
3200 struct scroll_bar *bar = (struct scroll_bar *) user_data; | |
3201 if (xg_timer) xg_stop_timer (); | |
3202 bar->dragging = Qnil; | |
3203 } | |
3204 | |
3205 return FALSE; | |
3206 } | |
3207 | |
3208 /* Create a scroll bar widget for frame F. Store the scroll bar | 3096 /* Create a scroll bar widget for frame F. Store the scroll bar |
3209 in BAR. | 3097 in BAR. |
3210 SCROLL_CALLBACK is the callback to invoke when the value of the | 3098 SCROLL_CALLBACK is the callback to invoke when the value of the |
3211 bar changes. | 3099 bar changes. |
3212 SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used | 3100 SCROLL_BAR_NAME is the name we use for the scroll bar. Can be used |
3243 /* The EMACS_INT cast avoids a warning. */ | 3131 /* The EMACS_INT cast avoids a warning. */ |
3244 g_signal_connect (G_OBJECT (wscroll), | 3132 g_signal_connect (G_OBJECT (wscroll), |
3245 "destroy", | 3133 "destroy", |
3246 G_CALLBACK (xg_gtk_scroll_destroy), | 3134 G_CALLBACK (xg_gtk_scroll_destroy), |
3247 (gpointer) (EMACS_INT) scroll_id); | 3135 (gpointer) (EMACS_INT) scroll_id); |
3248 | |
3249 /* Connect to button press and button release to detect if any scroll bar | |
3250 has the pointer. */ | |
3251 g_signal_connect (G_OBJECT (wscroll), | |
3252 "button-press-event", | |
3253 G_CALLBACK (scroll_bar_button_cb), | |
3254 (gpointer) bar); | |
3255 g_signal_connect (G_OBJECT (wscroll), | |
3256 "button-release-event", | |
3257 G_CALLBACK (scroll_bar_button_cb), | |
3258 (gpointer) bar); | |
3259 | 3136 |
3260 /* The scroll bar widget does not draw on a window of its own. Instead | 3137 /* The scroll bar widget does not draw on a window of its own. Instead |
3261 it draws on the parent window, in this case the edit widget. So | 3138 it draws on the parent window, in this case the edit widget. So |
3262 whenever the edit widget is cleared, the scroll bar needs to redraw | 3139 whenever the edit widget is cleared, the scroll bar needs to redraw |
3263 also, which causes flicker. Put an event box between the edit widget | 3140 also, which causes flicker. Put an event box between the edit widget |