📄 qmotifdnd_x11.cpp
字号:
} return byte_order ;}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);}/* 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));}/* protocol style equiv (preregister stuff really) */#define DND_DRAG_DROP_ONLY_EQUIV 3#define DND_DRAG_DYNAMIC_EQUIV1 2#define DND_DRAG_DYNAMIC_EQUIV2 4/* 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 thru 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 ; }}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 thru, 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 Window MotifWindow(Display *display){ Atom type; int format; unsigned long size; unsigned long bytes_after; unsigned char *property = 0; Window motif_window ; /* this version does no caching, so it's slow: round trip each time */ if ((XGetWindowProperty (display, DefaultRootWindow(display), ATOM(_MOTIF_DRAG_WINDOW), 0L, 100000L, False, AnyPropertyType, &type, &format, &size, &bytes_after, &property) == Success) && (type != XNone)) { motif_window = *(Window *)property; } else { XSetWindowAttributes sAttributes; /* really, this should be done on a separate connection, with XSetCloseDownMode (RetainPermanent), so that others don't have to recreate it; hopefully, some real Motif application will be around to do it */ sAttributes.override_redirect = True; sAttributes.event_mask = PropertyChangeMask; motif_window = XCreateWindow (display, DefaultRootWindow (display), -170, -560, 1, 1, 0, 0, InputOnly, CopyFromParent, (CWOverrideRedirect |CWEventMask), &sAttributes); XMapWindow (display, motif_window); } if (property) { XFree ((char *)property); } return (motif_window);}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 int _DndIndexToTargets(Display * display, int index, Atom ** targets){ DndTargetsTable targets_table; int i ; /* again, slow: no caching here, alloc/free each time */ if (!(targets_table = TargetsTable (display)) || (index >= targets_table->num_entries)) { if (targets_table) XFree((char*)targets_table); return -1; } /* transfer the correct target list index */ *targets = (Atom*)malloc(sizeof(Atom)*targets_table-> entries[index].num_targets); memcpy((char*)*targets, (char*)targets_table->entries[index].targets, sizeof(Atom)*targets_table->entries[index].num_targets); /* free the target table and its guts */ for (i=0 ; i < targets_table->num_entries; i++) XFree((char*)targets_table->entries[i].targets); int tmp = targets_table->entries[index].num_targets;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -