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); }
/* Produce a client message to be sent by the caller */ static void DndFillClientMessage(Display * dpy, Window window, XClientMessageEvent *cm, DndData * dnd_data, char receiver) { DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; cm->display = dpy; cm->type = ClientMessage; cm->serial = LastKnownRequestProcessed(dpy); cm->send_event = True; cm->window = window; cm->format = 8; cm->message_type = ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE); dnd_message->reason = dnd_data->reason | DND_SET_EVENT_TYPE(receiver); dnd_message->byte_order = DndByteOrder(); /* we're filling in flags with more stuff that necessary, depending on the reason, but it doesn't matter */ dnd_message->flags = 0 ; dnd_message->flags |= DND_SET_STATUS(dnd_data->status) ; dnd_message->flags |= DND_SET_OPERATION(dnd_data->operation) ; dnd_message->flags |= DND_SET_OPERATIONS(dnd_data->operations) ; dnd_message->flags |= DND_SET_COMPLETION(dnd_data->completion) ; dnd_message->time = dnd_data->time ; switch(dnd_data->reason) { case DND_DROP_SITE_LEAVE: break ; case DND_TOP_LEVEL_ENTER: case DND_TOP_LEVEL_LEAVE: dnd_message->data.top.src_window = dnd_data->src_window ; dnd_message->data.top.property = dnd_data->property ; break ; /* cannot fall through since the byte layout is different in both set of messages, see top and pot union stuff */ case DND_DRAG_MOTION: case DND_OPERATION_CHANGED: case DND_DROP_SITE_ENTER: case DND_DROP_START: dnd_message->data.pot.x = dnd_data->x ; /* mouse position */ dnd_message->data.pot.y = dnd_data->y ; dnd_message->data.pot.src_window = dnd_data->src_window ; dnd_message->data.pot.property = dnd_data->property ; break ; default: break ; } }
/* Position the _MOTIF_DRAG_RECEIVER_INFO property on the dropsite window. Called by the receiver of the drop to indicate the supported protocol style : dynamic, drop_only or none */ static void DndWriteReceiverProperty(Display * dpy, Window window, unsigned char protocol_style) { DndReceiverProp receiver_prop ; receiver_prop.byte_order = DndByteOrder() ; receiver_prop.protocol_version = DND_PROTOCOL_VERSION; receiver_prop.protocol_style = protocol_style ; receiver_prop.proxy_window = XNone ; receiver_prop.num_drop_sites = 0 ; receiver_prop.total_size = sizeof(DndReceiverProp); /* write the buffer to the property */ XChangeProperty (dpy, window, ATOM(_MOTIF_DRAG_RECEIVER_INFO), ATOM(_MOTIF_DRAG_RECEIVER_INFO), 8, PropModeReplace, (unsigned char *)&receiver_prop, sizeof(DndReceiverProp)); }
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 ; }