1 /*
2 * Copyright (C) 1995, 1996 Karl-Johan Johnsson.
3 */
4
5 #include <X11/IntrinsicP.h>
6 #include <X11/StringDefs.h>
7
8 #include "Compat.h"
9 #include "Manager.h"
10 #include "ScrollableP.h"
11 #include "Util.h"
12
13 static XtResource resources[] = {
14 #define offset(field) XtOffsetOf(ScrollableRec, scrollable.field)
15 {XtNhBar, XtCScrBar, XtRWidget, sizeof(Widget),
16 offset(h_bar), XtRImmediate, (XtPointer)NULL},
17 {XtNvBar, XtCScrBar, XtRWidget, sizeof(Widget),
18 offset(v_bar), XtRImmediate, (XtPointer)NULL},
19 #undef offset
20 };
21
22 static void ClassPartInitialize(WidgetClass);
23 static void Initialize(Widget, Widget, ArgList, Cardinal*);
24 static void Resize(Widget);
25 static void Realize(Widget, XtValueMask*, XSetWindowAttributes*);
26 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal*);
27 static void SetHPos(ScrollableWidget, long);
28 static void SetVPos(ScrollableWidget, long);
29
30 ScrollableClassRec scrollableClassRec = {
31 { /* core_class fields */
32 (WidgetClass) &shadowClassRec, /* superclass */
33 "Scrollable", /* class_name */
34 sizeof(ScrollableRec), /* widget_size */
35 NULL, /* class_initialize */
36 ClassPartInitialize, /* class_part_initialize */
37 FALSE, /* class_inited */
38 Initialize, /* initialize */
39 NULL, /* initialize_hook */
40 Realize, /* realize */
41 NULL, /* actions */
42 0, /* num_actions */
43 resources, /* resources */
44 XtNumber(resources), /* num_resources */
45 NULLQUARK, /* xrm_class */
46 TRUE, /* compress_motion */
47 TRUE, /* compress_exposure */
48 TRUE, /* compress_enterleave */
49 FALSE, /* visible_interest */
50 NULL, /* destroy */
51 Resize, /* resize */
52 NULL, /* expose */
53 SetValues, /* set_values */
54 NULL, /* set_values_hook */
55 XtInheritSetValuesAlmost, /* set_values_almost */
56 NULL, /* get_values_hook */
57 NULL, /* accept_focus */
58 XtVersion, /* version */
59 NULL, /* callback_private */
60 NULL, /* tm_table */
61 XtInheritQueryGeometry, /* query_geometry */
62 XtInheritDisplayAccelerator, /* display_accelerator */
63 NULL /* extension */
64 },
65 { /* shadow fields */
66 XtInheritPixelOffset, /* pixel_offset */
67 False, /* use_arm_for_background */
68 XtInheritAllocShadowColors, /* alloc_shadow_colors */
69 XtInheritAllocShadowPixmaps, /* alloc_shadow_pixmaps */
70 XtInheritAllocArmColor, /* alloc_arm_color */
71 XtInheritAllocArmPixmap, /* alloc_arm_pixmap */
72 XtInheritAllocGCs, /* alloc_gcs */
73 NULL, /* extension */
74 },
75 { /* scrollable fields */
76 SetHPos, /* set_hpos */
77 SetVPos, /* set_vpos */
78 NULL, /* suspend_hook */
79 NULL, /* extension */
80 }
81 };
82
83 WidgetClass scrollableWidgetClass = (WidgetClass)&scrollableClassRec;
84
85 /*************************************************************************/
86
hbar_callback(Widget scr_bar,XtPointer client_data,XtPointer call_data)87 static void hbar_callback(Widget scr_bar,
88 XtPointer client_data,
89 XtPointer call_data)
90 {
91 ScrollReport *rep = (ScrollReport *)call_data;
92 ScrollableWidget w = (ScrollableWidget)client_data;
93 ScrollableWidgetClass class = (ScrollableWidgetClass)XtClass(w);
94 long n_pos, n_shown, n_size;
95
96 if (!w->core.managed)
97 return;
98
99 class->scrollable_class.set_hpos(w, rep->pos);
100 n_pos = w->scrollable.pos_x;
101 n_shown = w->scrollable.shown_x;
102 n_size = w->scrollable.width;
103 if (rep->pos != n_pos || rep->shown != n_shown || rep->size != n_size)
104 ScrBarSetLengthsAndPos(scr_bar, n_size, n_shown, n_pos);
105 }
106
vbar_callback(Widget scr_bar,XtPointer client_data,XtPointer call_data)107 static void vbar_callback(Widget scr_bar,
108 XtPointer client_data,
109 XtPointer call_data)
110 {
111 ScrollReport *rep = (ScrollReport *)call_data;
112 ScrollableWidget w = (ScrollableWidget)client_data;
113 ScrollableWidgetClass class = (ScrollableWidgetClass)XtClass(w);
114 long n_pos, n_shown, n_size;
115
116 if (!w->core.managed)
117 return;
118
119 class->scrollable_class.set_vpos(w, rep->pos);
120 n_pos = w->scrollable.pos_y;
121 n_shown = w->scrollable.shown_y;
122 n_size = w->scrollable.height;
123 if (rep->pos != n_pos || rep->shown != n_shown || rep->size != n_size)
124 ScrBarSetLengthsAndPos(scr_bar, n_size, n_shown, n_pos);
125 }
126
remove_callback(ScrollableWidget w,Widget scr_bar,XtCallbackProc callback)127 static void remove_callback(ScrollableWidget w,
128 Widget scr_bar,
129 XtCallbackProc callback)
130 {
131 if (scr_bar)
132 XtRemoveCallback(scr_bar, XtNscrollCallback, callback, (XtPointer)w);
133 }
134
add_callback(ScrollableWidget w,Widget scr_bar,XtCallbackProc callback)135 static void add_callback(ScrollableWidget w,
136 Widget scr_bar,
137 XtCallbackProc callback)
138 {
139 if (scr_bar)
140 XtAddCallback(scr_bar, XtNscrollCallback, callback, (XtPointer)w);
141 }
142
call_suspend_hook(ScrollableWidget w)143 static void call_suspend_hook(ScrollableWidget w)
144 {
145 ScrollableWidgetClass class = (ScrollableWidgetClass)XtClass(w);
146
147 if (class->scrollable_class.suspend_hook)
148 class->scrollable_class.suspend_hook(w);
149 }
150
parent_resize_callback(Widget parent,XtPointer client_data,XtPointer call_data)151 static void parent_resize_callback(Widget parent,
152 XtPointer client_data,
153 XtPointer call_data)
154 {
155 Widget w = (Widget)client_data;
156
157 if (XtIsManaged(w) && w->core.widget_class->core_class.resize)
158 w->core.widget_class->core_class.resize(w);
159 }
160
161 /*************************************************************************/
162
ClassPartInitialize(WidgetClass gclass)163 static void ClassPartInitialize(WidgetClass gclass)
164 {
165 ScrollableWidgetClass class, super;
166
167 class = (ScrollableWidgetClass)gclass;
168 super = (ScrollableWidgetClass)class->core_class.superclass;
169
170 if (class->scrollable_class.set_hpos == XtInheritScrollableSetPos)
171 class->scrollable_class.set_hpos = super->scrollable_class.set_hpos;
172 if (class->scrollable_class.set_vpos == XtInheritScrollableSetPos)
173 class->scrollable_class.set_vpos = super->scrollable_class.set_vpos;
174 if (class->scrollable_class.suspend_hook == XtInheritScrollableSuspendHook)
175 class->scrollable_class.suspend_hook =
176 super->scrollable_class.suspend_hook;
177 }
178
Initialize(Widget grequest,Widget gnew,ArgList args,Cardinal * num_args)179 static void Initialize(Widget grequest, Widget gnew,
180 ArgList args, Cardinal *num_args)
181 {
182 ScrollableWidget new = (ScrollableWidget)gnew;
183 Widget parent = XtParent(new);
184
185 new->scrollable.pos_x = 0;
186 new->scrollable.shown_x = 0;
187 new->scrollable.width = 0;
188 new->scrollable.pos_y = 0;
189 new->scrollable.shown_y = 0;
190 new->scrollable.height = 0;
191 new->scrollable.suspended = False;
192 add_callback(new, new->scrollable.h_bar, hbar_callback);
193 add_callback(new, new->scrollable.v_bar, vbar_callback);
194 if (XtIsSubclass(parent, managerWidgetClass))
195 XtAddCallback(parent, XtNresizeCallback,
196 parent_resize_callback, (XtPointer)new);
197 }
198
Resize(Widget gw)199 static void Resize(Widget gw)
200 {
201 ScrollableWidget w = (ScrollableWidget)gw;
202
203 ScrollableHFromGeometry(w);
204 ScrollableVFromGeometry(w);
205 ScrollableFitHBar(w);
206 ScrollableFitVBar(w);
207 }
208
SetHPos(ScrollableWidget w,long x)209 static void SetHPos(ScrollableWidget w, long x)
210 {
211 Arg arg;
212
213 XtSetArg(arg, XtNx, - x);
214 XtSetValues((Widget)w, &arg, 1);
215 ScrollableHFromGeometry(w);
216 }
217
SetVPos(ScrollableWidget w,long y)218 static void SetVPos(ScrollableWidget w, long y)
219 {
220 Arg arg;
221
222 XtSetArg(arg, XtNy, - y);
223 XtSetValues((Widget)w, &arg, 1);
224 ScrollableVFromGeometry(w);
225 }
226
Realize(Widget gw,XtValueMask * mask,XSetWindowAttributes * attributes)227 static void Realize(Widget gw, XtValueMask *mask,
228 XSetWindowAttributes *attributes)
229 {
230 ScrollableWidget w = (ScrollableWidget)gw;
231
232 ScrollableFitHBar(w);
233 ScrollableFitVBar(w);
234 shadowWidgetClass->core_class.realize((Widget)w, mask, attributes);
235 }
236
SetValues(Widget gcurrent,Widget grequest,Widget gnew,ArgList args,Cardinal * num_args)237 static Boolean SetValues(Widget gcurrent,
238 Widget grequest,
239 Widget gnew,
240 ArgList args,
241 Cardinal *num_args)
242 {
243 ScrollableWidget new = (ScrollableWidget)gnew;
244 ScrollableWidget current = (ScrollableWidget)gcurrent;
245
246 if (new->scrollable.h_bar != current->scrollable.h_bar) {
247 remove_callback(new, current->scrollable.h_bar, hbar_callback);
248 add_callback(new, new->scrollable.h_bar, hbar_callback);
249 ScrollableFitHBar(new);
250 }
251
252 if (new->scrollable.v_bar != current->scrollable.v_bar) {
253 remove_callback(new, current->scrollable.v_bar, vbar_callback);
254 add_callback(new, new->scrollable.v_bar, vbar_callback);
255 ScrollableFitVBar(new);
256 }
257
258 return False;
259 }
260
261 /*************************************************************************/
262
ScrollableSetHBar(Widget gw,Widget h_bar)263 void ScrollableSetHBar(Widget gw, Widget h_bar)
264 {
265 ScrollableWidget w = (ScrollableWidget)gw;
266
267 remove_callback(w, w->scrollable.h_bar, hbar_callback);
268 w->scrollable.h_bar = h_bar;
269 add_callback(w, w->scrollable.h_bar, hbar_callback);
270 if (!w->scrollable.suspended)
271 ScrollableFitHBar(w);
272 }
273
ScrollableSetVBar(Widget gw,Widget v_bar)274 void ScrollableSetVBar(Widget gw, Widget v_bar)
275 {
276 ScrollableWidget w = (ScrollableWidget)gw;
277
278 remove_callback(w, w->scrollable.v_bar, vbar_callback);
279 w->scrollable.v_bar = v_bar;
280 add_callback(w, w->scrollable.v_bar, vbar_callback);
281 if (!w->scrollable.suspended)
282 ScrollableFitVBar(w);
283 }
284
ScrollableSuspend(Widget gw)285 void ScrollableSuspend(Widget gw)
286 {
287 ScrollableWidget w = (ScrollableWidget)gw;
288
289 w->scrollable.suspended = True;
290 call_suspend_hook(w);
291 }
292
ScrollableResume(Widget gw)293 void ScrollableResume(Widget gw)
294 {
295 ScrollableWidget w = (ScrollableWidget)gw;
296
297 w->scrollable.suspended = False;
298 call_suspend_hook(w);
299 ScrollableFitHBar(w);
300 ScrollableFitVBar(w);
301 }
302
ScrollableFitHBar(ScrollableWidget w)303 void ScrollableFitHBar(ScrollableWidget w)
304 {
305 if (!w->scrollable.h_bar || w->scrollable.suspended)
306 return;
307 ScrBarSetLengthsAndPos(w->scrollable.h_bar,
308 w->scrollable.width,
309 w->scrollable.shown_x,
310 w->scrollable.pos_x);
311 }
312
ScrollableFitVBar(ScrollableWidget w)313 void ScrollableFitVBar(ScrollableWidget w)
314 {
315 if (!w->scrollable.v_bar || w->scrollable.suspended)
316 return;
317 ScrBarSetLengthsAndPos(w->scrollable.v_bar,
318 w->scrollable.height,
319 w->scrollable.shown_y,
320 w->scrollable.pos_y);
321 }
322
ScrollableHFromGeometry(ScrollableWidget w)323 void ScrollableHFromGeometry(ScrollableWidget w)
324 {
325 w->scrollable.pos_x = -w->core.x;
326 w->scrollable.shown_x = XtParent(w)->core.width;
327 w->scrollable.width = w->core.width;
328 }
329
ScrollableVFromGeometry(ScrollableWidget w)330 void ScrollableVFromGeometry(ScrollableWidget w)
331 {
332 w->scrollable.pos_y = -w->core.y;
333 w->scrollable.shown_y = XtParent(w)->core.height;
334 w->scrollable.height = w->core.height;
335 }
336
ScrollableSetHPos(Widget gw,long pos_x)337 void ScrollableSetHPos(Widget gw, long pos_x)
338 {
339 ScrollableWidget w = (ScrollableWidget)gw;
340 ScrollableWidgetClass class = (ScrollableWidgetClass)XtClass(w);
341
342 class->scrollable_class.set_hpos(w, pos_x);
343 ScrollableFitHBar(w);
344 }
345
ScrollableSetVPos(Widget gw,long pos_y)346 void ScrollableSetVPos(Widget gw, long pos_y)
347 {
348 ScrollableWidget w = (ScrollableWidget)gw;
349 ScrollableWidgetClass class = (ScrollableWidgetClass)XtClass(w);
350
351 class->scrollable_class.set_vpos(w, pos_y);
352 ScrollableFitVBar(w);
353 }
354
ScrollableGetVPos(Widget gw)355 long ScrollableGetVPos(Widget gw)
356 {
357 ScrollableWidget w = (ScrollableWidget)gw;
358
359 return w->scrollable.pos_y;
360 }
361
ScrollableGetVSize(Widget gw)362 long ScrollableGetVSize(Widget gw)
363 {
364 ScrollableWidget w = (ScrollableWidget)gw;
365
366 return w->scrollable.height;
367 }
368
ScrollableGetVShown(Widget gw)369 long ScrollableGetVShown(Widget gw)
370 {
371 ScrollableWidget w = (ScrollableWidget)gw;
372
373 return w->scrollable.shown_y;
374 }
375
ScrollablePage(Widget gw,float amount)376 void ScrollablePage(Widget gw, float amount)
377 {
378 ScrollableWidget w = (ScrollableWidget)gw;
379
380 ScrollableSetVPos((Widget)w,
381 w->scrollable.pos_y + amount * w->scrollable.shown_y);
382 }
383