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>
41 #include <Dt/Control.h>
42 #include <Dt/MacrosP.h>
43 #include <Dt/DtStrDefs.h>
45 #define DELAY_DEFAULT 100
47 static void Initialize(
52 static void UpdateGCs(
54 static void Redisplay(
58 static Boolean SetValues(
66 Cardinal *num_params) ;
71 Cardinal *num_params) ;
76 Cardinal *num_params) ;
77 static void ArmAndActivate(
81 Cardinal *num_params) ;
82 static void InputDispatch(
86 static Boolean VisualChange(
90 static void ArmTimeout(
97 Cardinal *num_params) ;
102 Cardinal *num_params) ;
103 static void CallCallback(
108 static void DefaultSelectColor(
113 /* Resource list for button */
115 #define R_Offset(field) \
116 XtOffset (DtButtonGadget, button.field)
117 static XtResource resources[] =
121 XmCCursorFont, XmRInt, sizeof (int),
122 R_Offset (cursor_font),
123 XmRImmediate, (XtPointer) 1
127 XmCArmColor, XmRPixel, sizeof (Pixel),
128 R_Offset (arm_color),
129 XmRCallProc, (XtPointer) DefaultSelectColor
133 XmCSubpanel, XmRWidget, sizeof (Widget),
135 XmRImmediate, (XtPointer) NULL
139 XmCPushFunction, XmRFunction, sizeof (XtPointer),
140 R_Offset (push_function),
141 XmRImmediate, (XtPointer) NULL
145 XmCPushArgument, XmRPointer, sizeof (XtPointer),
146 R_Offset (push_argument),
147 XmRImmediate, (XtPointer) NULL
151 XmCString, XmRString, sizeof (String),
152 R_Offset (image_name),
153 XmRImmediate, (XtPointer) ""
158 XmCCallback, XmRCallback, sizeof(XtCallbackList),
160 XmRImmediate, (caddr_t) NULL
165 XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
166 R_Offset (multiClick),
167 XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
172 /* The button class record definition */
174 externaldef (dtbuttongadgetclassrec)
175 DtButtonGadgetClassRec dtButtonGadgetClassRec=
178 (WidgetClass) &xmGadgetClassRec, /* superclass */
179 "DtButton", /* class_name */
180 sizeof(DtButtonGadgetRec), /* widget_size */
181 NULL, /* class_initialize */
182 NULL, /* class_part_initialize */
183 FALSE, /* class_inited */
184 (XtInitProc) Initialize, /* initialize */
185 NULL, /* initialize_hook */
189 resources, /* resources */
190 XtNumber(resources), /* num_resources */
191 NULLQUARK, /* xrm_class */
192 TRUE, /* compress_motion */
193 XtExposeCompressMaximal, /* compress_exposure */
194 TRUE, /* compress_enterleave */
195 FALSE, /* visible_interest */
198 (XtExposeProc) Redisplay, /* expose */
199 (XtSetValuesFunc) SetValues, /* set_values */
200 NULL, /* set_values_hook */
201 XtInheritSetValuesAlmost, /* set_values_almost */
202 NULL, /* get_values_hook */
203 NULL, /* accept_focus */
204 XtVersion, /* version */
205 NULL, /* callback private */
207 NULL, /* query_geometry */
208 NULL, /* display_accelerator */
209 NULL, /* extension */
214 (XtWidgetProc) _XtInherit, /* Gadget border_highlight */
215 (XtWidgetProc) _XtInherit, /* Gadget border_unhighlight */
216 ArmAndActivate, /* arm_and_activate */
217 (XmWidgetDispatchProc)InputDispatch, /* input_dispatch */
218 VisualChange, /* visual_change */
219 NULL, /* get resources */
220 0, /* num get_resources */
221 NULL, /* class_cache_part */
222 NULL, /* extension */
227 externaldef(dtbuttonwidgetclass) WidgetClass dtButtonGadgetClass =
228 (WidgetClass) &dtButtonGadgetClassRec;
231 /************************************************************************
234 * The main widget instance initialization routine.
236 ************************************************************************/
243 DtButtonGadget request = (DtButtonGadget) request_w ;
244 DtButtonGadget new_g = (DtButtonGadget) new_w ;
245 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w) ;
247 new_g->button.timer = 0;
248 new_g->button.click_count = 0;
249 new_g->button.armTimeStamp = 0;
250 new_g->button.activateTimeStamp = 0;
252 B_Armed (new_g) = False;
254 /* Set the input mask for events handled by Manager.
256 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
257 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
258 XmHELP_EVENT | XmFOCUS_IN_EVENT |
259 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
261 /* Get pixmap and mask, get pixmap geometry, get gcs.
263 if (B_ImageName (new_g) != NULL)
265 String str = B_ImageName (new_g);
266 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
267 strcpy (B_ImageName (new_g), str);
270 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
271 M_BottomShadowColor (mw),
272 M_TopShadowColor (mw));
274 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
276 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
279 int int_x = 0, int_y = 0;
280 unsigned int int_w = 0, int_h = 0,
283 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
284 &root, &int_x, &int_y, &int_w, &int_h,
287 B_PixmapWidth (new_g) = (Dimension) int_w;
288 B_PixmapHeight (new_g) = (Dimension) int_h;
292 B_PixmapWidth (new_g) = 0;
293 B_PixmapHeight (new_g) = 0;
298 B_Pixmap (new_g) = XmUNSPECIFIED_PIXMAP;
299 B_Mask (new_g) = XmUNSPECIFIED_PIXMAP;
300 B_PixmapWidth (new_g) = 0;
301 B_PixmapHeight (new_g) = 0;
306 /* Set widget geometry.
308 new_g -> gadget.shadow_thickness = 1;
309 new_g -> gadget.highlight_thickness = 1;
310 if (G_Width(request) == 0)
312 if (B_PixmapWidth (new_g) > 0)
313 G_Width(new_g) = B_PixmapWidth (new_g) + 4;
317 if (G_Height(request) == 0)
319 if (B_PixmapHeight (new_g) > 0)
320 G_Height(new_g) = B_PixmapHeight (new_g) + 4;
322 G_Height(new_g) = 10;
329 /************************************************************************
332 * Get the graphics context used for drawing the button.
334 ************************************************************************/
340 DtButtonGadget bg = (DtButtonGadget) w ;
341 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
345 valueMask = GCForeground | GCBackground;
347 values.foreground = M_Foreground(mw);
348 values.background = M_Background(mw);
349 bg -> button.gc_normal = XtGetGC ((Widget) mw, valueMask, &values);
351 values.foreground = B_ArmColor (bg);
352 bg -> button.gc_armed_bg = XtGetGC ((Widget) mw, valueMask, &values);
354 values.foreground = M_Background(mw);
355 values.background = M_Foreground(mw);
356 bg -> button.gc_background = XtGetGC ((Widget) mw, valueMask, &values);
360 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
362 valueMask = GCForeground | GCBackground | GCClipMask;
363 values.clip_mask = B_Mask(bg);
364 values.foreground = M_Foreground (mw);
365 values.background = M_Background (mw);
366 bg->button.gc_clip = XtGetGC ((Widget) mw, valueMask, &values);
369 bg->button.gc_clip = NULL;
377 DtButtonGadget bg = (DtButtonGadget) w ;
378 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
381 XtReleaseGC ((Widget) mw, bg->button.gc_normal);
382 XtReleaseGC ((Widget) mw, bg->button.gc_background);
383 XtReleaseGC ((Widget) mw, bg->button.gc_armed_bg);
385 if (bg->button.gc_clip != NULL)
386 XtReleaseGC ((Widget) mw, bg->button.gc_clip);
392 /************************************************************************
395 * General redisplay function called on exposure events.
397 ************************************************************************/
405 DtButtonGadget bg = (DtButtonGadget) w;
406 XmManagerWidget mw = (XmManagerWidget) XtParent(w);
407 Dimension s_t = bg -> gadget.shadow_thickness;
408 Dimension h_t = bg -> gadget.highlight_thickness;
413 gc = (B_Armed (bg)) ? bg -> button.gc_armed_bg : bg -> button.gc_background;
414 XFillRectangle (XtDisplay (bg), XtWindow (bg),
415 gc, G_X(bg) +s_t + h_t, G_Y(bg) + s_t + h_t,
416 G_Width(bg) - 2 * (s_t + h_t),
417 G_Height(bg) - 2 * (s_t + h_t));
424 gc1 = XmParentBottomShadowGC(w);
425 gc2 = XmParentTopShadowGC(w);
429 gc1 = bg -> button.gc_background;
430 gc2 = bg -> button.gc_background;
432 XmeDrawShadows (XtDisplay(bg), XtWindow (bg), gc1, gc2,
433 G_X(bg) + h_t, G_Y(bg) + h_t,
434 G_Width(bg) - 2 * h_t, G_Height(bg) - 2 * h_t,
438 x = G_X(bg) + ((Position)(G_Width(bg) - B_PixmapWidth (bg))/2);
442 if (B_Mask (bg) != XmUNSPECIFIED_PIXMAP)
444 gc = bg->button.gc_clip;
445 XSetClipMask (XtDisplay(bg), gc, B_Mask (bg));
446 XSetClipOrigin (XtDisplay(bg), gc,
447 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
450 gc = bg->button.gc_normal;
453 if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP))
455 XCopyArea (XtDisplay ((Widget) bg), pix, XtWindow ((Widget) bg), gc, 0, 0,
456 B_PixmapWidth (bg), B_PixmapHeight (bg),
457 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
460 if (bg -> gadget.highlighted)
461 (*(xmGadgetClassRec.gadget_class.border_highlight))((Widget) bg);
466 /************************************************************************
469 * Clean up allocated resources when the widget is destroyed.
471 ************************************************************************/
477 DtButtonGadget bg = (DtButtonGadget) w ;
479 if (bg->button.timer)
480 XtRemoveTimeOut (bg->button.timer);
482 XtReleaseGC (w, bg -> button.gc_normal);
483 XtReleaseGC (w, bg -> button.gc_background);
484 XtReleaseGC (w, bg -> button.gc_armed_bg);
485 if (bg -> button.gc_clip != NULL)
486 XtReleaseGC (w, bg -> button.gc_clip);
488 XtRemoveAllCallbacks (w, "callback");
494 /************************************************************************
497 * Note: The only implementation within this function is to
498 * support the resetting of the image, cursor, and functions
499 * as needed by the front panel.
501 ************************************************************************/
511 DtButtonGadget current = (DtButtonGadget) current_w;
512 DtButtonGadget request = (DtButtonGadget) request_w;
513 DtButtonGadget new_g = (DtButtonGadget) new_w;
514 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w);
515 Boolean returnFlag = FALSE;
518 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
519 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
520 XmHELP_EVENT | XmFOCUS_IN_EVENT |
521 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
523 /* Change the image */
525 if (strcmp (B_ImageName (current), B_ImageName (new_g)) != 0)
527 String str = B_ImageName (new_g);
529 XtFree (B_ImageName (current));
530 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
531 strcpy (B_ImageName (new_g), str);
534 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
535 M_BottomShadowColor (mw),
536 M_TopShadowColor (mw));
538 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
540 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
543 int int_x = 0, int_y = 0;
544 unsigned int int_w = 0, int_h = 0,
547 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
548 &root, &int_x, &int_y, &int_w, &int_h, &int_bw, &depth);
550 B_PixmapWidth (new_g) = (Dimension) int_w;
551 B_PixmapHeight (new_g) = (Dimension) int_h;
555 B_PixmapWidth (new_g) = 0;
556 B_PixmapHeight (new_g) = 0;
565 if (B_ImageName (new_g) != B_ImageName (current))
567 String str = B_ImageName (new_g);
569 XtFree (B_ImageName (current));
570 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
571 strcpy (B_ImageName (new_g), str);
581 /************************************************************************
584 * This function processes button 1 down occuring on the button.
586 ************************************************************************/
593 Cardinal *num_params )
595 DtButtonGadget bg = (DtButtonGadget) w ;
597 (void) XmProcessTraversal((Widget) bg, XmTRAVERSE_CURRENT);
601 if ((event->xbutton.time - bg->button.armTimeStamp) >
602 XtGetMultiClickTime(XtDisplay(bg)))
604 bg -> button.armTimeStamp = event->xbutton.time;
605 B_Expose ( w, event, NULL);
610 /************************************************************************
613 * This function processes button 1 up occuring on the button.
615 ************************************************************************/
622 Cardinal *num_params )
624 DtButtonGadget bg = (DtButtonGadget) w ;
626 B_Armed (bg) = False;
628 B_Expose (w, event, NULL);
632 /************************************************************************
635 * This function processes button 1 up occuring on the button.
636 * If the button 1 up occurred inside the button the activate
637 * callbacks are called.
639 ************************************************************************/
646 Cardinal *num_params )
648 DtButtonGadget bg = (DtButtonGadget) w ;
649 DtButtonCallbackStruct call_value;
650 Dimension bw = G_BorderWidth(bg);
655 if ((event->xbutton.time - bg->button.activateTimeStamp) >
656 XtGetMultiClickTime(XtDisplay(bg)))
658 bg -> button.activateTimeStamp = event->xbutton.time;
659 bg->button.click_count = 1;
662 bg->button.click_count++;
664 B_Armed (bg) = False;
666 if (bg->button.callback)
668 call_value.reason = XmCR_ACTIVATE;
669 call_value.event = event;
670 call_value.click_count = bg->button.click_count;
672 if ((bg->button.multiClick == XmMULTICLICK_DISCARD) &&
673 (call_value.click_count > 1)) {
677 XFlush(XtDisplay(bg));
679 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
684 /************************************************************************
688 ************************************************************************/
695 Cardinal *num_params )
697 DtButtonCallbackStruct call_value;
698 DtButtonGadget bg = (DtButtonGadget) w ;
701 Redisplay ( w, event, FALSE);
703 XFlush (XtDisplay (bg));
705 call_value.reason = XmCR_ACTIVATE;
706 call_value.event = event;
707 call_value.click_count = 1; /* always 1 in kselect */
709 if (bg->button.callback)
711 XFlush (XtDisplay (bg));
712 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
714 B_Armed (bg) = False;
716 /* If the button is still around, show it released, after a short delay */
718 if (bg->object.being_destroyed == False)
720 bg->button.timer = XtAppAddTimeOut(
721 XtWidgetToApplicationContext((Widget)bg),
722 (unsigned long) DELAY_DEFAULT,
723 (XtTimerCallbackProc)ArmTimeout,
734 DtButtonGadget bg = (DtButtonGadget) w ;
736 bg -> button.timer = 0;
737 if (XtIsRealized ((Widget)bg) && XtIsManaged ((Widget)bg)) {
738 Redisplay ( w, NULL, FALSE);
739 XFlush (XtDisplay (bg));
745 /*-------------------------------------------------------------
747 ** Process event dispatched from parent or event handler.
755 DtButtonGadget bg = (DtButtonGadget) w ;
757 if (event_mask & XmARM_EVENT ||
758 event_mask & XmMULTI_ARM_EVENT)
760 if (event->button == Button1)
761 Arm (w, (XEvent*) event, (String *)NULL, (Cardinal)0);
763 else if (event_mask & XmACTIVATE_EVENT ||
764 event_mask & XmMULTI_ACTIVATE_EVENT)
766 if (event->button == Button1)
768 if (event->x >= G_X (bg) &&
769 event->x <= (Position)(G_X (bg) + G_Width (bg)) &&
770 event->y >= G_Y (bg) &&
771 event->y <= (Position)(G_Y (bg) + G_Height (bg)))
773 Activate (w, (XEvent*) event,
774 (String *)NULL, (Cardinal)0);
775 Disarm (w, (XEvent*) event,
776 (String *)NULL, (Cardinal)0);
779 Disarm (w, (XEvent*) event,
780 (String *)NULL, (Cardinal)0);
783 else if (event_mask & XmHELP_EVENT)
784 _XmSocorro (w, (XEvent *)event,
785 (String *)NULL,(Cardinal)0);
786 else if (event_mask & XmENTER_EVENT)
787 Enter (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
788 else if (event_mask & XmLEAVE_EVENT)
789 Leave (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
790 else if (event_mask & XmFOCUS_IN_EVENT)
791 _XmFocusInGadget (w, (XEvent *)event,
792 (String *)NULL,(Cardinal)0);
793 else if (event_mask & XmFOCUS_OUT_EVENT)
794 _XmFocusOutGadget (w, (XEvent *)event,
795 (String *)NULL,(Cardinal)0);
799 /*-------------------------------------------------------------
801 ** Update GCs when parent visuals change.
809 XmManagerWidget current = (XmManagerWidget) current_w;
810 XmManagerWidget new_m = (XmManagerWidget) new_w;
811 DtButtonGadget bg = (DtButtonGadget) w ;
812 Boolean update = False;
814 /* If the parent foreground or background has changed,
815 * then update gcs and pixmap.
817 if (M_Foreground (current) != M_Foreground (new_m) ||
818 M_Background (current) != M_Background (new_m))
826 if (B_ImageName (bg) != NULL)
828 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
829 XmDestroyPixmap (XtScreen(bg), B_Mask(bg));
831 if (B_Pixmap(bg) != XmUNSPECIFIED_PIXMAP)
832 XmDestroyPixmap (XtScreen(w), B_Pixmap (bg));
834 B_Pixmap (bg) = XmGetPixmap (XtScreen (bg), B_ImageName (bg),
835 M_TopShadowColor (new_m),
836 M_BottomShadowColor (new_m));
838 if (B_Pixmap (bg) != XmUNSPECIFIED_PIXMAP)
839 B_Mask(bg) = (Pixmap)_DtGetMask(XtScreen(bg), B_ImageName(bg));
848 /************************************************************************
852 ************************************************************************/
859 Cardinal *num_params )
861 DtButtonGadget bg = (DtButtonGadget) wid ;
863 _XmEnterGadget (wid, (XEvent *)event, (String *)NULL,(Cardinal *)0);
866 B_Expose (wid, event, NULL);
872 /************************************************************************
876 ************************************************************************/
883 Cardinal *num_params )
885 DtButtonGadget bg = (DtButtonGadget) wid ;
887 _XmLeaveGadget (wid, (XEvent *)event, (String *)NULL, (Cardinal *)0);
891 B_Armed (bg) = False;
892 B_Expose (wid, event, NULL);
898 /*-------------------------------------------------------------
900 ** Call callback, if any, with reason and event.
909 DtControlCallbackStruct cb_data;
913 cb_data.reason = reason;
914 cb_data.event = event;
915 cb_data.control_type = XmCONTROL_BUTTON;
917 cb_data.subpanel = B_Subpanel (w);
918 cb_data.push_function = B_PushFunction (w);
919 cb_data.push_argument = B_PushArgument (w);
920 cb_data.file_size = 0;
921 XtCallCallbackList ((Widget) w, cb, &cb_data);
926 /*-------------------------------------------------------------
927 ** DefaultSelectColor
928 ** Resource proc. to determine the default select color.
929 ** (Formerly _XmSelectColorDefault).
937 XmeGetDefaultPixel (widget, XmSELECT, offset, value);
941 /************************************************************************
943 * DtCreateButtonGadget
944 * Create an instance of an button and return the widget id.
946 ************************************************************************/
949 DtCreateButtonGadget(
955 return (XtCreateWidget (name, dtButtonGadgetClass,
956 parent, arglist, argcount));