/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$TOG: DrawnB.c /main/20 1999/04/29 13:05:14 samborn $" #endif #endif /* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ /* * Include files & Static Routine Definitions */ #include #include #include #include #include #include #include #include #include #include #include #include #include "XmI.h" #include "RepTypeI.h" #include "LabelI.h" #include "MenuProcI.h" #include "PrimitiveI.h" #include "TravActI.h" #include "TraversalI.h" #define DELAY_DEFAULT 100 /******** Static Function Declarations ********/ static void Arm( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void MultiArm( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void Activate( Widget wid, XEvent *buttonEvent, String *params, Cardinal *num_params) ; static void MultiActivate( Widget wid, XEvent *buttonEvent, String *params, Cardinal *num_params) ; static void ActivateCommon( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void ArmAndActivate( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void ArmTimeout ( XtPointer closure, XtIntervalId *id ) ; static void Disarm( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void BtnDown( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; static void BtnUp( Widget wid, XEvent *event, String *params, Cardinal *num_params) ; 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 BorderHighlight( Widget wid) ; static void BorderUnhighlight( Widget wid) ; static void ClassInitialize( void ) ; static void ClassPartInitialize( WidgetClass wc) ; static void InitializePrehook( Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void InitializePosthook( Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void Resize( Widget wid) ; static void Redisplay( Widget wid, XEvent *event, Region region) ; static void DrawPushButton( XmDrawnButtonWidget db, #if NeedWidePrototypes int armed) ; #else Boolean armed) ; #endif /* NeedWidePrototypes */ static Boolean SetValuesPrehook( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static Boolean SetValues( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void Realize( Widget w, XtValueMask *p_valueMask, XSetWindowAttributes *attributes) ; static void Destroy( Widget wid) ; static void ChangeCB(Widget w, XtCallbackProc activCB, XtPointer closure, Boolean setunset) ; static void DB_FixTearoff(XmDrawnButtonWidget db); /******** End Static Function Declarations ********/ /*************************************<->************************************* * * * Description: translation tables for class: DrawnButton * ----------- * * Matches events with string descriptors for internal routines. * *************************************<->***********************************/ static XtTranslations default_parsed; #define defaultTranslations _XmDrawnB_defaultTranslations static XtTranslations menu_parsed; #define menuTranslations _XmDrawnB_menuTranslations /*************************************<->************************************* * * * Description: action list for class: DrawnButton * ----------- * * Matches string descriptors with internal routines. * Note that Primitive will register additional event handlers * for traversal. * *************************************<->***********************************/ static XtActionsRec actionsList[] = { {"Arm", Arm }, {"Activate", Activate }, {"MultiActivate", MultiActivate }, {"MultiArm", MultiArm }, {"ArmAndActivate", ArmAndActivate }, {"Disarm", Disarm }, {"BtnDown", BtnDown }, {"BtnUp", BtnUp }, {"Enter", Enter }, {"Leave", Leave }, {"ButtonTakeFocus", _XmButtonTakeFocus }, {"MenuButtonTakeFocus", _XmMenuButtonTakeFocus }, {"MenuButtonTakeFocusUp", _XmMenuButtonTakeFocusUp } }; /* The resource list for Drawn Button */ static XtResource resources[] = { { XmNmultiClick, XmCMultiClick, XmRMultiClick, sizeof (unsigned char), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.multiClick), XmRImmediate, (XtPointer) XmMULTICLICK_KEEP }, { XmNpushButtonEnabled, XmCPushButtonEnabled, XmRBoolean, sizeof (Boolean), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.pushbutton_enabled), XmRImmediate, (XtPointer) False }, { XmNshadowType, XmCShadowType, XmRShadowType, sizeof(unsigned char), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.shadow_type), XmRImmediate, (XtPointer) XmSHADOW_ETCHED_IN }, { XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.activate_callback), XmRPointer, (XtPointer) NULL }, { XmNarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.arm_callback), XmRPointer, (XtPointer) NULL }, { XmNdisarmCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.disarm_callback), XmRPointer, (XtPointer) NULL }, { XmNexposeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.expose_callback), XmRPointer, (XtPointer) NULL }, { XmNresizeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf( struct _XmDrawnButtonRec, drawnbutton.resize_callback), XmRPointer, (XtPointer) NULL }, { XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffsetOf( struct _XmDrawnButtonRec, primitive.shadow_thickness), XmRCallProc, (XtPointer) _XmSetThickness }, { XmNlabelString, XmCXmString, XmRXmString, sizeof(XmString), XtOffsetOf( struct _XmDrawnButtonRec, label._label), XmRImmediate, (XtPointer) XmUNSPECIFIED }, { XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof(Boolean), XtOffsetOf( struct _XmPrimitiveRec, primitive.traversal_on), XmRImmediate, (XtPointer) True }, { XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension, sizeof (Dimension), XtOffsetOf( struct _XmPrimitiveRec, primitive.highlight_thickness), XmRCallProc, (XtPointer) _XmSetThickness } }; static XmBaseClassExtRec drawnBBaseClassExtRec = { NULL, /* Next extension */ NULLQUARK, /* record type XmQmotif */ XmBaseClassExtVersion, /* version */ sizeof(XmBaseClassExtRec), /* size */ InitializePrehook, /* initialize prehook */ SetValuesPrehook, /* set_values prehook */ InitializePosthook, /* initialize posthook */ XmInheritSetValuesPosthook, /* set_values posthook */ XmInheritClass, /* secondary class */ XmInheritSecObjectCreate, /* creation proc */ XmInheritGetSecResData, /* getSecResData */ {0}, /* fast subclass */ XmInheritGetValuesPrehook, /* get_values prehook */ XmInheritGetValuesPosthook, /* get_values posthook */ XmInheritClassPartInitPrehook, /* classPartInitPrehook */ XmInheritClassPartInitPosthook, /* classPartInitPosthook*/ NULL, /* ext_resources */ NULL, /* compiled_ext_resources*/ 0, /* num_ext_resources */ FALSE, /* use_sub_resources */ XmInheritWidgetNavigable, /* widgetNavigable */ XmInheritFocusChange, /* focusChange */ }; /*************************************<->************************************* * * * Description: global class record for instances of class: DrawnButton * ----------- * * Defines default field settings for this class record. * *************************************<->***********************************/ externaldef(xmdrawnbuttonclassrec) XmDrawnButtonClassRec xmDrawnButtonClassRec ={ { /* core_class record */ /* superclass */ (WidgetClass) &xmLabelClassRec, /* class_name */ "XmDrawnButton", /* widget_size */ sizeof(XmDrawnButtonRec), /* class_initialize */ ClassInitialize, /* class_part_init */ ClassPartInitialize, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ actionsList, /* num_actions */ XtNumber(actionsList), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ XtExposeNoCompress, /* compress_enterlv */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ defaultTranslations, /* query_geometry */ NULL, /* display_accelerator */ NULL, /* extension */ (XtPointer) &drawnBBaseClassExtRec, }, { /* primitive_class record */ /* Primitive border_highlight */ BorderHighlight, /* Primitive border_unhighlight */ BorderUnhighlight, /* translations */ XtInheritTranslations, /* arm_and_activate */ ArmAndActivate, /* get resources */ NULL, /* num get_resources */ 0, /* extension */ NULL, }, { /* label_class record */ /* setOverrideCallback*/ XmInheritWidgetProc, /* Menu procedures */ XmInheritMenuProc, /* menu trav xlations */ XtInheritTranslations, /* extension */ NULL, }, { /* drawnbutton_class record */ /* extension */ NULL, } }; externaldef(xmdrawnbuttonwidgetclass) WidgetClass xmDrawnButtonWidgetClass = (WidgetClass)&xmDrawnButtonClassRec; /* Trait record for drawnButton */ static XmConst XmActivatableTraitRec drawnButtonAT = { 0, /* version */ ChangeCB, }; /* Menu Savvy trait record */ static XmMenuSavvyTraitRec MenuSavvyRecord = { /* version: */ -1, NULL, NULL, NULL, _XmCBNameActivate, }; /************************************************************************ * * Arm * * This function processes button 1 down occuring on the drawnbutton. * Mark the drawnbutton as armed if XmNpushButtonEnabled is TRUE. * The callbacks for XmNarmCallback are called. * ************************************************************************/ /*ARGSUSED*/ static void Arm( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XButtonEvent *buttonEvent = (XButtonEvent *) event; XmDrawnButtonCallbackStruct call_value; (void) XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT); db -> drawnbutton.armed = TRUE; if (event && (event->type == ButtonPress)) db -> drawnbutton.armTimeStamp = buttonEvent->time; if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); if (db->drawnbutton.arm_callback) { XFlush(XtDisplay (db)); call_value.reason = XmCR_ARM; call_value.event = event; call_value.window = XtWindow (db); XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value); } } /*ARGSUSED*/ static void MultiArm( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { if (((XmDrawnButtonWidget) wid)->drawnbutton.multiClick == XmMULTICLICK_KEEP) Arm (wid, event, NULL, NULL); } /************************************************************************ * * Activate * * Mark the drawnbutton as unarmed (i.e. inactive). * The foreground and background colors will revert to the * unarmed state if XmNinvertOnArm is set to TRUE. * If the button release occurs inside of the DrawnButton, the * callbacks for XmNactivateCallback are called. * ************************************************************************/ static void Activate( Widget wid, XEvent *buttonEvent, String *params, Cardinal *num_params ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; if (db -> drawnbutton.armed == FALSE) return; db->drawnbutton.click_count = 1; ActivateCommon ((Widget) db, buttonEvent, params, num_params); } static void MultiActivate( Widget wid, XEvent *buttonEvent, String *params, Cardinal *num_params ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; /* When a multi click sequence occurs and the user Button Presses and * holds for a length of time, the final release should look like a * new/separate activate. */ if (db->drawnbutton.multiClick == XmMULTICLICK_KEEP) { if ((buttonEvent->xbutton.time - db->drawnbutton.armTimeStamp) > XtGetMultiClickTime(XtDisplay(db))) db->drawnbutton.click_count = 1; else db->drawnbutton.click_count++; ActivateCommon ((Widget) db, buttonEvent, params, num_params) ; Disarm ((Widget) db, buttonEvent, params, num_params) ; } } /*ARGSUSED*/ static void ActivateCommon( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem); if (event && (event->xbutton.type != ButtonRelease)) return; db -> drawnbutton.armed = FALSE; if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); /* CR 9181: Consider clipping when testing visibility. */ if ((db->drawnbutton.activate_callback) && ((event->xany.type == ButtonPress) || (event->xany.type == ButtonRelease)) && _XmGetPointVisibility(wid, event->xbutton.x_root, event->xbutton.y_root)) { XFlush(XtDisplay (db)); call_value.reason = XmCR_ACTIVATE; call_value.event = event; call_value.window = XtWindow (db); call_value.click_count = db->drawnbutton.click_count; if ((db->drawnbutton.multiClick == XmMULTICLICK_DISCARD) && (call_value.click_count > 1)) { return; } if (menuSTrait != NULL) { menuSTrait->entryCallback(XtParent(db), (Widget) db, &call_value); } if ((! db->label.skipCallback) && (db->drawnbutton.activate_callback)) { XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback, &call_value); } } } static void DB_FixTearoff( XmDrawnButtonWidget db) { if (XmMENU_PULLDOWN == db->label.menu_type) { Widget mwid = XmGetPostedFromWidget(XtParent(db)); if (mwid && XmIsRowColumn(mwid) && (XmMENU_OPTION == RC_Type(mwid)) && _XmIsActiveTearOff(XtParent(db))) XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT); } } /************************************************************************ * * ArmAndActivate * ************************************************************************/ /*ARGSUSED*/ static void ArmAndActivate( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem); db -> drawnbutton.armed = TRUE; if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); XFlush(XtDisplay (db)); if (db->drawnbutton.arm_callback) { call_value.reason = XmCR_ARM; call_value.event = event; call_value.window = XtWindow (db); XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value); } call_value.reason = XmCR_ACTIVATE; call_value.event = event; call_value.window = XtWindow (db); call_value.click_count = 1; /* always 1 in kselect */ if (menuSTrait != NULL) { menuSTrait->entryCallback(XtParent(db), (Widget) db, &call_value); } if ((! db->label.skipCallback) && (db->drawnbutton.activate_callback)) { XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback, &call_value); } db->drawnbutton.armed = FALSE; if (db->drawnbutton.disarm_callback) { call_value.reason = XmCR_DISARM; XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value); } /* If the button is still around, show it released, after a short delay */ if (!db->core.being_destroyed && db->drawnbutton.pushbutton_enabled) { db->drawnbutton.timer = XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)db), (unsigned long) DELAY_DEFAULT, ArmTimeout, (XtPointer)db); } } /*ARGSUSED*/ static void ArmTimeout ( XtPointer closure, XtIntervalId *id ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) closure ; db -> drawnbutton.timer = 0; if (db->drawnbutton.pushbutton_enabled && XtIsRealized((Widget)db) && XtIsManaged((Widget)db)) { DrawPushButton(db, db->drawnbutton.armed); XFlush (XtDisplay (db)); } } /************************************************************************ * * Disarm * * Mark the drawnbutton as unarmed (i.e. active). * The foreground and background colors will revert to the * unarmed state if XmNinvertOnSelect is set to TRUE and the * drawnbutton is not in a menu. * The callbacks for XmNdisarmCallback are called.. * ************************************************************************/ /*ARGSUSED*/ static void Disarm( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; db -> drawnbutton.armed = FALSE; if (db->drawnbutton.disarm_callback) { XFlush(XtDisplay (db)); call_value.reason = XmCR_DISARM; call_value.event = event; call_value.window = XtWindow (db); XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value); } } /************************************************************************ * * BtnDown * * This function processes a button down occuring on the drawnbutton * when it is in a popup, pulldown, or option menu. * Popdown the posted menu. * Turn parent's traversal off. * Mark the drawnbutton as armed (i.e. active). * The callbacks for XmNarmCallback are called. * ************************************************************************/ /*ARGSUSED*/ static void BtnDown( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; Boolean validButton = False; Boolean already_armed; ShellWidget popup; XmMenuSystemTrait menuSTrait; /* Support menu replay, free server input queue until next button event */ XAllowEvents(XtDisplay(db), SyncPointer, CurrentTime); /* If no menu system trait then parent isn't a menu as it should be. */ menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem); if (menuSTrait == NULL) return; if (event && (event->type == ButtonPress)) validButton = menuSTrait->verifyButton(XtParent(db), event); if (!validButton) return; _XmSetInDragMode((Widget)db, True); /* Popdown other popus that may be up */ if (!(popup = (ShellWidget)_XmGetRC_PopupPosted(XtParent(db)))) { if (!XmIsMenuShell(XtParent(XtParent(db)))) { /* In case tear off not armed and no grabs in place, do it now. * Ok if already armed and grabbed - nothing done. */ menuSTrait->tearOffArm(XtParent(db)); } } if (popup) { if (popup->shell.popped_up) menuSTrait->popdownEveryone((Widget) popup, event); } /* Set focus to this drawnbutton. This must follow the possible * unhighlighting of the CascadeButton else it'll screw up active_child. */ (void)XmProcessTraversal ((Widget) db, XmTRAVERSE_CURRENT); /* get the location cursor - get consistent with Gadgets */ already_armed = db->drawnbutton.armed; db->drawnbutton.armed = TRUE; if (db->drawnbutton.arm_callback && !already_armed) { XFlush (XtDisplay (db)); call_value.reason = XmCR_ARM; call_value.event = event; XtCallCallbackList((Widget) db, db->drawnbutton.arm_callback, &call_value); } _XmRecordEvent (event); } /************************************************************************ * * BtnUp * * This function processes a button up occuring on the drawnbutton * when it is in a popup, pulldown, or option menu. * Mark the drawnbutton as unarmed (i.e. inactive). * The callbacks for XmNactivateCallback are called. * The callbacks for XmNdisarmCallback are called. * ************************************************************************/ /*ARGSUSED*/ static void BtnUp( Widget wid, XEvent *event, String *params, /* unused */ Cardinal *num_params ) /* unused */ { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; Widget parent = XtParent(db); XmDrawnButtonCallbackStruct call_value; Boolean flushDone = False; Boolean validButton = False; Boolean popped_up; Boolean is_menupane = Lab_IsMenupane(db); Widget shell = XtParent(XtParent(db)); XmMenuSystemTrait menuSTrait; /* If no menu system trait then parent isn't a menu as it should be. */ menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(db)), XmQTmenuSystem); if (menuSTrait == NULL) return; if (event && (event->type == ButtonRelease)) validButton = menuSTrait->verifyButton(parent, event); if (!validButton || (db->drawnbutton.armed == FALSE)) return; db->drawnbutton.armed = FALSE; if (is_menupane && !XmIsMenuShell(shell)) popped_up = menuSTrait->popdown((Widget) db, event); else popped_up = menuSTrait->buttonPopdown((Widget) db, event); _XmRecordEvent(event); /* XmMENU_POPDOWN left the menu posted on button click - don't activate! */ if (popped_up) return; call_value.reason = XmCR_ACTIVATE; call_value.event = event; call_value.click_count = 1; /* if the parent is menu system able, notify it about the select */ if (menuSTrait != NULL) { menuSTrait->entryCallback(parent, (Widget) db, &call_value); flushDone = True; } if ((! db->label.skipCallback) && (db->drawnbutton.activate_callback)) { XFlush (XtDisplay (db)); flushDone = True; XtCallCallbackList ((Widget) db, db->drawnbutton.activate_callback, &call_value); } if (db->drawnbutton.disarm_callback) { if (!flushDone) XFlush (XtDisplay (db)); call_value.reason = XmCR_DISARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value); } /* If the original shell does not indicate an active menu, but rather a * tear off pane, leave the button in an armed state. Also, briefly * display the button as depressed to give the user some feedback of * the selection. */ if (is_menupane) /* necessary check? */ { if (!XmIsMenuShell(shell)) { if (XtIsSensitive((Widget)db)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(db)); Boolean etched_in = dpy->display.enable_etched_in_menu; if ((db->core.width > 2 * db->primitive.highlight_thickness) && (db->core.height > 2 * db->primitive.highlight_thickness)) XmeDrawShadows (XtDisplay (db), XtWindow (db), db->primitive.bottom_shadow_GC, db->primitive.top_shadow_GC, db->primitive.highlight_thickness, db->primitive.highlight_thickness, db->core.width - 2 * db->primitive.highlight_thickness, db->core.height - 2 * db->primitive.highlight_thickness, db->primitive.shadow_thickness, etched_in ? XmSHADOW_IN : XmSHADOW_OUT); XFlush (XtDisplay (db)); flushDone = True; if (db->core.being_destroyed == False) { if (!db->drawnbutton.timer) db->drawnbutton.timer = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)db), (unsigned long) DELAY_DEFAULT, ArmTimeout, (XtPointer)(db)); } db->drawnbutton.armed = TRUE; if (db->drawnbutton.arm_callback) { if (!flushDone) XFlush (XtDisplay (db)); call_value.reason = XmCR_ARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value); } } } else menuSTrait->reparentToTearOffShell(XtParent(db), event); } _XmSetInDragMode((Widget)db, False); /* For the benefit of tear off menus, we must set the focus item * to this button. In normal menus, this would not be a problem * because the focus is cleared when the menu is unposted. */ if (!XmIsMenuShell(shell)) XmProcessTraversal((Widget) db, XmTRAVERSE_CURRENT); DB_FixTearoff(db); } /************************************************************************ * * Enter * ************************************************************************/ static void Enter( Widget wid, XEvent *event, String *params, Cardinal *num_params ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; if (Lab_IsMenupane(db)) { if ((((ShellWidget) XtParent(XtParent(db)))->shell.popped_up) && _XmGetInDragMode((Widget)db)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); if (db->drawnbutton.armed) return; /* So KHelp event is delivered correctly */ _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, TRUE); XtSetKeyboardFocus(XtParent(XtParent(db)), (Widget)db); _XmSetFocusFlag (XtParent(XtParent(db)), XmFOCUS_IGNORE, FALSE); db -> drawnbutton.armed = TRUE; ((XmManagerWidget) XtParent(wid))->manager.active_child = wid; if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); if (db->drawnbutton.arm_callback) { XFlush (XtDisplay (db)); call_value.reason = XmCR_ARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value); } } } else { _XmPrimitiveEnter (wid, event, params, num_params); if (db -> drawnbutton.pushbutton_enabled && db -> drawnbutton.armed == TRUE) DrawPushButton(db, TRUE); } } /************************************************************************ * * Leave * ************************************************************************/ static void Leave( Widget wid, XEvent *event, String *params, Cardinal *num_params ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; if (Lab_IsMenupane(db)) { if (_XmGetInDragMode((Widget)db) && db->drawnbutton.armed && (/* !ActiveTearOff || */ event->xcrossing.mode == NotifyNormal)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); db->drawnbutton.armed = FALSE; ((XmManagerWidget) XtParent(wid))->manager.active_child = NULL; if (db->drawnbutton.pushbutton_enabled) { XmeClearBorder (XtDisplay (db), XtWindow (db), db->primitive.highlight_thickness, db->primitive.highlight_thickness, db->core.width - 2 * db->primitive.highlight_thickness, db->core.height - 2 * db->primitive.highlight_thickness, db->primitive.shadow_thickness); } if (db->drawnbutton.disarm_callback) { XFlush (XtDisplay (db)); call_value.reason = XmCR_DISARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value); } } } else { _XmPrimitiveLeave (wid, event, params, num_params); if (db -> drawnbutton.pushbutton_enabled && db -> drawnbutton.armed == TRUE) DrawPushButton(db, FALSE); } } /*************************************<->************************************* * * BorderHighlight * *************************************<->***********************************/ static void BorderHighlight( Widget wid ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; XEvent * event = NULL; if (Lab_IsMenupane(db)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean already_armed = db->drawnbutton.armed; db->drawnbutton.armed = TRUE; if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); if (!already_armed && db->drawnbutton.arm_callback) { XFlush (XtDisplay (db)); call_value.reason = XmCR_ARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.arm_callback, &call_value); } } else { XtWidgetProc border_highlight; _XmProcessLock(); border_highlight = xmLabelClassRec.primitive_class.border_highlight; _XmProcessUnlock(); (*border_highlight)(wid); } } /*************************************<->************************************* * * BorderUnhighlight * *************************************<->***********************************/ static void BorderUnhighlight( Widget wid ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; XEvent * event = NULL; if (Lab_IsMenupane(db)) { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); Boolean already_armed = db->drawnbutton.armed; db->drawnbutton.armed = FALSE; if (db->drawnbutton.pushbutton_enabled) { XmeClearBorder (XtDisplay (db), XtWindow (db), db->primitive.highlight_thickness, db->primitive.highlight_thickness, db->core.width - 2 * db->primitive.highlight_thickness, db->core.height - 2 * db->primitive.highlight_thickness, db->primitive.shadow_thickness); } if (already_armed && db->drawnbutton.disarm_callback) { XFlush (XtDisplay (db)); call_value.reason = XmCR_DISARM; call_value.event = event; XtCallCallbackList ((Widget) db, db->drawnbutton.disarm_callback, &call_value); } } else { XtWidgetProc border_unhighlight; _XmProcessLock(); border_unhighlight = xmLabelClassRec.primitive_class.border_unhighlight; _XmProcessUnlock(); (*border_unhighlight)(wid); } } /************************************************************************ * * ClassInitialize * Set up the base class extension record. * ************************************************************************/ static void ClassInitialize( void ) { /* parse the various translation tables */ menu_parsed = XtParseTranslationTable(menuTranslations); default_parsed = XtParseTranslationTable(defaultTranslations); /* set up base class extension quark */ drawnBBaseClassExtRec.record_type = XmQmotif; } /************************************************************************ * * ClassPartInitialize * Set up the fast subclassing for the widget * ************************************************************************/ static void ClassPartInitialize( WidgetClass wc ) { _XmFastSubclassInit (wc, XmDRAWN_BUTTON_BIT); /* Install the menu savvy trait record, copying fields from XmLabel */ _XmLabelCloneMenuSavvy (wc, &MenuSavvyRecord); /* Install the activatable trait for all subclasses */ XmeTraitSet((XtPointer)wc, XmQTactivatable, (XtPointer) &drawnButtonAT); } /************************************************************ * * InitializePrehook * * Put the proper translations in core_class tm_table so that * the data is massaged correctly * ************************************************************/ /*ARGSUSED*/ static void InitializePrehook( Widget rw, /* unused */ Widget nw, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ; unsigned char type; XmMenuSystemTrait menuSTrait; menuSTrait = (XmMenuSystemTrait) XmeTraitGet((XtPointer) XtClass(XtParent(nw)), XmQTmenuSystem); _XmSaveCoreClassTranslations (nw); if (menuSTrait != NULL) type = menuSTrait->type(XtParent(nw)); else type = XmWORK_AREA; _XmProcessLock(); if (type == XmMENU_PULLDOWN || type == XmMENU_POPUP) nw->core.widget_class->core_class.tm_table = (String) menu_parsed; else nw->core.widget_class->core_class.tm_table = (String) default_parsed; /* CR 2990: Use XmNbuttonFontList as the default font. */ if (bw->label.font == NULL) bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST); _XmProcessUnlock(); } /************************************************************ * * InitializePosthook * * restore core class translations * ************************************************************/ /*ARGSUSED*/ static void InitializePosthook( Widget rw, /* unused */ Widget nw, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { _XmRestoreCoreClassTranslations (nw); } /*************************************<->************************************* * * Initialize * *************************************<->***********************************/ /*ARGSUSED*/ static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args ) { XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ; XmDrawnButtonWidget req_w = (XmDrawnButtonWidget) rw ; /* CR 2990: Use XmNbuttonFontList as the default font. */ if (req_w->label.font == NULL) { XmFontListFree (new_w->label.font); new_w->label.font = XmFontListCopy (XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST)); } new_w->drawnbutton.armed = FALSE; new_w->drawnbutton.timer = 0; /* if menuProcs is not set up yet, try again */ if (xmLabelClassRec.label_class.menuProcs == (XmMenuProc)NULL) xmLabelClassRec.label_class.menuProcs = (XmMenuProc) _XmGetMenuProcContext(); if( !XmRepTypeValidValue( XmRID_SHADOW_TYPE, new_w->drawnbutton.shadow_type, (Widget) new_w) ) { new_w -> drawnbutton.shadow_type = XmSHADOW_ETCHED_IN; } } /*************************************<->************************************* * * Resize (db) * *************************************<->***********************************/ static void Resize( Widget wid ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; XtWidgetProc resize; _XmProcessLock(); resize = xmLabelClassRec.core_class.resize; _XmProcessUnlock(); (* resize) ((Widget) db); /* CR 5419: Suppress redundant calls to the resize callbacks. */ if (db->drawnbutton.resize_callback && !Lab_ComputingSize(db)) { XFlush(XtDisplay (db)); call_value.reason = XmCR_RESIZE; call_value.event = NULL; call_value.window = XtWindow (db); XtCallCallbackList ((Widget) db, db->drawnbutton.resize_callback, &call_value); } } /*************************************<->************************************* * * Redisplay (db, event, region) * *************************************<->***********************************/ /*ARGSUSED*/ static void Redisplay( Widget wid, XEvent *event, Region region ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; XmDrawnButtonCallbackStruct call_value; if (XtIsRealized((Widget)db)) { if (event) { XtExposeProc expose; _XmProcessLock(); expose = xmLabelClassRec.core_class.expose; _XmProcessUnlock(); (* expose) ((Widget) db, event, region); } if (db->drawnbutton.pushbutton_enabled) DrawPushButton(db, db->drawnbutton.armed); else XmeDrawShadows(XtDisplay((Widget) db), XtWindow((Widget) db), db -> primitive.top_shadow_GC, db -> primitive.bottom_shadow_GC, db -> primitive.highlight_thickness, db -> primitive.highlight_thickness, db -> core.width - 2 * db -> primitive.highlight_thickness, db -> core.height - 2 * db -> primitive.highlight_thickness, db -> primitive.shadow_thickness, db->drawnbutton.shadow_type); if (db->drawnbutton.expose_callback) { XFlush(XtDisplay (db)); call_value.reason = XmCR_EXPOSE; call_value.event = event; call_value.window = XtWindow (db); XtCallCallbackList ((Widget) db, db->drawnbutton.expose_callback, &call_value); } } } static void DrawPushButton( XmDrawnButtonWidget db, #if NeedWidePrototypes int armed ) #else Boolean armed ) #endif /* NeedWidePrototypes */ { XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay((Widget) db)); Boolean etched_in = dpy -> display.enable_etched_in_menu; Boolean in_menu = Lab_IsMenupane((Widget) db); Boolean do_draw; unsigned int type; do_draw = (! in_menu) || (in_menu && armed); if (in_menu) type = etched_in ? XmSHADOW_IN : XmSHADOW_OUT; else type = armed ? XmSHADOW_IN : XmSHADOW_OUT; if (do_draw) XmeDrawShadows (XtDisplay (db), XtWindow (db), db -> primitive.top_shadow_GC, db -> primitive.bottom_shadow_GC, db -> primitive.highlight_thickness, db -> primitive.highlight_thickness, db -> core.width - 2 * db->primitive.highlight_thickness, db -> core.height - 2 * db->primitive.highlight_thickness, db -> primitive.shadow_thickness, type); } /************************************************************************ * * SetValuesPrehook * ************************************************************************/ /*ARGSUSED*/ static Boolean SetValuesPrehook( Widget cw, /* unused */ Widget rw, /* unused */ Widget nw, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { XmDrawnButtonWidget bw = (XmDrawnButtonWidget) nw ; /* CR 2990: Use XmNbuttonFontList as the default font. */ if (bw->label.font == NULL) bw->label.font = XmeGetDefaultRenderTable (nw, XmBUTTON_FONTLIST); return False; } /*************************************<->************************************* * * SetValues(current, request, new_w) * * Description: * ----------- * This is the set values procedure for the drawnbutton class. It is * called last (the set values rtnes for its superclasses are called * first). * * * Inputs: * ------ * current = original widget; * request = original copy of request; * new_w = copy of request which reflects changes made to it by * set values procedures of its superclasses; * last = TRUE if this is the last set values procedure to be called. * * Outputs: * ------- * * Procedures Called * ----------------- * *************************************<->***********************************/ /*ARGSUSED*/ static Boolean SetValues( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args ) { XmDrawnButtonWidget current = (XmDrawnButtonWidget) cw ; XmDrawnButtonWidget new_w = (XmDrawnButtonWidget) nw ; Boolean flag = FALSE; /* our return value */ /* Check the data put into the new widget. */ if( !XmRepTypeValidValue( XmRID_SHADOW_TYPE, new_w->drawnbutton.shadow_type, (Widget) new_w) ) { new_w->drawnbutton.shadow_type = current->drawnbutton.shadow_type ; } if (new_w -> drawnbutton.shadow_type != current-> drawnbutton.shadow_type || new_w -> primitive.foreground != current -> primitive.foreground || new_w -> core.background_pixel != current -> core.background_pixel || new_w -> primitive.highlight_thickness != current -> primitive.highlight_thickness || new_w -> primitive.shadow_thickness != current -> primitive.shadow_thickness) { flag = TRUE; } return(flag); } /************************************************************************* * * Realize * This function sets the bit gravity to forget. * *************************************************************************/ static void Realize( Widget w, XtValueMask *p_valueMask, XSetWindowAttributes *attributes ) { Mask valueMask = *p_valueMask; valueMask |= CWBitGravity | CWDontPropagate; attributes->bit_gravity = ForgetGravity; attributes->do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | PointerMotionMask; XtCreateWindow (w, InputOutput, CopyFromParent, valueMask, attributes); } /************************************************************************ * * Destroy * Clean up allocated resources when the widget is destroyed. * ************************************************************************/ static void Destroy( Widget wid ) { XmDrawnButtonWidget db = (XmDrawnButtonWidget) wid ; if (db->drawnbutton.timer) XtRemoveTimeOut (db->drawnbutton.timer); } /************************************************************************ * * ChangeCB * add or remove the activate callback list. * ************************************************************************/ static void ChangeCB( Widget w, XtCallbackProc activCB, XtPointer closure, Boolean setunset) { if (setunset) { XtAddCallback (w, XmNactivateCallback, activCB, closure); } else { XtRemoveCallback (w, XmNactivateCallback, activCB, closure); } } /************************************************************************ * * Application Accessible External Functions * ************************************************************************/ /************************************************************************ * * XmCreateDrawnButton * Create an instance of a drawnbutton and return the widget id. * ************************************************************************/ Widget XmCreateDrawnButton( Widget parent, char *name, ArgList arglist, Cardinal argcount ) { return (XtCreateWidget (name, xmDrawnButtonWidgetClass, parent, arglist, argcount)); }