2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: Button.c /main/7 1995/11/14 10:03:27 rswiston $ */
26 static char SCCSID[] = "OSF/Motif: @(#)Button.c 1.19 95/05/01";
29 /******************************************************************************
30 *******************************************************************************
32 * (c) Copyright 1992 HEWLETT-PACKARD COMPANY
35 *******************************************************************************
36 ******************************************************************************/
38 #include <X11/cursorfont.h>
40 #include <Xm/ManagerP.h>
42 #include <Dt/Control.h>
43 #include <Dt/MacrosP.h>
44 #include <Dt/DtStrDefs.h>
46 #define DELAY_DEFAULT 100
48 static void Initialize(
53 static void UpdateGCs(
55 static void Redisplay(
59 static Boolean SetValues(
67 Cardinal *num_params) ;
72 Cardinal *num_params) ;
77 Cardinal *num_params) ;
78 static void ArmAndActivate(
82 Cardinal *num_params) ;
83 static void InputDispatch(
87 static Boolean VisualChange(
91 static void ArmTimeout(
98 Cardinal *num_params) ;
103 Cardinal *num_params) ;
104 static void CallCallback(
109 static void DefaultSelectColor(
114 /* Resource list for button */
116 #define R_Offset(field) \
117 XtOffset (DtButtonGadget, button.field)
118 static XtResource resources[] =
122 XmCCursorFont, XmRInt, sizeof (int),
123 R_Offset (cursor_font),
124 XmRImmediate, (XtPointer) 1
128 XmCArmColor, XmRPixel, sizeof (Pixel),
129 R_Offset (arm_color),
130 XmRCallProc, (XtPointer) DefaultSelectColor
134 XmCSubpanel, XmRWidget, sizeof (Widget),
136 XmRImmediate, (XtPointer) NULL
140 XmCPushFunction, XmRFunction, sizeof (XtPointer),
141 R_Offset (push_function),
142 XmRImmediate, (XtPointer) NULL
146 XmCPushArgument, XmRPointer, sizeof (XtPointer),
147 R_Offset (push_argument),
148 XmRImmediate, (XtPointer) NULL
152 XmCString, XmRString, sizeof (String),
153 R_Offset (image_name),
154 XmRImmediate, (XtPointer) ""
159 XmCCallback, XmRCallback, sizeof(XtCallbackList),
161 XmRImmediate, (caddr_t) NULL
166 XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
167 R_Offset (multiClick),
168 XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
173 /* The button class record definition */
175 externaldef (dtbuttongadgetclassrec)
176 DtButtonGadgetClassRec dtButtonGadgetClassRec=
179 (WidgetClass) &xmGadgetClassRec, /* superclass */
180 "DtButton", /* class_name */
181 sizeof(DtButtonGadgetRec), /* widget_size */
182 NULL, /* class_initialize */
183 NULL, /* class_part_initialize */
184 FALSE, /* class_inited */
185 (XtInitProc) Initialize, /* initialize */
186 NULL, /* initialize_hook */
190 resources, /* resources */
191 XtNumber(resources), /* num_resources */
192 NULLQUARK, /* xrm_class */
193 TRUE, /* compress_motion */
194 XtExposeCompressMaximal, /* compress_exposure */
195 TRUE, /* compress_enterleave */
196 FALSE, /* visible_interest */
199 (XtExposeProc) Redisplay, /* expose */
200 (XtSetValuesFunc) SetValues, /* set_values */
201 NULL, /* set_values_hook */
202 XtInheritSetValuesAlmost, /* set_values_almost */
203 NULL, /* get_values_hook */
204 NULL, /* accept_focus */
205 XtVersion, /* version */
206 NULL, /* callback private */
208 NULL, /* query_geometry */
209 NULL, /* display_accelerator */
210 NULL, /* extension */
215 (XtWidgetProc) _XtInherit, /* Gadget border_highlight */
216 (XtWidgetProc) _XtInherit, /* Gadget border_unhighlight */
217 ArmAndActivate, /* arm_and_activate */
218 (XmWidgetDispatchProc)InputDispatch, /* input_dispatch */
219 VisualChange, /* visual_change */
220 NULL, /* get resources */
221 0, /* num get_resources */
222 NULL, /* class_cache_part */
223 NULL, /* extension */
228 externaldef(dtbuttonwidgetclass) WidgetClass dtButtonGadgetClass =
229 (WidgetClass) &dtButtonGadgetClassRec;
232 /************************************************************************
235 * The main widget instance initialization routine.
237 ************************************************************************/
244 DtButtonGadget request = (DtButtonGadget) request_w ;
245 DtButtonGadget new_g = (DtButtonGadget) new_w ;
246 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w) ;
248 new_g->button.timer = 0;
249 new_g->button.click_count = 0;
250 new_g->button.armTimeStamp = 0;
251 new_g->button.activateTimeStamp = 0;
253 B_Armed (new_g) = False;
255 /* Set the input mask for events handled by Manager.
257 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
258 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
259 XmHELP_EVENT | XmFOCUS_IN_EVENT |
260 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
262 /* Get pixmap and mask, get pixmap geometry, get gcs.
264 if (B_ImageName (new_g) != NULL)
266 String str = B_ImageName (new_g);
267 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
268 strcpy (B_ImageName (new_g), str);
271 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
272 M_BottomShadowColor (mw),
273 M_TopShadowColor (mw));
275 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
277 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
280 int int_x = 0, int_y = 0;
281 unsigned int int_w = 0, int_h = 0,
284 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
285 &root, &int_x, &int_y, &int_w, &int_h,
288 B_PixmapWidth (new_g) = (Dimension) int_w;
289 B_PixmapHeight (new_g) = (Dimension) int_h;
293 B_PixmapWidth (new_g) = 0;
294 B_PixmapHeight (new_g) = 0;
299 B_Pixmap (new_g) = XmUNSPECIFIED_PIXMAP;
300 B_Mask (new_g) = XmUNSPECIFIED_PIXMAP;
301 B_PixmapWidth (new_g) = 0;
302 B_PixmapHeight (new_g) = 0;
307 /* Set widget geometry.
309 new_g -> gadget.shadow_thickness = 1;
310 new_g -> gadget.highlight_thickness = 1;
311 if (G_Width(request) == 0)
313 if (B_PixmapWidth (new_g) > 0)
314 G_Width(new_g) = B_PixmapWidth (new_g) + 4;
318 if (G_Height(request) == 0)
320 if (B_PixmapHeight (new_g) > 0)
321 G_Height(new_g) = B_PixmapHeight (new_g) + 4;
323 G_Height(new_g) = 10;
330 /************************************************************************
333 * Get the graphics context used for drawing the button.
335 ************************************************************************/
341 DtButtonGadget bg = (DtButtonGadget) w ;
342 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
346 valueMask = GCForeground | GCBackground;
348 values.foreground = M_Foreground(mw);
349 values.background = M_Background(mw);
350 bg -> button.gc_normal = XtGetGC ((Widget) mw, valueMask, &values);
352 values.foreground = B_ArmColor (bg);
353 bg -> button.gc_armed_bg = XtGetGC ((Widget) mw, valueMask, &values);
355 values.foreground = M_Background(mw);
356 values.background = M_Foreground(mw);
357 bg -> button.gc_background = XtGetGC ((Widget) mw, valueMask, &values);
361 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
363 valueMask = GCForeground | GCBackground | GCClipMask;
364 values.clip_mask = B_Mask(bg);
365 values.foreground = M_Foreground (mw);
366 values.background = M_Background (mw);
367 bg->button.gc_clip = XtGetGC ((Widget) mw, valueMask, &values);
370 bg->button.gc_clip = NULL;
378 DtButtonGadget bg = (DtButtonGadget) w ;
379 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
382 XtReleaseGC ((Widget) mw, bg->button.gc_normal);
383 XtReleaseGC ((Widget) mw, bg->button.gc_background);
384 XtReleaseGC ((Widget) mw, bg->button.gc_armed_bg);
386 if (bg->button.gc_clip != NULL)
387 XtReleaseGC ((Widget) mw, bg->button.gc_clip);
393 /************************************************************************
396 * General redisplay function called on exposure events.
398 ************************************************************************/
406 DtButtonGadget bg = (DtButtonGadget) w;
407 XmManagerWidget mw = (XmManagerWidget) XtParent(w);
408 Dimension s_t = bg -> gadget.shadow_thickness;
409 Dimension h_t = bg -> gadget.highlight_thickness;
414 gc = (B_Armed (bg)) ? bg -> button.gc_armed_bg : bg -> button.gc_background;
415 XFillRectangle (XtDisplay (bg), XtWindow (bg),
416 gc, G_X(bg) +s_t + h_t, G_Y(bg) + s_t + h_t,
417 G_Width(bg) - 2 * (s_t + h_t),
418 G_Height(bg) - 2 * (s_t + h_t));
425 gc1 = XmParentBottomShadowGC(w);
426 gc2 = XmParentTopShadowGC(w);
430 gc1 = bg -> button.gc_background;
431 gc2 = bg -> button.gc_background;
433 XmeDrawShadows (XtDisplay(bg), XtWindow (bg), gc1, gc2,
434 G_X(bg) + h_t, G_Y(bg) + h_t,
435 G_Width(bg) - 2 * h_t, G_Height(bg) - 2 * h_t,
439 x = G_X(bg) + ((Position)(G_Width(bg) - B_PixmapWidth (bg))/2);
443 if (B_Mask (bg) != XmUNSPECIFIED_PIXMAP)
445 gc = bg->button.gc_clip;
446 XSetClipMask (XtDisplay(bg), gc, B_Mask (bg));
447 XSetClipOrigin (XtDisplay(bg), gc,
448 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
451 gc = bg->button.gc_normal;
454 if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP))
456 XCopyArea (XtDisplay ((Widget) bg), pix, XtWindow ((Widget) bg), gc, 0, 0,
457 B_PixmapWidth (bg), B_PixmapHeight (bg),
458 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
461 if (bg -> gadget.highlighted)
462 (*(xmGadgetClassRec.gadget_class.border_highlight))((Widget) bg);
467 /************************************************************************
470 * Clean up allocated resources when the widget is destroyed.
472 ************************************************************************/
478 DtButtonGadget bg = (DtButtonGadget) w ;
480 if (bg->button.timer)
481 XtRemoveTimeOut (bg->button.timer);
483 XtReleaseGC (w, bg -> button.gc_normal);
484 XtReleaseGC (w, bg -> button.gc_background);
485 XtReleaseGC (w, bg -> button.gc_armed_bg);
486 if (bg -> button.gc_clip != NULL)
487 XtReleaseGC (w, bg -> button.gc_clip);
489 XtRemoveAllCallbacks (w, "callback");
495 /************************************************************************
498 * Note: The only implementation within this function is to
499 * support the resetting of the image, cursor, and functions
500 * as needed by the front panel.
502 ************************************************************************/
512 DtButtonGadget current = (DtButtonGadget) current_w;
513 DtButtonGadget request = (DtButtonGadget) request_w;
514 DtButtonGadget new_g = (DtButtonGadget) new_w;
515 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w);
516 Boolean returnFlag = FALSE;
519 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
520 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
521 XmHELP_EVENT | XmFOCUS_IN_EVENT |
522 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
524 /* Change the image */
526 if (strcmp (B_ImageName (current), B_ImageName (new_g)) != 0)
528 String str = B_ImageName (new_g);
530 XtFree (B_ImageName (current));
531 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
532 strcpy (B_ImageName (new_g), str);
535 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
536 M_BottomShadowColor (mw),
537 M_TopShadowColor (mw));
539 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
541 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
544 int int_x = 0, int_y = 0;
545 unsigned int int_w = 0, int_h = 0,
548 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
549 &root, &int_x, &int_y, &int_w, &int_h, &int_bw, &depth);
551 B_PixmapWidth (new_g) = (Dimension) int_w;
552 B_PixmapHeight (new_g) = (Dimension) int_h;
556 B_PixmapWidth (new_g) = 0;
557 B_PixmapHeight (new_g) = 0;
566 if (B_ImageName (new_g) != B_ImageName (current))
568 String str = B_ImageName (new_g);
570 XtFree (B_ImageName (current));
571 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
572 strcpy (B_ImageName (new_g), str);
582 /************************************************************************
585 * This function processes button 1 down occuring on the button.
587 ************************************************************************/
594 Cardinal *num_params )
596 DtButtonGadget bg = (DtButtonGadget) w ;
598 (void) XmProcessTraversal((Widget) bg, XmTRAVERSE_CURRENT);
602 if ((event->xbutton.time - bg->button.armTimeStamp) >
603 XtGetMultiClickTime(XtDisplay(bg)))
605 bg -> button.armTimeStamp = event->xbutton.time;
606 B_Expose ( w, event, NULL);
611 /************************************************************************
614 * This function processes button 1 up occuring on the button.
616 ************************************************************************/
623 Cardinal *num_params )
625 DtButtonGadget bg = (DtButtonGadget) w ;
627 B_Armed (bg) = False;
629 B_Expose (w, event, NULL);
633 /************************************************************************
636 * This function processes button 1 up occuring on the button.
637 * If the button 1 up occurred inside the button the activate
638 * callbacks are called.
640 ************************************************************************/
647 Cardinal *num_params )
649 DtButtonGadget bg = (DtButtonGadget) w ;
650 DtButtonCallbackStruct call_value;
651 Dimension bw = G_BorderWidth(bg);
656 if ((event->xbutton.time - bg->button.activateTimeStamp) >
657 XtGetMultiClickTime(XtDisplay(bg)))
659 bg -> button.activateTimeStamp = event->xbutton.time;
660 bg->button.click_count = 1;
663 bg->button.click_count++;
665 B_Armed (bg) = False;
667 if (bg->button.callback)
669 call_value.reason = XmCR_ACTIVATE;
670 call_value.event = event;
671 call_value.click_count = bg->button.click_count;
673 if ((bg->button.multiClick == XmMULTICLICK_DISCARD) &&
674 (call_value.click_count > 1)) {
678 XFlush(XtDisplay(bg));
680 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
685 /************************************************************************
689 ************************************************************************/
696 Cardinal *num_params )
698 DtButtonCallbackStruct call_value;
699 DtButtonGadget bg = (DtButtonGadget) w ;
702 Redisplay ( w, event, FALSE);
704 XFlush (XtDisplay (bg));
706 call_value.reason = XmCR_ACTIVATE;
707 call_value.event = event;
708 call_value.click_count = 1; /* always 1 in kselect */
710 if (bg->button.callback)
712 XFlush (XtDisplay (bg));
713 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
715 B_Armed (bg) = False;
717 /* If the button is still around, show it released, after a short delay */
719 if (bg->object.being_destroyed == False)
721 bg->button.timer = XtAppAddTimeOut(
722 XtWidgetToApplicationContext((Widget)bg),
723 (unsigned long) DELAY_DEFAULT,
724 (XtTimerCallbackProc)ArmTimeout,
735 DtButtonGadget bg = (DtButtonGadget) w ;
737 bg -> button.timer = 0;
738 if (XtIsRealized ((Widget)bg) && XtIsManaged ((Widget)bg)) {
739 Redisplay ( w, NULL, FALSE);
740 XFlush (XtDisplay (bg));
746 /*-------------------------------------------------------------
748 ** Process event dispatched from parent or event handler.
756 DtButtonGadget bg = (DtButtonGadget) w ;
758 if (event_mask & XmARM_EVENT ||
759 event_mask & XmMULTI_ARM_EVENT)
761 if (event->button == Button1)
762 Arm (w, (XEvent*) event, (String *)NULL, (Cardinal)0);
764 else if (event_mask & XmACTIVATE_EVENT ||
765 event_mask & XmMULTI_ACTIVATE_EVENT)
767 if (event->button == Button1)
769 if (event->x >= G_X (bg) &&
770 event->x <= (Position)(G_X (bg) + G_Width (bg)) &&
771 event->y >= G_Y (bg) &&
772 event->y <= (Position)(G_Y (bg) + G_Height (bg)))
774 Activate (w, (XEvent*) event,
775 (String *)NULL, (Cardinal)0);
776 Disarm (w, (XEvent*) event,
777 (String *)NULL, (Cardinal)0);
780 Disarm (w, (XEvent*) event,
781 (String *)NULL, (Cardinal)0);
784 else if (event_mask & XmHELP_EVENT)
785 _XmSocorro (w, (XEvent *)event,
786 (String *)NULL,(Cardinal)0);
787 else if (event_mask & XmENTER_EVENT)
788 Enter (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
789 else if (event_mask & XmLEAVE_EVENT)
790 Leave (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
791 else if (event_mask & XmFOCUS_IN_EVENT)
792 _XmFocusInGadget (w, (XEvent *)event,
793 (String *)NULL,(Cardinal)0);
794 else if (event_mask & XmFOCUS_OUT_EVENT)
795 _XmFocusOutGadget (w, (XEvent *)event,
796 (String *)NULL,(Cardinal)0);
800 /*-------------------------------------------------------------
802 ** Update GCs when parent visuals change.
810 XmManagerWidget current = (XmManagerWidget) current_w;
811 XmManagerWidget new_m = (XmManagerWidget) new_w;
812 DtButtonGadget bg = (DtButtonGadget) w ;
813 Boolean update = False;
815 /* If the parent foreground or background has changed,
816 * then update gcs and pixmap.
818 if (M_Foreground (current) != M_Foreground (new_m) ||
819 M_Background (current) != M_Background (new_m))
827 if (B_ImageName (bg) != NULL)
829 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
830 XmDestroyPixmap (XtScreen(bg), B_Mask(bg));
832 if (B_Pixmap(bg) != XmUNSPECIFIED_PIXMAP)
833 XmDestroyPixmap (XtScreen(w), B_Pixmap (bg));
835 B_Pixmap (bg) = XmGetPixmap (XtScreen (bg), B_ImageName (bg),
836 M_TopShadowColor (new_m),
837 M_BottomShadowColor (new_m));
839 if (B_Pixmap (bg) != XmUNSPECIFIED_PIXMAP)
840 B_Mask(bg) = (Pixmap)_DtGetMask(XtScreen(bg), B_ImageName(bg));
849 /************************************************************************
853 ************************************************************************/
860 Cardinal *num_params )
862 DtButtonGadget bg = (DtButtonGadget) wid ;
864 _XmEnterGadget (wid, (XEvent *)event, (String *)NULL,(Cardinal *)0);
867 B_Expose (wid, event, NULL);
873 /************************************************************************
877 ************************************************************************/
884 Cardinal *num_params )
886 DtButtonGadget bg = (DtButtonGadget) wid ;
888 _XmLeaveGadget (wid, (XEvent *)event, (String *)NULL, (Cardinal *)0);
892 B_Armed (bg) = False;
893 B_Expose (wid, event, NULL);
899 /*-------------------------------------------------------------
901 ** Call callback, if any, with reason and event.
910 DtControlCallbackStruct cb_data;
914 cb_data.reason = reason;
915 cb_data.event = event;
916 cb_data.control_type = XmCONTROL_BUTTON;
918 cb_data.subpanel = B_Subpanel (w);
919 cb_data.push_function = B_PushFunction (w);
920 cb_data.push_argument = B_PushArgument (w);
921 cb_data.file_size = 0;
922 XtCallCallbackList ((Widget) w, cb, &cb_data);
927 /*-------------------------------------------------------------
928 ** DefaultSelectColor
929 ** Resource proc. to determine the default select color.
930 ** (Formerly _XmSelectColorDefault).
938 XmeGetDefaultPixel (widget, XmSELECT, offset, value);
942 /************************************************************************
944 * DtCreateButtonGadget
945 * Create an instance of an button and return the widget id.
947 ************************************************************************/
950 DtCreateButtonGadget(
956 return (XtCreateWidget (name, dtButtonGadgetClass,
957 parent, arglist, argcount));