/* * @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: Display.c /main/23 1997/06/18 17:36:59 samborn $" #endif #endif /* (c) Copyright 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #include #include #include #include #include #include #include #include #include #include "XmI.h" #include "DisplayI.h" #include "DragBSI.h" #include "DragCI.h" #include "DragICCI.h" #include "MessagesI.h" #include "VirtKeysI.h" #include "ColorObjI.h" #define MESSAGE1 _XmMMsgDisplay_0001 #define MESSAGE2 _XmMMsgDisplay_0002 #define MESSAGE3 _XmMMsgDisplay_0003 #define TheDisplay(dd) (XtDisplayOfObject((Widget)dd)) #define TheScreen(dd) (XtScreen((Widget)dd)) #define Offset(x) (XtOffsetOf( struct _XmDisplayRec, x)) #define CHECK_TIME(dc, time) \ ((dc->drag.dragStartTime <= time) && \ ((dc->drag.dragFinishTime == 0) || (time <= dc->drag.dragFinishTime))) #define INVALID_PROTOCOL_VALUE 255 /******** Static Function Declarations ********/ static void DisplayClassPartInitialize( WidgetClass wc) ; static void DisplayClassInitialize( void ) ; static void SetDragReceiverInfo( Widget w, XtPointer client_data, XEvent *event, Boolean *dontSwallow) ; static void TreeUpdateHandler( Widget w, XtPointer client, XtPointer call) ; static void DisplayInitialize( Widget requested_widget, Widget new_widget, ArgList args, Cardinal *num_args) ; static void DisplayInsertChild( Widget w) ; static void DisplayDeleteChild( Widget w) ; static void DisplayDestroy( Widget w) ; static XmDragContext FindDC( XmDisplay xmDisplay, Time time, #if NeedWidePrototypes int sourceIsExternal) ; #else Boolean sourceIsExternal) ; #endif /* NeedWidePrototypes */ static int isMine( Display *dpy, register XEvent *event, char *arg) ; static void ReceiverShellExternalSourceHandler( Widget w, XtPointer client_data, XEvent *event, Boolean *dontSwallow) ; static Widget GetDisplay( Display *display) ; /******** End Static Function Declarations ********/ externaldef(displaymsg) String _Xm_MOTIF_DRAG_AND_DROP_MESSAGE = NULL; static XContext displayContext = 0; static WidgetClass curDisplayClass = NULL; static XtResource resources[] = { { XmNdropSiteManagerClass, XmCDropSiteManagerClass, XmRWidgetClass, sizeof(WidgetClass), Offset(display.dropSiteManagerClass), XmRImmediate, (XtPointer)&xmDropSiteManagerClassRec, }, { XmNdropTransferClass, XmCDropTransferClass, XmRWidgetClass, sizeof(WidgetClass), Offset(display.dropTransferClass), XmRImmediate, (XtPointer)&xmDropTransferClassRec, }, { XmNdragContextClass, XmCDragContextClass, XmRWidgetClass, sizeof(WidgetClass), Offset(display.dragContextClass), XmRImmediate, (XtPointer)&xmDragContextClassRec, }, { XmNdragInitiatorProtocolStyle, XmCDragInitiatorProtocolStyle, XmRDragInitiatorProtocolStyle, sizeof(unsigned char), Offset(display.dragInitiatorProtocolStyle), XmRImmediate, (XtPointer)XmDRAG_PREFER_RECEIVER, }, { XmNdragReceiverProtocolStyle, XmCDragReceiverProtocolStyle, XmRDragReceiverProtocolStyle, sizeof(unsigned char), Offset(display.dragReceiverProtocolStyle), XmRImmediate, (XtPointer) XmDRAG_PREFER_PREREGISTER, }, { XmNdefaultVirtualBindings, XmCDefaultVirtualBindings, XmRString, sizeof(String), Offset(display.bindingsString), XmRImmediate, (XtPointer)NULL, }, { XmNuserData, XmCUserData, XmRPointer, sizeof(XtPointer), Offset(display.user_data), XmRImmediate, (XtPointer) NULL }, { XmNmotifVersion, XmCMotifVersion, XmRInt, sizeof(int), Offset(display.motif_version), XmRImmediate, (XtPointer) XmVersion }, { XmNenableWarp, XmCEnableWarp, XmREnableWarp, sizeof(XtEnum), Offset(display.enable_warp), XmRImmediate, (XtPointer) True }, { XmNdragStartCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), Offset(display.dragStartCallback), XmRImmediate, (XtPointer)NULL, }, { XmNnoFontCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), Offset(display.noFontCallback), XmRImmediate, (XtPointer)NULL, }, { XmNnoRenditionCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), Offset(display.noRenditionCallback), XmRImmediate, (XtPointer)NULL, }, { XmNenableBtn1Transfer, XmCEnableBtn1Transfer, XmREnableBtn1Transfer, sizeof(XtEnum), Offset(display.enable_btn1_transfer), XmRImmediate, (XtPointer) XmOFF }, { XmNenableButtonTab, XmCEnableButtonTab, XmRBoolean, sizeof(Boolean), Offset(display.enable_button_tab), XmRImmediate, (XtPointer) False }, { XmNenableEtchedInMenu, XmCEnableEtchedInMenu, XmRBoolean, sizeof(Boolean), Offset(display.enable_etched_in_menu), XmRImmediate, (XtPointer) False }, { XmNdefaultButtonEmphasis, XmCDefaultButtonEmphasis, XmRDefaultButtonEmphasis, sizeof(XtEnum), Offset(display.default_button_emphasis), XmRImmediate, (XtPointer) XmEXTERNAL_HIGHLIGHT }, { XmNenableToggleColor, XmCEnableToggleColor, XmRBoolean, sizeof(Boolean), Offset(display.enable_toggle_color), XmRImmediate, (XtPointer) False }, { XmNenableToggleVisual, XmCEnableToggleVisual, XmRBoolean, sizeof(Boolean), Offset(display.enable_toggle_visual), XmRImmediate, (XtPointer) False }, { XmNenableDragIcon, XmCEnableDragIcon, XmRBoolean, sizeof(Boolean), Offset(display.enable_drag_icon), XmRImmediate, (XtPointer) False }, { XmNenableUnselectableDrag, XmCEnableUnselectableDrag, XmRBoolean, sizeof(Boolean), Offset(display.enable_unselectable_drag), XmRImmediate, (XtPointer) True }, { XmNenableThinThickness, XmCEnableThinThickness, XmRBoolean, sizeof(Boolean), Offset(display.enable_thin_thickness), XmRImmediate, (XtPointer) False }, { XmNenableMultiKeyBindings, XmCEnableMultiKeyBindings, XmRBoolean, sizeof(Boolean), Offset(display.enable_multi_key_bindings), XmRImmediate, (XtPointer) False }, /* Force this resource to avoid loop in the pixmap conversion. XmDisplay is a VendorShell, so when iconPixmap is set in a resource file, the VendorShell converter is called, but since it needs an XmDisplay (via an XmScreen resource), it goes and create the XmDisplay, for which the iconPixmap is also converted: loop. By forcing it to Bitmap, the screen bitmapConversionModel is not needed and it works. This is a small limitation in XmDisplay */ { XmNiconPixmap, XmCIconPixmap, XmRBitmap, sizeof(Pixmap), XtOffsetOf(WMShellRec, wm.wm_hints.icon_pixmap), XmRImmediate, NULL }, }; #undef Offset static XmBaseClassExtRec baseClassExtRec = { NULL, NULLQUARK, XmBaseClassExtVersion, sizeof(XmBaseClassExtRec), (XtInitProc)NULL, /* InitializePrehook */ (XtSetValuesFunc)NULL, /* SetValuesPrehook */ (XtInitProc)NULL, /* InitializePosthook */ (XtSetValuesFunc)NULL, /* SetValuesPosthook */ NULL, /* secondaryObjectClass */ (XtInitProc)NULL, /* secondaryCreate */ (XmGetSecResDataFunc)NULL, /* getSecRes data */ { 0 }, /* fastSubclass flags */ (XtArgsProc)NULL, /* getValuesPrehook */ (XtArgsProc)NULL, /* getValuesPosthook */ (XtWidgetClassProc)NULL, /* classPartInitPrehook */ (XtWidgetClassProc)NULL, /* classPartInitPosthook*/ NULL, /* ext_resources */ NULL, /* compiled_ext_resources*/ 0, /* num_ext_resources */ FALSE, /* use_sub_resources */ (XmWidgetNavigableProc)NULL, /* widgetNavigable */ (XmFocusChangeProc)NULL, /* focusChange */ (XmWrapperData)NULL /* wrapperData */ }; externaldef(xmdisplayclassrec) XmDisplayClassRec xmDisplayClassRec = { { (WidgetClass) &applicationShellClassRec, /* superclass */ "XmDisplay", /* class_name */ sizeof(XmDisplayRec), /* size */ DisplayClassInitialize, /* Class Initializer */ DisplayClassPartInitialize, /* class_part_init */ FALSE, /* Class init'ed ? */ DisplayInitialize, /* initialize */ _XmColorObjCreate, /* initialize_notify */ XtInheritRealize, /* realize */ NULL, /* actions */ 0, /* num_actions */ resources, /* resources */ XtNumber(resources), /* resource_count */ NULLQUARK, /* xrm_class */ FALSE, /* compress_motion */ FALSE, /* compress_exposure */ FALSE, /* compress_enterleave */ FALSE, /* visible_interest */ DisplayDestroy, /* destroy */ (XtWidgetProc)NULL, /* resize */ (XtExposeProc)NULL, /* expose */ (XtSetValuesFunc)NULL, /* set_values */ (XtArgsFunc)NULL, /* set_values_hook */ (XtAlmostProc)NULL, /* set_values_almost */ (XtArgsProc)NULL, /* get_values_hook */ (XtAcceptFocusProc)NULL, /* accept_focus */ XtVersion, /* intrinsics version */ NULL, /* callback offsets */ NULL, /* tm_table */ (XtGeometryHandler)NULL, /* query_geometry */ (XtStringProc)NULL, /* display_accelerator */ (XtPointer)&baseClassExtRec, /* extension */ }, { /* composite class record */ (XtGeometryHandler)NULL, /* geometry_manager */ (XtWidgetProc)NULL, /* change_managed */ DisplayInsertChild, /* insert_child */ DisplayDeleteChild, /* from the shell */ NULL, /* extension record */ }, { /* shell class record */ NULL, /* extension record */ }, { /* wm shell class record */ NULL, /* extension record */ }, { /* vendor shell class record */ NULL, /* extension record */ }, { /* toplevelclass record */ NULL, /* extension record */ }, { /* appShell record */ NULL, /* extension record */ }, { /* Display class */ GetDisplay, /* GetDisplay */ NULL, /* extension */ }, }; externaldef(xmdisplayclass) WidgetClass xmDisplayClass = (WidgetClass) (&xmDisplayClassRec); static void DisplayClassPartInitialize( WidgetClass wc ) { _XmFastSubclassInit(wc, XmDISPLAY_BIT); } static void DisplayClassInitialize( void ) { baseClassExtRec.record_type = XmQmotif; _Xm_MOTIF_DRAG_AND_DROP_MESSAGE = XmMakeCanonicalString("_MOTIF_DRAG_AND_DROP_MESSAGE"); } /*ARGSUSED*/ static void SetDragReceiverInfo( Widget w, XtPointer client_data, XEvent *event, Boolean *dontSwallow ) { XmDisplay dd = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); if (XtIsRealized(w)) { _XmSetDragReceiverInfo(dd, (Widget)client_data); XtRemoveEventHandler(w, StructureNotifyMask, False, SetDragReceiverInfo, client_data); } } /* * this routine is registered on the XmNtreeUpdateProc resource of the * dropSiteManager. It is called whenever the tree is changed. */ /*ARGSUSED*/ static void TreeUpdateHandler( Widget w, XtPointer client, XtPointer call ) { XmAnyCallbackStruct *anyCB = (XmAnyCallbackStruct *)call; XmDisplay dd = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); if (dd->display.dragReceiverProtocolStyle == XmDRAG_NONE) return; switch(anyCB->reason) { case XmCR_DROP_SITE_TREE_ADD: { XmDropSiteTreeAddCallback cb = (XmDropSiteTreeAddCallback)anyCB; if (XtIsRealized(cb->rootShell)) { _XmSetDragReceiverInfo(dd, cb->rootShell); } else { XtAddEventHandler(cb->rootShell, StructureNotifyMask, False, SetDragReceiverInfo, (XtPointer)cb->rootShell); } /* * ClientMessages are not maskable so all we have to * do is indicate interest in non-maskable events. */ XtAddEventHandler(cb->rootShell, NoEventMask, True, ReceiverShellExternalSourceHandler, (XtPointer)dd); } break; case XmCR_DROP_SITE_TREE_REMOVE: { XmDropSiteTreeRemoveCallback cb = (XmDropSiteTreeRemoveCallback)anyCB; XtRemoveEventHandler(cb->rootShell, NoEventMask, True, ReceiverShellExternalSourceHandler, (XtPointer)dd); if (XtIsRealized(cb->rootShell)) _XmClearDragReceiverInfo(cb->rootShell); } break; default: break; } } /************************************************************************ * * DisplayInitialize * ************************************************************************/ /* ARGSUSED */ static void DisplayInitialize( Widget requested_widget, Widget new_widget, ArgList args, Cardinal *num_args ) { static char *atom_names[] = { "Customize Data:0", /* XmSCUSTOMIZE_DATA + "0" */ XmIATOM_PAIR, XmIAVERAGE_WIDTH, XmIPIXEL_SIZE, XmIRESOLUTION_Y, XmIWM_DELETE_WINDOW, XmI_MOTIF_DRAG_ATOMS, XmI_MOTIF_DRAG_INITIATOR_INFO, XmI_MOTIF_DRAG_PROXY_WINDOW, XmI_MOTIF_DRAG_RECEIVER_INFO, XmI_MOTIF_DRAG_TARGETS, XmI_MOTIF_DRAG_WINDOW, XmSCLIPBOARD, XmSCLIP_TEMPORARY, XmSCOMPOUND_TEXT, XmSDELETE, XmSINCR, XmSINSERT_SELECTION, XmSLENGTH, XmSLINK_SELECTION, XmSMULTIPLE, XmSNULL, XmSTARGETS, XmSTEXT, XmSTIMESTAMP, XmSTRANSFER_FAILURE, XmSTRANSFER_SUCCESS, XmSWM_STATE, XmS_MOTIF_ATOM_0, XmS_MOTIF_CLIP_DATA_DELETE, XmS_MOTIF_CLIP_DATA_REQUEST, XmS_MOTIF_CLIP_HEADER, XmS_MOTIF_CLIP_LOCK_ACCESS_VALID, XmS_MOTIF_CLIP_MESSAGE, XmS_MOTIF_CLIP_NEXT_ID, XmS_MOTIF_CLIP_TIME, XmS_MOTIF_CLIPBOARD_TARGETS, XmS_MOTIF_DESTINATION, XmS_MOTIF_DRAG_OFFSET, XmS_MOTIF_DEFERRED_CLIPBOARD_TARGETS, XmS_MOTIF_DROP, XmS_MOTIF_EXPORT_TARGETS, XmS_MOTIF_LOSE_SELECTION, _XA_MOTIF_BINDINGS, _XA_MOTIF_WM_HINTS, _XA_MOTIF_WM_INFO, _XA_MOTIF_WM_MENU, _XA_MOTIF_WM_MESSAGES, _XA_MOTIF_WM_OFFSET, "WM_PROTOCOLS" }; Atom atoms[XtNumber(atom_names)]; XmDisplay xmDisplay = (XmDisplay)new_widget; int dummy1, dummy2; XContext context; /* * Pre-load the Xlib atom cache with atoms we are likely to use, * similar to the way _XmInitAtomPairs() did in Motif 1.2.x. */ XInternAtoms(XtDisplay(xmDisplay), atom_names, XtNumber(atom_names), False, atoms); xmDisplay->display.shellCount = 0; xmDisplay->display.numModals = 0; xmDisplay->display.modals = NULL; xmDisplay->display.maxModals = 0; xmDisplay->display.userGrabbed = False; xmDisplay->display.activeDC = NULL; xmDisplay->display.dsm = (XmDropSiteManagerObject) NULL; xmDisplay->display.proxyWindow = _XmGetDragProxyWindow(XtDisplay(xmDisplay)); _XmInitByteOrderChar(); xmDisplay->display.xmim_info = NULL; xmDisplay->display.displayInfo = (XtPointer) XtNew(XmDisplayInfo); ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->SashCursor = 0L; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->TearOffCursor = 0L; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->UniqueStamp = 0L; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->destinationWidget= (Widget)NULL; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->excParentPane.pane = (Widget *)NULL; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->excParentPane.pane_list_size = 0; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->excParentPane.num_panes= 0; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->resetFocusFlag = 0; ((XmDisplayInfo *)(xmDisplay->display.displayInfo))->traversal_in_progress= FALSE; xmDisplay->display.displayHasShapeExtension = XShapeQueryExtension(XtDisplay(xmDisplay), &dummy1, &dummy2); /* Handle dynamic default of receiver protocol style */ if (xmDisplay->display.dragReceiverProtocolStyle == INVALID_PROTOCOL_VALUE) { if (xmDisplay->display.displayHasShapeExtension) xmDisplay->display.dragReceiverProtocolStyle = XmDRAG_PREFER_DYNAMIC; else xmDisplay->display.dragReceiverProtocolStyle = XmDRAG_PREFER_PREREGISTER; } _XmVirtKeysInitialize (new_widget); _XmProcessLock(); if (displayContext == 0) displayContext = XUniqueContext(); context = displayContext; _XmProcessUnlock(); if (! XFindContext(XtDisplay(xmDisplay), None, context, (char **) &xmDisplay)) { /* * There's one already created for this display. * What should we do? If we destroy the previous one, we may * wreak havoc with shell modality and screen objects. BUT, * Xt doesn't really give us a way to abort a create. We'll * just let the new one dangle. */ XmeWarning((Widget) xmDisplay, MESSAGE1); } else { XSaveContext(XtDisplayOfObject((Widget)xmDisplay), None, context, (char *)xmDisplay); } if (xmDisplay->display.enable_multi_key_bindings) { Display * display = XtDisplay(new_widget); int i, num_screens = ScreenCount(display); XrmDatabase new_db; for (i = 0; i < num_screens; i++) { Screen * screen = ScreenOfDisplay(display, i); XrmDatabase db = XtScreenDatabase(screen); new_db = XrmGetStringDatabase(_XmDisplay_baseTranslations); XrmCombineDatabase(new_db, &db, False); } } } /************************************************************************ * * DisplayInsertChild * ************************************************************************/ static void DisplayInsertChild( Widget w ) { if (XtIsRectObj(w)) { XtWidgetProc insert_child; _XmProcessLock(); insert_child = ((CompositeWidgetClass)compositeWidgetClass) ->composite_class.insert_child; _XmProcessUnlock(); (*insert_child)(w); } } /************************************************************************ * * DisplayDeleteChild * ************************************************************************/ static void DisplayDeleteChild( Widget w ) { if (XtIsRectObj(w)) { XtWidgetProc delete_child; _XmProcessLock(); delete_child = ((CompositeWidgetClass)compositeWidgetClass) ->composite_class.delete_child; _XmProcessUnlock(); (*delete_child)(w); } } /************************************************************************ * * DisplayDestroy * ************************************************************************/ /* ARGSUSED */ static void DisplayDestroy( Widget w ) { XmDisplay dd = (XmDisplay) w ; XContext context; _XmProcessLock(); context = displayContext; _XmProcessUnlock(); XtFree((char *) dd->display.modals); if (((XmDisplayInfo *)(dd->display.displayInfo)) ->excParentPane.pane != (Widget *)NULL) XtFree((char *) ((XmDisplayInfo *)(dd->display.displayInfo)) ->excParentPane.pane); XtFree((char *) dd->display.displayInfo); /* Destroy the DropSiteManager object. */ if (dd->display.dsm != NULL) XtDestroyWidget((Widget) dd->display.dsm); _XmClearDisplayTables(XtDisplay(w)); _XmVirtKeysDestroy (w); XDeleteContext( XtDisplay( w), None, context) ; } /*ARGSUSED*/ XmDropSiteManagerObject _XmGetDropSiteManagerObject( XmDisplay xmDisplay ) { /* Defer the creation of the XmDisplayObject's DropSiteManager until * it is referenced, since the converters of some DSM resources * (animationPixmap, for instance) depend on the presence of the * Display/Screen objects, and a circular recursive creation loop * results if the DSM is created during DisplayInitialize. */ if( xmDisplay->display.dsm == NULL ) { Arg lclArgs[1] ; XtSetArg( lclArgs[0], XmNtreeUpdateProc, TreeUpdateHandler) ; xmDisplay->display.dsm = (XmDropSiteManagerObject) XtCreateWidget( "dsm", xmDisplay->display.dropSiteManagerClass, (Widget) xmDisplay, lclArgs, 1) ; } return( xmDisplay->display.dsm); } unsigned char _XmGetDragProtocolStyle( Widget w ) { XmDisplay xmDisplay; unsigned char style; xmDisplay = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); switch(xmDisplay->display.dragReceiverProtocolStyle) { case XmDRAG_NONE: case XmDRAG_DROP_ONLY: style = XmDRAG_NONE; break; case XmDRAG_DYNAMIC: style = XmDRAG_DYNAMIC; break; case XmDRAG_PREFER_DYNAMIC: case XmDRAG_PREFER_PREREGISTER: case XmDRAG_PREREGISTER: style = XmDRAG_PREREGISTER; break; default: style = XmDRAG_NONE; break; } return style; } Widget XmGetDragContext( Widget w, Time time ) { XmDisplay xmDisplay; XmDragContext matchedDC = NULL, dc = NULL; Cardinal i; _XmWidgetToAppContext(w); _XmAppLock(app); xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(w)); for(i = 0; i < xmDisplay->composite.num_children; i++) { dc = (XmDragContext)(xmDisplay->composite.children[i]); if ((XmIsDragContext((Widget) dc)) && (CHECK_TIME(dc, time)) && ((!matchedDC) || (matchedDC->drag.dragStartTime < dc->drag.dragStartTime)) && !dc->core.being_destroyed) matchedDC = dc; } _XmAppUnlock(app); return((Widget)matchedDC); } Widget _XmGetDragContextFromHandle( Widget w, Atom iccHandle ) { XmDisplay xmDisplay; XmDragContext dc; Cardinal i; xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(w)); for(i = 0; i < xmDisplay->composite.num_children; i++) { dc = (XmDragContext)(xmDisplay->composite.children[i]); if ((XmIsDragContext((Widget) dc)) && (dc->drag.iccHandle == iccHandle) && !dc->core.being_destroyed) return((Widget)dc); } return(NULL); } static XmDragContext FindDC( XmDisplay xmDisplay, Time time, #if NeedWidePrototypes int sourceIsExternal ) #else Boolean sourceIsExternal ) #endif /* NeedWidePrototypes */ { XmDragContext dc = NULL; Cardinal i; for(i = 0; i < xmDisplay->composite.num_children; i++) { dc = (XmDragContext)(xmDisplay->composite.children[i]); if ((XmIsDragContext((Widget) dc)) && (CHECK_TIME(dc, time)) && (dc->drag.sourceIsExternal == sourceIsExternal) && !dc->core.being_destroyed) return(dc); } return(NULL); } /*ARGSUSED*/ static int isMine( Display *dpy, register XEvent *event, char *arg ) { XmDisplayEventQueryStruct *q = (XmDisplayEventQueryStruct *) arg; XmICCCallbackStruct callback, *cb = &callback; /* Once we have a drop start we must stop looking at the queue */ if (q->hasDropStart) return(False); if (!_XmICCEventToICCCallback((XClientMessageEvent *)event, cb, XmICC_INITIATOR_EVENT)) return(False); if ((cb->any.reason == XmCR_DROP_SITE_ENTER) || (cb->any.reason == XmCR_DROP_SITE_LEAVE)) { /* * We must assume this to be a dangling set of messages, so * we will quietly consume it in the interest of hygene. */ return(True); } if (!q->dc) q->dc = FindDC(q->dd, cb->any.timeStamp, True); /* * if we can find a dc then we have already processed * an enter for this shell. */ switch(cb->any.reason) { case XmCR_TOP_LEVEL_ENTER: q->hasLeave = False; if (q->dc == NULL) { *(q->enterCB) = *(XmTopLevelEnterCallbackStruct *)cb; q->hasEnter = True; } break; case XmCR_TOP_LEVEL_LEAVE: if (q->dc != NULL) { *(q->leaveCB) = *(XmTopLevelLeaveCallbackStruct *)cb; q->hasLeave = True; q->hasMotion = False; } else { /* * hasEnter is true if we are missing a * drag context because an enter got compressed. * In that case, all is OK, and no warning is * needed. ??? Is a warning ever needed ??? */ if (!q->hasEnter) XmeWarning((Widget) q->dd, MESSAGE2); } q->hasEnter = False; break; case XmCR_DRAG_MOTION: *(q->motionCB) = *(XmDragMotionCallbackStruct *)cb; q->hasMotion = True; break; case XmCR_DROP_START: *(q->dropStartCB) = *(XmDropStartCallbackStruct *)cb; q->hasDropStart = True; break; default: break; } return True; } /* * this handler is used to catch messages from external drag * contexts that want to map motion or drop events */ /*ARGSUSED*/ static void ReceiverShellExternalSourceHandler( Widget w, XtPointer client_data, XEvent *event, Boolean *dontSwallow ) { XmDragTopLevelClientDataStruct topClientData; XmTopLevelEnterCallbackStruct enterCB; XmTopLevelLeaveCallbackStruct leaveCB; XmDropStartCallbackStruct dropStartCB; XmDragMotionCallbackStruct motionCB; XmDisplayEventQueryStruct q; Widget shell = w; XmDisplay dd = (XmDisplay) XmGetXmDisplay(XtDisplay(w)); XmDragContext dc; XmDropSiteManagerObject dsm = _XmGetDropSiteManagerObject( dd); /* * If dd has an active dc then we are the initiator. We shouldn't * do receiver processing as the initiator, so bail out. */ if (dd->display.activeDC != NULL) return; q.dd = dd; q.dc = (XmDragContext)NULL; q.enterCB = &enterCB; q.leaveCB = &leaveCB; q.motionCB = &motionCB; q.dropStartCB = &dropStartCB; q.hasEnter = q.hasDropStart = q.hasLeave = q.hasMotion = False; /* * Since this event handler gets called for all non-maskable events, * we want to bail out now with don't swallow if we don't want this * event. Otherwise we'll swallow it. */ /* * process the event that fired this event handler. * If it's not a Receiver DND event, bail out. */ if (!isMine(XtDisplayOfObject(w), event, (char*)&q)) return; /* * swallow all the pending messages inline except the last motion */ while (XCheckIfEvent( XtDisplayOfObject(w), event, isMine, (char*)&q)) /*EMPTY*/; dc = q.dc; if (q.hasEnter || q.hasMotion || q.hasDropStart || q.hasLeave) { /* * handle a dangling leave first */ if (q.hasLeave) { XmTopLevelLeaveCallback callback = &leaveCB; topClientData.destShell = shell; topClientData.xOrigin = shell->core.x; topClientData.yOrigin = shell->core.y; topClientData.sourceIsExternal = True; topClientData.iccInfo = NULL; topClientData.window = XtWindow(w); topClientData.dragOver = NULL; _XmDSMUpdate(dsm, (XtPointer)&topClientData, (XtPointer)callback); /* destroy it if no drop. otherwise done in dropTransfer */ if (!q.hasDropStart) { XtDestroyWidget((Widget)dc); q.dc = dc = NULL; } } /* * check for a dropStart from a preregister client or an enter * either of which require a dc to be alloced */ if (q.hasEnter || q.hasDropStart) { if (!q.dc) { Arg args[4]; Cardinal i = 0; Time timeStamp; Window window; Atom iccHandle; if (q.hasDropStart) { XmDropStartCallback dsCallback = &dropStartCB; timeStamp = dsCallback->timeStamp; window = dsCallback->window; iccHandle = dsCallback->iccHandle; } else { XmTopLevelEnterCallback teCallback = &enterCB; timeStamp = teCallback->timeStamp; window = teCallback->window; iccHandle = teCallback->iccHandle; } XtSetArg(args[i], XmNsourceWindow, window);i++; XtSetArg(args[i], XmNsourceIsExternal,True);i++; XtSetArg(args[i], XmNstartTime, timeStamp);i++; XtSetArg(args[i], XmNiccHandle, iccHandle);i++; dc = (XmDragContext) XtCreateWidget("dragContext", dd->display.dragContextClass, (Widget)dd, args, i); _XmReadInitiatorInfo((Widget)dc); /* * force in value for dropTransfer to use in selection * calls. */ dc->drag.currReceiverInfo = _XmAllocReceiverInfo(dc); dc->drag.currReceiverInfo->shell = shell; dc->drag.currReceiverInfo->dragProtocolStyle = dd->display.dragReceiverProtocolStyle; } topClientData.destShell = shell; topClientData.xOrigin = XtX(shell); topClientData.yOrigin = XtY(shell); topClientData.width = XtWidth(shell); topClientData.height = XtHeight(shell); topClientData.sourceIsExternal = True; topClientData.iccInfo = NULL; } if (!dc) return; if (q.hasDropStart) { dc->drag.dragFinishTime = dropStartCB.timeStamp; _XmDSMUpdate(dsm, (XtPointer)&topClientData, (XtPointer)&dropStartCB); } /* * we only see enters if they're not matched with a leave */ if (q.hasEnter) { _XmDSMUpdate(dsm, (XtPointer)&topClientData, (XtPointer)&enterCB); } if (q.hasMotion) { XmDragMotionCallback callback = &motionCB; XmDragMotionClientDataStruct motionData; motionData.window = XtWindow(w); motionData.dragOver = NULL; _XmDSMUpdate(dsm, (XtPointer)&motionData, (XtPointer)callback); } } } static Widget GetDisplay( Display *display ) { XmDisplay xmDisplay = NULL; XContext context; Arg args[3]; int n; _XmProcessLock(); context = displayContext; _XmProcessUnlock(); if ((context == 0) || (XFindContext(display, None, context, (char **) &xmDisplay))) { String name, w_class; XtGetApplicationNameAndClass(display, &name, &w_class); n = 0; XtSetArg(args[n], XmNmappedWhenManaged, False); n++; XtSetArg(args[n], XmNwidth, 1); n++; XtSetArg(args[n], XmNheight, 1); n++; xmDisplay = (XmDisplay) XtAppCreateShell(name, w_class, xmDisplayClass, display, args, n); } /* We need a window to be useful */ if (!XtIsRealized((Widget)xmDisplay)) { XtRealizeWidget((Widget)xmDisplay); /* * Got the resources - get rid of name-type properties. * Otherwise, clients (ie: xwd) may get the wrong window * using the -name option. */ XDeleteProperty(display, XtWindow(xmDisplay), XA_WM_NAME); XDeleteProperty(display, XtWindow(xmDisplay), XA_WM_ICON_NAME); XDeleteProperty(display, XtWindow(xmDisplay), XA_WM_CLASS); } return ((Widget)xmDisplay); } Widget XmGetXmDisplay( Display *display ) { XmDisplayClass dC; Widget w; _XmDisplayToAppContext(display); /* * We have a chicken and egg problem here; we'd like to get * the display via a class function, but we don't know which * class to use. Hence the magic functions _XmGetXmDisplayClass * and _XmSetXmDisplayClass. */ _XmAppLock(app); _XmProcessLock(); dC = (XmDisplayClass) _XmGetXmDisplayClass(); w = (*(dC->display_class.GetDisplay))(display); _XmProcessUnlock(); _XmAppUnlock(app); return w; } /* * It would be nice if the next two functions were methods, but * for obvious reasons they're not. */ WidgetClass _XmGetXmDisplayClass( void ) { WidgetClass class; _XmProcessLock(); if (curDisplayClass == NULL) curDisplayClass = xmDisplayClass; class = curDisplayClass; _XmProcessUnlock(); return class; } WidgetClass _XmSetXmDisplayClass( WidgetClass wc ) { WidgetClass oldDisplayClass; WidgetClass sc = wc; _XmProcessLock(); oldDisplayClass = curDisplayClass; /* * We aren't going to let folks just set any old class in as the * display class. They will have to use subclasses of xmDisplay. */ while ((sc != NULL) && (sc != xmDisplayClass)) sc = sc->core_class.superclass; if (sc != NULL) curDisplayClass = wc; else XmeWarning(NULL, MESSAGE3); _XmProcessUnlock(); return(oldDisplayClass); } /********************************************************************** * * _XmSetThickness * This procedure is called as the resource default XtRCallProc * to default the shadow and highlight thickness resources. If * enablethinThickness is true (CDE apps), the value is "1 pixel", * else defaults to "2". **********************************************************************/ void _XmSetThickness( Widget widget, int offset, XrmValue *value ) { XmDisplay xmDisplay; static Dimension thickness; xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(widget)); if (xmDisplay->display.enable_thin_thickness) { thickness = 1; } else { thickness = 2; } value->addr = (XPointer)&thickness; } /********************************************************************** * * _XmSetThicknessDefault0 * This procedure is called as the resource default XtRCallProc * to default the shadow and highlight thickness resources. If * enablethinThickness is true (CDE apps), the value is "1 pixel", * else defaults to "0". **********************************************************************/ void _XmSetThicknessDefault0( Widget widget, int offset, XrmValue *value ) { XmDisplay xmDisplay; static Dimension thickness; xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(widget)); if (xmDisplay->display.enable_thin_thickness) { thickness = 1; } else { thickness = 0; } value->addr = (XPointer)&thickness; }