1 /**
2 *
3 * $Id: ArrowBG.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright (C) 1995-2001 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Id: ArrowBG.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <XmI/XmI.h>
31 #include <Xm/XmP.h>
32 #include <Xm/ArrowBGP.h>
33 #include <Xm/RepType.h>
34
35 #include <XmI/DebugUtil.h>
36
37 /*
38 * Experiment
39 *
40 * Try to add trait stuff by #ifdeffing it.
41 */
42 #if XmVERSION > 1
43 #include <Xm/TraitP.h>
44 #include <Xm/ActivatableT.h>
45
46 void _XmArrowBG_TraitAddCallback(Widget, XtCallbackProc, XtPointer, Boolean);
47
48 static XmActivatableTraitRec _XmArrowBGTraitRec = {
49 /* version */ 0,
50 /* cb */ _XmArrowBG_TraitAddCallback
51 };
52 #endif
53
54 #if XmVERSION > 1
55 #define PUSH_GC(w) (XtSensitive(w) \
56 ? ABG_ArrowGC(w) \
57 : ABG_InsensitiveGC(w))
58 #define DETAIL_SHADOW_THICKNESS(w) ABG_DetailShadowThickness(w)
59 #else
60 #define PUSH_GC(w) NULL
61 #define DETAIL_SHADOW_THICKNESS(w) Xm3D_ENHANCE_PIXEL
62 #endif
63
64 /* Forward Declarations */
65
66
67 #if XmVERSION > 1
68 static void class_initialize(void);
69 #endif
70
71 static void class_part_initialize(WidgetClass w_class);
72
73 static void initialize(Widget request, Widget w_new,
74 ArgList args, Cardinal *num_args);
75
76 static void destroy(Widget w);
77
78 static void expose(Widget w, XEvent *event, Region region);
79
80 #if 0
81 static XtGeometryResult query_geometry(Widget w,
82 XtWidgetGeometry *proposed,
83 XtWidgetGeometry *answer);
84 #endif
85
86 static Boolean set_values(Widget current, Widget request, Widget new_w,
87 ArgList args, Cardinal *num_args);
88
89 static void input_dispatch(Widget gadget, XEvent *event, Mask event_mask);
90
91 /*
92 * Resources for the arrowbuttongadget class
93 */
94 #define Offset(field) XtOffsetOf(XmArrowButtonGadgetRec, arrowbutton.field)
95 static XtResource resources[] =
96 {
97 {
98 XmNmultiClick, XmCMultiClick, XmRMultiClick,
99 sizeof(unsigned char), Offset(multiClick),
100 XmRImmediate, (XtPointer)XmMULTICLICK_KEEP
101 },
102 {
103 XmNarrowDirection, XmCArrowDirection, XmRArrowDirection,
104 sizeof(unsigned char), Offset(direction),
105 XmRImmediate, (XtPointer)XmARROW_UP
106 },
107 {
108 XmNactivateCallback, XmCCallback, XmRCallback,
109 sizeof(XtCallbackList), Offset(activate_callback),
110 XmRPointer, (XtPointer)NULL
111 },
112 {
113 XmNarmCallback, XmCCallback, XmRCallback,
114 sizeof(XtCallbackList), Offset(arm_callback),
115 XmRPointer, (XtPointer)NULL
116 },
117 {
118 XmNdisarmCallback, XmCCallback, XmRCallback,
119 sizeof(XtCallbackList), Offset(disarm_callback),
120 XmRPointer, (XtPointer)NULL
121 },
122 #if XmVERSION > 1
123 {
124 XmNdetailShadowThickness, XmCShadowThickness, XmRHorizontalDimension,
125 sizeof(Dimension), Offset(detail_shadow_thickness),
126 XmRImmediate, (XtPointer)2 /* FIX ME */
127 }
128 #endif
129 };
130
131 #if XmVERSION > 1
132 static XmSyntheticResource syn_resources[] =
133 {
134 {
135 XmNdetailShadowThickness,
136 sizeof(Dimension), Offset(detail_shadow_thickness),
137 _XmFromHorizontalPixels, _XmToHorizontalPixels
138 }
139 };
140 #endif
141
142 static void Arm(Widget w, XEvent *event,
143 String *params, Cardinal *num_params);
144
145 static void Activate(Widget w, XEvent *event,
146 String *params, Cardinal *num_params);
147
148 static void Disarm(Widget w, XEvent *event,
149 String *params, Cardinal *num_params);
150
151 static void ArmAndActivate(Widget w, XEvent *event,
152 String *params, Cardinal *num_params);
153
154 static void Help(Widget w, XEvent *event,
155 String *params, Cardinal *num_params);
156
157 static void EnterWindow(Widget w, XEvent *event,
158 String *params, Cardinal *num_params);
159
160 static void LeaveWindow(Widget w, XEvent *event,
161 String *params, Cardinal *num_params);
162
163
164 #if 0
165 static XmBaseClassExtRec _XmArrowBGRectClassExtRec = {
166 /* next_extension */ NULL,
167 /* record_type */ NULLQUARK,
168 /* version */ XmBaseClassExtVersion,
169 /* size */ sizeof(XmBaseClassExtRec),
170 /* initialize_prehook */ NULL,
171 /* set_values_prehook */ NULL,
172 /* initialize_posthook */ NULL,
173 /* set_values_posthook */ NULL,
174 /* secondary_object_class */ NULL,
175 /* secondary_object_create */ NULL,
176 /* get_secondary_resources */ NULL,
177 /* fast_subclass */ { 0 },
178 /* get_values_prehook */ NULL,
179 /* get_values_posthook */ NULL,
180 /* class_part_init_prehook */ NULL,
181 /* class_part_init_posthook */ NULL,
182 /* ext_resources */ NULL,
183 /* compiled_ext_resources */ NULL,
184 /* num_ext_resources */ 0,
185 /* use_sub_resources */ False,
186 /* widget_navigable */ XmInheritWidgetNavigable,
187 /* focus_change */ XmInheritFocusChange,
188 /* wrapper_data */ NULL
189 };
190
191 static XmGadgetClassExtRec _XmArrowBGadgetClassExtRec = {
192 /* next_extension */ NULL,
193 /* record_type */ NULLQUARK,
194 /* version */ XmGadgetClassExtVersion,
195 /* size */ sizeof(XmGadgetClassExtRec),
196 /* widget_baseline_proc */ NULL,
197 /* display_rect_proc */ NULL,
198 };
199 #endif
200
201 XmArrowButtonGadgetClassRec xmArrowButtonGadgetClassRec = {
202 /* RectObj class part */
203 {
204 /* superclass */ (WidgetClass) &xmGadgetClassRec,
205 /* class_name */ "XmArrowButtonGadget",
206 /* widget_size */ sizeof(XmArrowButtonGadgetRec),
207 #if XmVERSION > 1
208 /* class_initialize */ class_initialize,
209 #else
210 /* class_initialize */ NULL,
211 #endif
212 /* class_part_initialize */ class_part_initialize,
213 /* class_inited */ False,
214 /* initialize */ initialize,
215 /* initialize_hook */ NULL,
216 /* realize */ NULL,
217 /* actions */ NULL,
218 /* num_actions */ 0,
219 /* resources */ resources,
220 /* num_resources */ XtNumber(resources),
221 /* xrm_class */ NULLQUARK,
222 /* compress_motion */ True /*False*/,
223 /* compress_exposure */ XtExposeCompressMaximal,
224 /* compress_enterleave */ True /*False*/,
225 /* visible_interest */ False,
226 /* destroy */ destroy,
227 /* resize */ NULL,
228 /* expose */ expose,
229 /* set_values */ set_values,
230 /* set_values_hook */ NULL,
231 /* set_values_almost */ XtInheritSetValuesAlmost,
232 /* get_values_hook */ NULL,
233 /* accept_focus */ NULL,
234 /* version */ XtVersionDontCheck,
235 /* callback offsets */ NULL,
236 /* tm_table */ NULL,
237 /* query_geometry */ NULL /* query_geometry */,
238 /* display_accelerator */ NULL,
239 /* extension */ (XtPointer)NULL /*&_XmArrowBGRectClassExtRec*/
240 },
241 /* XmGadget part */
242 {
243 /* border_highlight */ XmInheritBorderHighlight,
244 /* border_unhighlight */ XmInheritBorderUnhighlight,
245 /* arm_and_activate */ ArmAndActivate,
246 /* input_dispatch */ input_dispatch,
247 /* visual_change */ NULL, /* FIX ME */
248 #if XmVERSION > 1
249 /* syn_resources */ syn_resources,
250 #else
251 /* syn_resources */ NULL,
252 #endif
253 /* num_syn_resources */ 0,
254 /* cache_part */ NULL,
255 /* extension */ (XtPointer)NULL /*&_XmArrowBGadgetClassExtRec*/
256 },
257 /* XmArrowButtonGadget part */
258 {
259 /* extension */ NULL
260 },
261 };
262
263
264 WidgetClass xmArrowButtonGadgetClass =
265 (WidgetClass)&xmArrowButtonGadgetClassRec;
266
267 #if XmVERSION > 1
268 static void
class_initialize(void)269 class_initialize(void)
270 {
271 #if 0
272 _XmArrowBGRectClassExtRec.record_type = XmQmotif;
273 #endif
274
275 if (! XmeTraitSet((XtPointer)xmArrowButtonGadgetClass, XmQTactivatable,
276 (XtPointer)&_XmArrowBGTraitRec)) {
277 _XmWarning(NULL,
278 "XmArrowButtonGadget ClassInitialize: XmeTraitSet failed\n");
279 }
280 }
281 #endif
282
283 static void
class_part_initialize(WidgetClass widget_class)284 class_part_initialize(WidgetClass widget_class)
285 {
286 _XmFastSubclassInit(widget_class, XmARROW_BUTTON_GADGET_BIT);
287 }
288
289 static void
CreateArrowGC(Widget w)290 CreateArrowGC(Widget w)
291 {
292 XGCValues values;
293 XtGCMask mask;
294
295 mask = GCForeground | GCBackground | GCFillStyle | GCFunction |
296 GCSubwindowMode | GCGraphicsExposures | GCPlaneMask;
297
298 values.function = GXcopy;
299 values.plane_mask = -1;
300 values.subwindow_mode = ClipByChildren;
301 values.graphics_exposures = False;
302 values.foreground = XmParentForeground(w);
303 values.background = XmParentBackground(w);
304 values.fill_style = FillSolid;
305
306 ABG_ArrowGC(w) = XtGetGC(w, mask, &values);
307 }
308
309 static void
CreateInsensitiveGC(Widget w)310 CreateInsensitiveGC(Widget w)
311 {
312 XGCValues values;
313 XtGCMask mask;
314
315 mask = GCForeground | GCBackground | GCFillStyle | GCFunction | GCStipple |
316 GCSubwindowMode | GCGraphicsExposures | GCPlaneMask |
317 GCTileStipXOrigin | GCTileStipYOrigin;
318
319 values.function = GXcopy;
320 values.plane_mask = -1;
321 values.subwindow_mode = ClipByChildren;
322 values.graphics_exposures = False;
323 values.foreground = XmParentForeground(w);
324 values.background = XmParentBackground(w);
325 values.fill_style = FillStippled;
326 values.ts_x_origin = values.ts_y_origin = 0;
327
328 values.stipple =
329 XmGetPixmapByDepth(XtScreen(w), "50_foreground", 1, 0, 1);
330
331 ABG_InsensitiveGC(w) = XtGetGC(w, mask, &values);
332 }
333
334 static void
initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)335 initialize(Widget request, Widget new_w, ArgList args, Cardinal *num_args)
336 {
337 if (!XtIsSubclass(XtParent(new_w), xmManagerWidgetClass))
338 {
339 _XmError(new_w, "parent should be manager.");
340 }
341
342 if (!XmRepTypeValidValue(XmRepTypeGetId(XmRArrowDirection),
343 ABG_Direction(new_w), new_w))
344 ABG_Direction(new_w) = XmARROW_UP;
345
346 if (!XmRepTypeValidValue(XmRepTypeGetId(XmRMultiClick),
347 ABG_MultiClick(new_w), new_w))
348 ABG_MultiClick(new_w) = XmMULTICLICK_KEEP;
349
350 if (XtWidth(request) == 0)
351 {
352 XtWidth(new_w) += 15;
353 }
354
355 if (XtHeight(request) == 0)
356 {
357 XtHeight(new_w) += 15;
358 }
359
360 /* Gadget override */
361 G_HighlightOnEnter(new_w) = True;
362
363 ABG_Armed(new_w) = False;
364
365 CreateArrowGC(new_w);
366 CreateInsensitiveGC(new_w);
367
368 G_EventMask(new_w) = XmARM_EVENT | XmACTIVATE_EVENT | XmENTER_EVENT |
369 XmLEAVE_EVENT | XmFOCUS_IN_EVENT |
370 XmFOCUS_OUT_EVENT | XmMULTI_ARM_EVENT |
371 XmMULTI_ACTIVATE_EVENT | XmHELP_EVENT;
372
373 ABG_Timer(new_w) = 0;
374 }
375
376 static void
destroy(Widget w)377 destroy(Widget w)
378 {
379 if (ABG_Timer(w) != 0)
380 {
381 XtRemoveTimeOut(ABG_Timer(w));
382 ABG_Timer(w) = 0;
383 }
384
385 XtReleaseGC(w, ABG_ArrowGC(w));
386 XtReleaseGC(w, ABG_InsensitiveGC(w));
387 }
388
389 static Boolean
set_values(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)390 set_values(Widget old, Widget request, Widget new_w,
391 ArgList args, Cardinal *num_args)
392 {
393 XGCValues gcv;
394 Boolean refresh_needed = False;
395
396 if (!XmRepTypeValidValue(XmRepTypeGetId(XmRArrowDirection),
397 ABG_Direction(new_w), new_w))
398 ABG_Direction(new_w) = ABG_Direction(old);
399
400 if (!XmRepTypeValidValue(XmRepTypeGetId(XmRMultiClick),
401 ABG_MultiClick(new_w), new_w))
402 ABG_MultiClick(new_w) = ABG_MultiClick(old);
403
404 /* See bug #772755 : need to query the old widget's values */
405 XGetGCValues(XtDisplayOfObject(old), ABG_ArrowGC(old), GCForeground, &gcv);
406 if (XmParentForeground(new_w) != gcv.foreground) {
407 XtReleaseGC(new_w, ABG_ArrowGC(new_w));
408 XtReleaseGC(new_w, ABG_InsensitiveGC(new_w));
409
410 CreateArrowGC(new_w);
411 CreateInsensitiveGC(new_w);
412
413 refresh_needed = True;
414 }
415
416 if (ABG_Direction(new_w) != ABG_Direction(old) ||
417 #if XmVERSION > 1
418 ABG_DetailShadowThickness(old) != ABG_DetailShadowThickness(new_w) ||
419 #endif
420 XtSensitive(new_w) != XtSensitive(old))
421 {
422 refresh_needed = True;
423 }
424
425 return refresh_needed;
426 }
427
428 static void
expose(Widget w,XEvent * event,Region region)429 expose(Widget w, XEvent *event, Region region)
430 {
431 Dimension margin = G_ShadowThickness(w) + G_HighlightThickness(w);
432 GC myGC;
433
434 /* use the right GC */
435 if (XtIsSensitive(w))
436 {
437 myGC = ABG_ArrowGC(w);
438 }
439 else
440 {
441 myGC = ABG_InsensitiveGC(w);
442 }
443
444 if (G_Highlighted(w))
445 {
446 (*GC_BorderHighlight(XtClass(w))) (w);
447 }
448 else
449 {
450 (*GC_BorderUnhighlight(XtClass(w))) (w);
451 }
452
453
454 _XmDrawShadows(XtDisplayOfObject(w),
455 XtWindowOfObject(w),
456 XmParentTopShadowGC(w),
457 XmParentBottomShadowGC(w),
458 XtX(w) + G_HighlightThickness(w),
459 XtY(w) + G_HighlightThickness(w),
460 XtWidth(w) - 2 * G_HighlightThickness(w),
461 XtHeight(w) - 2 * G_HighlightThickness(w),
462 G_ShadowThickness(w),
463 XmSHADOW_OUT);
464
465 if (ABG_Armed(w))
466 {
467 _XmDrawArrow(XtDisplayOfObject(w),
468 XtWindowOfObject(w),
469 XmParentBottomShadowGC(w),
470 XmParentTopShadowGC(w),
471 myGC,
472 XtX(w) + margin, XtY(w) + margin,
473 XtWidth(w) - (margin << 1), XtHeight(w) - (margin << 1),
474 DETAIL_SHADOW_THICKNESS(w),
475 ABG_Direction(w));
476 }
477 else
478 {
479 _XmDrawArrow(XtDisplayOfObject(w),
480 XtWindowOfObject(w),
481 XmParentTopShadowGC(w),
482 XmParentBottomShadowGC(w),
483 myGC,
484 XtX(w) + margin, XtY(w) + margin,
485 XtWidth(w) - (margin << 1), XtHeight(w) - (margin << 1),
486 DETAIL_SHADOW_THICKNESS(w),
487 ABG_Direction(w));
488 }
489 }
490
491 #if 0
492 static XtGeometryResult
493 query_geometry(Widget w, XtWidgetGeometry *proposed, XtWidgetGeometry *answer)
494 {
495 /* Motif does not have this method */
496 answer->request_mode = CWWidth | CWHeight;
497
498 answer->width = XtWidth(w);
499
500 answer->height = XtHeight(w);
501
502 if (((proposed->request_mode & (CWWidth | CWHeight))
503 == (CWWidth | CWHeight)) &&
504 proposed->width == answer->width &&
505 proposed->height == answer->height)
506 {
507 return XtGeometryYes;
508 }
509 else if (answer->width == XtWidth(w) && answer->height == XtHeight(w))
510 {
511 return XtGeometryNo;
512 }
513 else
514 {
515 return XtGeometryAlmost;
516 }
517 }
518 #endif
519
520 static void
Arm(Widget w,XEvent * event,String * params,Cardinal * num_params)521 Arm(Widget w, XEvent *event, String *params, Cardinal *num_params)
522 {
523 int margin;
524 XmArrowButtonCallbackStruct cbs;
525
526 if (!ABG_Armed(w))
527 {
528 ABG_Armed(w) = True;
529
530 if (XtIsRealized(w))
531 {
532 margin = G_ShadowThickness(w) + G_HighlightThickness(w);
533 _XmDrawArrow(XtDisplayOfObject(w),
534 XtWindowOfObject(w),
535 XmParentBottomShadowGC(w),
536 XmParentTopShadowGC(w),
537 PUSH_GC(w),
538 XtX(w) + margin, XtY(w) + margin,
539 XtWidth(w) - (margin << 1),
540 XtHeight(w) - (margin << 1),
541 DETAIL_SHADOW_THICKNESS(w),
542 ABG_Direction(w));
543 }
544
545 if (ABG_ArmCallback(w))
546 {
547 cbs.reason = XmCR_ARM;
548 cbs.event = event;
549 cbs.click_count = ABG_ClickCount(w);
550
551 XFlush(XtDisplay(w));
552
553 XtCallCallbackList(w,
554 ABG_ArmCallback(w),
555 (XtPointer)&cbs);
556 }
557 }
558 }
559
560 static void
Disarm(Widget w,XEvent * event,String * params,Cardinal * num_params)561 Disarm(Widget w, XEvent *event, String *params, Cardinal *num_params)
562 {
563 int margin;
564 XmArrowButtonCallbackStruct cbs;
565
566 if (XtIsRealized(w))
567 {
568 margin = G_ShadowThickness(w) + G_HighlightThickness(w);
569 _XmDrawArrow(XtDisplayOfObject(w),
570 XtWindowOfObject(w),
571 XmParentTopShadowGC(w),
572 XmParentBottomShadowGC(w),
573 PUSH_GC(w),
574 XtX(w) + margin, XtY(w) + margin,
575 XtWidth(w) - (margin << 1),
576 XtHeight(w) - (margin << 1),
577 DETAIL_SHADOW_THICKNESS(w),
578 ABG_Direction(w));
579 }
580
581 if (ABG_DisarmCallback(w))
582 {
583 cbs.reason = XmCR_DISARM;
584 cbs.event = event;
585 cbs.click_count = ABG_ClickCount(w);
586
587 XFlush(XtDisplay(w));
588
589 XtCallCallbackList(w,
590 ABG_DisarmCallback(w),
591 (XtPointer)&cbs);
592 }
593 ABG_Armed(w) = False;
594 }
595
596 static void
Activate(Widget w,XEvent * event,String * params,Cardinal * num_params)597 Activate(Widget w,
598 XEvent *event,
599 String *params,
600 Cardinal *num_params)
601 {
602 int margin;
603 XButtonEvent *ev = (XButtonEvent *)event;
604 XmArrowButtonCallbackStruct cbs;
605
606 if ((ev->x >= XtX(w) && ev->x < XtX(w) + XtWidth(w)) &&
607 (ev->y >= XtY(w) && ev->y < XtY(w) + XtHeight(w)))
608 {
609 cbs.reason = XmCR_ACTIVATE;
610 cbs.event = event;
611 cbs.click_count = ABG_ClickCount(w);
612
613 if (ABG_ActivateCallback(w))
614 {
615 if (XtIsRealized(w))
616 {
617 margin = G_ShadowThickness(w) + G_HighlightThickness(w);
618 _XmDrawArrow(XtDisplayOfObject(w),
619 XtWindowOfObject(w),
620 XmParentBottomShadowGC(w),
621 XmParentTopShadowGC(w),
622 PUSH_GC(w),
623 XtX(w) + margin, XtY(w) + margin,
624 XtWidth(w) - (margin << 1),
625 XtHeight(w) - (margin << 1),
626 DETAIL_SHADOW_THICKNESS(w),
627 ABG_Direction(w));
628 XFlush(XtDisplay(w));
629 }
630
631 XtCallCallbackList(w,
632 ABG_ActivateCallback(w),
633 (XtPointer)&cbs);
634 }
635 }
636
637 Disarm(w, event, params, num_params);
638 }
639
640 static void
ArmTimeout(XtPointer data,XtIntervalId * id)641 ArmTimeout(XtPointer data, XtIntervalId *id)
642 {
643 int margin;
644 Widget w = (Widget)data;
645
646 DEBUGOUT(_LtDebug(__FILE__, w, "ArmTimeout\n"));
647
648 ABG_Timer(w) = 0;
649
650 if (XtIsRealized(w))
651 {
652 margin = G_ShadowThickness(w) + G_HighlightThickness(w);
653 if (ABG_Armed(w))
654 {
655 _XmDrawArrow(XtDisplayOfObject(w),
656 XtWindowOfObject(w),
657 XmParentBottomShadowGC(w),
658 XmParentTopShadowGC(w),
659 PUSH_GC(w),
660 XtX(w) + margin, XtY(w) + margin,
661 XtWidth(w) - (margin << 1),
662 XtHeight(w) - (margin << 1),
663 DETAIL_SHADOW_THICKNESS(w),
664 ABG_Direction(w));
665 }
666 else
667 {
668 _XmDrawArrow(XtDisplayOfObject(w),
669 XtWindowOfObject(w),
670 XmParentTopShadowGC(w),
671 XmParentBottomShadowGC(w),
672 PUSH_GC(w),
673 XtX(w) + margin, XtY(w) + margin,
674 XtWidth(w) - (margin << 1),
675 XtHeight(w) - (margin << 1),
676 DETAIL_SHADOW_THICKNESS(w),
677 ABG_Direction(w));
678 }
679 XFlush(XtDisplayOfObject(w));
680 }
681 }
682
683 static void
ArmAndActivate(Widget w,XEvent * event,String * params,Cardinal * num_params)684 ArmAndActivate(Widget w, XEvent *event, String *params, Cardinal *num_params)
685 {
686 XmArrowButtonCallbackStruct cbs;
687
688 DEBUGOUT(_LtDebug(__FILE__, w, "ArmAndActivate\n"));
689
690 /* Arm, Activate, and Disarm now, but draw the disarmed state later */
691
692 Arm(w, event, params, num_params);
693 ABG_Armed(w) = False;
694 if (ABG_ActivateCallback(w))
695 {
696 XFlush(XtDisplayOfObject(w));
697 cbs.reason = XmCR_ACTIVATE;
698 cbs.event = event;
699 cbs.click_count = 1;
700 XtCallCallbackList(w,
701 ABG_ActivateCallback(w),
702 (XtPointer)&cbs);
703 }
704 if (ABG_DisarmCallback(w))
705 {
706 XFlush(XtDisplayOfObject(w));
707 cbs.reason = XmCR_DISARM;
708 cbs.event = event;
709 cbs.click_count = 1;
710 XtCallCallbackList(w,
711 ABG_DisarmCallback(w),
712 (XtPointer)&cbs);
713 }
714
715 if (ABG_Timer(w) != 0)
716 {
717 XtRemoveTimeOut(ABG_Timer(w));
718 ABG_Timer(w) = 0;
719 }
720
721 ABG_Timer(w) = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
722 ACTIVATE_DELAY, ArmTimeout, (XtPointer)w);
723 }
724
725 static void
EnterWindow(Widget w,XEvent * event,String * params,Cardinal * num_params)726 EnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
727 {
728 int margin = G_ShadowThickness(w) + G_HighlightThickness(w);
729
730 if (ABG_Armed(w))
731 {
732 _XmDrawArrow(XtDisplayOfObject(w),
733 XtWindowOfObject(w),
734 XmParentBottomShadowGC(w),
735 XmParentTopShadowGC(w),
736 PUSH_GC(w),
737 XtX(w) + margin, XtY(w) + margin,
738 XtWidth(w) - (margin << 1), XtHeight(w) - (margin << 1),
739 DETAIL_SHADOW_THICKNESS(w),
740 ABG_Direction(w));
741 }
742 }
743
744 static void
LeaveWindow(Widget w,XEvent * event,String * params,Cardinal * num_params)745 LeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
746 {
747 int margin = G_ShadowThickness(w) + G_HighlightThickness(w);
748
749 if (ABG_Armed(w))
750 {
751 _XmDrawArrow(XtDisplayOfObject(w),
752 XtWindowOfObject(w),
753 XmParentTopShadowGC(w),
754 XmParentBottomShadowGC(w),
755 PUSH_GC(w),
756 XtX(w) + margin, XtY(w) + margin,
757 XtWidth(w) - (margin << 1), XtHeight(w) - (margin << 1),
758 DETAIL_SHADOW_THICKNESS(w),
759 ABG_Direction(w));
760 }
761 }
762
763 static void
Help(Widget w,XEvent * event,String * params,Cardinal * num_params)764 Help(Widget w, XEvent *event, String *params, Cardinal *num_params)
765 {
766 Widget cur = w;
767 XmAnyCallbackStruct cbs;
768
769 cbs.reason = XmCR_HELP;
770 cbs.event = event;
771
772 while (cur != NULL)
773 {
774 if (XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome)
775 {
776 XtCallCallbacks(w, XmNhelpCallback, (XtPointer)&cbs);
777
778 return;
779 }
780
781 cur = XtParent(cur);
782 }
783 }
784
785 static void
input_dispatch(Widget gadget,XEvent * event,Mask event_mask)786 input_dispatch(Widget gadget, XEvent *event, Mask event_mask)
787 {
788 Cardinal num_params = 0;
789
790 switch (event_mask)
791 {
792 case XmARM_EVENT:
793 DEBUGOUT(_LtDebug(__FILE__, gadget,
794 "ArrowButtonGadget got arm event\n"));
795 Arm(gadget, event, NULL, &num_params);
796 break;
797
798 case XmACTIVATE_EVENT:
799 DEBUGOUT(_LtDebug(__FILE__, gadget,
800 "ArrowButtonGadget got activate event\n"));
801 ABG_ClickCount(gadget) = 1;
802 Activate(gadget, event, NULL, &num_params);
803 break;
804
805 case XmENTER_EVENT:
806 DEBUGOUT(_LtDebug(__FILE__, gadget,
807 "ArrowButtonGadget got enter event\n"));
808 EnterWindow(gadget, event, NULL, &num_params);
809 break;
810
811 case XmLEAVE_EVENT:
812 DEBUGOUT(_LtDebug(__FILE__, gadget,
813 "ArrowButtonGadget got leave event\n"));
814 LeaveWindow(gadget, event, NULL, &num_params);
815 break;
816
817 case XmFOCUS_IN_EVENT:
818 _XmFocusInGadget(gadget, event, NULL, &num_params);
819 break;
820
821 case XmFOCUS_OUT_EVENT:
822 _XmFocusOutGadget(gadget, event, NULL, &num_params);
823 break;
824
825 case XmHELP_EVENT:
826 Help(gadget, event, NULL, &num_params);
827 break;
828
829 case XmMULTI_ARM_EVENT:
830 if (ABG_MultiClick(gadget) == XmMULTICLICK_KEEP)
831 {
832 Arm(gadget, event, NULL, &num_params);
833 }
834 break;
835
836 case XmMULTI_ACTIVATE_EVENT:
837 if (ABG_MultiClick(gadget) == XmMULTICLICK_KEEP)
838 {
839 ABG_ClickCount(gadget)++;
840 Activate(gadget, event, NULL, &num_params);
841 }
842 break;
843
844 default:
845 _XmError(gadget, "Unexpected event in ArrowButton gadget\n");
846 break;
847 }
848 }
849
850 Widget
XmCreateArrowButtonGadget(Widget parent,char * name,Arg * arglist,Cardinal argcount)851 XmCreateArrowButtonGadget(Widget parent, char *name,
852 Arg *arglist, Cardinal argcount)
853 {
854 return XtCreateWidget(name,
855 xmArrowButtonGadgetClass,
856 parent,
857 arglist,
858 argcount);
859 }
860
861 #if XmVERSION > 1
_XmArrowBG_TraitAddCallback(Widget w,XtCallbackProc cb,XtPointer cbp,Boolean set)862 void _XmArrowBG_TraitAddCallback(Widget w,
863 XtCallbackProc cb,
864 XtPointer cbp,
865 Boolean set)
866 {
867 if (set)
868 XtAddCallback(w, XmNactivateCallback, cb, cbp);
869 else
870 XtRemoveCallback(w, XmNactivateCallback, cb, cbp);
871 }
872 #endif
873