📄 xdnd.c
字号:
/* result must be free'd */void xdnd_get_type_list (DndClass * dnd, Window window, Atom ** typelist){ Atom type, *a; int format, i; unsigned long count, remaining; unsigned char *data = NULL; *typelist = 0; XGetWindowProperty (dnd->display, window, dnd->XdndTypeList, 0, 0x8000000L, False, XA_ATOM, &type, &format, &count, &remaining, &data); if (type != XA_ATOM || format != 32 || count == 0 || !data) { if (data) XFree (data); dnd_debug2 ("XGetWindowProperty failed in xdnd_get_type_list - dnd->XdndTypeList = %ld", dnd->XdndTypeList); return; } *typelist = malloc ((count + 1) * sizeof (Atom)); a = (Atom *) data; for (i = 0; i < count; i++) (*typelist)[i] = a[i]; (*typelist)[count] = 0; XFree (data);}void xdnd_get_three_types (DndClass * dnd, XEvent * xevent, Atom ** typelist){ int i; *typelist = malloc ((XDND_THREE + 1) * sizeof (Atom)); for (i = 0; i < XDND_THREE; i++) (*typelist)[i] = XDND_ENTER_TYPE (xevent, i); (*typelist)[XDND_THREE] = 0; /* although (*typelist)[1] or (*typelist)[2] may also be set to nill */}/* result must be free'd */static char *concat_string_list (char **t, int *bytes){ int l, n; char *s; for (l = n = 0;; n++) { if (!t[n]) break; if (!t[n][0]) break; l += strlen (t[n]) + 1; } s = malloc (l + 1); for (l = n = 0;; n++) { if (!t[n]) break; if (!(t[n][0])) break; strcpy (s + l, t[n]); l += strlen (t[n]) + 1; } *bytes = l; s[l] = '\0'; return s;}void xdnd_set_actions (DndClass * dnd, Window window, Atom * actions, char **descriptions){ int n, l; char *s; n = array_length (actions); XChangeProperty (dnd->display, window, dnd->XdndActionList, XA_ATOM, 32, PropModeReplace, (unsigned char *) actions, n); s = concat_string_list (descriptions, &l); XChangeProperty (dnd->display, window, dnd->XdndActionList, XA_STRING, 8, PropModeReplace, (unsigned char *) s, l); xdnd_xfree (s);}/* returns 1 on error or no actions, otherwise result must be free'd xdnd_get_actions (window, &actions, &descriptions); free (actions); free (descriptions); */int xdnd_get_actions (DndClass * dnd, Window window, Atom ** actions, char ***descriptions){ Atom type, *a; int format, i; unsigned long count, dcount, remaining; unsigned char *data = 0, *r; *actions = 0; *descriptions = 0; XGetWindowProperty (dnd->display, window, dnd->XdndActionList, 0, 0x8000000L, False, XA_ATOM, &type, &format, &count, &remaining, &data); if (type != XA_ATOM || format != 32 || count == 0 || !data) { if (data) XFree (data); return 1; } *actions = malloc ((count + 1) * sizeof (Atom)); a = (Atom *) data; for (i = 0; i < count; i++) (*actions)[i] = a[i]; (*actions)[count] = 0; XFree (data); data = 0; XGetWindowProperty (dnd->display, window, dnd->XdndActionDescription, 0, 0x8000000L, False, XA_STRING, &type, &format, &dcount, &remaining, &data); if (type != XA_STRING || format != 8 || dcount == 0) { if (data) XFree (data); *descriptions = malloc ((count + 1) * sizeof (char *)); dnd_warning ("XGetWindowProperty no property or wrong format for action descriptions"); for (i = 0; i < count; i++) (*descriptions)[i] = ""; (*descriptions)[count] = 0; } else { int l; l = (count + 1) * sizeof (char *); *descriptions = malloc (l + dcount); memcpy (*descriptions + l, data, dcount); XFree (data); data = (unsigned char *) *descriptions; data += l; l = 0; for (i = 0, r = data;; r += l + 1, i++) { l = strlen ((char *) r); if (!l || i >= count) break; (*descriptions)[i] = (char *) r; } for (; i < count; i++) { (*descriptions)[i] = ""; } (*descriptions)[count] = 0; } return 0;}/* returns non-zero on cancel */int xdnd_choose_action_dialog (DndClass * dnd, Atom * actions, char **descriptions, Atom * result){ if (!actions[0]) return 1; if (!dnd->action_choose_dialog) { /* default to return the first action if no dialog set */ *result = actions[0]; return 0; } return (*dnd->action_choose_dialog) (dnd, descriptions, actions, result);}static void xdnd_send_event (DndClass * dnd, Window window, XEvent * xevent){ dnd_debug4 ("xdnd_send_event(), window = %ld, l[0] = %ld, l[4] = %ld", window, xevent->xclient.data.l[0], xevent->xclient.data.l[4]); dnd_debug2 ("xdnd_send_event(), from widget widget %s", (char *) CWidgetOfWindow (xevent->xclient.data.l[0])); XSendEvent (dnd->display, window, 0, 0, xevent);}void xdnd_send_enter (DndClass * dnd, Window window, Window from, Atom * typelist){ XEvent xevent; int n, i; n = array_length (typelist); memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndEnter; xevent.xclient.format = 32; XDND_ENTER_SOURCE_WIN (&xevent) = from; XDND_ENTER_THREE_TYPES_SET (&xevent, n > XDND_THREE); XDND_ENTER_VERSION_SET (&xevent, dnd->version); for (i = 0; i < n && i < XDND_THREE; i++) XDND_ENTER_TYPE (&xevent, i) = typelist[i]; xdnd_send_event (dnd, window, &xevent);}void xdnd_send_position (DndClass * dnd, Window window, Window from, Atom action, int x, int y, unsigned long time){ XEvent xevent; memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndPosition; xevent.xclient.format = 32; XDND_POSITION_SOURCE_WIN (&xevent) = from; XDND_POSITION_ROOT_SET (&xevent, x, y); if (dnd_version_at_least (dnd->dragging_version, 1)) XDND_POSITION_TIME (&xevent) = time; if (dnd_version_at_least (dnd->dragging_version, 2)) XDND_POSITION_ACTION (&xevent) = action; xdnd_send_event (dnd, window, &xevent);}void xdnd_send_status (DndClass * dnd, Window window, Window from, int will_accept, \ int want_position, int x, int y, int w, int h, Atom action){ XEvent xevent; memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndStatus; xevent.xclient.format = 32; XDND_STATUS_TARGET_WIN (&xevent) = from; XDND_STATUS_WILL_ACCEPT_SET (&xevent, will_accept); if (will_accept) XDND_STATUS_WANT_POSITION_SET (&xevent, want_position); if (want_position) XDND_STATUS_RECT_SET (&xevent, x, y, w, h); if (dnd_version_at_least (dnd->dragging_version, 2)) if (will_accept) XDND_STATUS_ACTION (&xevent) = action; xdnd_send_event (dnd, window, &xevent);}void xdnd_send_leave (DndClass * dnd, Window window, Window from){ XEvent xevent; memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndLeave; xevent.xclient.format = 32; XDND_LEAVE_SOURCE_WIN (&xevent) = from; xdnd_send_event (dnd, window, &xevent);}void xdnd_send_drop (DndClass * dnd, Window window, Window from, unsigned long time){ XEvent xevent; memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndDrop; xevent.xclient.format = 32; XDND_DROP_SOURCE_WIN (&xevent) = from; if (dnd_version_at_least (dnd->dragging_version, 1)) XDND_DROP_TIME (&xevent) = time; xdnd_send_event (dnd, window, &xevent);}/* error is not actually used, i think future versions of the protocol should return an error status to the calling window with the XdndFinished client message */void xdnd_send_finished (DndClass * dnd, Window window, Window from, int error){ XEvent xevent; memset (&xevent, 0, sizeof (xevent)); xevent.xany.type = ClientMessage; xevent.xany.display = dnd->display; xevent.xclient.window = window; xevent.xclient.message_type = dnd->XdndFinished; xevent.xclient.format = 32; XDND_FINISHED_TARGET_WIN (&xevent) = from; xdnd_send_event (dnd, window, &xevent);}/* returns non-zero on error - i.e. no selection owner set. Type is of course the mime type */int xdnd_convert_selection (DndClass * dnd, Window window, Window requester, Atom type){ if (!(window = XGetSelectionOwner (dnd->display, dnd->XdndSelection))) { dnd_debug1 ("xdnd_convert_selection(): XGetSelectionOwner failed"); return 1; } XConvertSelection (dnd->display, dnd->XdndSelection, type, dnd->Xdnd_NON_PROTOCOL_ATOM, requester, CurrentTime); return 0;}/* returns non-zero on error */int xdnd_set_selection_owner (DndClass * dnd, Window window, Atom type){ if (!XSetSelectionOwner (dnd->display, dnd->XdndSelection, window, CurrentTime)) { dnd_debug1 ("xdnd_set_selection_owner(): XSetSelectionOwner failed"); return 1; } return 0;}void xdnd_selection_send (DndClass * dnd, XSelectionRequestEvent * request, unsigned char *data, int length){ XEvent xevent; dnd_debug2 (" requestor = %ld", request->requestor); dnd_debug2 (" property = %ld", request->property); dnd_debug2 (" length = %d", length); XChangeProperty (dnd->display, request->requestor, request->property, request->target, 8, PropModeReplace, data, length); xevent.xselection.type = SelectionNotify; xevent.xselection.property = request->property; xevent.xselection.display = request->display; xevent.xselection.requestor = request->requestor; xevent.xselection.selection = request->selection; xevent.xselection.target = request->target; xevent.xselection.time = request->time; xdnd_send_event (dnd, request->requestor, &xevent);}#if 0/* respond to a notification that a primary selection has been sent */int xdnd_get_selection (DndClass * dnd, Window from, Atom property, Window insert){ long read; int error = 0; unsigned long remaining; if (!property) return 1; read = 0; do { unsigned char *s; Atom actual; int format; unsigned long count; if (XGetWindowProperty (dnd->display, insert, property, read / 4, 65536, 1, AnyPropertyType, &actual, &format, &count, &remaining, &s) != Success) { XFree (s); return 1; } read += count; if (dnd->widget_insert_drop && !error) error = (*dnd->widget_insert_drop) (dnd, s, count, remaining, insert, from, actual); XFree (s); } while (remaining); return error;}#endifstatic int paste_prop_internal (DndClass * dnd, Window from, Window insert, unsigned long prop, int delete_prop){ long nread = 0; unsigned long nitems; unsigned long bytes_after; int error = 0; do { Atom actual_type; int actual_fmt; unsigned char *s = 0; if (XGetWindowProperty (dnd->display, insert, prop, nread / 4, 65536, delete_prop, AnyPropertyType, &actual_type, &actual_fmt, &nitems, &bytes_after, &s) != Success) { XFree (s); return 1; } nread += nitems; if (dnd->widget_insert_drop && !error) error = (*dnd->widget_insert_drop) (dnd, s, nitems, bytes_after, insert, from, actual_fmt); XFree (s); } while (bytes_after); if (!nread) return 1; return 0;}/* * Respond to a notification that a primary selection has been sent (supports INCR) */int xdnd_get_selection (DndClass * dnd, Window from, Atom prop, Window insert){ struct timeval tv, tv_start; long nread; unsigned long bytes_after; Atom actual_type; int actual_fmt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -