/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /****************************************************************************** ******************************************************************************* * * (c) Copyright 1992 HEWLETT-PACKARD COMPANY * ALL RIGHTS RESERVED * ******************************************************************************* ******************************************************************************/ #include #include #include "ButtonP.h" #include #include #include
#include
#include
#include "DtSvcInternal.h" /* _DtGetMask */ #include /* _XmFocusInGadget, _XmFocusOutGadget, _XmSocorro */ #define DELAY_DEFAULT 100 static void Initialize( Widget request_w, Widget new_w) ; static void GetGCs( Widget w) ; static void UpdateGCs( Widget w) ; static void Redisplay( Widget w, XEvent *event, Region region) ; static Boolean SetValues( Widget current_w, Widget request_w, Widget new_w) ; static void Arm( Widget w, XEvent *event, String *params, Cardinal *num_params) ; static void Disarm( Widget w, XEvent *event, String *params, Cardinal *num_params) ; static void Activate( Widget w, XEvent *event, String *params, Cardinal *num_params) ; static void ArmAndActivate( Widget w, XEvent *event, String *params, Cardinal *num_params) ; static void InputDispatch( Widget w, XButtonEvent *event, Mask event_mask) ; static Boolean VisualChange( Widget w, Widget current_w, Widget new_w) ; static void ArmTimeout( Widget w, XtIntervalId *id) ; static void Enter( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void Leave( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void CallCallback( DtButtonGadget g, XtCallbackList cb, int reason, XEvent *event) ; static void DefaultSelectColor( Widget widget, int offset, XrmValue *value) ; /* Resource list for button */ #define R_Offset(field) \ XtOffset (DtButtonGadget, button.field) static XtResource resources[] = { { XmNcursorFont, XmCCursorFont, XmRInt, sizeof (int), R_Offset (cursor_font), XmRImmediate, (XtPointer) 1 }, { XmNarmColor, XmCArmColor, XmRPixel, sizeof (Pixel), R_Offset (arm_color), XmRCallProc, (XtPointer) DefaultSelectColor }, { XmNsubpanel, XmCSubpanel, XmRWidget, sizeof (Widget), R_Offset (subpanel), XmRImmediate, (XtPointer) NULL }, { XmNpushFunction, XmCPushFunction, XmRFunction, sizeof (XtPointer), R_Offset (push_function), XmRImmediate, (XtPointer) NULL }, { XmNpushArgument, XmCPushArgument, XmRPointer, sizeof (XtPointer), R_Offset (push_argument), XmRImmediate, (XtPointer) NULL }, { XmNimageName, XmCString, XmRString, sizeof (String), R_Offset (image_name), XmRImmediate, (XtPointer) "" }, { XmNcallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), R_Offset (callback), XmRImmediate, (caddr_t) NULL }, { XmNmultiClick, XmCMultiClick, XmRMultiClick, sizeof (unsigned char), R_Offset (multiClick), XmRImmediate, (XtPointer) XmMULTICLICK_KEEP } }; /* The button class record definition */ externaldef (dtbuttongadgetclassrec) DtButtonGadgetClassRec dtButtonGadgetClassRec= { { (WidgetClass) &xmGadgetClassRec, /* superclass */ "DtButton", /* class_name */ sizeof(DtButtonGadgetRec), /* widget_size */ NULL, /* class_initialize */ NULL, /* class_part_initialize */ FALSE, /* class_inited */ (XtInitProc) Initialize, /* initialize */ NULL, /* initialize_hook */ NULL, /* realize */ NULL, /* actions */ 0, /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMaximal, /* compress_exposure */ TRUE, /* compress_enterleave */ FALSE, /* visible_interest */ NULL, /* destroy */ NULL, /* resize */ (XtExposeProc) Redisplay, /* expose */ (XtSetValuesFunc) SetValues, /* set_values */ NULL, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback private */ NULL, /* tm_table */ NULL, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ }, /* XmGadget Part */ { (XtWidgetProc) _XtInherit, /* Gadget border_highlight */ (XtWidgetProc) _XtInherit, /* Gadget border_unhighlight */ ArmAndActivate, /* arm_and_activate */ (XmWidgetDispatchProc)InputDispatch, /* input_dispatch */ VisualChange, /* visual_change */ NULL, /* get resources */ 0, /* num get_resources */ NULL, /* class_cache_part */ NULL, /* extension */ } }; externaldef(dtbuttonwidgetclass) WidgetClass dtButtonGadgetClass = (WidgetClass) &dtButtonGadgetClassRec; /************************************************************************ * * Initialize * The main widget instance initialization routine. * ************************************************************************/ static void Initialize( Widget request_w, Widget new_w ) { DtButtonGadget request = (DtButtonGadget) request_w ; DtButtonGadget new_g = (DtButtonGadget) new_w ; XmManagerWidget mw = (XmManagerWidget) XtParent(new_w) ; new_g->button.timer = 0; new_g->button.click_count = 0; new_g->button.armTimeStamp = 0; new_g->button.activateTimeStamp = 0; B_Armed (new_g) = False; /* Set the input mask for events handled by Manager. */ G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT | XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT | XmHELP_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT); /* Get pixmap and mask, get pixmap geometry, get gcs. */ if (B_ImageName (new_g) != NULL) { String str = B_ImageName (new_g); B_ImageName (new_g) = XtMalloc (strlen (str) + 1); strcpy (B_ImageName (new_g), str); B_Pixmap (new_g) = XmGetPixmap (XtScreen (new_g), B_ImageName (new_g), M_BottomShadowColor (mw), M_TopShadowColor (mw)); B_Mask (new_g) = _DtGetMask (XtScreen (new_g), B_ImageName (new_g)); if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP) { Window root; int int_x = 0, int_y = 0; unsigned int int_w = 0, int_h = 0, int_bw, depth; XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g), &root, &int_x, &int_y, &int_w, &int_h, &int_bw, &depth); B_PixmapWidth (new_g) = (Dimension) int_w; B_PixmapHeight (new_g) = (Dimension) int_h; } else { B_PixmapWidth (new_g) = 0; B_PixmapHeight (new_g) = 0; } } else { B_Pixmap (new_g) = XmUNSPECIFIED_PIXMAP; B_Mask (new_g) = XmUNSPECIFIED_PIXMAP; B_PixmapWidth (new_g) = 0; B_PixmapHeight (new_g) = 0; } GetGCs (new_w); /* Set widget geometry. */ new_g -> gadget.shadow_thickness = 1; new_g -> gadget.highlight_thickness = 1; if (G_Width(request) == 0) { if (B_PixmapWidth (new_g) > 0) G_Width(new_g) = B_PixmapWidth (new_g) + 4; else G_Width(new_g) = 10; } if (G_Height(request) == 0) { if (B_PixmapHeight (new_g) > 0) G_Height(new_g) = B_PixmapHeight (new_g) + 4; else G_Height(new_g) = 10; } } /************************************************************************ * * GetGCs * Get the graphics context used for drawing the button. * ************************************************************************/ static void GetGCs( Widget w ) { DtButtonGadget bg = (DtButtonGadget) w ; XmManagerWidget mw = (XmManagerWidget) XtParent(w) ; XGCValues values; XtGCMask valueMask; valueMask = GCForeground | GCBackground; values.foreground = M_Foreground(mw); values.background = M_Background(mw); bg -> button.gc_normal = XtGetGC ((Widget) mw, valueMask, &values); values.foreground = B_ArmColor (bg); bg -> button.gc_armed_bg = XtGetGC ((Widget) mw, valueMask, &values); values.foreground = M_Background(mw); values.background = M_Foreground(mw); bg -> button.gc_background = XtGetGC ((Widget) mw, valueMask, &values); /* Get Clip GC */ if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP) { valueMask = GCForeground | GCBackground | GCClipMask; values.clip_mask = B_Mask(bg); values.foreground = M_Foreground (mw); values.background = M_Background (mw); bg->button.gc_clip = XtGetGC ((Widget) mw, valueMask, &values); } else bg->button.gc_clip = NULL; } static void UpdateGCs( Widget w ) { DtButtonGadget bg = (DtButtonGadget) w ; XmManagerWidget mw = (XmManagerWidget) XtParent(w) ; XtReleaseGC ((Widget) mw, bg->button.gc_normal); XtReleaseGC ((Widget) mw, bg->button.gc_background); XtReleaseGC ((Widget) mw, bg->button.gc_armed_bg); if (bg->button.gc_clip != NULL) XtReleaseGC ((Widget) mw, bg->button.gc_clip); GetGCs (w); } /************************************************************************ * * Redisplay * General redisplay function called on exposure events. * ************************************************************************/ /* ARGSUSED */ static void Redisplay( Widget w, XEvent *event, Region region ) { DtButtonGadget bg = (DtButtonGadget) w; Dimension s_t = bg -> gadget.shadow_thickness; Dimension h_t = bg -> gadget.highlight_thickness; Position x; Pixmap pix; GC gc; gc = (B_Armed (bg)) ? bg -> button.gc_armed_bg : bg -> button.gc_background; XFillRectangle (XtDisplay (bg), XtWindow (bg), gc, G_X(bg) +s_t + h_t, G_Y(bg) + s_t + h_t, G_Width(bg) - 2 * (s_t + h_t), G_Height(bg) - 2 * (s_t + h_t)); if (s_t > 0) { GC gc1, gc2; if (B_Armed (bg)) { gc1 = XmParentBottomShadowGC(w); gc2 = XmParentTopShadowGC(w); } else { gc1 = bg -> button.gc_background; gc2 = bg -> button.gc_background; } XmeDrawShadows (XtDisplay(bg), XtWindow (bg), gc1, gc2, G_X(bg) + h_t, G_Y(bg) + h_t, G_Width(bg) - 2 * h_t, G_Height(bg) - 2 * h_t, s_t,XmSHADOW_OUT); } x = G_X(bg) + ((Position)(G_Width(bg) - B_PixmapWidth (bg))/2); if (x % 2 == 1) x++; if (B_Mask (bg) != XmUNSPECIFIED_PIXMAP) { gc = bg->button.gc_clip; XSetClipMask (XtDisplay(bg), gc, B_Mask (bg)); XSetClipOrigin (XtDisplay(bg), gc, x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2); } else gc = bg->button.gc_normal; pix = B_Pixmap (bg); if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP)) { XCopyArea (XtDisplay ((Widget) bg), pix, XtWindow ((Widget) bg), gc, 0, 0, B_PixmapWidth (bg), B_PixmapHeight (bg), x, G_Y(bg) + (Position)(G_Height(bg) - B_PixmapHeight (bg))/2); } if (bg -> gadget.highlighted) (*(xmGadgetClassRec.gadget_class.border_highlight))((Widget) bg); } /************************************************************************ * * Destroy * Clean up allocated resources when the widget is destroyed. * ************************************************************************/ #if 0 static void Destroy( Widget w ) { DtButtonGadget bg = (DtButtonGadget) w ; if (bg->button.timer) XtRemoveTimeOut (bg->button.timer); XtReleaseGC (w, bg -> button.gc_normal); XtReleaseGC (w, bg -> button.gc_background); XtReleaseGC (w, bg -> button.gc_armed_bg); if (bg -> button.gc_clip != NULL) XtReleaseGC (w, bg -> button.gc_clip); XtRemoveAllCallbacks (w, "callback"); } #endif /* 0 */ /************************************************************************ * * SetValues * Note: The only implementation within this function is to * support the resetting of the image, cursor, and functions * as needed by the front panel. * ************************************************************************/ /* ARGSUSED */ static Boolean SetValues( Widget current_w, Widget request_w, Widget new_w ) { DtButtonGadget current = (DtButtonGadget) current_w; DtButtonGadget new_g = (DtButtonGadget) new_w; XmManagerWidget mw = (XmManagerWidget) XtParent(new_w); Boolean returnFlag = FALSE; G_EventMask (new_g) = (XmARM_EVENT | XmACTIVATE_EVENT | XmMULTI_ARM_EVENT | XmMULTI_ACTIVATE_EVENT | XmHELP_EVENT | XmFOCUS_IN_EVENT | XmFOCUS_OUT_EVENT | XmENTER_EVENT | XmLEAVE_EVENT); /* Change the image */ if (strcmp (B_ImageName (current), B_ImageName (new_g)) != 0) { String str = B_ImageName (new_g); XtFree (B_ImageName (current)); B_ImageName (new_g) = XtMalloc (strlen (str) + 1); strcpy (B_ImageName (new_g), str); B_Pixmap (new_g) = XmGetPixmap (XtScreen (new_g), B_ImageName (new_g), M_BottomShadowColor (mw), M_TopShadowColor (mw)); B_Mask (new_g) = _DtGetMask (XtScreen (new_g), B_ImageName (new_g)); if (B_Pixmap (new_g) != XmUNSPECIFIED_PIXMAP) { Window root; int int_x = 0, int_y = 0; unsigned int int_w = 0, int_h = 0, int_bw, depth; XGetGeometry (XtDisplay (new_g), B_Pixmap (new_g), &root, &int_x, &int_y, &int_w, &int_h, &int_bw, &depth); B_PixmapWidth (new_g) = (Dimension) int_w; B_PixmapHeight (new_g) = (Dimension) int_h; } else { B_PixmapWidth (new_g) = 0; B_PixmapHeight (new_g) = 0; } UpdateGCs(new_w); returnFlag = TRUE; } else { if (B_ImageName (new_g) != B_ImageName (current)) { String str = B_ImageName (new_g); XtFree (B_ImageName (current)); B_ImageName (new_g) = XtMalloc (strlen (str) + 1); strcpy (B_ImageName (new_g), str); } } return (returnFlag); } /************************************************************************ * * arm * This function processes button 1 down occurring on the button. * ************************************************************************/ static void Arm( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtButtonGadget bg = (DtButtonGadget) w ; (void) XmProcessTraversal((Widget) bg, XmTRAVERSE_CURRENT); B_Armed (bg) = True; if ((event->xbutton.time - bg->button.armTimeStamp) > XtGetMultiClickTime(XtDisplay(bg))) { bg -> button.armTimeStamp = event->xbutton.time; B_Expose ( w, event, NULL); } } /************************************************************************ * * disarm * This function processes button 1 up occurring on the button. * ************************************************************************/ static void Disarm( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtButtonGadget bg = (DtButtonGadget) w ; B_Armed (bg) = False; B_Expose (w, event, NULL); } /************************************************************************ * * activate * This function processes button 1 up occurring on the button. * If the button 1 up occurred inside the button the activate * callbacks are called. * ************************************************************************/ static void Activate( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtButtonGadget bg = (DtButtonGadget) w ; DtButtonCallbackStruct call_value; if (!B_Armed (bg)) return; if ((event->xbutton.time - bg->button.activateTimeStamp) > XtGetMultiClickTime(XtDisplay(bg))) { bg -> button.activateTimeStamp = event->xbutton.time; bg->button.click_count = 1; } else bg->button.click_count++; B_Armed (bg) = False; if (bg->button.callback) { call_value.reason = XmCR_ACTIVATE; call_value.event = event; call_value.click_count = bg->button.click_count; if ((bg->button.multiClick == XmMULTICLICK_DISCARD) && (call_value.click_count > 1)) { return; } XFlush(XtDisplay(bg)); CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event); } } /************************************************************************ * * ArmAndActivate * ************************************************************************/ static void ArmAndActivate( Widget w, XEvent *event, String *params, Cardinal *num_params ) { DtButtonCallbackStruct call_value; DtButtonGadget bg = (DtButtonGadget) w ; B_Armed (bg) = True; Redisplay ( w, event, FALSE); XFlush (XtDisplay (bg)); call_value.reason = XmCR_ACTIVATE; call_value.event = event; call_value.click_count = 1; /* always 1 in kselect */ if (bg->button.callback) { XFlush (XtDisplay (bg)); CallCallback (bg, B_Callback (bg), XmCR_ACTIVATE, event); } B_Armed (bg) = False; /* If the button is still around, show it released, after a short delay */ if (bg->object.being_destroyed == False) { bg->button.timer = XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)bg), (unsigned long) DELAY_DEFAULT, (XtTimerCallbackProc)ArmTimeout, (caddr_t)bg); } } /* ARGSUSED */ static void ArmTimeout( Widget w, XtIntervalId *id ) { DtButtonGadget bg = (DtButtonGadget) w ; bg -> button.timer = 0; if (XtIsRealized ((Widget)bg) && XtIsManaged ((Widget)bg)) { Redisplay ( w, NULL, FALSE); XFlush (XtDisplay (bg)); } return; } /*------------------------------------------------------------- ** InputDispatch ** Process event dispatched from parent or event handler. */ static void InputDispatch( Widget w, XButtonEvent *event, Mask event_mask ) { DtButtonGadget bg = (DtButtonGadget) w ; if (event_mask & XmARM_EVENT || event_mask & XmMULTI_ARM_EVENT) { if (event->button == Button1) Arm (w, (XEvent*) event, (String *)NULL, (Cardinal*)NULL); } else if (event_mask & XmACTIVATE_EVENT || event_mask & XmMULTI_ACTIVATE_EVENT) { if (event->button == Button1) { if (event->x >= G_X (bg) && event->x <= (Position)(G_X (bg) + G_Width (bg)) && event->y >= G_Y (bg) && event->y <= (Position)(G_Y (bg) + G_Height (bg))) { Activate (w, (XEvent*) event, (String *)NULL, (Cardinal*)NULL); Disarm (w, (XEvent*) event, (String *)NULL, (Cardinal*)NULL); } else Disarm (w, (XEvent*) event, (String *)NULL, (Cardinal*)NULL); } } else if (event_mask & XmHELP_EVENT) _XmSocorro (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL); else if (event_mask & XmENTER_EVENT) Enter (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL); else if (event_mask & XmLEAVE_EVENT) Leave (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL); else if (event_mask & XmFOCUS_IN_EVENT) _XmFocusInGadget (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL); else if (event_mask & XmFOCUS_OUT_EVENT) _XmFocusOutGadget (w, (XEvent *)event, (String *)NULL,(Cardinal*)NULL); } /*------------------------------------------------------------- ** VisualChange ** Update GCs when parent visuals change. */ static Boolean VisualChange( Widget w, Widget current_w, Widget new_w ) { XmManagerWidget current = (XmManagerWidget) current_w; XmManagerWidget new_m = (XmManagerWidget) new_w; DtButtonGadget bg = (DtButtonGadget) w ; Boolean update = False; /* If the parent foreground or background has changed, * then update gcs and pixmap. */ if (M_Foreground (current) != M_Foreground (new_m) || M_Background (current) != M_Background (new_m)) { UpdateGCs(w); update = True; } if (update) { if (B_ImageName (bg) != NULL) { if (B_Mask(bg) != XmUNSPECIFIED_PIXMAP) XmDestroyPixmap (XtScreen(bg), B_Mask(bg)); if (B_Pixmap(bg) != XmUNSPECIFIED_PIXMAP) XmDestroyPixmap (XtScreen(w), B_Pixmap (bg)); B_Pixmap (bg) = XmGetPixmap (XtScreen (bg), B_ImageName (bg), M_TopShadowColor (new_m), M_BottomShadowColor (new_m)); if (B_Pixmap (bg) != XmUNSPECIFIED_PIXMAP) B_Mask(bg) = (Pixmap)_DtGetMask(XtScreen(bg), B_ImageName(bg)); return (True); } else return (False); } return (False); } /************************************************************************ * * Enter * ************************************************************************/ static void Enter( Widget wid, XEvent *event, String *params, Cardinal *num_params ) { DtButtonGadget bg = (DtButtonGadget) wid ; _XmEnterGadget (wid, (XEvent *)event, (String *)NULL,(Cardinal *)NULL); if (B_Armed (bg)) B_Expose (wid, event, NULL); } /************************************************************************ * * Leave * ************************************************************************/ static void Leave( Widget wid, XEvent *event, String *params, Cardinal *num_params ) { DtButtonGadget bg = (DtButtonGadget) wid ; _XmLeaveGadget (wid, (XEvent *)event, (String *)NULL, (Cardinal *)0); if (B_Armed (bg)) { B_Armed (bg) = False; B_Expose (wid, event, NULL); B_Armed (bg) = True; } } /*------------------------------------------------------------- ** CallCallback ** Call callback, if any, with reason and event. */ static void CallCallback( DtButtonGadget w, XtCallbackList cb, int reason, XEvent *event ) { DtControlCallbackStruct cb_data; if (cb != NULL) { cb_data.reason = reason; cb_data.event = event; cb_data.control_type = XmCONTROL_BUTTON; cb_data.set = False; cb_data.subpanel = B_Subpanel (w); cb_data.push_function = B_PushFunction (w); cb_data.push_argument = B_PushArgument (w); cb_data.file_size = 0; XtCallCallbackList ((Widget) w, cb, &cb_data); } } /*------------------------------------------------------------- ** DefaultSelectColor ** Resource proc. to determine the default select color. ** (Formerly _XmSelectColorDefault). */ static void DefaultSelectColor( Widget widget, int offset, XrmValue *value ) { XmeGetDefaultPixel (widget, XmSELECT, offset, value); } /************************************************************************ * * DtCreateButtonGadget * Create an instance of an button and return the widget id. * ************************************************************************/ Widget DtCreateButtonGadget( Widget parent, char *name, ArgList arglist, Cardinal argcount ) { return (XtCreateWidget (name, dtButtonGadgetClass, parent, arglist, argcount)); }