1 /* scrollbar implementation -- X interface.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1994 Amdahl Corporation.
4 Copyright (C) 1995 Sun Microsystems, Inc.
5 Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>.
7 This file is part of XEmacs.
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
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
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. */
24 /* Synched up with: Not in FSF. */
26 /* This file Mule-ized (more like Mule-verified) by Ben Wing, 7-8-00. */
31 #include "console-x.h"
32 #include "EmacsFrame.h"
35 #include "scrollbar-x.h"
40 static void x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id,
41 XtPointer client_data);
42 static void x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id,
43 XtPointer client_data);
45 /* Used to prevent changing the size of the slider while drag
46 scrolling, under Motif. This is necessary because the Motif
47 scrollbar is incredibly stupid about updating the slider and causes
48 lots of flicker if it is done too often. */
49 static int inhibit_slider_size_change;
50 int stupid_vertical_scrollbar_drag_hack;
52 /* Doesn't work with athena */
53 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
54 static int vertical_drag_in_progress;
58 /* A device method. */
60 x_inhibit_scrollbar_slider_size_change (void)
62 /* Doesn't work with Athena */
63 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
64 return inhibit_slider_size_change;
70 /* A device method. */
72 x_free_scrollbar_instance (struct scrollbar_instance *instance)
74 if (instance->scrollbar_data)
76 if (SCROLLBAR_X_NAME (instance))
77 xfree (SCROLLBAR_X_NAME (instance));
79 if (SCROLLBAR_X_WIDGET (instance))
81 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance)))
82 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
84 lw_destroy_all_widgets (SCROLLBAR_X_ID (instance));
87 xfree (instance->scrollbar_data);
91 /* A device method. */
93 x_release_scrollbar_instance (struct scrollbar_instance *instance)
95 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance)))
96 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
99 /* A device method. */
101 x_create_scrollbar_instance (struct frame *f, int vertical,
102 struct scrollbar_instance *instance)
106 /* initialize the X specific data section. */
107 instance->scrollbar_data = xnew_and_zero (struct x_scrollbar_data);
109 SCROLLBAR_X_ID (instance) = new_lwlib_id ();
110 sprintf (buffer, "scrollbar_%d", SCROLLBAR_X_ID (instance));
111 SCROLLBAR_X_NAME (instance) = xstrdup (buffer);
112 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
113 defined (LWLIB_SCROLLBARS_ATHENA3D)
114 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = -1;
119 SCROLLBAR_X_WIDGET (instance) =
120 lw_create_widget ("vertical-scrollbar", SCROLLBAR_X_NAME (instance),
121 SCROLLBAR_X_ID (instance),
122 NULL, FRAME_X_CONTAINER_WIDGET (f), 0,
123 x_update_vertical_scrollbar_callback, NULL, NULL);
127 SCROLLBAR_X_WIDGET (instance) =
128 lw_create_widget ("horizontal-scrollbar", SCROLLBAR_X_NAME (instance),
129 SCROLLBAR_X_ID (instance),
130 NULL, FRAME_X_CONTAINER_WIDGET (f), 0,
131 x_update_horizontal_scrollbar_callback, NULL, NULL);
135 #define UPDATE_DATA_FIELD(field) \
136 if (new_##field >= 0 && \
137 SCROLLBAR_X_POS_DATA (inst).field != new_##field) { \
138 SCROLLBAR_X_POS_DATA (inst).field = new_##field; \
139 inst->scrollbar_instance_changed = 1; \
142 /* A device method. */
143 /* #### The -1 check is such a hack. */
145 x_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,
151 int new_slider_position,
152 int new_scrollbar_width,
153 int new_scrollbar_height,
154 int new_scrollbar_x, int new_scrollbar_y)
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);
167 /* This doesn't work with Athena, why? */
168 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
169 if (w && !vertical_drag_in_progress)
171 int new_vov = SCROLLBAR_X_POS_DATA (inst).slider_position;
172 int new_vows = marker_position (w->start[CURRENT_DISP]);
174 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) != new_vov)
176 SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) = new_vov;
177 inst->scrollbar_instance_changed = 1;
179 if (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) != new_vows)
181 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) = new_vows;
182 inst->scrollbar_instance_changed = 1;
188 /* Used by x_update_scrollbar_instance_status. */
190 update_one_scrollbar_bs (struct frame *f, Widget sb_widget)
192 Boolean use_backing_store;
194 Xt_GET_VALUE (FRAME_X_TEXT_WIDGET (f), XtNuseBackingStore, &use_backing_store);
196 if (use_backing_store && sb_widget)
198 unsigned long mask = CWBackingStore;
199 XSetWindowAttributes attrs;
201 attrs.backing_store = Always;
202 XChangeWindowAttributes (XtDisplay (sb_widget),
203 XtWindow (sb_widget),
209 /* Create a widget value structure for passing down to lwlib so that
210 it can update the scrollbar widgets. Used by
211 x_update_scrollbar_instance_status. */
212 static widget_value *
213 scrollbar_instance_to_widget_value (struct scrollbar_instance *instance)
217 wv = xmalloc_widget_value ();
218 /* #### maybe should add malloc_scrollbar_values to resource these? */
219 wv->scrollbar_data = xnew (scrollbar_values);
221 wv->name = SCROLLBAR_X_NAME (instance);
222 wv->name = xstrdup (wv->name);
225 wv->enabled = instance->scrollbar_is_active;
227 wv->call_data = NULL;
229 *wv->scrollbar_data = SCROLLBAR_X_POS_DATA (instance);
236 /* Used by x_update_scrollbar_instance_status. */
238 update_one_widget_scrollbar_pointer (struct window *w, Widget wid)
240 if (POINTER_IMAGE_INSTANCEP (w->scrollbar_pointer))
242 XDefineCursor (XtDisplay (wid), XtWindow (wid),
243 XIMAGE_INSTANCE_X_CURSOR (w->scrollbar_pointer));
244 XSync (XtDisplay (wid), False);
248 /* A device method. */
250 x_update_scrollbar_instance_status (struct window *w, int active, int size,
251 struct scrollbar_instance *instance)
253 struct frame *f = XFRAME (w->frame);
254 Boolean managed = XtIsManaged (SCROLLBAR_X_WIDGET (instance));
258 widget_value *wv = scrollbar_instance_to_widget_value (instance);
260 if (instance->scrollbar_instance_changed)
262 lw_modify_all_widgets (SCROLLBAR_X_ID (instance), wv, 0);
263 instance->scrollbar_instance_changed = 0;
268 XtManageChild (SCROLLBAR_X_WIDGET (instance));
269 if (XtWindow (SCROLLBAR_X_WIDGET (instance)))
271 /* Raise this window so that it's visible on top of the
272 text window below it. */
273 XRaiseWindow (XtDisplay (SCROLLBAR_X_WIDGET (instance)),
274 XtWindow (SCROLLBAR_X_WIDGET (instance)));
275 update_one_widget_scrollbar_pointer
276 (w, SCROLLBAR_X_WIDGET (instance));
277 if (!SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance))
279 update_one_scrollbar_bs (f, SCROLLBAR_X_WIDGET (instance));
280 SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance) = 1;
285 if (!wv->scrollbar_data) ABORT ();
286 free_widget_value_tree (wv);
290 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
291 /* This isn't needed with Athena Scrollbars. It might not be needed */
292 /* with Motif scrollbars (it is apparently needed with Lesstif). */
293 XtUngrabKeyboard (SCROLLBAR_X_WIDGET (instance), CurrentTime);
295 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
299 enum x_scrollbar_loop
301 X_FIND_SCROLLBAR_WINDOW_MIRROR,
302 X_SET_SCROLLBAR_POINTER,
303 X_WINDOW_IS_SCROLLBAR,
304 X_UPDATE_FRAME_SCROLLBARS
307 static struct window_mirror *
308 x_scrollbar_loop (enum x_scrollbar_loop type, Lisp_Object window,
309 struct window_mirror *mir,
310 LWLIB_ID id, Window x_win)
312 struct window_mirror *retval = NULL;
316 struct scrollbar_instance *vinstance = mir->scrollbar_vertical_instance;
317 struct scrollbar_instance *hinstance = mir->scrollbar_horizontal_instance;
318 struct window *w = XWINDOW (window);
321 retval = x_scrollbar_loop (type, w->vchild, mir->vchild, id, x_win);
322 else if (mir->hchild)
323 retval = x_scrollbar_loop (type, w->hchild, mir->hchild, id, x_win);
327 if (hinstance || vinstance)
331 case X_FIND_SCROLLBAR_WINDOW_MIRROR:
332 if ((vinstance && SCROLLBAR_X_ID (vinstance) == id) ||
333 (hinstance && SCROLLBAR_X_ID (hinstance) == id))
336 case X_UPDATE_FRAME_SCROLLBARS:
337 if (!mir->vchild && !mir->hchild)
338 update_window_scrollbars (w, mir, 1, 0);
340 case X_SET_SCROLLBAR_POINTER:
341 if (!mir->vchild && !mir->hchild)
345 widget = SCROLLBAR_X_WIDGET (hinstance);
346 if (widget && XtIsManaged (widget))
347 update_one_widget_scrollbar_pointer (w, widget);
349 widget = SCROLLBAR_X_WIDGET (vinstance);
350 if (widget && XtIsManaged (widget))
351 update_one_widget_scrollbar_pointer (w, widget);
354 case X_WINDOW_IS_SCROLLBAR:
355 if (!mir->vchild && !mir->hchild)
359 widget = SCROLLBAR_X_WIDGET (hinstance);
360 if (widget && XtIsManaged (widget) &&
361 XtWindow (widget) == x_win)
362 return (struct window_mirror *) 1;
364 widget = SCROLLBAR_X_WIDGET (vinstance);
365 if (widget && XtIsManaged (widget) &&
366 XtWindow (widget) == x_win)
367 return (struct window_mirror *) 1;
382 /* Used by callbacks. */
383 static struct window_mirror *
384 find_scrollbar_window_mirror (struct frame *f, LWLIB_ID id)
387 update_frame_window_mirror (f);
388 return x_scrollbar_loop (X_FIND_SCROLLBAR_WINDOW_MIRROR, f->root_window,
389 f->root_mirror, id, (Window) NULL);
393 * This is the only callback provided for vertical scrollbars. It
394 * should be able to handle all of the scrollbar events in
395 * scroll_action (see lwlib.h). The client data will be of type
396 * scroll_event (see lwlib.h). */
398 x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id,
399 XtPointer client_data)
401 /* This function can GC */
402 scroll_event *data = (scroll_event *) client_data;
403 struct device *d = get_device_from_display (XtDisplay (widget));
404 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
405 Lisp_Object win, frame;
406 struct scrollbar_instance *instance;
407 struct window_mirror *mirror;
412 mirror = find_scrollbar_window_mirror (f, id);
416 win = real_window (mirror, 1);
420 instance = mirror->scrollbar_vertical_instance;
421 frame = WINDOW_FRAME (XWINDOW (win));
423 /* It seems that this is necessary whenever signal_special_Xt_user_event()
424 is called. #### Why??? */
425 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
427 switch (data->action)
429 case SCROLLBAR_LINE_UP:
430 signal_special_Xt_user_event (frame, Qscrollbar_line_up, win);
433 case SCROLLBAR_LINE_DOWN:
434 signal_special_Xt_user_event (frame, Qscrollbar_line_down, win);
437 /* The Athena scrollbar paging behavior is that of xterms.
438 Depending on where you click the size of the page varies.
439 Motif always does a standard Emacs page. */
440 case SCROLLBAR_PAGE_UP:
441 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
442 !defined (LWLIB_SCROLLBARS_ATHENA3D)
444 double tmp = ((double) data->slider_value /
445 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
447 (double) window_displayed_height (XWINDOW (win));
451 signal_special_Xt_user_event (frame, Qscrollbar_page_up,
452 Fcons (win, make_int ((int) line)));
455 signal_special_Xt_user_event (frame, Qscrollbar_page_up,
460 case SCROLLBAR_PAGE_DOWN:
461 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
462 !defined (LWLIB_SCROLLBARS_ATHENA3D)
464 double tmp = ((double) data->slider_value /
465 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
467 (double) window_displayed_height (XWINDOW (win));
469 if (SCROLLBAR_X_POS_DATA(instance).maximum >
470 (SCROLLBAR_X_POS_DATA(instance).slider_size + SCROLLBAR_X_POS_DATA(instance).slider_position))
474 signal_special_Xt_user_event (frame, Qscrollbar_page_down,
476 make_int ((int) line)));
480 signal_special_Xt_user_event (frame, Qscrollbar_page_down,
486 signal_special_Xt_user_event (frame, Qscrollbar_to_top, win);
489 case SCROLLBAR_BOTTOM:
490 signal_special_Xt_user_event (frame, Qscrollbar_to_bottom, win);
494 case SCROLLBAR_CHANGE:
495 inhibit_slider_size_change = 0;
496 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
497 vertical_drag_in_progress = 0;
498 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
499 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
500 XINT (Fwindow_start (win));
502 stupid_vertical_scrollbar_drag_hack = 0;
510 inhibit_slider_size_change = 1;
512 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
513 /* Doing drags with Motif-like scrollbars is a mess, since we
514 want to avoid having the window position jump when you
515 first grab the scrollbar, but we also want to ensure that
516 you can scroll all the way to the top or bottom of the
517 buffer. This can all be replaced with something sane when
518 we get line-based scrolling. */
520 vertical_drag_in_progress = 1;
522 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) < 0)
524 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
525 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
526 XINT (Fwindow_start (win));
529 /* Could replace this piecewise linear scrolling with a
530 quadratic through the three points, but I'm not sure that
531 would feel any nicer in practice. */
532 if (data->slider_value < SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))
534 /* We've dragged up; slide linearly from original position to
535 window-start=data.minimum, slider-value=data.minimum. */
537 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
538 <= SCROLLBAR_X_POS_DATA (instance).minimum)
540 /* shouldn't get here, but just in case */
541 value = SCROLLBAR_X_POS_DATA (instance).minimum;
546 (SCROLLBAR_X_POS_DATA (instance).minimum
548 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
549 - SCROLLBAR_X_POS_DATA (instance).minimum)
550 * (data->slider_value -
551 SCROLLBAR_X_POS_DATA (instance).minimum))
552 / (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
553 - SCROLLBAR_X_POS_DATA (instance).minimum)));
558 /* We've dragged down; slide linearly from original position to
559 window-start=data.maximum, slider-value=data.maximum. */
561 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
562 >= (SCROLLBAR_X_POS_DATA (instance).maximum -
563 SCROLLBAR_X_POS_DATA (instance).slider_size))
565 /* avoid divide by zero */
566 value = SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance);
571 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
573 (SCROLLBAR_X_POS_DATA (instance).maximum
574 - SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance))
575 * (data->slider_value
576 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)))
577 / (SCROLLBAR_X_POS_DATA (instance).maximum
578 - SCROLLBAR_X_POS_DATA (instance).slider_size
579 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))));
583 stupid_vertical_scrollbar_drag_hack = 0;
584 value = data->slider_value;
587 if (value >= SCROLLBAR_X_POS_DATA (instance).maximum)
588 value = SCROLLBAR_X_POS_DATA (instance).maximum - 1;
589 if (value < SCROLLBAR_X_POS_DATA (instance).minimum)
590 value = SCROLLBAR_X_POS_DATA (instance).minimum;
592 signal_special_Xt_user_event (frame, Qscrollbar_vertical_drag,
593 Fcons (win, make_int (value)));
601 * This is the only callback provided for horizontal scrollbars. It
602 * should be able to handle all of the scrollbar events in
603 * scroll_action (see lwlib.h). The client data will be of type
604 * scroll_event (see lwlib.h). */
606 x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id,
607 XtPointer client_data)
609 scroll_event *data = (scroll_event *) client_data;
610 struct device *d = get_device_from_display (XtDisplay (widget));
611 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
612 Lisp_Object win, frame;
613 struct window_mirror *mirror;
618 mirror = find_scrollbar_window_mirror (f, id);
622 win = real_window (mirror, 1);
626 frame = WINDOW_FRAME (XWINDOW (win));
628 /* It seems that this is necessary whenever signal_special_Xt_user_event()
629 is called. #### Why??? */
630 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
632 switch (data->action)
634 case SCROLLBAR_LINE_UP:
635 signal_special_Xt_user_event (frame, Qscrollbar_char_left, win);
637 case SCROLLBAR_LINE_DOWN:
638 signal_special_Xt_user_event (frame, Qscrollbar_char_right, win);
640 case SCROLLBAR_PAGE_UP:
641 signal_special_Xt_user_event (frame, Qscrollbar_page_left, win);
643 case SCROLLBAR_PAGE_DOWN:
644 signal_special_Xt_user_event (frame, Qscrollbar_page_right, win);
647 signal_special_Xt_user_event (frame, Qscrollbar_to_left, win);
649 case SCROLLBAR_BOTTOM:
650 signal_special_Xt_user_event (frame, Qscrollbar_to_right, win);
652 case SCROLLBAR_CHANGE:
653 inhibit_slider_size_change = 0;
656 inhibit_slider_size_change = 1;
657 /* #### Fix the damn toolkit code so they all work the same way.
658 Lucid is the one mostly wrong.*/
659 #if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D)
660 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
662 (win, make_int (data->slider_value))));
664 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
667 make_int (data->slider_value - 1))));
676 x_scrollbar_pointer_changed_in_window (struct window *w)
680 XSETWINDOW (window, w);
681 x_scrollbar_loop (X_SET_SCROLLBAR_POINTER, window, find_window_mirror (w),
685 /* Make sure that all scrollbars on frame are up-to-date. Called
686 directly from x_set_frame_properties in frame-x.c*/
688 x_update_frame_scrollbars (struct frame *f)
690 /* Consider this code to be "in_display" so that we ABORT() if Fsignal()
693 x_scrollbar_loop (X_UPDATE_FRAME_SCROLLBARS, f->root_window, f->root_mirror,
696 if (in_display < 0) ABORT ();
699 #ifdef MEMORY_USAGE_STATS
702 x_compute_scrollbar_instance_usage (struct device *d,
703 struct scrollbar_instance *inst,
704 struct overhead_stats *ovstats)
710 struct x_scrollbar_data *data =
711 (struct x_scrollbar_data *) inst->scrollbar_data;
713 total += malloced_storage_size (data, sizeof (*data), ovstats);
714 total += malloced_storage_size (data->name, 1 + strlen (data->name),
722 #endif /* MEMORY_USAGE_STATS */
725 /************************************************************************/
727 /************************************************************************/
730 console_type_create_scrollbar_x (void)
732 CONSOLE_HAS_METHOD (x, inhibit_scrollbar_slider_size_change);
733 CONSOLE_HAS_METHOD (x, free_scrollbar_instance);
734 CONSOLE_HAS_METHOD (x, release_scrollbar_instance);
735 CONSOLE_HAS_METHOD (x, create_scrollbar_instance);
736 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_values);
737 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_status);
738 CONSOLE_HAS_METHOD (x, scrollbar_pointer_changed_in_window);
739 #ifdef MEMORY_USAGE_STATS
740 CONSOLE_HAS_METHOD (x, compute_scrollbar_instance_usage);
741 #endif /* MEMORY_USAGE_STATS */
745 reinit_vars_of_scrollbar_x (void)
747 stupid_vertical_scrollbar_drag_hack = 1;
751 vars_of_scrollbar_x (void)
753 reinit_vars_of_scrollbar_x ();
755 #if defined (LWLIB_SCROLLBARS_LUCID)
756 Fprovide (intern ("lucid-scrollbars"));
757 #elif defined (LWLIB_SCROLLBARS_MOTIF)
758 Fprovide (intern ("motif-scrollbars"));
759 #elif defined (LWLIB_SCROLLBARS_ATHENA)
760 Fprovide (intern ("athena-scrollbars"));