Mercurial > hg > xemacs-beta
annotate src/scrollbar-x.c @ 5518:3cc7470ea71c
gnuclient: if TMPDIR was set and connect failed, try again with /tmp
2011-06-03 Aidan Kehoe <kehoea@parhasard.net>
* gnuslib.c (connect_to_unix_server):
Retry with /tmp as a directory in which to search for Unix sockets
if an attempt to connect with some other directory failed (which
may be because gnuclient and gnuserv don't share an environment
value for TMPDIR, or because gnuserv was compiled with USE_TMPDIR
turned off).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Fri, 03 Jun 2011 18:40:57 +0100 |
parents | 308d34e9f07d |
children | 56144c8593a8 |
rev | line source |
---|---|
428 | 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>. | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4976
diff
changeset
|
6 Copyright (C) 2010 Ben Wing. |
428 | 7 |
8 This file is part of XEmacs. | |
9 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5170
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
428 | 11 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5170
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5170
diff
changeset
|
13 option) any later version. |
428 | 14 |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5170
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 22 |
23 /* Synched up with: Not in FSF. */ | |
24 | |
442 | 25 /* This file Mule-ized (more like Mule-verified) by Ben Wing, 7-8-00. */ |
26 | |
428 | 27 #include <config.h> |
28 #include "lisp.h" | |
29 | |
872 | 30 #include "device-impl.h" |
31 #include "frame-impl.h" | |
800 | 32 #include "window.h" |
33 | |
872 | 34 #include "console-x-impl.h" |
428 | 35 #include "glyphs-x.h" |
36 #include "scrollbar-x.h" | |
37 | |
800 | 38 #include "EmacsFrame.h" |
428 | 39 |
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); | |
44 | |
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; | |
51 | |
52 /* Doesn't work with athena */ | |
53 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
54 static int vertical_drag_in_progress; | |
55 #endif | |
56 | |
57 | |
58 /* A device method. */ | |
59 static int | |
60 x_inhibit_scrollbar_slider_size_change (void) | |
61 { | |
62 /* Doesn't work with Athena */ | |
63 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
64 return inhibit_slider_size_change; | |
65 #else | |
66 return 0; | |
67 #endif | |
68 } | |
69 | |
70 /* A device method. */ | |
71 static void | |
72 x_free_scrollbar_instance (struct scrollbar_instance *instance) | |
73 { | |
3462 | 74 if (instance->scrollbar_data) |
428 | 75 { |
3462 | 76 if (SCROLLBAR_X_NAME (instance)) |
5169
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
77 { |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
78 xfree (SCROLLBAR_X_NAME (instance)); |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
79 SCROLLBAR_X_NAME (instance) = 0; |
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
80 } |
428 | 81 |
3462 | 82 if (SCROLLBAR_X_WIDGET (instance)) |
83 { | |
84 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance))) | |
85 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance)); | |
428 | 86 |
3462 | 87 lw_destroy_all_widgets (SCROLLBAR_X_ID (instance)); |
88 } | |
89 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
3462
diff
changeset
|
90 xfree (instance->scrollbar_data); |
5169
6c6d78781d59
cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup
Ben Wing <ben@xemacs.org>
parents:
5157
diff
changeset
|
91 instance->scrollbar_data = 0; |
3462 | 92 } |
428 | 93 } |
94 | |
95 /* A device method. */ | |
96 static void | |
97 x_release_scrollbar_instance (struct scrollbar_instance *instance) | |
98 { | |
99 if (XtIsManaged (SCROLLBAR_X_WIDGET (instance))) | |
100 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance)); | |
101 } | |
102 | |
103 /* A device method. */ | |
104 static void | |
105 x_create_scrollbar_instance (struct frame *f, int vertical, | |
106 struct scrollbar_instance *instance) | |
107 { | |
108 char buffer[32]; | |
109 | |
110 /* initialize the X specific data section. */ | |
111 instance->scrollbar_data = xnew_and_zero (struct x_scrollbar_data); | |
112 | |
113 SCROLLBAR_X_ID (instance) = new_lwlib_id (); | |
114 sprintf (buffer, "scrollbar_%d", SCROLLBAR_X_ID (instance)); | |
115 SCROLLBAR_X_NAME (instance) = xstrdup (buffer); | |
116 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) || \ | |
117 defined (LWLIB_SCROLLBARS_ATHENA3D) | |
118 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = -1; | |
119 #endif | |
120 | |
121 if (vertical) | |
122 { | |
123 SCROLLBAR_X_WIDGET (instance) = | |
124 lw_create_widget ("vertical-scrollbar", SCROLLBAR_X_NAME (instance), | |
125 SCROLLBAR_X_ID (instance), | |
126 NULL, FRAME_X_CONTAINER_WIDGET (f), 0, | |
127 x_update_vertical_scrollbar_callback, NULL, NULL); | |
128 } | |
129 else | |
130 { | |
131 SCROLLBAR_X_WIDGET (instance) = | |
132 lw_create_widget ("horizontal-scrollbar", SCROLLBAR_X_NAME (instance), | |
133 SCROLLBAR_X_ID (instance), | |
134 NULL, FRAME_X_CONTAINER_WIDGET (f), 0, | |
135 x_update_horizontal_scrollbar_callback, NULL, NULL); | |
136 } | |
137 } | |
138 | |
139 #define UPDATE_DATA_FIELD(field) \ | |
140 if (new_##field >= 0 && \ | |
141 SCROLLBAR_X_POS_DATA (inst).field != new_##field) { \ | |
142 SCROLLBAR_X_POS_DATA (inst).field = new_##field; \ | |
143 inst->scrollbar_instance_changed = 1; \ | |
144 } | |
145 | |
146 /* A device method. */ | |
147 /* #### The -1 check is such a hack. */ | |
148 static void | |
149 x_update_scrollbar_instance_values (struct window *w, | |
150 struct scrollbar_instance *inst, | |
151 int new_line_increment, | |
152 int new_page_increment, | |
153 int new_minimum, int new_maximum, | |
154 int new_slider_size, | |
155 int new_slider_position, | |
156 int new_scrollbar_width, | |
157 int new_scrollbar_height, | |
158 int new_scrollbar_x, int new_scrollbar_y) | |
159 { | |
160 UPDATE_DATA_FIELD (line_increment); | |
161 UPDATE_DATA_FIELD (page_increment); | |
162 UPDATE_DATA_FIELD (minimum); | |
163 UPDATE_DATA_FIELD (maximum); | |
164 UPDATE_DATA_FIELD (slider_size); | |
165 UPDATE_DATA_FIELD (slider_position); | |
166 UPDATE_DATA_FIELD (scrollbar_width); | |
167 UPDATE_DATA_FIELD (scrollbar_height); | |
168 UPDATE_DATA_FIELD (scrollbar_x); | |
169 UPDATE_DATA_FIELD (scrollbar_y); | |
170 | |
171 /* This doesn't work with Athena, why? */ | |
172 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
173 if (w && !vertical_drag_in_progress) | |
174 { | |
175 int new_vov = SCROLLBAR_X_POS_DATA (inst).slider_position; | |
176 int new_vows = marker_position (w->start[CURRENT_DISP]); | |
177 | |
178 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) != new_vov) | |
179 { | |
180 SCROLLBAR_X_VDRAG_ORIG_VALUE (inst) = new_vov; | |
181 inst->scrollbar_instance_changed = 1; | |
182 } | |
183 if (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) != new_vows) | |
184 { | |
185 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (inst) = new_vows; | |
186 inst->scrollbar_instance_changed = 1; | |
187 } | |
188 } | |
189 #endif | |
190 } | |
191 | |
192 /* Used by x_update_scrollbar_instance_status. */ | |
193 static void | |
194 update_one_scrollbar_bs (struct frame *f, Widget sb_widget) | |
195 { | |
196 Boolean use_backing_store; | |
197 | |
198 Xt_GET_VALUE (FRAME_X_TEXT_WIDGET (f), XtNuseBackingStore, &use_backing_store); | |
199 | |
200 if (use_backing_store && sb_widget) | |
201 { | |
202 unsigned long mask = CWBackingStore; | |
203 XSetWindowAttributes attrs; | |
204 | |
205 attrs.backing_store = Always; | |
206 XChangeWindowAttributes (XtDisplay (sb_widget), | |
207 XtWindow (sb_widget), | |
208 mask, | |
209 &attrs); | |
210 } | |
211 } | |
212 | |
213 /* Create a widget value structure for passing down to lwlib so that | |
214 it can update the scrollbar widgets. Used by | |
215 x_update_scrollbar_instance_status. */ | |
216 static widget_value * | |
217 scrollbar_instance_to_widget_value (struct scrollbar_instance *instance) | |
218 { | |
219 widget_value *wv; | |
220 | |
221 wv = xmalloc_widget_value (); | |
222 /* #### maybe should add malloc_scrollbar_values to resource these? */ | |
223 wv->scrollbar_data = xnew (scrollbar_values); | |
224 | |
225 wv->name = SCROLLBAR_X_NAME (instance); | |
436 | 226 wv->name = xstrdup (wv->name); |
428 | 227 wv->value = 0; |
228 wv->key = 0; | |
229 wv->enabled = instance->scrollbar_is_active; | |
230 wv->selected = 0; | |
231 wv->call_data = NULL; | |
232 | |
233 *wv->scrollbar_data = SCROLLBAR_X_POS_DATA (instance); | |
234 | |
235 wv->next = NULL; | |
236 | |
237 return wv; | |
238 } | |
239 | |
240 /* Used by x_update_scrollbar_instance_status. */ | |
241 static void | |
242 update_one_widget_scrollbar_pointer (struct window *w, Widget wid) | |
243 { | |
244 if (POINTER_IMAGE_INSTANCEP (w->scrollbar_pointer)) | |
245 { | |
246 XDefineCursor (XtDisplay (wid), XtWindow (wid), | |
247 XIMAGE_INSTANCE_X_CURSOR (w->scrollbar_pointer)); | |
248 XSync (XtDisplay (wid), False); | |
249 } | |
250 } | |
251 | |
252 /* A device method. */ | |
253 static void | |
254 x_update_scrollbar_instance_status (struct window *w, int active, int size, | |
255 struct scrollbar_instance *instance) | |
256 { | |
257 struct frame *f = XFRAME (w->frame); | |
258 Boolean managed = XtIsManaged (SCROLLBAR_X_WIDGET (instance)); | |
259 | |
260 if (active && size) | |
261 { | |
262 widget_value *wv = scrollbar_instance_to_widget_value (instance); | |
263 | |
264 if (instance->scrollbar_instance_changed) | |
265 { | |
266 lw_modify_all_widgets (SCROLLBAR_X_ID (instance), wv, 0); | |
267 instance->scrollbar_instance_changed = 0; | |
268 } | |
269 | |
270 if (!managed) | |
271 { | |
272 XtManageChild (SCROLLBAR_X_WIDGET (instance)); | |
273 if (XtWindow (SCROLLBAR_X_WIDGET (instance))) | |
274 { | |
275 /* Raise this window so that it's visible on top of the | |
276 text window below it. */ | |
277 XRaiseWindow (XtDisplay (SCROLLBAR_X_WIDGET (instance)), | |
278 XtWindow (SCROLLBAR_X_WIDGET (instance))); | |
279 update_one_widget_scrollbar_pointer | |
280 (w, SCROLLBAR_X_WIDGET (instance)); | |
281 if (!SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance)) | |
282 { | |
283 update_one_scrollbar_bs (f, SCROLLBAR_X_WIDGET (instance)); | |
284 SCROLLBAR_X_BACKING_STORE_INITIALIZED (instance) = 1; | |
285 } | |
286 } | |
287 } | |
288 | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4976
diff
changeset
|
289 assert (wv->scrollbar_data); |
436 | 290 free_widget_value_tree (wv); |
428 | 291 } |
292 else if (managed) | |
293 { | |
294 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
295 /* This isn't needed with Athena Scrollbars. It might not be needed */ | |
296 /* with Motif scrollbars (it is apparently needed with Lesstif). */ | |
297 XtUngrabKeyboard (SCROLLBAR_X_WIDGET (instance), CurrentTime); | |
298 #endif | |
299 XtUnmanageChild (SCROLLBAR_X_WIDGET (instance)); | |
300 } | |
301 } | |
302 | |
303 enum x_scrollbar_loop | |
304 { | |
305 X_FIND_SCROLLBAR_WINDOW_MIRROR, | |
306 X_SET_SCROLLBAR_POINTER, | |
307 X_WINDOW_IS_SCROLLBAR, | |
308 X_UPDATE_FRAME_SCROLLBARS | |
309 }; | |
310 | |
311 static struct window_mirror * | |
312 x_scrollbar_loop (enum x_scrollbar_loop type, Lisp_Object window, | |
313 struct window_mirror *mir, | |
314 LWLIB_ID id, Window x_win) | |
315 { | |
316 struct window_mirror *retval = NULL; | |
317 | |
318 while (mir) | |
319 { | |
320 struct scrollbar_instance *vinstance = mir->scrollbar_vertical_instance; | |
321 struct scrollbar_instance *hinstance = mir->scrollbar_horizontal_instance; | |
322 struct window *w = XWINDOW (window); | |
323 | |
324 if (mir->vchild) | |
325 retval = x_scrollbar_loop (type, w->vchild, mir->vchild, id, x_win); | |
326 else if (mir->hchild) | |
327 retval = x_scrollbar_loop (type, w->hchild, mir->hchild, id, x_win); | |
328 if (retval) | |
329 return retval; | |
330 | |
331 if (hinstance || vinstance) | |
332 { | |
333 switch (type) | |
334 { | |
335 case X_FIND_SCROLLBAR_WINDOW_MIRROR: | |
336 if ((vinstance && SCROLLBAR_X_ID (vinstance) == id) || | |
337 (hinstance && SCROLLBAR_X_ID (hinstance) == id)) | |
338 return mir; | |
339 break; | |
340 case X_UPDATE_FRAME_SCROLLBARS: | |
341 if (!mir->vchild && !mir->hchild) | |
342 update_window_scrollbars (w, mir, 1, 0); | |
343 break; | |
344 case X_SET_SCROLLBAR_POINTER: | |
345 if (!mir->vchild && !mir->hchild) | |
346 { | |
347 Widget widget; | |
348 | |
349 widget = SCROLLBAR_X_WIDGET (hinstance); | |
350 if (widget && XtIsManaged (widget)) | |
351 update_one_widget_scrollbar_pointer (w, widget); | |
352 | |
353 widget = SCROLLBAR_X_WIDGET (vinstance); | |
354 if (widget && XtIsManaged (widget)) | |
355 update_one_widget_scrollbar_pointer (w, widget); | |
356 } | |
357 break; | |
358 case X_WINDOW_IS_SCROLLBAR: | |
359 if (!mir->vchild && !mir->hchild) | |
360 { | |
361 Widget widget; | |
362 | |
363 widget = SCROLLBAR_X_WIDGET (hinstance); | |
364 if (widget && XtIsManaged (widget) && | |
365 XtWindow (widget) == x_win) | |
366 return (struct window_mirror *) 1; | |
367 | |
368 widget = SCROLLBAR_X_WIDGET (vinstance); | |
369 if (widget && XtIsManaged (widget) && | |
370 XtWindow (widget) == x_win) | |
371 return (struct window_mirror *) 1; | |
372 } | |
373 break; | |
374 default: | |
2500 | 375 ABORT (); |
428 | 376 } |
377 } | |
378 | |
379 mir = mir->next; | |
380 window = w->next; | |
381 } | |
382 | |
383 return NULL; | |
384 } | |
385 | |
386 /* Used by callbacks. */ | |
387 static struct window_mirror * | |
388 find_scrollbar_window_mirror (struct frame *f, LWLIB_ID id) | |
389 { | |
390 if (f->mirror_dirty) | |
391 update_frame_window_mirror (f); | |
392 return x_scrollbar_loop (X_FIND_SCROLLBAR_WINDOW_MIRROR, f->root_window, | |
617 | 393 XWINDOW_MIRROR (f->root_mirror), id, (Window) NULL); |
428 | 394 } |
395 | |
396 /* | |
397 * This is the only callback provided for vertical scrollbars. It | |
398 * should be able to handle all of the scrollbar events in | |
399 * scroll_action (see lwlib.h). The client data will be of type | |
400 * scroll_event (see lwlib.h). */ | |
401 static void | |
402 x_update_vertical_scrollbar_callback (Widget widget, LWLIB_ID id, | |
403 XtPointer client_data) | |
404 { | |
405 /* This function can GC */ | |
406 scroll_event *data = (scroll_event *) client_data; | |
407 struct device *d = get_device_from_display (XtDisplay (widget)); | |
408 struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); | |
409 Lisp_Object win, frame; | |
410 struct scrollbar_instance *instance; | |
411 struct window_mirror *mirror; | |
412 | |
413 if (!f) | |
414 return; | |
415 | |
416 mirror = find_scrollbar_window_mirror (f, id); | |
442 | 417 if (!mirror) |
418 return; | |
419 | |
428 | 420 win = real_window (mirror, 1); |
421 | |
422 if (NILP (win)) | |
423 return; | |
424 instance = mirror->scrollbar_vertical_instance; | |
425 frame = WINDOW_FRAME (XWINDOW (win)); | |
426 | |
427 /* It seems that this is necessary whenever signal_special_Xt_user_event() | |
428 is called. #### Why??? */ | |
429 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d); | |
430 | |
431 switch (data->action) | |
432 { | |
433 case SCROLLBAR_LINE_UP: | |
434 signal_special_Xt_user_event (frame, Qscrollbar_line_up, win); | |
435 break; | |
436 | |
437 case SCROLLBAR_LINE_DOWN: | |
438 signal_special_Xt_user_event (frame, Qscrollbar_line_down, win); | |
439 break; | |
440 | |
441 /* The Athena scrollbar paging behavior is that of xterms. | |
442 Depending on where you click the size of the page varies. | |
443 Motif always does a standard Emacs page. */ | |
444 case SCROLLBAR_PAGE_UP: | |
445 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \ | |
446 !defined (LWLIB_SCROLLBARS_ATHENA3D) | |
447 { | |
448 double tmp = ((double) data->slider_value / | |
449 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height); | |
450 double line = tmp * | |
451 (double) window_displayed_height (XWINDOW (win)); | |
452 | |
453 if (line > -1.0) | |
454 line = -1.0; | |
455 signal_special_Xt_user_event (frame, Qscrollbar_page_up, | |
456 Fcons (win, make_int ((int) line))); | |
457 } | |
458 #else | |
459 signal_special_Xt_user_event (frame, Qscrollbar_page_up, | |
460 Fcons (win, Qnil)); | |
461 #endif | |
462 break; | |
463 | |
464 case SCROLLBAR_PAGE_DOWN: | |
465 #if !defined (LWLIB_SCROLLBARS_MOTIF) && !defined (LWLIB_SCROLLBARS_LUCID) && \ | |
466 !defined (LWLIB_SCROLLBARS_ATHENA3D) | |
467 { | |
468 double tmp = ((double) data->slider_value / | |
469 (double) SCROLLBAR_X_POS_DATA(instance).scrollbar_height); | |
470 double line = tmp * | |
471 (double) window_displayed_height (XWINDOW (win)); | |
472 | |
473 if (SCROLLBAR_X_POS_DATA(instance).maximum > | |
474 (SCROLLBAR_X_POS_DATA(instance).slider_size + SCROLLBAR_X_POS_DATA(instance).slider_position)) | |
475 { | |
476 if (line < 1.0) | |
477 line = 1.0; | |
478 signal_special_Xt_user_event (frame, Qscrollbar_page_down, | |
479 Fcons (win, | |
480 make_int ((int) line))); | |
481 } | |
482 } | |
483 #else | |
484 signal_special_Xt_user_event (frame, Qscrollbar_page_down, | |
485 Fcons (win, Qnil)); | |
486 #endif | |
487 break; | |
488 | |
489 case SCROLLBAR_TOP: | |
490 signal_special_Xt_user_event (frame, Qscrollbar_to_top, win); | |
491 break; | |
492 | |
493 case SCROLLBAR_BOTTOM: | |
494 signal_special_Xt_user_event (frame, Qscrollbar_to_bottom, win); | |
495 break; | |
496 | |
497 | |
498 case SCROLLBAR_CHANGE: | |
499 inhibit_slider_size_change = 0; | |
500 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
501 vertical_drag_in_progress = 0; | |
502 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value; | |
503 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) = | |
504 XINT (Fwindow_start (win)); | |
505 #else | |
506 stupid_vertical_scrollbar_drag_hack = 0; | |
507 #endif | |
508 break; | |
509 | |
510 case SCROLLBAR_DRAG: | |
511 { | |
512 int value; | |
513 | |
514 inhibit_slider_size_change = 1; | |
515 | |
516 #if defined (LWLIB_SCROLLBARS_MOTIF) || defined (LWLIB_SCROLLBARS_LUCID) | |
517 /* Doing drags with Motif-like scrollbars is a mess, since we | |
518 want to avoid having the window position jump when you | |
519 first grab the scrollbar, but we also want to ensure that | |
520 you can scroll all the way to the top or bottom of the | |
521 buffer. This can all be replaced with something sane when | |
522 we get line-based scrolling. */ | |
523 | |
524 vertical_drag_in_progress = 1; | |
525 | |
526 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) < 0) | |
527 { | |
528 SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) = data->slider_value; | |
529 SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) = | |
530 XINT (Fwindow_start (win)); | |
531 } | |
532 | |
533 /* Could replace this piecewise linear scrolling with a | |
534 quadratic through the three points, but I'm not sure that | |
535 would feel any nicer in practice. */ | |
536 if (data->slider_value < SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)) | |
537 { | |
538 /* We've dragged up; slide linearly from original position to | |
539 window-start=data.minimum, slider-value=data.minimum. */ | |
540 | |
541 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) | |
542 <= SCROLLBAR_X_POS_DATA (instance).minimum) | |
543 { | |
544 /* shouldn't get here, but just in case */ | |
545 value = SCROLLBAR_X_POS_DATA (instance).minimum; | |
546 } | |
547 else | |
548 { | |
549 value = (int) | |
550 (SCROLLBAR_X_POS_DATA (instance).minimum | |
551 + (((double) | |
552 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) | |
553 - SCROLLBAR_X_POS_DATA (instance).minimum) | |
554 * (data->slider_value - | |
555 SCROLLBAR_X_POS_DATA (instance).minimum)) | |
556 / (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) | |
557 - SCROLLBAR_X_POS_DATA (instance).minimum))); | |
558 } | |
559 } | |
560 else | |
561 { | |
562 /* We've dragged down; slide linearly from original position to | |
563 window-start=data.maximum, slider-value=data.maximum. */ | |
564 | |
565 if (SCROLLBAR_X_VDRAG_ORIG_VALUE (instance) | |
566 >= (SCROLLBAR_X_POS_DATA (instance).maximum - | |
567 SCROLLBAR_X_POS_DATA (instance).slider_size)) | |
568 { | |
569 /* avoid divide by zero */ | |
570 value = SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance); | |
571 } | |
572 else | |
573 { | |
574 value = (int) | |
575 (SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance) | |
576 + (((double) | |
577 (SCROLLBAR_X_POS_DATA (instance).maximum | |
578 - SCROLLBAR_X_VDRAG_ORIG_WINDOW_START (instance)) | |
579 * (data->slider_value | |
580 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance))) | |
581 / (SCROLLBAR_X_POS_DATA (instance).maximum | |
582 - SCROLLBAR_X_POS_DATA (instance).slider_size | |
583 - SCROLLBAR_X_VDRAG_ORIG_VALUE (instance)))); | |
584 } | |
585 } | |
586 #else | |
587 stupid_vertical_scrollbar_drag_hack = 0; | |
588 value = data->slider_value; | |
589 #endif | |
590 | |
591 if (value >= SCROLLBAR_X_POS_DATA (instance).maximum) | |
592 value = SCROLLBAR_X_POS_DATA (instance).maximum - 1; | |
593 if (value < SCROLLBAR_X_POS_DATA (instance).minimum) | |
594 value = SCROLLBAR_X_POS_DATA (instance).minimum; | |
595 | |
596 signal_special_Xt_user_event (frame, Qscrollbar_vertical_drag, | |
597 Fcons (win, make_int (value))); | |
598 } | |
599 break; | |
600 | |
601 } | |
602 } | |
603 | |
604 /* | |
605 * This is the only callback provided for horizontal scrollbars. It | |
606 * should be able to handle all of the scrollbar events in | |
607 * scroll_action (see lwlib.h). The client data will be of type | |
608 * scroll_event (see lwlib.h). */ | |
609 static void | |
610 x_update_horizontal_scrollbar_callback (Widget widget, LWLIB_ID id, | |
611 XtPointer client_data) | |
612 { | |
613 scroll_event *data = (scroll_event *) client_data; | |
614 struct device *d = get_device_from_display (XtDisplay (widget)); | |
615 struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); | |
616 Lisp_Object win, frame; | |
617 struct window_mirror *mirror; | |
618 | |
619 if (!f) | |
620 return; | |
621 | |
622 mirror = find_scrollbar_window_mirror (f, id); | |
442 | 623 if (!mirror) |
624 return; | |
625 | |
428 | 626 win = real_window (mirror, 1); |
627 | |
628 if (NILP (win)) | |
629 return; | |
630 frame = WINDOW_FRAME (XWINDOW (win)); | |
631 | |
632 /* It seems that this is necessary whenever signal_special_Xt_user_event() | |
633 is called. #### Why??? */ | |
634 DEVICE_X_MOUSE_TIMESTAMP (d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP (d); | |
635 | |
636 switch (data->action) | |
637 { | |
638 case SCROLLBAR_LINE_UP: | |
639 signal_special_Xt_user_event (frame, Qscrollbar_char_left, win); | |
640 break; | |
641 case SCROLLBAR_LINE_DOWN: | |
642 signal_special_Xt_user_event (frame, Qscrollbar_char_right, win); | |
643 break; | |
644 case SCROLLBAR_PAGE_UP: | |
645 signal_special_Xt_user_event (frame, Qscrollbar_page_left, win); | |
646 break; | |
647 case SCROLLBAR_PAGE_DOWN: | |
648 signal_special_Xt_user_event (frame, Qscrollbar_page_right, win); | |
649 break; | |
650 case SCROLLBAR_TOP: | |
651 signal_special_Xt_user_event (frame, Qscrollbar_to_left, win); | |
652 break; | |
653 case SCROLLBAR_BOTTOM: | |
654 signal_special_Xt_user_event (frame, Qscrollbar_to_right, win); | |
655 break; | |
656 case SCROLLBAR_CHANGE: | |
657 inhibit_slider_size_change = 0; | |
658 break; | |
659 case SCROLLBAR_DRAG: | |
660 inhibit_slider_size_change = 1; | |
661 /* #### Fix the damn toolkit code so they all work the same way. | |
662 Lucid is the one mostly wrong.*/ | |
663 #if defined (LWLIB_SCROLLBARS_LUCID) || defined (LWLIB_SCROLLBARS_ATHENA3D) | |
664 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag, | |
665 (Fcons | |
666 (win, make_int (data->slider_value)))); | |
667 #else | |
668 signal_special_Xt_user_event (frame, Qscrollbar_horizontal_drag, | |
669 (Fcons | |
670 (win, | |
671 make_int (data->slider_value - 1)))); | |
672 #endif | |
673 break; | |
674 default: | |
675 break; | |
676 } | |
677 } | |
678 | |
679 static void | |
680 x_scrollbar_pointer_changed_in_window (struct window *w) | |
681 { | |
793 | 682 Lisp_Object window = wrap_window (w); |
428 | 683 |
684 x_scrollbar_loop (X_SET_SCROLLBAR_POINTER, window, find_window_mirror (w), | |
685 0, (Window) NULL); | |
686 } | |
687 | |
688 /* Make sure that all scrollbars on frame are up-to-date. Called | |
689 directly from x_set_frame_properties in frame-x.c*/ | |
690 void | |
691 x_update_frame_scrollbars (struct frame *f) | |
692 { | |
617 | 693 x_scrollbar_loop (X_UPDATE_FRAME_SCROLLBARS, f->root_window, |
694 XWINDOW_MIRROR (f->root_mirror), 0, (Window) NULL); | |
428 | 695 } |
696 | |
697 #ifdef MEMORY_USAGE_STATS | |
698 | |
5170
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
699 static Bytecount |
2286 | 700 x_compute_scrollbar_instance_usage (struct device *UNUSED (d), |
428 | 701 struct scrollbar_instance *inst, |
5157
1fae11d56ad2
redo memory-usage mechanism, add way of dynamically initializing Lisp objects
Ben Wing <ben@xemacs.org>
parents:
5050
diff
changeset
|
702 struct usage_stats *ustats) |
428 | 703 { |
5170
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
704 Bytecount total = 0; |
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
705 struct x_scrollbar_data *data = |
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
706 (struct x_scrollbar_data *) inst->scrollbar_data; |
428 | 707 |
5170
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
708 total += malloced_storage_size (data, sizeof (*data), ustats); |
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
709 total += malloced_storage_size (data->name, 1 + strlen (data->name), |
5ddbab03b0e6
various fixes to memory-usage stats
Ben Wing <ben@xemacs.org>
parents:
5169
diff
changeset
|
710 ustats); |
428 | 711 |
712 return total; | |
713 } | |
714 | |
715 #endif /* MEMORY_USAGE_STATS */ | |
716 | |
717 | |
718 /************************************************************************/ | |
719 /* initialization */ | |
720 /************************************************************************/ | |
721 | |
722 void | |
723 console_type_create_scrollbar_x (void) | |
724 { | |
725 CONSOLE_HAS_METHOD (x, inhibit_scrollbar_slider_size_change); | |
726 CONSOLE_HAS_METHOD (x, free_scrollbar_instance); | |
727 CONSOLE_HAS_METHOD (x, release_scrollbar_instance); | |
728 CONSOLE_HAS_METHOD (x, create_scrollbar_instance); | |
729 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_values); | |
730 CONSOLE_HAS_METHOD (x, update_scrollbar_instance_status); | |
731 CONSOLE_HAS_METHOD (x, scrollbar_pointer_changed_in_window); | |
732 #ifdef MEMORY_USAGE_STATS | |
733 CONSOLE_HAS_METHOD (x, compute_scrollbar_instance_usage); | |
734 #endif /* MEMORY_USAGE_STATS */ | |
735 } | |
736 | |
737 void | |
738 reinit_vars_of_scrollbar_x (void) | |
739 { | |
740 stupid_vertical_scrollbar_drag_hack = 1; | |
741 } | |
742 | |
743 void | |
744 vars_of_scrollbar_x (void) | |
745 { | |
746 #if defined (LWLIB_SCROLLBARS_LUCID) | |
747 Fprovide (intern ("lucid-scrollbars")); | |
748 #elif defined (LWLIB_SCROLLBARS_MOTIF) | |
749 Fprovide (intern ("motif-scrollbars")); | |
750 #elif defined (LWLIB_SCROLLBARS_ATHENA) | |
751 Fprovide (intern ("athena-scrollbars")); | |
752 #endif | |
753 } |