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 #include "DtSvcInternal.h" /* _DtGetMask */
47 #include <Xm/XmPrivate.h> /* _XmFocusInGadget, _XmFocusOutGadget, _XmSocorro */
49 #define DELAY_DEFAULT 100
51 static void Initialize(
56 static void UpdateGCs(
58 static void Redisplay(
62 static Boolean SetValues(
70 Cardinal *num_params) ;
75 Cardinal *num_params) ;
80 Cardinal *num_params) ;
81 static void ArmAndActivate(
85 Cardinal *num_params) ;
86 static void InputDispatch(
90 static Boolean VisualChange(
94 static void ArmTimeout(
101 Cardinal *num_params) ;
106 Cardinal *num_params) ;
107 static void CallCallback(
112 static void DefaultSelectColor(
117 /* Resource list for button */
119 #define R_Offset(field) \
120 XtOffset (DtButtonGadget, button.field)
121 static XtResource resources[] =
125 XmCCursorFont, XmRInt, sizeof (int),
126 R_Offset (cursor_font),
127 XmRImmediate, (XtPointer) 1
131 XmCArmColor, XmRPixel, sizeof (Pixel),
132 R_Offset (arm_color),
133 XmRCallProc, (XtPointer) DefaultSelectColor
137 XmCSubpanel, XmRWidget, sizeof (Widget),
139 XmRImmediate, (XtPointer) NULL
143 XmCPushFunction, XmRFunction, sizeof (XtPointer),
144 R_Offset (push_function),
145 XmRImmediate, (XtPointer) NULL
149 XmCPushArgument, XmRPointer, sizeof (XtPointer),
150 R_Offset (push_argument),
151 XmRImmediate, (XtPointer) NULL
155 XmCString, XmRString, sizeof (String),
156 R_Offset (image_name),
157 XmRImmediate, (XtPointer) ""
162 XmCCallback, XmRCallback, sizeof(XtCallbackList),
164 XmRImmediate, (caddr_t) NULL
169 XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
170 R_Offset (multiClick),
171 XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
176 /* The button class record definition */
178 externaldef (dtbuttongadgetclassrec)
179 DtButtonGadgetClassRec dtButtonGadgetClassRec=
182 (WidgetClass) &xmGadgetClassRec, /* superclass */
183 "DtButton", /* class_name */
184 sizeof(DtButtonGadgetRec), /* widget_size */
185 NULL, /* class_initialize */
186 NULL, /* class_part_initialize */
187 FALSE, /* class_inited */
188 (XtInitProc) Initialize, /* initialize */
189 NULL, /* initialize_hook */
193 resources, /* resources */
194 XtNumber(resources), /* num_resources */
195 NULLQUARK, /* xrm_class */
196 TRUE, /* compress_motion */
197 XtExposeCompressMaximal, /* compress_exposure */
198 TRUE, /* compress_enterleave */
199 FALSE, /* visible_interest */
202 (XtExposeProc) Redisplay, /* expose */
203 (XtSetValuesFunc) SetValues, /* set_values */
204 NULL, /* set_values_hook */
205 XtInheritSetValuesAlmost, /* set_values_almost */
206 NULL, /* get_values_hook */
207 NULL, /* accept_focus */
208 XtVersion, /* version */
209 NULL, /* callback private */
211 NULL, /* query_geometry */
212 NULL, /* display_accelerator */
213 NULL, /* extension */
218 (XtWidgetProc) _XtInherit, /* Gadget border_highlight */
219 (XtWidgetProc) _XtInherit, /* Gadget border_unhighlight */
220 ArmAndActivate, /* arm_and_activate */
221 (XmWidgetDispatchProc)InputDispatch, /* input_dispatch */
222 VisualChange, /* visual_change */
223 NULL, /* get resources */
224 0, /* num get_resources */
225 NULL, /* class_cache_part */
226 NULL, /* extension */
231 externaldef(dtbuttonwidgetclass) WidgetClass dtButtonGadgetClass =
232 (WidgetClass) &dtButtonGadgetClassRec;
235 /************************************************************************
238 * The main widget instance initialization routine.
240 ************************************************************************/
247 DtButtonGadget request = (DtButtonGadget) request_w ;
248 DtButtonGadget new_g = (DtButtonGadget) new_w ;
249 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w) ;
251 new_g->button.timer = 0;
252 new_g->button.click_count = 0;
253 new_g->button.armTimeStamp = 0;
254 new_g->button.activateTimeStamp = 0;
256 B_Armed (new_g) = False;
258 /* Set the input mask for events handled by Manager.
260 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
261 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
262 XmHELP_EVENT | XmFOCUS_IN_EVENT |
263 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
265 /* Get pixmap and mask, get pixmap geometry, get gcs.
267 if (B_ImageName (new_g) != NULL)
269 String str = B_ImageName (new_g);
270 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
271 strcpy (B_ImageName (new_g), str);
274 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
275 M_BottomShadowColor (mw),
276 M_TopShadowColor (mw));
278 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
280 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
283 int int_x = 0, int_y = 0;
284 unsigned int int_w = 0, int_h = 0,
287 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
288 &root, &int_x, &int_y, &int_w, &int_h,
291 B_PixmapWidth (new_g) = (Dimension) int_w;
292 B_PixmapHeight (new_g) = (Dimension) int_h;
296 B_PixmapWidth (new_g) = 0;
297 B_PixmapHeight (new_g) = 0;
302 B_Pixmap (new_g) = XmUNSPECIFIED_PIXMAP;
303 B_Mask (new_g) = XmUNSPECIFIED_PIXMAP;
304 B_PixmapWidth (new_g) = 0;
305 B_PixmapHeight (new_g) = 0;
310 /* Set widget geometry.
312 new_g -> gadget.shadow_thickness = 1;
313 new_g -> gadget.highlight_thickness = 1;
314 if (G_Width(request) == 0)
316 if (B_PixmapWidth (new_g) > 0)
317 G_Width(new_g) = B_PixmapWidth (new_g) + 4;
321 if (G_Height(request) == 0)
323 if (B_PixmapHeight (new_g) > 0)
324 G_Height(new_g) = B_PixmapHeight (new_g) + 4;
326 G_Height(new_g) = 10;
333 /************************************************************************
336 * Get the graphics context used for drawing the button.
338 ************************************************************************/
344 DtButtonGadget bg = (DtButtonGadget) w ;
345 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
349 valueMask = GCForeground | GCBackground;
351 values.foreground = M_Foreground(mw);
352 values.background = M_Background(mw);
353 bg -> button.gc_normal = XtGetGC ((Widget) mw, valueMask, &values);
355 values.foreground = B_ArmColor (bg);
356 bg -> button.gc_armed_bg = XtGetGC ((Widget) mw, valueMask, &values);
358 values.foreground = M_Background(mw);
359 values.background = M_Foreground(mw);
360 bg -> button.gc_background = XtGetGC ((Widget) mw, valueMask, &values);
364 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
366 valueMask = GCForeground | GCBackground | GCClipMask;
367 values.clip_mask = B_Mask(bg);
368 values.foreground = M_Foreground (mw);
369 values.background = M_Background (mw);
370 bg->button.gc_clip = XtGetGC ((Widget) mw, valueMask, &values);
373 bg->button.gc_clip = NULL;
381 DtButtonGadget bg = (DtButtonGadget) w ;
382 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
384 XtReleaseGC ((Widget) mw, bg->button.gc_normal);
385 XtReleaseGC ((Widget) mw, bg->button.gc_background);
386 XtReleaseGC ((Widget) mw, bg->button.gc_armed_bg);
388 if (bg->button.gc_clip != NULL)
389 XtReleaseGC ((Widget) mw, bg->button.gc_clip);
395 /************************************************************************
398 * General redisplay function called on exposure events.
400 ************************************************************************/
408 DtButtonGadget bg = (DtButtonGadget) w;
409 Dimension s_t = bg -> gadget.shadow_thickness;
410 Dimension h_t = bg -> gadget.highlight_thickness;
415 gc = (B_Armed (bg)) ? bg -> button.gc_armed_bg : bg -> button.gc_background;
416 XFillRectangle (XtDisplay (bg), XtWindow (bg),
417 gc, G_X(bg) +s_t + h_t, G_Y(bg) + s_t + h_t,
418 G_Width(bg) - 2 * (s_t + h_t),
419 G_Height(bg) - 2 * (s_t + h_t));
426 gc1 = XmParentBottomShadowGC(w);
427 gc2 = XmParentTopShadowGC(w);
431 gc1 = bg -> button.gc_background;
432 gc2 = bg -> button.gc_background;
434 XmeDrawShadows (XtDisplay(bg), XtWindow (bg), gc1, gc2,
435 G_X(bg) + h_t, G_Y(bg) + h_t,
436 G_Width(bg) - 2 * h_t, G_Height(bg) - 2 * h_t,
440 x = G_X(bg) + ((Position)(G_Width(bg) - B_PixmapWidth (bg))/2);
444 if (B_Mask (bg) != XmUNSPECIFIED_PIXMAP)
446 gc = bg->button.gc_clip;
447 XSetClipMask (XtDisplay(bg), gc, B_Mask (bg));
448 XSetClipOrigin (XtDisplay(bg), gc,
449 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
452 gc = bg->button.gc_normal;
455 if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP))
457 XCopyArea (XtDisplay ((Widget) bg), pix, XtWindow ((Widget) bg), gc, 0, 0,
458 B_PixmapWidth (bg), B_PixmapHeight (bg),
459 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
462 if (bg -> gadget.highlighted)
463 (*(xmGadgetClassRec.gadget_class.border_highlight))((Widget) bg);
468 /************************************************************************
471 * Clean up allocated resources when the widget is destroyed.
473 ************************************************************************/
479 DtButtonGadget bg = (DtButtonGadget) w ;
481 if (bg->button.timer)
482 XtRemoveTimeOut (bg->button.timer);
484 XtReleaseGC (w, bg -> button.gc_normal);
485 XtReleaseGC (w, bg -> button.gc_background);
486 XtReleaseGC (w, bg -> button.gc_armed_bg);
487 if (bg -> button.gc_clip != NULL)
488 XtReleaseGC (w, bg -> button.gc_clip);
490 XtRemoveAllCallbacks (w, "callback");
496 /************************************************************************
499 * Note: The only implementation within this function is to
500 * support the resetting of the image, cursor, and functions
501 * as needed by the front panel.
503 ************************************************************************/
513 DtButtonGadget current = (DtButtonGadget) current_w;
514 DtButtonGadget new_g = (DtButtonGadget) new_w;
515 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w);
516 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;
654 if ((event->xbutton.time - bg->button.activateTimeStamp) >
655 XtGetMultiClickTime(XtDisplay(bg)))
657 bg -> button.activateTimeStamp = event->xbutton.time;
658 bg->button.click_count = 1;
661 bg->button.click_count++;
663 B_Armed (bg) = False;
665 if (bg->button.callback)
667 call_value.reason = XmCR_ACTIVATE;
668 call_value.event = event;
669 call_value.click_count = bg->button.click_count;
671 if ((bg->button.multiClick == XmMULTICLICK_DISCARD) &&
672 (call_value.click_count > 1)) {
676 XFlush(XtDisplay(bg));
678 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
683 /************************************************************************
687 ************************************************************************/
694 Cardinal *num_params )
696 DtButtonCallbackStruct call_value;
697 DtButtonGadget bg = (DtButtonGadget) w ;
700 Redisplay ( w, event, FALSE);
702 XFlush (XtDisplay (bg));
704 call_value.reason = XmCR_ACTIVATE;
705 call_value.event = event;
706 call_value.click_count = 1; /* always 1 in kselect */
708 if (bg->button.callback)
710 XFlush (XtDisplay (bg));
711 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
713 B_Armed (bg) = False;
715 /* If the button is still around, show it released, after a short delay */
717 if (bg->object.being_destroyed == False)
719 bg->button.timer = XtAppAddTimeOut(
720 XtWidgetToApplicationContext((Widget)bg),
721 (unsigned long) DELAY_DEFAULT,
722 (XtTimerCallbackProc)ArmTimeout,
733 DtButtonGadget bg = (DtButtonGadget) w ;
735 bg -> button.timer = 0;
736 if (XtIsRealized ((Widget)bg) && XtIsManaged ((Widget)bg)) {
737 Redisplay ( w, NULL, FALSE);
738 XFlush (XtDisplay (bg));
744 /*-------------------------------------------------------------
746 ** Process event dispatched from parent or event handler.
754 DtButtonGadget bg = (DtButtonGadget) w ;
756 if (event_mask & XmARM_EVENT ||
757 event_mask & XmMULTI_ARM_EVENT)
759 if (event->button == Button1)
760 Arm (w, (XEvent*) event, (String *)NULL, (Cardinal)0);
762 else if (event_mask & XmACTIVATE_EVENT ||
763 event_mask & XmMULTI_ACTIVATE_EVENT)
765 if (event->button == Button1)
767 if (event->x >= G_X (bg) &&
768 event->x <= (Position)(G_X (bg) + G_Width (bg)) &&
769 event->y >= G_Y (bg) &&
770 event->y <= (Position)(G_Y (bg) + G_Height (bg)))
772 Activate (w, (XEvent*) event,
773 (String *)NULL, (Cardinal)0);
774 Disarm (w, (XEvent*) event,
775 (String *)NULL, (Cardinal)0);
778 Disarm (w, (XEvent*) event,
779 (String *)NULL, (Cardinal)0);
782 else if (event_mask & XmHELP_EVENT)
783 _XmSocorro (w, (XEvent *)event,
784 (String *)NULL,(Cardinal)0);
785 else if (event_mask & XmENTER_EVENT)
786 Enter (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
787 else if (event_mask & XmLEAVE_EVENT)
788 Leave (w, (XEvent *)event, (String *)NULL,(Cardinal)0);
789 else if (event_mask & XmFOCUS_IN_EVENT)
790 _XmFocusInGadget (w, (XEvent *)event,
791 (String *)NULL,(Cardinal)0);
792 else if (event_mask & XmFOCUS_OUT_EVENT)
793 _XmFocusOutGadget (w, (XEvent *)event,
794 (String *)NULL,(Cardinal)0);
798 /*-------------------------------------------------------------
800 ** Update GCs when parent visuals change.
808 XmManagerWidget current = (XmManagerWidget) current_w;
809 XmManagerWidget new_m = (XmManagerWidget) new_w;
810 DtButtonGadget bg = (DtButtonGadget) w ;
811 Boolean update = False;
813 /* If the parent foreground or background has changed,
814 * then update gcs and pixmap.
816 if (M_Foreground (current) != M_Foreground (new_m) ||
817 M_Background (current) != M_Background (new_m))
825 if (B_ImageName (bg) != NULL)
827 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
828 XmDestroyPixmap (XtScreen(bg), B_Mask(bg));
830 if (B_Pixmap(bg) != XmUNSPECIFIED_PIXMAP)
831 XmDestroyPixmap (XtScreen(w), B_Pixmap (bg));
833 B_Pixmap (bg) = XmGetPixmap (XtScreen (bg), B_ImageName (bg),
834 M_TopShadowColor (new_m),
835 M_BottomShadowColor (new_m));
837 if (B_Pixmap (bg) != XmUNSPECIFIED_PIXMAP)
838 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));