Mercurial > hg > xemacs-beta
annotate src/scrollbar-gtk.c @ 5157:1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* diagnose.el (show-memory-usage):
Rewrite to take into account API changes in memory-usage functions.
src/ChangeLog addition:
2010-03-18 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (disksave_object_finalization_1):
* alloc.c (lisp_object_storage_size):
* alloc.c (listu):
* alloc.c (listn):
* alloc.c (Fobject_memory_usage_stats):
* alloc.c (compute_memusage_stats_length):
* alloc.c (Fobject_memory_usage):
* alloc.c (Ftotal_object_memory_usage):
* alloc.c (malloced_storage_size):
* alloc.c (common_init_alloc_early):
* alloc.c (reinit_alloc_objects_early):
* alloc.c (reinit_alloc_early):
* alloc.c (init_alloc_once_early):
* alloc.c (syms_of_alloc):
* alloc.c (reinit_vars_of_alloc):
* buffer.c:
* buffer.c (struct buffer_stats):
* buffer.c (compute_buffer_text_usage):
* buffer.c (compute_buffer_usage):
* buffer.c (buffer_memory_usage):
* buffer.c (buffer_objects_create):
* buffer.c (syms_of_buffer):
* buffer.c (vars_of_buffer):
* console-impl.h (struct console_methods):
* dynarr.c (Dynarr_memory_usage):
* emacs.c (main_1):
* events.c (clear_event_resource):
* extents.c:
* extents.c (compute_buffer_extent_usage):
* extents.c (extent_objects_create):
* extents.h:
* faces.c:
* faces.c (compute_face_cachel_usage):
* faces.c (face_objects_create):
* faces.h:
* general-slots.h:
* glyphs.c:
* glyphs.c (compute_glyph_cachel_usage):
* glyphs.c (glyph_objects_create):
* glyphs.h:
* lisp.h:
* lisp.h (struct usage_stats):
* lrecord.h:
* lrecord.h (enum lrecord_type):
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER_FOR_DISKSAVE):
* lrecord.h (DEFINE_DUMPABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_FROB_BLOCK_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_INTERNAL_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_SIZABLE_INTERNAL_LISP_OBJECT):
* lrecord.h (MAKE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_DUMPABLE_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_LISP_OBJECT):
* lrecord.h (DEFINE_NODUMP_MODULE_SIZABLE_LISP_OBJECT):
* lrecord.h (MAKE_MODULE_LISP_OBJECT):
* lrecord.h (INIT_LISP_OBJECT):
* lrecord.h (INIT_MODULE_LISP_OBJECT):
* lrecord.h (UNDEF_LISP_OBJECT):
* lrecord.h (UNDEF_MODULE_LISP_OBJECT):
* lrecord.h (DECLARE_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_API_LISP_OBJECT):
* lrecord.h (DECLARE_MODULE_LISP_OBJECT):
* lstream.c:
* lstream.c (syms_of_lstream):
* lstream.c (vars_of_lstream):
* marker.c:
* marker.c (compute_buffer_marker_usage):
* mc-alloc.c (mc_alloced_storage_size):
* mc-alloc.h:
* mule-charset.c:
* mule-charset.c (struct charset_stats):
* mule-charset.c (compute_charset_usage):
* mule-charset.c (charset_memory_usage):
* mule-charset.c (mule_charset_objects_create):
* mule-charset.c (syms_of_mule_charset):
* mule-charset.c (vars_of_mule_charset):
* redisplay.c:
* redisplay.c (compute_rune_dynarr_usage):
* redisplay.c (compute_display_block_dynarr_usage):
* redisplay.c (compute_glyph_block_dynarr_usage):
* redisplay.c (compute_display_line_dynarr_usage):
* redisplay.c (compute_line_start_cache_dynarr_usage):
* redisplay.h:
* scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage):
* scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage):
* scrollbar-x.c (x_compute_scrollbar_instance_usage):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h:
* symbols.c:
* symbols.c (reinit_symbol_objects_early):
* symbols.c (init_symbols_once_early):
* symbols.c (reinit_symbols_early):
* symbols.c (defsymbol_massage_name_1):
* symsinit.h:
* ui-gtk.c:
* ui-gtk.c (emacs_gtk_object_getprop):
* ui-gtk.c (emacs_gtk_object_putprop):
* ui-gtk.c (ui_gtk_objects_create):
* unicode.c (compute_from_unicode_table_size_1):
* unicode.c (compute_to_unicode_table_size_1):
* unicode.c (compute_from_unicode_table_size):
* unicode.c (compute_to_unicode_table_size):
* window.c:
* window.c (struct window_stats):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
* window.c (window_memory_usage):
* window.c (window_objects_create):
* window.c (syms_of_window):
* window.c (vars_of_window):
* window.h:
Redo memory-usage mechanism, make it general; add way of dynamically
initializing Lisp object types -- OBJECT_HAS_METHOD(), similar to
CONSOLE_HAS_METHOD().
(1) Create OBJECT_HAS_METHOD(), OBJECT_HAS_PROPERTY() etc. for
specifying that a Lisp object type has a particular method or
property. Call such methods with OBJECT_METH, MAYBE_OBJECT_METH,
OBJECT_METH_OR_GIVEN; retrieve properties with OBJECT_PROPERTY.
Methods that formerly required a DEFINE_*GENERAL_LISP_OBJECT() to
specify them (getprop, putprop, remprop, plist, disksave) now
instead use the dynamic-method mechanism. The main benefit of
this is that new methods or properties can be added without
requiring that the declaration statements of all existing methods
be modified. We have to make the `struct lrecord_implementation'
non-const, but I don't think this should have any effect on speed --
the only possible method that's really speed-critical is the
mark method, and we already extract those out into a separate
(non-const) array for increased cache locality.
Object methods need to be reinitialized after pdump, so we put
them in separate functions such as face_objects_create(),
extent_objects_create() and call them appropriately from emacs.c
The only current object property (`memusage_stats_list') that
objects can specify is a Lisp object and gets staticpro()ed so it
only needs to be set during dump time, but because it references
symbols that might not exist in a syms_of_() function, we
initialize it in vars_of_(). There is also an object property
(`num_extra_memusage_stats') that is automatically initialized based
on `memusage_stats_list'; we do that in reinit_vars_of_alloc(),
which is called after all vars_of_() functions are called.
`disksaver' method was renamed `disksave' to correspond with the
name normally given to the function (e.g. disksave_lstream()).
(2) Generalize the memory-usage mechanism in `buffer-memory-usage',
`window-memory-usage', `charset-memory-usage' into an object-type-
specific mechanism called by a single function
`object-memory-usage'. (Former function `object-memory-usage'
renamed to `total-object-memory-usage'). Generalize the mechanism
of different "slices" so that we can have different "classes" of
memory described and different "slices" onto each class; `t'
separates classes, `nil' separates slices. Currently we have
three classes defined: the memory of an object itself,
non-Lisp-object memory associated with the object (e.g. arrays or
dynarrs stored as fields in the object), and Lisp-object memory
associated with the object (other internal Lisp objects stored in
the object). This isn't completely finished yet and we might need
to further separate the "other internal Lisp objects" class into
two classes.
The memory-usage mechanism uses a `struct usage_stats' (renamed
from `struct overhead_stats') to describe a malloc-view onto a set
of allocated memory (listing how much was requested and various
types of overhead) and a more general `struct generic_usage_stats'
(with a `struct usage_stats' in it) to hold all statistics about
object memory. `struct generic_usage_stats' contains an array of
32 Bytecounts, which are statistics of unspecified semantics. The
intention is that individual types declare a corresponding struct
(e.g. `struct window_stats') with the same structure but with
specific fields in place of the array, corresponding to specific
statistics. The number of such statistics is an object property
computed from the list of tags (Lisp symbols describing the
statistics) stored in `memusage_stats_list'. The idea here is to
allow particular object types to customize the number and
semantics of the statistics where completely avoiding consing.
This doesn't matter so much yet, but the intention is to have the
memory usage of all objects computed at the end of GC, at the same
time as other statistics are currently computed. The values for
all statistics for a single type would be added up to compute
aggregate values for all objects of a specific type. To make this
efficient, we can't allow any memory allocation at all.
(3) Create some additional functions for creating lists that
specify the elements directly as args rather than indirectly through
an array: listn() (number of args given), listu() (list terminated
by Qunbound).
(4) Delete a bit of remaining unused C window_config stuff, also
unused lrecord_type_popup_data.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 18 Mar 2010 10:50:06 -0500 |
parents | 16112448d484 |
children | 6c6d78781d59 |
rev | line source |
---|---|
2168 | 1 /* scrollbar implementation -- GTK interface. |
462 | 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. |
3 Copyright (C) 1994 Amdhal Corporation. | |
4 Copyright (C) 1995 Sun Microsystems, Inc. | |
5 Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>. | |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not in FSF. */ | |
25 /* Gtk version by William M. Perry */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
872 | 30 #include "frame-impl.h" |
31 #include "window.h" | |
32 | |
33 #include "console-gtk-impl.h" | |
462 | 34 #include "glyphs-gtk.h" |
35 #include "scrollbar-gtk.h" | |
36 | |
37 static gboolean scrollbar_cb (GtkAdjustment *adj, gpointer user_data); | |
38 | |
39 /* Used to prevent changing the size of the slider while drag | |
40 scrolling, under Motif. This is necessary because the Motif | |
41 scrollbar is incredibly stupid about updating the slider and causes | |
42 lots of flicker if it is done too often. */ | |
43 static int inhibit_slider_size_change; | |
44 | |
45 static int vertical_drag_in_progress; | |
46 | |
47 | |
48 /* A device method. */ | |
49 static int | |
50 gtk_inhibit_scrollbar_slider_size_change (void) | |
51 { | |
52 return inhibit_slider_size_change; | |
53 } | |
54 | |
55 /* A device method. */ | |
56 static void | |
57 gtk_free_scrollbar_instance (struct scrollbar_instance *instance) | |
58 { | |
3482 | 59 if (instance->scrollbar_data) |
462 | 60 { |
3482 | 61 if (SCROLLBAR_GTK_WIDGET (instance)) |
62 { | |
63 gtk_widget_hide_all (SCROLLBAR_GTK_WIDGET (instance)); | |
64 gtk_widget_destroy (SCROLLBAR_GTK_WIDGET (instance)); | |
65 } | |
66 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
3482
diff
changeset
|
67 xfree (instance->scrollbar_data); |
462 | 68 } |
69 } | |
70 | |
71 /* A device method. */ | |
72 static void | |
73 gtk_release_scrollbar_instance (struct scrollbar_instance *instance) | |
74 { | |
75 /* It won't hurt to hide it all the time, will it? */ | |
76 gtk_widget_hide_all (SCROLLBAR_GTK_WIDGET (instance)); | |
77 } | |
78 | |
79 static gboolean | |
2286 | 80 scrollbar_drag_hack_cb (GtkWidget *UNUSED (w), GdkEventButton *UNUSED (ev), |
81 gpointer v) | |
462 | 82 { |
83 vertical_drag_in_progress = (int) v; | |
84 inhibit_slider_size_change = (int) v; | |
85 return (FALSE); | |
86 } | |
87 | |
88 /* A device method. */ | |
89 static void | |
90 gtk_create_scrollbar_instance (struct frame *f, int vertical, | |
91 struct scrollbar_instance *instance) | |
92 { | |
93 GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_adjustment_new (0,0,0,0,0,0)); | |
94 GtkScrollbar *sb = NULL; | |
95 | |
96 /* initialize the X specific data section. */ | |
97 instance->scrollbar_data = xnew_and_zero (struct gtk_scrollbar_data); | |
98 | |
99 SCROLLBAR_GTK_ID (instance) = new_gui_id (); | |
100 SCROLLBAR_GTK_VDRAG_ORIG_VALUE (instance) = -1; | |
101 SCROLLBAR_GTK_LAST_VALUE (instance) = adj->value; | |
102 | |
2168 | 103 gtk_object_set_data (GTK_OBJECT (adj), GTK_DATA_GUI_IDENTIFIER, (void *) SCROLLBAR_GTK_ID (instance)); |
104 gtk_object_set_data (GTK_OBJECT (adj), GTK_DATA_FRAME_IDENTIFIER, f); | |
462 | 105 |
106 sb = GTK_SCROLLBAR (vertical ? gtk_vscrollbar_new (adj) : gtk_hscrollbar_new (adj)); | |
107 SCROLLBAR_GTK_WIDGET (instance) = GTK_WIDGET (sb); | |
108 | |
109 gtk_signal_connect (GTK_OBJECT (adj),"value-changed", | |
110 GTK_SIGNAL_FUNC (scrollbar_cb), (gpointer) vertical); | |
111 | |
112 gtk_signal_connect (GTK_OBJECT (sb), "button-press-event", | |
113 GTK_SIGNAL_FUNC (scrollbar_drag_hack_cb), (gpointer) 1); | |
114 gtk_signal_connect (GTK_OBJECT (sb), "button-release-event", | |
115 GTK_SIGNAL_FUNC (scrollbar_drag_hack_cb), (gpointer) 0); | |
116 | |
117 gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), SCROLLBAR_GTK_WIDGET (instance), 0, 0); | |
525 | 118 |
119 /* | |
120 ** With gtk version > 1.2.8 the scrollbars in gtk-xemacs and xemacs | |
121 ** from CVS are invisible. In fact they are not invisible but very | |
122 ** thin (0 pixels wide). This is so, because the new gtk code does | |
123 ** not call gtk_widget_request_size() on the newly created | |
124 ** scrollbars anymore. this change was done to allow the theme | |
125 ** engines to manipulate the scrollbar width. This patch calls | |
126 ** gtk_widget_request_size with the newly created scollbars. Maybe | |
127 ** it is better to postpone this call just before the | |
128 ** gtk_widget_show() call is done on the scrolbar. | |
129 */ | |
130 gtk_widget_size_request(GTK_WIDGET(sb), &(GTK_WIDGET(sb)->requisition)); | |
131 | |
462 | 132 gtk_widget_hide (SCROLLBAR_GTK_WIDGET (instance)); |
133 } | |
134 | |
135 #define UPDATE_DATA_FIELD(field) \ | |
136 if (new_##field >= 0 && \ | |
137 SCROLLBAR_GTK_POS_DATA (inst).field != new_##field) { \ | |
138 SCROLLBAR_GTK_POS_DATA (inst).field = new_##field; \ | |
139 inst->scrollbar_instance_changed = 1; \ | |
140 } | |
141 | |
142 /* A device method. */ | |
143 /* #### The -1 check is such a hack. */ | |
144 static void | |
145 gtk_update_scrollbar_instance_values (struct window *w, | |
146 struct scrollbar_instance *inst, | |
147 int new_line_increment, | |
148 int new_page_increment, | |
149 int new_minimum, int new_maximum, | |
150 int new_slider_size, | |
151 int new_slider_position, | |
152 int new_scrollbar_width, | |
153 int new_scrollbar_height, | |
154 int new_scrollbar_x, int new_scrollbar_y) | |
155 { | |
156 UPDATE_DATA_FIELD (line_increment); | |
157 UPDATE_DATA_FIELD (page_increment); | |
158 UPDATE_DATA_FIELD (minimum); | |
159 UPDATE_DATA_FIELD (maximum); | |
160 UPDATE_DATA_FIELD (slider_size); | |
161 UPDATE_DATA_FIELD (slider_position); | |
162 UPDATE_DATA_FIELD (scrollbar_width); | |
163 UPDATE_DATA_FIELD (scrollbar_height); | |
164 UPDATE_DATA_FIELD (scrollbar_x); | |
165 UPDATE_DATA_FIELD (scrollbar_y); | |
166 | |
167 if (w && !vertical_drag_in_progress) | |
168 { | |
169 int new_vov = SCROLLBAR_GTK_POS_DATA (inst).slider_position; | |
170 int new_vows = marker_position (w->start[CURRENT_DISP]); | |
171 | |
172 if (SCROLLBAR_GTK_VDRAG_ORIG_VALUE (inst) != new_vov) | |
173 { | |
174 SCROLLBAR_GTK_VDRAG_ORIG_VALUE (inst) = new_vov; | |
175 inst->scrollbar_instance_changed = 1; | |
176 } | |
177 if (SCROLLBAR_GTK_VDRAG_ORIG_WINDOW_START (inst) != new_vows) | |
178 { | |
179 SCROLLBAR_GTK_VDRAG_ORIG_WINDOW_START (inst) = new_vows; | |
180 inst->scrollbar_instance_changed = 1; | |
181 } | |
182 } | |
183 } | |
184 | |
185 /* Used by gtk_update_scrollbar_instance_status. */ | |
186 static void | |
187 update_one_widget_scrollbar_pointer (struct window *w, GtkWidget *wid) | |
188 { | |
189 if (!wid->window) | |
190 gtk_widget_realize (wid); | |
191 | |
192 if (POINTER_IMAGE_INSTANCEP (w->scrollbar_pointer)) | |
193 { | |
194 gdk_window_set_cursor (GET_GTK_WIDGET_WINDOW (wid), | |
195 XIMAGE_INSTANCE_GTK_CURSOR (w->scrollbar_pointer)); | |
196 gdk_flush (); | |
197 } | |
198 } | |
199 | |
200 /* A device method. */ | |
201 static void | |
202 gtk_update_scrollbar_instance_status (struct window *w, int active, int size, | |
203 struct scrollbar_instance *instance) | |
204 { | |
205 struct frame *f = XFRAME (w->frame); | |
206 GtkWidget *wid = SCROLLBAR_GTK_WIDGET (instance); | |
207 gboolean managed = GTK_WIDGET_MAPPED (wid); | |
208 | |
209 if (active && size) | |
210 { | |
211 if (instance->scrollbar_instance_changed) | |
212 { | |
213 /* Need to set the height, width, and position of the widget */ | |
214 GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (wid)); | |
215 scrollbar_values *pos_data = & SCROLLBAR_GTK_POS_DATA (instance); | |
216 int modified_p = 0; | |
217 | |
218 /* We do not want to update the size all the time if we can | |
219 help it. This cuts down on annoying flicker. | |
220 */ | |
221 if ((wid->allocation.width != pos_data->scrollbar_width) || | |
222 (wid->allocation.height != pos_data->scrollbar_height)) | |
223 { | |
224 gtk_widget_set_usize (wid, | |
225 pos_data->scrollbar_width, | |
226 pos_data->scrollbar_height); | |
2195 | 227 |
228 /* | |
229 UGLY! UGLY! UGLY! Changes to wid->allocation are queued and | |
230 not performed until the GTK event loop. However, when the | |
231 fontlock progress bar is run, the vertical scrollbar's height | |
232 is change and then changed back before events are again | |
233 processed. This means that the change back is not seen and | |
234 the scrollbar is left too short. Fix this by making the | |
235 change manually so the test above sees the change. This does | |
236 not seem to cause problems in other cases. | |
237 */ | |
238 | |
239 wid->allocation.width = pos_data->scrollbar_width; | |
240 wid->allocation.height = pos_data->scrollbar_height; | |
241 | |
462 | 242 modified_p = 1; |
243 } | |
244 | |
245 /* Ditto for the x/y position. */ | |
246 if ((wid->allocation.x != pos_data->scrollbar_x) || | |
247 (wid->allocation.y != pos_data->scrollbar_y)) | |
248 { | |
249 gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), | |
250 wid, | |
251 pos_data->scrollbar_x, | |
252 pos_data->scrollbar_y); | |
2195 | 253 |
254 /* | |
255 UGLY! UGLY! UGLY! Changes to wid->allocation are queued and | |
256 not performed until the GTK event loop. However, when the | |
257 fontlock progress bar is run, the horizontal scrollbar's | |
258 position is change and then changed back before events are | |
259 again processed. This means that the change back is not seen | |
260 and the scrollbar is left in the wrong position. Fix this by | |
261 making the change manually so the test above sees the change. | |
262 This does not seem to cause problems in other cases. | |
263 */ | |
264 | |
265 wid->allocation.x = pos_data->scrollbar_x; | |
266 wid->allocation.y = pos_data->scrollbar_y; | |
267 | |
462 | 268 modified_p = 1; |
269 } | |
270 | |
271 adj->lower = pos_data->minimum; | |
272 adj->upper = pos_data->maximum; | |
273 adj->page_increment = pos_data->slider_size + 1; | |
274 adj->step_increment = w->max_line_len - 1; | |
275 adj->page_size = pos_data->slider_size + 1; | |
276 adj->value = pos_data->slider_position; | |
277 | |
278 /* But, if we didn't resize or move the scrollbar, the | |
279 widget will not get redrawn correctly when the user | |
280 scrolls around in the XEmacs frame manually. So we | |
281 update the slider manually here. | |
282 */ | |
283 if (!modified_p) | |
284 gtk_range_slider_update (GTK_RANGE (wid)); | |
285 | |
286 instance->scrollbar_instance_changed = 0; | |
287 } | |
288 | |
289 if (!managed) | |
290 { | |
291 gtk_widget_show (wid); | |
292 update_one_widget_scrollbar_pointer (w, wid); | |
293 } | |
294 } | |
295 else if (managed) | |
296 { | |
297 gtk_widget_hide (wid); | |
298 } | |
299 } | |
300 | |
301 enum gtk_scrollbar_loop | |
302 { | |
303 GTK_FIND_SCROLLBAR_WINDOW_MIRROR, | |
304 GTK_SET_SCROLLBAR_POINTER, | |
305 GTK_WINDOW_IS_SCROLLBAR, | |
306 GTK_UPDATE_FRAME_SCROLLBARS | |
307 }; | |
308 | |
309 static struct window_mirror * | |
310 gtk_scrollbar_loop (enum gtk_scrollbar_loop type, Lisp_Object window, | |
311 struct window_mirror *mir, | |
312 GUI_ID id, GdkWindow *x_win) | |
313 { | |
314 struct window_mirror *retval = NULL; | |
315 | |
316 while (mir) | |
317 { | |
318 struct scrollbar_instance *vinstance = mir->scrollbar_vertical_instance; | |
319 struct scrollbar_instance *hinstance = mir->scrollbar_horizontal_instance; | |
320 struct window *w = XWINDOW (window); | |
321 | |
322 if (mir->vchild) | |
323 retval = gtk_scrollbar_loop (type, w->vchild, mir->vchild, id, x_win); | |
324 else if (mir->hchild) | |
325 retval = gtk_scrollbar_loop (type, w->hchild, mir->hchild, id, x_win); | |
326 if (retval) | |
327 return retval; | |
328 | |
329 if (hinstance || vinstance) | |
330 { | |
331 switch (type) | |
332 { | |
333 case GTK_FIND_SCROLLBAR_WINDOW_MIRROR: | |
334 if ((vinstance && SCROLLBAR_GTK_ID (vinstance) == id) || | |
335 (hinstance && SCROLLBAR_GTK_ID (hinstance) == id)) | |
336 return mir; | |
337 break; | |
338 case GTK_UPDATE_FRAME_SCROLLBARS: | |
339 if (!mir->vchild && !mir->hchild) | |
340 update_window_scrollbars (w, mir, 1, 0); | |
341 break; | |
342 case GTK_SET_SCROLLBAR_POINTER: | |
343 if (!mir->vchild && !mir->hchild) | |
344 { | |
345 GtkWidget *widget; | |
346 | |
347 widget = SCROLLBAR_GTK_WIDGET (hinstance); | |
348 if (widget && GTK_WIDGET_MAPPED (widget)) | |
349 update_one_widget_scrollbar_pointer (w, widget); | |
350 | |
351 widget = SCROLLBAR_GTK_WIDGET (vinstance); | |
352 if (widget && GTK_WIDGET_MAPPED (widget)) | |
353 update_one_widget_scrollbar_pointer (w, widget); | |
354 } | |
355 break; | |
356 case GTK_WINDOW_IS_SCROLLBAR: | |
357 if (!mir->vchild && !mir->hchild) | |
358 { | |
359 GtkWidget *widget; | |
360 | |
361 widget = SCROLLBAR_GTK_WIDGET (hinstance); | |
362 if (widget && GTK_WIDGET_MAPPED (widget) && | |
363 GET_GTK_WIDGET_WINDOW (widget) == x_win) | |
364 return (struct window_mirror *) 1; | |
365 | |
366 widget = SCROLLBAR_GTK_WIDGET (vinstance); | |
367 if (widget && GTK_WIDGET_MAPPED (widget) && | |
368 GET_GTK_WIDGET_WINDOW (widget) == x_win) | |
369 return (struct window_mirror *) 1; | |
370 } | |
371 break; | |
372 default: | |
2500 | 373 ABORT (); |
462 | 374 } |
375 } | |
376 | |
377 mir = mir->next; | |
378 window = w->next; | |
379 } | |
380 | |
381 return NULL; | |
382 } | |
383 | |
384 /* Used by callbacks. */ | |
385 static struct window_mirror * | |
386 find_scrollbar_window_mirror (struct frame *f, GUI_ID id) | |
387 { | |
388 if (f->mirror_dirty) | |
389 update_frame_window_mirror (f); | |
390 return gtk_scrollbar_loop (GTK_FIND_SCROLLBAR_WINDOW_MIRROR, f->root_window, | |
617 | 391 XWINDOW_MIRROR (f->root_mirror), id, |
392 (GdkWindow *) NULL); | |
462 | 393 } |
394 | |
395 static gboolean | |
396 scrollbar_cb (GtkAdjustment *adj, gpointer user_data) | |
397 { | |
398 /* This function can GC */ | |
399 int vertical = (int) user_data; | |
2168 | 400 struct frame *f = (struct frame*) gtk_object_get_data (GTK_OBJECT (adj), GTK_DATA_FRAME_IDENTIFIER); |
617 | 401 struct scrollbar_instance *instance; |
2168 | 402 GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (adj), GTK_DATA_GUI_IDENTIFIER); |
462 | 403 Lisp_Object win, frame; |
404 struct window_mirror *mirror; | |
405 Lisp_Object event_type = Qnil; | |
406 Lisp_Object event_data = Qnil; | |
407 | |
408 if (!f) | |
409 return(FALSE); | |
410 | |
411 mirror = find_scrollbar_window_mirror (f, id); | |
412 if (!mirror) | |
413 return(FALSE); | |
414 | |
415 win = real_window (mirror, 1); | |
416 | |
417 if (NILP (win)) | |
418 return(FALSE); | |
419 instance = vertical ? mirror->scrollbar_vertical_instance : mirror->scrollbar_horizontal_instance; | |
420 frame = WINDOW_FRAME (XWINDOW (win)); | |
421 | |
422 inhibit_slider_size_change = 0; | |
423 switch (GTK_RANGE (SCROLLBAR_GTK_WIDGET (instance))->scroll_type) | |
424 { | |
425 case GTK_SCROLL_PAGE_BACKWARD: | |
426 event_type = vertical ? Qscrollbar_page_up : Qscrollbar_page_left; | |
427 event_data = Fcons (win, Qnil); | |
428 break; | |
429 case GTK_SCROLL_PAGE_FORWARD: | |
430 event_type = vertical ? Qscrollbar_page_down : Qscrollbar_page_right; | |
431 event_data = Fcons (win, Qnil); | |
432 break; | |
433 case GTK_SCROLL_STEP_FORWARD: | |
434 event_type = vertical ? Qscrollbar_line_down : Qscrollbar_char_right; | |
435 event_data = win; | |
436 break; | |
437 case GTK_SCROLL_STEP_BACKWARD: | |
438 event_type = vertical ? Qscrollbar_line_up : Qscrollbar_char_left; | |
439 event_data = win; | |
440 break; | |
441 case GTK_SCROLL_NONE: | |
442 case GTK_SCROLL_JUMP: | |
443 inhibit_slider_size_change = 1; | |
444 event_type = vertical ? Qscrollbar_vertical_drag : Qscrollbar_horizontal_drag; | |
445 event_data = Fcons (win, make_int ((int)adj->value)); | |
446 break; | |
447 default: | |
2500 | 448 ABORT(); |
462 | 449 } |
450 | |
451 signal_special_gtk_user_event (frame, event_type, event_data); | |
452 | |
453 return (TRUE); | |
454 } | |
455 | |
456 static void | |
457 gtk_scrollbar_pointer_changed_in_window (struct window *w) | |
458 { | |
793 | 459 Lisp_Object window = wrap_window (w); |
462 | 460 |
617 | 461 gtk_scrollbar_loop (GTK_SET_SCROLLBAR_POINTER, window, |
462 find_window_mirror (w), 0, (GdkWindow *) NULL); | |
462 | 463 } |
464 | |
465 /* #### BILL!!! This comment is not true for Gtk - should it be? */ | |
466 /* Make sure that all scrollbars on frame are up-to-date. Called | |
467 directly from gtk_set_frame_properties in frame-gtk.c*/ | |
468 void | |
469 gtk_update_frame_scrollbars (struct frame *f) | |
470 { | |
617 | 471 gtk_scrollbar_loop (GTK_UPDATE_FRAME_SCROLLBARS, f->root_window, |
472 XWINDOW_MIRROR (f->root_mirror), | |
462 | 473 0, (GdkWindow *) NULL); |
474 } | |
475 | |
476 #ifdef MEMORY_USAGE_STATS | |
477 static int | |
2286 | 478 gtk_compute_scrollbar_instance_usage (struct device *UNUSED (d), |
462 | 479 struct scrollbar_instance *inst, |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
4976
diff
changeset
|
480 struct usage_stats *ustats) |
462 | 481 { |
482 int total = 0; | |
483 | |
484 while (inst) | |
485 { | |
486 struct gtk_scrollbar_data *data = | |
487 (struct gtk_scrollbar_data *) inst->scrollbar_data; | |
488 | |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
4976
diff
changeset
|
489 total += malloced_storage_size (data, sizeof (*data), ustats); |
462 | 490 inst = inst->next; |
491 } | |
492 | |
493 return total; | |
494 } | |
495 | |
496 #endif /* MEMORY_USAGE_STATS */ | |
497 | |
498 | |
499 /************************************************************************/ | |
500 /* initialization */ | |
501 /************************************************************************/ | |
502 | |
503 void | |
504 console_type_create_scrollbar_gtk (void) | |
505 { | |
506 CONSOLE_HAS_METHOD (gtk, inhibit_scrollbar_slider_size_change); | |
507 CONSOLE_HAS_METHOD (gtk, free_scrollbar_instance); | |
508 CONSOLE_HAS_METHOD (gtk, release_scrollbar_instance); | |
509 CONSOLE_HAS_METHOD (gtk, create_scrollbar_instance); | |
510 CONSOLE_HAS_METHOD (gtk, update_scrollbar_instance_values); | |
511 CONSOLE_HAS_METHOD (gtk, update_scrollbar_instance_status); | |
512 CONSOLE_HAS_METHOD (gtk, scrollbar_pointer_changed_in_window); | |
513 #ifdef MEMORY_USAGE_STATS | |
514 CONSOLE_HAS_METHOD (gtk, compute_scrollbar_instance_usage); | |
515 #endif /* MEMORY_USAGE_STATS */ | |
516 } | |
517 | |
518 void | |
519 vars_of_scrollbar_gtk (void) | |
520 { | |
521 Fprovide (intern ("gtk-scrollbars")); | |
522 } |