static void DndReadSourceProperty(Display * dpy, Window window, Atom dnd_selection, Atom ** targets, unsigned short * num_targets) { unsigned char *retval = 0; Atom type ; int format ; unsigned long bytesafter, lengthRtn; if ((XGetWindowProperty (dpy, window, dnd_selection, 0L, 100000L, False, ATOM(_MOTIF_DRAG_INITIATOR_INFO), &type, &format, &lengthRtn, &bytesafter, &retval) != Success) || (type == XNone)) { *num_targets = 0; return ; } DndSrcProp * src_prop = (DndSrcProp *)retval; if (src_prop->byte_order != DndByteOrder()) { SWAP2BYTES(src_prop->target_index); SWAP4BYTES(src_prop->selection); } *num_targets = _DndIndexToTargets(dpy, src_prop->target_index, targets); XFree((char*)src_prop); }
static DndTargetsTable TargetsTable(Display *display) { Atom type; int format; unsigned long size; unsigned long bytes_after; Window motif_window = MotifWindow(display) ; unsigned char *retval; DndTargetsTable targets_table ; int i,j ; char * target_data ; /* this version does no caching, so it's slow: round trip each time */ /* ideally, register for property notify on this target_list atom and update when necessary only */ if ((XGetWindowProperty (display, motif_window, ATOM(_MOTIF_DRAG_TARGETS), 0L, 100000L, False, ATOM(_MOTIF_DRAG_TARGETS), &type, &format, &size, &bytes_after, &retval) != Success) || type == XNone) { qWarning("QMotifDND: Cannot get property on Motif window"); return 0; } DndTargets * target_prop = (DndTargets *)retval; if (target_prop->protocol_version != DND_PROTOCOL_VERSION) { qWarning("QMotifDND: Protocol mismatch"); } if (target_prop->byte_order != DndByteOrder()) { /* need to swap num_target_lists and size */ SWAP2BYTES(target_prop->num_target_lists); SWAP4BYTES(target_prop->data_size); } /* now parse DndTarget prop data in a TargetsTable */ targets_table = (DndTargetsTable)malloc(sizeof(DndTargetsTableRec)); targets_table->num_entries = target_prop->num_target_lists ; targets_table->entries = (DndTargetsTableEntry) malloc(sizeof(DndTargetsTableEntryRec) * target_prop->num_target_lists); target_data = (char*)target_prop + sizeof(*target_prop) ; for (i = 0 ; i < targets_table->num_entries; i++) { CARD16 num_targets ; CARD32 atom ; memcpy(&num_targets, target_data, 2); target_data += 2; /* potential swap needed here */ if (target_prop->byte_order != DndByteOrder()) SWAP2BYTES(num_targets); targets_table->entries[i].num_targets = num_targets ; targets_table->entries[i].targets = (Atom *) malloc(sizeof(Atom) * targets_table->entries[i].num_targets); for (j = 0; j < num_targets; j++) { memcpy(&atom, target_data, 4); target_data += 4; /* another potential swap needed here */ if (target_prop->byte_order != DndByteOrder()) SWAP4BYTES(atom); targets_table->entries[i].targets[j] = (Atom) atom ; } } if (target_prop) { XFree((char *)target_prop); } return targets_table ; }
static Bool DndParseClientMessage(XClientMessageEvent *cm, DndData * dnd_data, char * receiver) { DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; if (cm->message_type != ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE)) { return False ; } if (dnd_message->byte_order != DndByteOrder()) { SWAP2BYTES(dnd_message->flags); SWAP4BYTES(dnd_message->time); } /* do the rest in the switch */ dnd_data->reason = dnd_message->reason ; if (DND_GET_EVENT_TYPE(dnd_data->reason)) *receiver = 1 ; else *receiver = 0 ; dnd_data->reason &= DND_CLEAR_EVENT_TYPE ; dnd_data->time = dnd_message->time ; /* we're reading in more stuff that necessary. but who cares */ dnd_data->status = DND_GET_STATUS(dnd_message->flags) ; dnd_data->operation = DND_GET_OPERATION(dnd_message->flags) ; dnd_data->operations = DND_GET_OPERATIONS(dnd_message->flags) ; dnd_data->completion = DND_GET_COMPLETION(dnd_message->flags) ; switch(dnd_data->reason) { case DND_TOP_LEVEL_ENTER: case DND_TOP_LEVEL_LEAVE: if (dnd_message->byte_order != DndByteOrder()) { SWAP4BYTES(dnd_message->data.top.src_window); SWAP4BYTES(dnd_message->data.top.property); } dnd_data->src_window = dnd_message->data.top.src_window ; dnd_data->property = dnd_message->data.top.property ; break ; /* cannot fall through, see above comment in write msg */ case DND_DRAG_MOTION: case DND_OPERATION_CHANGED: case DND_DROP_SITE_ENTER: case DND_DROP_START: if (dnd_message->byte_order != DndByteOrder()) { SWAP2BYTES(dnd_message->data.pot.x); SWAP2BYTES(dnd_message->data.pot.y); SWAP4BYTES(dnd_message->data.pot.property); SWAP4BYTES(dnd_message->data.pot.src_window); } dnd_data->x = dnd_message->data.pot.x ; dnd_data->y = dnd_message->data.pot.y ; dnd_data->property = dnd_message->data.pot.property ; dnd_data->src_window = dnd_message->data.pot.src_window ; break ; case DND_DROP_SITE_LEAVE: break; default: break ; } return True ; }
static Boolean read_atoms_table(Display *display, XmDndAtomsTable tbl) { Atom da, atype; Window win; int aformat, i; unsigned long nitems, bafter; XmDndAtoms *atoms = NULL; Boolean got_it = False; XmDndAtomsTableEntryRec atom_ent; XmDndBufMgrRec bmgr; DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atoms_table(%d)\n", __FILE__, __LINE__)); da = XmInternAtom(display, _XA_MOTIF_DRAG_ATOMS, False); win = get_drag_window(display); begin_protection(display, win); if (XGetWindowProperty(display, win, da, 0L, PROP_LENGTH, False, da, &atype, &aformat, &nitems, &bafter, (unsigned char **)&atoms) == Success && nitems >= 8) { DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d) - got property, bafter=%i\n", __FILE__, __LINE__, bafter)); got_it = True; } end_protection(display); if (bad_window) { _XmWarning((Widget)XmGetXmDisplay(display), "Invalid DRAG WINDOW fetching DRAG_ATOMS."); } if (!got_it) { if (atoms) { XFree((XPointer)atoms); } return False; } if (atoms->protocol_version != DND_PROTOCOL_VERSION) { _XmWarning((Widget)XmGetXmDisplay(display), "DND Protocol version mismatch."); } if (atoms->byte_order != _XmByteOrder()) { SWAP2BYTES(atoms->num_atoms); SWAP4BYTES(atoms->data_size); } if (!tbl) { tbl = (XmDndAtomsTable) XtMalloc(sizeof(XmDndAtomsTableRec)); tbl->num_entries = 0; tbl->entries = NULL; set_atoms_table(display, tbl); } if (tbl->num_entries < atoms->num_atoms) { tbl->entries = (XmDndAtomsTableEntry) XtRealloc((char *)tbl->entries, atoms->num_atoms * sizeof(XmDndAtomsTableEntryRec)); } if (atoms->num_atoms > 0) { bmgr.atoms = (char *)atoms; bmgr.atom_start = (char *)(atoms + 1); bmgr.atom_size = atoms->data_size; for (i = 0; i < atoms->num_atoms; i++) { _XmReadDragBuffer(&bmgr, False, (char *)&atom_ent, sizeof(XmDndAtomsTableEntryRec)); if (atoms->byte_order != _XmByteOrder()) { SWAP4BYTES(atom_ent.atom); SWAP4BYTES(atom_ent.time); } tbl->entries[i].atom = atom_ent.atom; tbl->entries[i].time = atom_ent.time; } } return True; }
/* * get the ATOM_PAIRS. They may or may not already exist */ static Boolean read_atom_pairs(Display *display) { Atom pa, atype; Window win; Boolean gotit = False; XmDndAtomPairs *pairs; XmDndBufMgrRec bmgr; int i; XmDndAtomPair pair; char buf[32]; int aformat; unsigned long nitems, bafter; unsigned char *prop = NULL; DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d)\n", __FILE__, __LINE__)); pa = XmInternAtom(display, _XA_MOTIF_DRAG_ATOM_PAIRS, False); win = get_drag_window(display); begin_protection(display, win); if (XGetWindowProperty(display, win, pa, 0L, PROP_LENGTH, False, pa, &atype, &aformat, &nitems, &bafter, (unsigned char **)&pairs) == Success && nitems >= 8 && pairs != NULL) { DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d) - got property, bafter=%i\n", __FILE__, __LINE__, bafter)); gotit = True; prop = (unsigned char *)pairs; } end_protection(display); if (bad_window) { _XmWarning((Widget)XmGetXmDisplay(display), "Bad window ATOM_PAIRS property on DRAG_WINDOW."); } if (!gotit) { #if 0 _XmWarning((Widget)XmGetXmDisplay(display), "No ATOM_PAIRS property on DRAG_WINDOW."); #endif if (prop) { XFree((char *)prop); } DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d) - did not get property\n", __FILE__, __LINE__)); return False; } if (pairs->protocol_version != DND_PROTOCOL_VERSION) { _XmWarning((Widget)XmGetXmDisplay(display), "DND Protocol version mismatch."); } if (pairs->byte_order != _XmByteOrder()) { SWAP2BYTES(pairs->num_pairs); SWAP4BYTES(pairs->data_size); } DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d) - %i pairs\n", __FILE__, __LINE__, pairs->num_pairs)); if (pairs->num_pairs > 0) { bmgr.atoms = (char *)pairs; bmgr.atom_start = (char *)(pairs + 1); bmgr.atom_size = pairs->data_size; bmgr.names = (char *)pairs + pairs->data_size; bmgr.name_start = (char *)pairs + pairs->data_size; bmgr.name_size = nitems - pairs->data_size; for (i = 0; i < pairs->num_pairs; i++) { _XmReadDragBuffer(&bmgr, False, (char *)&pair, sizeof(XmDndAtomPair)); if (pairs->byte_order != _XmByteOrder()) { SWAP4BYTES(pair.atom); SWAP2BYTES(pair.namelen); } _XmReadDragBuffer(&bmgr, True, buf, pair.namelen); DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_atom_pairs(%d) - intern %s\n", __FILE__, __LINE__, buf)); _XmInternAtomAndName(display, pair.atom, buf); } } if (prop) { XFree((char *)prop); } return gotit; }
/* * get the drag receiver info property from the target * * check out the _XA_MOTIF_DRAG_RECEIVER_INFO property on a Motif * application's window. There's a lot more there than what Daniel * talks about. Must be due to PREREGISTER, yes? */ extern Boolean _XmGetDragReceiverInfo(Display *display, Window win, XmDragReceiverInfo ri) { Atom dri; XmDndReceiverProp *receiver; Atom type; int format; unsigned int border; unsigned long bafter, length; Window root; DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:_XmGetDragReceiverInfo(%d)\n", __FILE__, __LINE__)); DEBUGOUT(_LtDebug0("DRAGSOURCE", NULL, "%s:_XmGetDragReceiverInfo(%d) - %p\n", __FILE__, __LINE__, win)); dri = XmInternAtom(display, _XA_MOTIF_DRAG_RECEIVER_INFO, False); if (XGetWindowProperty(display, win, dri, 0L, PROP_LENGTH, False, dri, &type, &format, &length, &bafter, (unsigned char **)&receiver) != Success) { DEBUGOUT(_LtDebug0("DRAGSOURCE", NULL, "%s:_XmGetDragReceiverInfo(%d) - getting prop failed\n", __FILE__, __LINE__)); return False; } if (length < sizeof(XmDndReceiverProp)) { ri->dragProtocolStyle = XmDRAG_NONE; XFree((char *)receiver); DEBUGOUT(_LtDebug0("DRAGSOURCE", NULL, "%s:_XmGetDragReceiverInfo(%d) - None available\n", __FILE__, __LINE__)); return False; } if (receiver->protocol_version != DND_PROTOCOL_VERSION) { _XmWarning(NULL, "Drag protocol version mismatch: %d vs %d\n", DND_PROTOCOL_VERSION, receiver->protocol_version); } if (receiver->byte_order != _XmByteOrder()) { SWAP4BYTES(receiver->proxy_window); SWAP2BYTES(receiver->num_drop_sites); SWAP4BYTES(receiver->total_size); } Display_ProxyWindow(XmGetXmDisplay(display)) = receiver->proxy_window; ri->dragProtocolStyle = receiver->protocol_style; ri->iccInfo = (XtPointer)XtMalloc(sizeof(XmShellDropSiteInfoRec)); DSI_ByteOrder(ri->iccInfo) = receiver->byte_order; DSI_NumDropSites(ri->iccInfo) = receiver->num_drop_sites; DSI_Info(ri->iccInfo).atoms = (char *)receiver; DSI_Info(ri->iccInfo).atom_size = receiver->total_size; DSI_Info(ri->iccInfo).atom_start = (char *)(receiver + 1); DSI_Info(ri->iccInfo).names = (char *)receiver + receiver->total_size; DSI_Info(ri->iccInfo).name_size = length - receiver->total_size; XGetGeometry(display, win, &root, &ri->xOrigin, &ri->yOrigin, &ri->width, &ri->height, &border, &ri->depth); XTranslateCoordinates(display, win, root, -border, -border, &ri->xOrigin, &ri->yOrigin, &root); return True; }
static Boolean read_targets_table(Display *display, XmDndTargetsTable tbl) { Atom ta, atype; Window win; int aformat, i; unsigned long nitems, bafter; XmDndTargets *targets = NULL; Boolean got_it = False; XmDndBufMgrRec bmgr; CARD16 nents; DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_targets_table(%d)\n", __FILE__, __LINE__)); ta = XmInternAtom(display, _XA_MOTIF_DRAG_TARGETS, False); win = get_drag_window(display); begin_protection(display, win); if (XGetWindowProperty(display, win, ta, 0L, PROP_LENGTH, False, ta, &atype, &aformat, &nitems, &bafter, (unsigned char **)&targets) == Success && nitems >= 8) { DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_targets_table(%d) bafter=%i\n", __FILE__, __LINE__, bafter)); got_it = True; } end_protection(display); if (bad_window) { _XmWarning((Widget)XmGetXmDisplay(display), "Invalid DRAG WINDOW fetching DRAG_ATOMS."); } if (!got_it) { if (targets) { XFree((XPointer)targets); } DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_targets_table(%d) - False\n", __FILE__, __LINE__)); return False; } if (targets->protocol_version != DND_PROTOCOL_VERSION) { _XmWarning((Widget)XmGetXmDisplay(display), "DND Protocol version mismatch."); } if (targets->byte_order != _XmByteOrder()) { SWAP2BYTES(targets->num_target_lists); SWAP4BYTES(targets->data_size); } if (!tbl) { tbl = (XmDndTargetsTable)XtMalloc(sizeof(XmDndTargetsTableRec)); tbl->num_entries = 0; tbl->entries = NULL; set_targets_table(display, tbl); } if (tbl->num_entries < targets->num_target_lists) { tbl->num_entries = targets->num_target_lists; tbl->entries = (XmDndTargetsTableEntry)XtRealloc((char *)tbl->entries, targets->num_target_lists * sizeof(XmDndTargetsTableEntryRec)); } if (targets->num_target_lists > 0) { bmgr.atoms = (char *)targets; bmgr.atom_start = (char *)(targets + 1); bmgr.atom_size = targets->data_size; for (i = 0; i < targets->num_target_lists; i++) { _XmReadDragBuffer(&bmgr, False, (char *)&nents, sizeof(CARD16)); if (targets->byte_order != _XmByteOrder()) { SWAP2BYTES(nents); } tbl->entries[i].num_targets = nents; tbl->entries[i].targets = (Atom *)XtMalloc(nents * sizeof(Atom)); read_atoms_from_drag_buffer(&bmgr, tbl->entries[i].num_targets, targets->byte_order != _XmByteOrder(), tbl->entries[i].targets); } } DEBUGOUT(_LtDebug0(__FILE__, NULL, "%s:read_targets_table(%d) - True %p\n", __FILE__, __LINE__, tbl)); if (targets) { XFree((XPointer)targets); } return True; }