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 libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /******************************************************************************
24 *******************************************************************************
26 * (c) Copyright 1992 HEWLETT-PACKARD COMPANY
29 *******************************************************************************
30 ******************************************************************************/
32 #include <X11/cursorfont.h>
34 #include <Xm/ManagerP.h>
36 #include <Dt/Control.h>
37 #include <Dt/MacrosP.h>
38 #include <Dt/DtStrDefs.h>
40 #include "DtSvcInternal.h" /* _DtGetMask */
41 #include <Xm/XmPrivate.h> /* _XmFocusInGadget, _XmFocusOutGadget, _XmSocorro */
43 #define DELAY_DEFAULT 100
45 static void Initialize(
50 static void UpdateGCs(
52 static void Redisplay(
56 static Boolean SetValues(
64 Cardinal *num_params) ;
69 Cardinal *num_params) ;
74 Cardinal *num_params) ;
75 static void ArmAndActivate(
79 Cardinal *num_params) ;
80 static void InputDispatch(
84 static Boolean VisualChange(
88 static void ArmTimeout(
95 Cardinal *num_params) ;
100 Cardinal *num_params) ;
101 static void CallCallback(
106 static void DefaultSelectColor(
111 /* Resource list for button */
113 #define R_Offset(field) \
114 XtOffset (DtButtonGadget, button.field)
115 static XtResource resources[] =
119 XmCCursorFont, XmRInt, sizeof (int),
120 R_Offset (cursor_font),
121 XmRImmediate, (XtPointer) 1
125 XmCArmColor, XmRPixel, sizeof (Pixel),
126 R_Offset (arm_color),
127 XmRCallProc, (XtPointer) DefaultSelectColor
131 XmCSubpanel, XmRWidget, sizeof (Widget),
133 XmRImmediate, (XtPointer) NULL
137 XmCPushFunction, XmRFunction, sizeof (XtPointer),
138 R_Offset (push_function),
139 XmRImmediate, (XtPointer) NULL
143 XmCPushArgument, XmRPointer, sizeof (XtPointer),
144 R_Offset (push_argument),
145 XmRImmediate, (XtPointer) NULL
149 XmCString, XmRString, sizeof (String),
150 R_Offset (image_name),
151 XmRImmediate, (XtPointer) ""
156 XmCCallback, XmRCallback, sizeof(XtCallbackList),
158 XmRImmediate, (caddr_t) NULL
163 XmCMultiClick, XmRMultiClick, sizeof (unsigned char),
164 R_Offset (multiClick),
165 XmRImmediate, (XtPointer) XmMULTICLICK_KEEP
170 /* The button class record definition */
172 externaldef (dtbuttongadgetclassrec)
173 DtButtonGadgetClassRec dtButtonGadgetClassRec=
176 (WidgetClass) &xmGadgetClassRec, /* superclass */
177 "DtButton", /* class_name */
178 sizeof(DtButtonGadgetRec), /* widget_size */
179 NULL, /* class_initialize */
180 NULL, /* class_part_initialize */
181 FALSE, /* class_inited */
182 (XtInitProc) Initialize, /* initialize */
183 NULL, /* initialize_hook */
187 resources, /* resources */
188 XtNumber(resources), /* num_resources */
189 NULLQUARK, /* xrm_class */
190 TRUE, /* compress_motion */
191 XtExposeCompressMaximal, /* compress_exposure */
192 TRUE, /* compress_enterleave */
193 FALSE, /* visible_interest */
196 (XtExposeProc) Redisplay, /* expose */
197 (XtSetValuesFunc) SetValues, /* set_values */
198 NULL, /* set_values_hook */
199 XtInheritSetValuesAlmost, /* set_values_almost */
200 NULL, /* get_values_hook */
201 NULL, /* accept_focus */
202 XtVersion, /* version */
203 NULL, /* callback private */
205 NULL, /* query_geometry */
206 NULL, /* display_accelerator */
207 NULL, /* extension */
212 (XtWidgetProc) _XtInherit, /* Gadget border_highlight */
213 (XtWidgetProc) _XtInherit, /* Gadget border_unhighlight */
214 ArmAndActivate, /* arm_and_activate */
215 (XmWidgetDispatchProc)InputDispatch, /* input_dispatch */
216 VisualChange, /* visual_change */
217 NULL, /* get resources */
218 0, /* num get_resources */
219 NULL, /* class_cache_part */
220 NULL, /* extension */
225 externaldef(dtbuttonwidgetclass) WidgetClass dtButtonGadgetClass =
226 (WidgetClass) &dtButtonGadgetClassRec;
229 /************************************************************************
232 * The main widget instance initialization routine.
234 ************************************************************************/
241 DtButtonGadget request = (DtButtonGadget) request_w ;
242 DtButtonGadget new_g = (DtButtonGadget) new_w ;
243 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w) ;
245 new_g->button.timer = 0;
246 new_g->button.click_count = 0;
247 new_g->button.armTimeStamp = 0;
248 new_g->button.activateTimeStamp = 0;
250 B_Armed (new_g) = False;
252 /* Set the input mask for events handled by Manager.
254 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
255 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
256 XmHELP_EVENT | XmFOCUS_IN_EVENT |
257 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
259 /* Get pixmap and mask, get pixmap geometry, get gcs.
261 if (B_ImageName (new_g) != NULL)
263 String str = B_ImageName (new_g);
264 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
265 strcpy (B_ImageName (new_g), str);
268 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
269 M_BottomShadowColor (mw),
270 M_TopShadowColor (mw));
272 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
274 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
277 int int_x = 0, int_y = 0;
278 unsigned int int_w = 0, int_h = 0,
281 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
282 &root, &int_x, &int_y, &int_w, &int_h,
285 B_PixmapWidth (new_g) = (Dimension) int_w;
286 B_PixmapHeight (new_g) = (Dimension) int_h;
290 B_PixmapWidth (new_g) = 0;
291 B_PixmapHeight (new_g) = 0;
296 B_Pixmap (new_g) = XmUNSPECIFIED_PIXMAP;
297 B_Mask (new_g) = XmUNSPECIFIED_PIXMAP;
298 B_PixmapWidth (new_g) = 0;
299 B_PixmapHeight (new_g) = 0;
304 /* Set widget geometry.
306 new_g -> gadget.shadow_thickness = 1;
307 new_g -> gadget.highlight_thickness = 1;
308 if (G_Width(request) == 0)
310 if (B_PixmapWidth (new_g) > 0)
311 G_Width(new_g) = B_PixmapWidth (new_g) + 4;
315 if (G_Height(request) == 0)
317 if (B_PixmapHeight (new_g) > 0)
318 G_Height(new_g) = B_PixmapHeight (new_g) + 4;
320 G_Height(new_g) = 10;
327 /************************************************************************
330 * Get the graphics context used for drawing the button.
332 ************************************************************************/
338 DtButtonGadget bg = (DtButtonGadget) w ;
339 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
343 valueMask = GCForeground | GCBackground;
345 values.foreground = M_Foreground(mw);
346 values.background = M_Background(mw);
347 bg -> button.gc_normal = XtGetGC ((Widget) mw, valueMask, &values);
349 values.foreground = B_ArmColor (bg);
350 bg -> button.gc_armed_bg = XtGetGC ((Widget) mw, valueMask, &values);
352 values.foreground = M_Background(mw);
353 values.background = M_Foreground(mw);
354 bg -> button.gc_background = XtGetGC ((Widget) mw, valueMask, &values);
358 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
360 valueMask = GCForeground | GCBackground | GCClipMask;
361 values.clip_mask = B_Mask(bg);
362 values.foreground = M_Foreground (mw);
363 values.background = M_Background (mw);
364 bg->button.gc_clip = XtGetGC ((Widget) mw, valueMask, &values);
367 bg->button.gc_clip = NULL;
375 DtButtonGadget bg = (DtButtonGadget) w ;
376 XmManagerWidget mw = (XmManagerWidget) XtParent(w) ;
378 XtReleaseGC ((Widget) mw, bg->button.gc_normal);
379 XtReleaseGC ((Widget) mw, bg->button.gc_background);
380 XtReleaseGC ((Widget) mw, bg->button.gc_armed_bg);
382 if (bg->button.gc_clip != NULL)
383 XtReleaseGC ((Widget) mw, bg->button.gc_clip);
389 /************************************************************************
392 * General redisplay function called on exposure events.
394 ************************************************************************/
402 DtButtonGadget bg = (DtButtonGadget) w;
403 Dimension s_t = bg -> gadget.shadow_thickness;
404 Dimension h_t = bg -> gadget.highlight_thickness;
409 gc = (B_Armed (bg)) ? bg -> button.gc_armed_bg : bg -> button.gc_background;
410 XFillRectangle (XtDisplay (bg), XtWindow (bg),
411 gc, G_X(bg) +s_t + h_t, G_Y(bg) + s_t + h_t,
412 G_Width(bg) - 2 * (s_t + h_t),
413 G_Height(bg) - 2 * (s_t + h_t));
420 gc1 = XmParentBottomShadowGC(w);
421 gc2 = XmParentTopShadowGC(w);
425 gc1 = bg -> button.gc_background;
426 gc2 = bg -> button.gc_background;
428 XmeDrawShadows (XtDisplay(bg), XtWindow (bg), gc1, gc2,
429 G_X(bg) + h_t, G_Y(bg) + h_t,
430 G_Width(bg) - 2 * h_t, G_Height(bg) - 2 * h_t,
434 x = G_X(bg) + ((Position)(G_Width(bg) - B_PixmapWidth (bg))/2);
438 if (B_Mask (bg) != XmUNSPECIFIED_PIXMAP)
440 gc = bg->button.gc_clip;
441 XSetClipMask (XtDisplay(bg), gc, B_Mask (bg));
442 XSetClipOrigin (XtDisplay(bg), gc,
443 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
446 gc = bg->button.gc_normal;
449 if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP))
451 XCopyArea (XtDisplay ((Widget) bg), pix, XtWindow ((Widget) bg), gc, 0, 0,
452 B_PixmapWidth (bg), B_PixmapHeight (bg),
453 x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2);
456 if (bg -> gadget.highlighted)
457 (*(xmGadgetClassRec.gadget_class.border_highlight))((Widget) bg);
462 /************************************************************************
465 * Clean up allocated resources when the widget is destroyed.
467 ************************************************************************/
473 DtButtonGadget bg = (DtButtonGadget) w ;
475 if (bg->button.timer)
476 XtRemoveTimeOut (bg->button.timer);
478 XtReleaseGC (w, bg -> button.gc_normal);
479 XtReleaseGC (w, bg -> button.gc_background);
480 XtReleaseGC (w, bg -> button.gc_armed_bg);
481 if (bg -> button.gc_clip != NULL)
482 XtReleaseGC (w, bg -> button.gc_clip);
484 XtRemoveAllCallbacks (w, "callback");
490 /************************************************************************
493 * Note: The only implementation within this function is to
494 * support the resetting of the image, cursor, and functions
495 * as needed by the front panel.
497 ************************************************************************/
507 DtButtonGadget current = (DtButtonGadget) current_w;
508 DtButtonGadget new_g = (DtButtonGadget) new_w;
509 XmManagerWidget mw = (XmManagerWidget) XtParent(new_w);
510 Boolean returnFlag = FALSE;
512 G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT |
513 XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT |
514 XmHELP_EVENT | XmFOCUS_IN_EVENT |
515 XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT);
517 /* Change the image */
519 if (strcmp (B_ImageName (current), B_ImageName (new_g)) != 0)
521 String str = B_ImageName (new_g);
523 XtFree (B_ImageName (current));
524 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
525 strcpy (B_ImageName (new_g), str);
528 XmGetPixmap (XtScreen (new_g), B_ImageName (new_g),
529 M_BottomShadowColor (mw),
530 M_TopShadowColor (mw));
532 _DtGetMask (XtScreen (new_g), B_ImageName (new_g));
534 if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP)
537 int int_x = 0, int_y = 0;
538 unsigned int int_w = 0, int_h = 0,
541 XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g),
542 &root, &int_x, &int_y, &int_w, &int_h, &int_bw, &depth);
544 B_PixmapWidth (new_g) = (Dimension) int_w;
545 B_PixmapHeight (new_g) = (Dimension) int_h;
549 B_PixmapWidth (new_g) = 0;
550 B_PixmapHeight (new_g) = 0;
559 if (B_ImageName (new_g) != B_ImageName (current))
561 String str = B_ImageName (new_g);
563 XtFree (B_ImageName (current));
564 B_ImageName (new_g) = XtMalloc (strlen (str) + 1);
565 strcpy (B_ImageName (new_g), str);
575 /************************************************************************
578 * This function processes button 1 down occurring on the button.
580 ************************************************************************/
587 Cardinal *num_params )
589 DtButtonGadget bg = (DtButtonGadget) w ;
591 (void) XmProcessTraversal((Widget) bg, XmTRAVERSE_CURRENT);
595 if ((event->xbutton.time - bg->button.armTimeStamp) >
596 XtGetMultiClickTime(XtDisplay(bg)))
598 bg -> button.armTimeStamp = event->xbutton.time;
599 B_Expose ( w, event, NULL);
604 /************************************************************************
607 * This function processes button 1 up occurring on the button.
609 ************************************************************************/
616 Cardinal *num_params )
618 DtButtonGadget bg = (DtButtonGadget) w ;
620 B_Armed (bg) = False;
622 B_Expose (w, event, NULL);
626 /************************************************************************
629 * This function processes button 1 up occurring on the button.
630 * If the button 1 up occurred inside the button the activate
631 * callbacks are called.
633 ************************************************************************/
640 Cardinal *num_params )
642 DtButtonGadget bg = (DtButtonGadget) w ;
643 DtButtonCallbackStruct call_value;
648 if ((event->xbutton.time - bg->button.activateTimeStamp) >
649 XtGetMultiClickTime(XtDisplay(bg)))
651 bg -> button.activateTimeStamp = event->xbutton.time;
652 bg->button.click_count = 1;
655 bg->button.click_count++;
657 B_Armed (bg) = False;
659 if (bg->button.callback)
661 call_value.reason = XmCR_ACTIVATE;
662 call_value.event = event;
663 call_value.click_count = bg->button.click_count;
665 if ((bg->button.multiClick == XmMULTICLICK_DISCARD) &&
666 (call_value.click_count > 1)) {
670 XFlush(XtDisplay(bg));
672 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
677 /************************************************************************
681 ************************************************************************/
688 Cardinal *num_params )
690 DtButtonCallbackStruct call_value;
691 DtButtonGadget bg = (DtButtonGadget) w ;
694 Redisplay ( w, event, FALSE);
696 XFlush (XtDisplay (bg));
698 call_value.reason = XmCR_ACTIVATE;
699 call_value.event = event;
700 call_value.click_count = 1; /* always 1 in kselect */
702 if (bg->button.callback)
704 XFlush (XtDisplay (bg));
705 CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event);
707 B_Armed (bg) = False;
709 /* If the button is still around, show it released, after a short delay */
711 if (bg->object.being_destroyed == False)
713 bg->button.timer = XtAppAddTimeOut(
714 XtWidgetToApplicationContext((Widget)bg),
715 (unsigned long) DELAY_DEFAULT,
716 (XtTimerCallbackProc)ArmTimeout,
727 DtButtonGadget bg = (DtButtonGadget) w ;
729 bg -> button.timer = 0;
730 if (XtIsRealized ((Widget)bg) && XtIsManaged ((Widget)bg)) {
731 Redisplay ( w, NULL, FALSE);
732 XFlush (XtDisplay (bg));
738 /*-------------------------------------------------------------
740 ** Process event dispatched from parent or event handler.
748 DtButtonGadget bg = (DtButtonGadget) w ;
750 if (event_mask & XmARM_EVENT ||
751 event_mask & XmMULTI_ARM_EVENT)
753 if (event->button == Button1)
754 Arm (w, (XEvent*) event, (String *)NULL, (Cardinal*)NULL);
756 else if (event_mask & XmACTIVATE_EVENT ||
757 event_mask & XmMULTI_ACTIVATE_EVENT)
759 if (event->button == Button1)
761 if (event->x >= G_X (bg) &&
762 event->x <= (Position)(G_X (bg) + G_Width (bg)) &&
763 event->y >= G_Y (bg) &&
764 event->y <= (Position)(G_Y (bg) + G_Height (bg)))
766 Activate (w, (XEvent*) event,
767 (String *)NULL, (Cardinal*)NULL);
768 Disarm (w, (XEvent*) event,
769 (String *)NULL, (Cardinal*)NULL);
772 Disarm (w, (XEvent*) event,
773 (String *)NULL, (Cardinal*)NULL);
776 else if (event_mask & XmHELP_EVENT)
777 _XmSocorro (w, (XEvent *)event,
778 (String *)NULL,(Cardinal*)NULL);
779 else if (event_mask & XmENTER_EVENT)
780 Enter (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL);
781 else if (event_mask & XmLEAVE_EVENT)
782 Leave (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL);
783 else if (event_mask & XmFOCUS_IN_EVENT)
784 _XmFocusInGadget (w, (XEvent *)event,
785 (String *)NULL,(Cardinal*)NULL);
786 else if (event_mask & XmFOCUS_OUT_EVENT)
787 _XmFocusOutGadget (w, (XEvent *)event,
788 (String *)NULL,(Cardinal*)NULL);
792 /*-------------------------------------------------------------
794 ** Update GCs when parent visuals change.
802 XmManagerWidget current = (XmManagerWidget) current_w;
803 XmManagerWidget new_m = (XmManagerWidget) new_w;
804 DtButtonGadget bg = (DtButtonGadget) w ;
805 Boolean update = False;
807 /* If the parent foreground or background has changed,
808 * then update gcs and pixmap.
810 if (M_Foreground (current) != M_Foreground (new_m) ||
811 M_Background (current) != M_Background (new_m))
819 if (B_ImageName (bg) != NULL)
821 if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP)
822 XmDestroyPixmap (XtScreen(bg), B_Mask(bg));
824 if (B_Pixmap(bg) != XmUNSPECIFIED_PIXMAP)
825 XmDestroyPixmap (XtScreen(w), B_Pixmap (bg));
827 B_Pixmap (bg) = XmGetPixmap (XtScreen (bg), B_ImageName (bg),
828 M_TopShadowColor (new_m),
829 M_BottomShadowColor (new_m));
831 if (B_Pixmap (bg) != XmUNSPECIFIED_PIXMAP)
832 B_Mask(bg) = (Pixmap)_DtGetMask(XtScreen(bg), B_ImageName(bg));
842 /************************************************************************
846 ************************************************************************/
853 Cardinal *num_params )
855 DtButtonGadget bg = (DtButtonGadget) wid ;
857 _XmEnterGadget (wid, (XEvent *)event, (String *)NULL,(Cardinal *)NULL);
860 B_Expose (wid, event, NULL);
866 /************************************************************************
870 ************************************************************************/
877 Cardinal *num_params )
879 DtButtonGadget bg = (DtButtonGadget) wid ;
881 _XmLeaveGadget (wid, (XEvent *)event, (String *)NULL, (Cardinal *)0);
885 B_Armed (bg) = False;
886 B_Expose (wid, event, NULL);
892 /*-------------------------------------------------------------
894 ** Call callback, if any, with reason and event.
903 DtControlCallbackStruct cb_data;
907 cb_data.reason = reason;
908 cb_data.event = event;
909 cb_data.control_type = XmCONTROL_BUTTON;
911 cb_data.subpanel = B_Subpanel (w);
912 cb_data.push_function = B_PushFunction (w);
913 cb_data.push_argument = B_PushArgument (w);
914 cb_data.file_size = 0;
915 XtCallCallbackList ((Widget) w, cb, &cb_data);
920 /*-------------------------------------------------------------
921 ** DefaultSelectColor
922 ** Resource proc. to determine the default select color.
923 ** (Formerly _XmSelectColorDefault).
931 XmeGetDefaultPixel (widget, XmSELECT, offset, value);
935 /************************************************************************
937 * DtCreateButtonGadget
938 * Create an instance of an button and return the widget id.
940 ************************************************************************/
943 DtCreateButtonGadget(
949 return (XtCreateWidget (name, dtButtonGadgetClass,
950 parent, arglist, argcount));