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. */
29 #include "console-x.h"
32 #include "scrollbar-x.h"
37 static void x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id,
38 XtPointer client_data);
39 static void x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id,
40 XtPointer client_data);
42 /* Used to prevent changing the size of the slider while drag
43 scrolling, under Motif. This is necessary because the Motif
44 scrollbar is incredibly stupid about updating the slider and causes
45 lots of flicker if it is done too often. */
46 static int inhibit_slider_size_change;
47 int stupid_vertical_scrollbar_drag_hack;
49 /* Doesn't work with athena */
50 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
51 static int vertical_drag_in_progress;
55 /* A device method. */
57 x_inhibit_scrollbar_slider_size_change (void)
59 /* Doesn't work with Athena */
60 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
61 return inhibit_slider_size_change;
67 /* A device method. */
69 x_free_scrollbar_instance (struct scrollbar_instance *instance)
71 if (SCROLLBAR_X_NAME (instance))
72 xfree (SCROLLBAR_X_NAME (instance));
74 if (SCROLLBAR_X_WIDGET (instance))
76 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance)))
77 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
79 lw_destroy_all_widgets (SCROLLBAR_X_ID (instance));
82 if (instance->scrollbar_data)
83 xfree (instance->scrollbar_data);
86 /* A device method. */
88 x_release_scrollbar_instance (struct scrollbar_instance *instance)
90 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance)))
91 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
94 /* A device method. */
96 x_create_scrollbar_instance (struct frame *f, int vertical,
97 struct scrollbar_instance *instance)
101 /* initialize the X specific data section. */
102 instance->scrollbar_data = xnew_and_zero (struct x_scrollbar_data);
104 SCROLLBAR_X_ID (instance) = new_lwlib_id ();
105 sprintf (buffer, "scrollbar_%d", SCROLLBAR_X_ID (instance));
106 SCROLLBAR_X_NAME (instance) = xstrdup (buffer);
107 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \
108 defined (LWLIB_SCROLLBARS_ATHENA3D)
109 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = -1;
114 SCROLLBAR_X_WIDGET (instance) =
115 lw_create_widget ("vertical-scrollbar", SCROLLBAR_X_NAME (instance),
116 SCROLLBAR_X_ID (instance),
117 NULL, FRAME_X_CONTAINER_WIDGET (f), 0,
118 x_update_vertical_scrollbar_callback, NULL, NULL);
122 SCROLLBAR_X_WIDGET (instance) =
123 lw_create_widget ("horizontal-scrollbar", SCROLLBAR_X_NAME (instance),
124 SCROLLBAR_X_ID (instance),
125 NULL, FRAME_X_CONTAINER_WIDGET (f), 0,
126 x_update_horizontal_scrollbar_callback, NULL, NULL);
130 #define UPDATE_DATA_FIELD(field) \
131 if (new_##field >= 0 && \
132 SCROLLBAR_X_POS_DATA (inst).field != new_##field) { \
133 SCROLLBAR_X_POS_DATA (inst).field = new_##field; \
134 inst->scrollbar_instance_changed = 1; \
137 /* A device method. */
138 /* #### The -1 check is such a hack. */
140 x_update_scrollbar_instance_values (struct window *w,
141 struct scrollbar_instance *inst,
142 int new_line_increment,
143 int new_page_increment,
144 int new_minimum, int new_maximum,
146 int new_slider_position,
147 int new_scrollbar_width,
148 int new_scrollbar_height,
149 int new_scrollbar_x, int new_scrollbar_y)
151 UPDATE_DATA_FIELD (line_increment);
152 UPDATE_DATA_FIELD (page_increment);
153 UPDATE_DATA_FIELD (minimum);
154 UPDATE_DATA_FIELD (maximum);
155 UPDATE_DATA_FIELD (slider_size);
156 UPDATE_DATA_FIELD (slider_position);
157 UPDATE_DATA_FIELD (scrollbar_width);
158 UPDATE_DATA_FIELD (scrollbar_height);
159 UPDATE_DATA_FIELD (scrollbar_x);
160 UPDATE_DATA_FIELD (scrollbar_y);
162 /* This doesn't work with Athena, why? */
163 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
164 if (w && !vertical_drag_in_progress)
166 int new_vov = SCROLLBAR_X_POS_DATA (inst).slider_position;
167 int new_vows = marker_position (w->start[CURRENT_DISP]);
169 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) != new_vov)
171 SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) = new_vov;
172 inst->scrollbar_instance_changed = 1;
174 if (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) != new_vows)
176 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) = new_vows;
177 inst->scrollbar_instance_changed = 1;
183 /* Used by x_update_scrollbar_instance_status. */
185 update_one_scrollbar_bs (struct frame *f, Widget sb_widget)
187 Boolean use_backing_store;
189 Xt_GET_VALUE (FRAME_X_TEXT_WIDGET (f), XtNuseBackingStore, &use_backing_store);
191 if (use_backing_store && sb_widget)
193 unsigned long mask = CWBackingStore;
194 XSetWindowAttributes attrs;
196 attrs.backing_store = Always;
197 XChangeWindowAttributes (XtDisplay (sb_widget),
198 XtWindow (sb_widget),
204 /* Create a widget value structure for passing down to lwlib so that
205 it can update the scrollbar widgets. Used by
206 x_update_scrollbar_instance_status. */
207 static widget_value *
208 scrollbar_instance_to_widget_value (struct scrollbar_instance *instance)
212 wv = xmalloc_widget_value ();
213 /* #### maybe should add malloc_scrollbar_values to resource these? */
214 wv->scrollbar_data = xnew (scrollbar_values);
216 wv->name = SCROLLBAR_X_NAME (instance);
219 wv->enabled = instance->scrollbar_is_active;
221 wv->call_data = NULL;
223 *wv->scrollbar_data = SCROLLBAR_X_POS_DATA (instance);
230 /* Used by x_update_scrollbar_instance_status. */
232 update_one_widget_scrollbar_pointer (struct window *w, Widget wid)
234 if (POINTER_IMAGE_INSTANCEP (w->scrollbar_pointer))
236 XDefineCursor (XtDisplay (wid), XtWindow (wid),
237 XIMAGE_INSTANCE_X_CURSOR (w->scrollbar_pointer));
238 XSync (XtDisplay (wid), False);
242 /* A device method. */
244 x_update_scrollbar_instance_status (struct window *w, int active, int size,
245 struct scrollbar_instance *instance)
247 struct frame *f = XFRAME (w->frame);
248 Boolean managed = XtIsManaged (SCROLLBAR_X_WIDGET (instance));
252 widget_value *wv = scrollbar_instance_to_widget_value (instance);
254 if (instance->scrollbar_instance_changed)
256 lw_modify_all_widgets (SCROLLBAR_X_ID (instance), wv, 0);
257 instance->scrollbar_instance_changed = 0;
262 XtManageChild (SCROLLBAR_X_WIDGET (instance));
263 if (XtWindow (SCROLLBAR_X_WIDGET (instance)))
265 /* Raise this window so that it's visible on top of the
266 text window below it. */
267 XRaiseWindow (XtDisplay (SCROLLBAR_X_WIDGET (instance)),
268 XtWindow (SCROLLBAR_X_WIDGET (instance)));
269 update_one_widget_scrollbar_pointer
270 (w, SCROLLBAR_X_WIDGET (instance));
271 if (!SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance))
273 update_one_scrollbar_bs (f, SCROLLBAR_X_WIDGET (instance));
274 SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance) = 1;
279 if (!wv->scrollbar_data) abort ();
280 xfree (wv->scrollbar_data);
281 wv->scrollbar_data = 0;
282 free_widget_value (wv);
286 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
287 /* This isn't needed with Athena Scrollbars. It might not be needed */
288 /* with Motif scrollbars (it is apparently needed with Lesstif). */
289 XtUngrabKeyboard (SCROLLBAR_X_WIDGET (instance), CurrentTime);
291 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance));
295 enum x_scrollbar_loop
297 X_FIND_SCROLLBAR_WINDOW_MIRROR,
298 X_SET_SCROLLBAR_POINTER,
299 X_WINDOW_IS_SCROLLBAR,
300 X_UPDATE_FRAME_SCROLLBARS
303 static struct window_mirror *
304 x_scrollbar_loop (enum x_scrollbar_loop type, Lisp_Object window,
305 struct window_mirror *mir,
306 LWLIB_ID id, Window x_win)
308 struct window_mirror *retval = NULL;
312 struct scrollbar_instance *vinstance = mir->scrollbar_vertical_instance;
313 struct scrollbar_instance *hinstance = mir->scrollbar_horizontal_instance;
314 struct window *w = XWINDOW (window);
317 retval = x_scrollbar_loop (type, w->vchild, mir->vchild, id, x_win);
318 else if (mir->hchild)
319 retval = x_scrollbar_loop (type, w->hchild, mir->hchild, id, x_win);
323 if (hinstance || vinstance)
327 case X_FIND_SCROLLBAR_WINDOW_MIRROR:
328 if ((vinstance && SCROLLBAR_X_ID (vinstance) == id) ||
329 (hinstance && SCROLLBAR_X_ID (hinstance) == id))
332 case X_UPDATE_FRAME_SCROLLBARS:
333 if (!mir->vchild && !mir->hchild)
334 update_window_scrollbars (w, mir, 1, 0);
336 case X_SET_SCROLLBAR_POINTER:
337 if (!mir->vchild && !mir->hchild)
341 widget = SCROLLBAR_X_WIDGET (hinstance);
342 if (widget && XtIsManaged (widget))
343 update_one_widget_scrollbar_pointer (w, widget);
345 widget = SCROLLBAR_X_WIDGET (vinstance);
346 if (widget && XtIsManaged (widget))
347 update_one_widget_scrollbar_pointer (w, widget);
350 case X_WINDOW_IS_SCROLLBAR:
351 if (!mir->vchild && !mir->hchild)
355 widget = SCROLLBAR_X_WIDGET (hinstance);
356 if (widget && XtIsManaged (widget) &&
357 XtWindow (widget) == x_win)
358 return (struct window_mirror *) 1;
360 widget = SCROLLBAR_X_WIDGET (vinstance);
361 if (widget && XtIsManaged (widget) &&
362 XtWindow (widget) == x_win)
363 return (struct window_mirror *) 1;
378 /* Used by callbacks. */
379 static struct window_mirror *
380 find_scrollbar_window_mirror (struct frame *f, LWLIB_ID id)
383 update_frame_window_mirror (f);
384 return x_scrollbar_loop (X_FIND_SCROLLBAR_WINDOW_MIRROR, f->root_window,
385 f->root_mirror, id, (Window) NULL);
389 * This is the only callback provided for vertical scrollbars. It
390 * should be able to handle all of the scrollbar events in
391 * scroll_action (see lwlib.h). The client data will be of type
392 * scroll_event (see lwlib.h). */
394 x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id,
395 XtPointer client_data)
397 /* This function can GC */
398 scroll_event *data = (scroll_event *) client_data;
399 struct device *d = get_device_from_display (XtDisplay (widget));
400 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
401 Lisp_Object win, frame;
402 struct scrollbar_instance *instance;
403 struct window_mirror *mirror;
408 mirror = find_scrollbar_window_mirror (f, id);
409 win = real_window (mirror, 1);
413 instance = mirror->scrollbar_vertical_instance;
414 frame = WINDOW_FRAME (XWINDOW (win));
416 /* It seems that this is necessary whenever signal_special_Xt_user_event()
417 is called. #### Why??? */
418 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
420 switch (data->action)
422 case SCROLLBAR_LINE_UP:
423 signal_special_Xt_user_event (frame, Qscrollbar_line_up, win);
426 case SCROLLBAR_LINE_DOWN:
427 signal_special_Xt_user_event (frame, Qscrollbar_line_down, win);
430 /* The Athena scrollbar paging behavior is that of xterms.
431 Depending on where you click the size of the page varies.
432 Motif always does a standard Emacs page. */
433 case SCROLLBAR_PAGE_UP:
434 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
435 !defined (LWLIB_SCROLLBARS_ATHENA3D)
437 double tmp = ((double) data->slider_value /
438 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
440 (double) window_displayed_height (XWINDOW (win));
444 signal_special_Xt_user_event (frame, Qscrollbar_page_up,
445 Fcons (win, make_int ((int) line)));
448 signal_special_Xt_user_event (frame, Qscrollbar_page_up,
453 case SCROLLBAR_PAGE_DOWN:
454 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \
455 !defined (LWLIB_SCROLLBARS_ATHENA3D)
457 double tmp = ((double) data->slider_value /
458 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height);
460 (double) window_displayed_height (XWINDOW (win));
462 if (SCROLLBAR_X_POS_DATA(instance).maximum >
463 (SCROLLBAR_X_POS_DATA(instance).slider_size + SCROLLBAR_X_POS_DATA(instance).slider_position))
467 signal_special_Xt_user_event (frame, Qscrollbar_page_down,
469 make_int ((int) line)));
473 signal_special_Xt_user_event (frame, Qscrollbar_page_down,
479 signal_special_Xt_user_event (frame, Qscrollbar_to_top, win);
482 case SCROLLBAR_BOTTOM:
483 signal_special_Xt_user_event (frame, Qscrollbar_to_bottom, win);
487 case SCROLLBAR_CHANGE:
488 inhibit_slider_size_change = 0;
489 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
490 vertical_drag_in_progress = 0;
491 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
492 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
493 XINT (Fwindow_start (win));
495 stupid_vertical_scrollbar_drag_hack = 0;
503 inhibit_slider_size_change = 1;
505 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID)
506 /* Doing drags with Motif-like scrollbars is a mess, since we
507 want to avoid having the window position jump when you
508 first grab the scrollbar, but we also want to ensure that
509 you can scroll all the way to the top or bottom of the
510 buffer. This can all be replaced with something sane when
511 we get line-based scrolling. */
513 vertical_drag_in_progress = 1;
515 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) < 0)
517 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value;
518 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) =
519 XINT (Fwindow_start (win));
522 /* Could replace this piecewise linear scrolling with a
523 quadratic through the three points, but I'm not sure that
524 would feel any nicer in practice. */
525 if (data->slider_value < SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))
527 /* We've dragged up; slide linearly from original position to
528 window-start=data.minimum, slider-value=data.minimum. */
530 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
531 <= SCROLLBAR_X_POS_DATA (instance).minimum)
533 /* shouldn't get here, but just in case */
534 value = SCROLLBAR_X_POS_DATA (instance).minimum;
539 (SCROLLBAR_X_POS_DATA (instance).minimum
541 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
542 - SCROLLBAR_X_POS_DATA (instance).minimum)
543 * (data->slider_value -
544 SCROLLBAR_X_POS_DATA (instance).minimum))
545 / (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
546 - SCROLLBAR_X_POS_DATA (instance).minimum)));
551 /* We've dragged down; slide linearly from original position to
552 window-start=data.maximum, slider-value=data.maximum. */
554 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)
555 >= (SCROLLBAR_X_POS_DATA (instance).maximum -
556 SCROLLBAR_X_POS_DATA (instance).slider_size))
558 /* avoid divide by zero */
559 value = SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance);
564 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)
566 (SCROLLBAR_X_POS_DATA (instance).maximum
567 - SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance))
568 * (data->slider_value
569 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)))
570 / (SCROLLBAR_X_POS_DATA (instance).maximum
571 - SCROLLBAR_X_POS_DATA (instance).slider_size
572 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))));
576 stupid_vertical_scrollbar_drag_hack = 0;
577 value = data->slider_value;
580 if (value >= SCROLLBAR_X_POS_DATA (instance).maximum)
581 value = SCROLLBAR_X_POS_DATA (instance).maximum - 1;
582 if (value < SCROLLBAR_X_POS_DATA (instance).minimum)
583 value = SCROLLBAR_X_POS_DATA (instance).minimum;
585 signal_special_Xt_user_event (frame, Qscrollbar_vertical_drag,
586 Fcons (win, make_int (value)));
594 * This is the only callback provided for horizontal scrollbars. It
595 * should be able to handle all of the scrollbar events in
596 * scroll_action (see lwlib.h). The client data will be of type
597 * scroll_event (see lwlib.h). */
599 x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id,
600 XtPointer client_data)
602 scroll_event *data = (scroll_event *) client_data;
603 struct device *d = get_device_from_display (XtDisplay (widget));
604 struct frame *f = x_any_window_to_frame (d, XtWindow (widget));
605 Lisp_Object win, frame;
606 struct window_mirror *mirror;
611 mirror = find_scrollbar_window_mirror (f, id);
612 win = real_window (mirror, 1);
616 frame = WINDOW_FRAME (XWINDOW (win));
618 /* It seems that this is necessary whenever signal_special_Xt_user_event()
619 is called. #### Why??? */
620 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d);
622 switch (data->action)
624 case SCROLLBAR_LINE_UP:
625 signal_special_Xt_user_event (frame, Qscrollbar_char_left, win);
627 case SCROLLBAR_LINE_DOWN:
628 signal_special_Xt_user_event (frame, Qscrollbar_char_right, win);
630 case SCROLLBAR_PAGE_UP:
631 signal_special_Xt_user_event (frame, Qscrollbar_page_left, win);
633 case SCROLLBAR_PAGE_DOWN:
634 signal_special_Xt_user_event (frame, Qscrollbar_page_right, win);
637 signal_special_Xt_user_event (frame, Qscrollbar_to_left, win);
639 case SCROLLBAR_BOTTOM:
640 signal_special_Xt_user_event (frame, Qscrollbar_to_right, win);
642 case SCROLLBAR_CHANGE:
643 inhibit_slider_size_change = 0;
646 inhibit_slider_size_change = 1;
647 /* #### Fix the damn toolkit code so they all work the same way.
648 Lucid is the one mostly wrong.*/
649 #if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D)
650 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
652 (win, make_int (data->slider_value))));
654 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag,
657 make_int (data->slider_value - 1))));
666 x_scrollbar_pointer_changed_in_window (struct window *w)
670 XSETWINDOW (window, w);
671 x_scrollbar_loop (X_SET_SCROLLBAR_POINTER, window, find_window_mirror (w),
675 /* Called directly from x_any_window_to_frame in frame-x.c */
677 x_window_is_scrollbar (struct frame *f, Window win)
683 update_frame_window_mirror (f);
684 return (EMACS_INT) x_scrollbar_loop (X_WINDOW_IS_SCROLLBAR, f->root_window,
685 f->root_mirror, 0, win);
688 /* Make sure that all scrollbars on frame are up-to-date. Called
689 directly from x_set_frame_properties in frame-x.c*/
691 x_update_frame_scrollbars (struct frame *f)
693 /* Consider this code to be "in_display" so that we abort() if Fsignal()
696 x_scrollbar_loop (X_UPDATE_FRAME_SCROLLBARS, f->root_window, f->root_mirror,
699 if (in_display < 0) abort ();
702 #ifdef MEMORY_USAGE_STATS
705 x_compute_scrollbar_instance_usage (struct device *d,
706 struct scrollbar_instance *inst,
707 struct overhead_stats *ovstats)
713 struct x_scrollbar_data *data =
714 (struct x_scrollbar_data *) inst->scrollbar_data;
716 total += malloced_storage_size (data, sizeof (*data), ovstats);
717 total += malloced_storage_size (data->name, 1 + strlen (data->name),
725 #endif /* MEMORY_USAGE_STATS */
728 /************************************************************************/
730 /************************************************************************/
733 console_type_create_scrollbar_x (void)
735 CONSOLE_HAS_METHOD (x, inhibit_scrollbar_slider_size_change);
736 CONSOLE_HAS_METHOD (x, free_scrollbar_instance);
737 CONSOLE_HAS_METHOD (x, release_scrollbar_instance);
738 CONSOLE_HAS_METHOD (x, create_scrollbar_instance);
739 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_values);
740 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_status);
741 CONSOLE_HAS_METHOD (x, scrollbar_pointer_changed_in_window);
742 #ifdef MEMORY_USAGE_STATS
743 CONSOLE_HAS_METHOD (x, compute_scrollbar_instance_usage);
744 #endif /* MEMORY_USAGE_STATS */
748 vars_of_scrollbar_x (void)
750 #if defined (LWLIB_SCROLLBARS_LUCID)
751 Fprovide (intern ("lucid-scrollbars"));
752 #elif defined (LWLIB_SCROLLBARS_MOTIF)
753 Fprovide (intern ("motif-scrollbars"));
754 #elif defined (LWLIB_SCROLLBARS_ATHENA)
755 Fprovide (intern ("athena-scrollbars"));
757 stupid_vertical_scrollbar_drag_hack = 1;