📄 xdnd.c
字号:
/* xdnd.c, xdnd.h - C program library for handling the Xdnd protocol Copyright (C) 1996-2000 Paul Sheer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. *//* Released 1998-08-07 Changes: 2000-08-08: INCR protocol implemented.*//* DONE: - INCR protocol now implemented TODO: - action_choose_dialog not yet supported (never called) - widget_delete_selection not yet supported and DELETE requests are ignored - not yet tested with applications that only supported XDND 0 or 1*/#include <config.h>#include <X11/Xlib.h>#include <X11/X.h>#include <X11/Xatom.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#include <sys/types.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_SYS_SELECT_H# include <sys/select.h>#endif#include "xdnd.h"#include "mad.h"/* just to remind us : */#if 0typedef struct { int type; unsigned long serial; Bool send_event; Display *display; Window window; Atom message_type; int format; union { char b[20]; short s[10]; long l[5]; } data;} XClientMessageEvent;XClientMessageEvent xclient;#endif/* #define DND_DEBUG */#define xdnd_xfree(x) {if (x) { free (x); x = 0; }}#ifdef DND_DEBUG#include <sys/time.h>#include <unistd.h>char *xdnd_debug_milliseconds (void){ struct timeval tv; static char r[22]; gettimeofday (&tv, 0); sprintf (r, "%.2ld.%.3ld", tv.tv_sec % 100L, tv.tv_usec / 1000L); return r;}#define dnd_debug1(a) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds ())#define dnd_debug2(a,b) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b)#define dnd_debug3(a,b,c) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b, c)#define dnd_debug4(a,b,c,d) printf("%s: %d: %s: " a "\n", __FILE__, __LINE__, xdnd_debug_milliseconds (), b, c, d)#else#define dnd_debug1(a) #define dnd_debug2(a,b) #define dnd_debug3(a,b,c) #define dnd_debug4(a,b,c,d) #endif#define dnd_warning(a) fprintf (stderr, a)#define dnd_version_at_least(a,b) ((a) >= (b))static unsigned char dnd_copy_cursor_bits[] ={ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};static unsigned char dnd_copy_mask_bits[] ={ 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00};static unsigned char dnd_move_cursor_bits[] ={ 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x04, 0x08, 0x02, 0x0c, 0x08, 0x02, 0x1c, 0x08, 0x02, 0x3c, 0x08, 0x02, 0x7c, 0x08, 0x02, 0xfc, 0x08, 0x02, 0xfc, 0x09, 0x02, 0xfc, 0x0b, 0x02, 0x7c, 0x08, 0xfe, 0x6d, 0x0f, 0x00, 0xc4, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00};static unsigned char dnd_move_mask_bits[] ={ 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1f, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x00, 0x1c, 0x07, 0x06, 0x1c, 0x07, 0x0e, 0x1c, 0x07, 0x1e, 0x1c, 0x07, 0x3e, 0x1c, 0x07, 0x7e, 0x1c, 0x07, 0xfe, 0x1c, 0x07, 0xfe, 0x1d, 0x07, 0xfe, 0x1f, 0x07, 0xfe, 0x1f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x1e, 0xff, 0xef, 0x1f, 0x00, 0xe6, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01};static unsigned char dnd_link_cursor_bits[] ={ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0xe8, 0x0f, 0x02, 0x00, 0x48, 0x00, 0x02, 0x00, 0x88, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};static unsigned char dnd_link_mask_bits[] ={ 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00};static unsigned char dnd_ask_cursor_bits[] ={ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x02, 0x00, 0x88, 0x03, 0x02, 0x00, 0x48, 0x04, 0x02, 0x00, 0x08, 0x04, 0x02, 0x00, 0x08, 0x02, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x01, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x01, 0x02, 0x04, 0x08, 0x00, 0x02, 0x0c, 0x08, 0x00, 0x02, 0x1c, 0x08, 0x00, 0x02, 0x3c, 0x08, 0x00, 0x02, 0x7c, 0x08, 0x00, 0x02, 0xfc, 0x08, 0x00, 0x02, 0xfc, 0x09, 0x00, 0x02, 0xfc, 0x0b, 0x00, 0x02, 0x7c, 0x08, 0x00, 0xfe, 0x6d, 0x0f, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};static unsigned char dnd_ask_mask_bits[] ={ 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x00, 0xfc, 0x1f, 0x07, 0x06, 0xfc, 0x1f, 0x07, 0x0e, 0xfc, 0x1f, 0x07, 0x1e, 0x1c, 0x00, 0x07, 0x3e, 0x1c, 0x00, 0x07, 0x7e, 0x1c, 0x00, 0x07, 0xfe, 0x1c, 0x00, 0x07, 0xfe, 0x1d, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0x07, 0xfe, 0x1f, 0x00, 0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x1e, 0x00, 0xff, 0xef, 0x1f, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00};static DndCursor dnd_cursors[] ={ {29, 25, 10, 10, dnd_copy_cursor_bits, dnd_copy_mask_bits, "XdndActionCopy", 0, 0, 0, 0}, {21, 25, 10, 10, dnd_move_cursor_bits, dnd_move_mask_bits, "XdndActionMove", 0, 0, 0, 0}, {29, 25, 10, 10, dnd_link_cursor_bits, dnd_link_mask_bits, "XdndActionLink", 0, 0, 0, 0}, {29, 25, 10, 10, dnd_ask_cursor_bits, dnd_ask_mask_bits, "XdndActionAsk", 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};void xdnd_reset (DndClass * dnd){ dnd->stage = XDND_DROP_STAGE_IDLE; dnd->dragging_version = 0; dnd->internal_drag = 0; dnd->want_position = 0; dnd->ready_to_drop = 0; dnd->will_accept = 0; dnd->rectangle.x = dnd->rectangle.y = 0; dnd->rectangle.width = dnd->rectangle.height = 0; dnd->dropper_window = 0; dnd->dropper_toplevel = 0; dnd->dragger_window = 0; dnd->dragger_typelist = 0; dnd->desired_type = 0; dnd->time = 0;}void xdnd_init (DndClass * dnd, Display * display){ DndCursor *cursor; XColor black, white; memset (dnd, 0, sizeof (*dnd)); dnd->display = display; dnd->root_window = DefaultRootWindow (display); dnd->version = XDND_VERSION; dnd->XdndAware = XInternAtom (dnd->display, "XdndAware", False); dnd->XdndSelection = XInternAtom (dnd->display, "XdndSelection", False); dnd->XdndEnter = XInternAtom (dnd->display, "XdndEnter", False); dnd->XdndLeave = XInternAtom (dnd->display, "XdndLeave", False); dnd->XdndPosition = XInternAtom (dnd->display, "XdndPosition", False); dnd->XdndDrop = XInternAtom (dnd->display, "XdndDrop", False); dnd->XdndFinished = XInternAtom (dnd->display, "XdndFinished", False); dnd->XdndStatus = XInternAtom (dnd->display, "XdndStatus", False); dnd->XdndActionCopy = XInternAtom (dnd->display, "XdndActionCopy", False); dnd->XdndActionMove = XInternAtom (dnd->display, "XdndActionMove", False); dnd->XdndActionLink = XInternAtom (dnd->display, "XdndActionLink", False); dnd->XdndActionAsk = XInternAtom (dnd->display, "XdndActionAsk", False); dnd->XdndActionPrivate = XInternAtom (dnd->display, "XdndActionPrivate", False); dnd->XdndTypeList = XInternAtom (dnd->display, "XdndTypeList", False); dnd->XdndActionList = XInternAtom (dnd->display, "XdndActionList", False); dnd->XdndActionDescription = XInternAtom (dnd->display, "XdndActionDescription", False); dnd->Xdnd_NON_PROTOCOL_ATOM = XInternAtom (dnd->display, "JXSelectionWindowProperty", False); xdnd_reset (dnd); dnd->cursors = dnd_cursors; black.pixel = BlackPixel (dnd->display, DefaultScreen (dnd->display)); white.pixel = WhitePixel (dnd->display, DefaultScreen (dnd->display)); XQueryColor (dnd->display, DefaultColormap (dnd->display, DefaultScreen (dnd->display)), &black); XQueryColor (dnd->display, DefaultColormap (dnd->display, DefaultScreen (dnd->display)), &white); for (cursor = &dnd->cursors[0]; cursor->width; cursor++) { cursor->image_pixmap = XCreateBitmapFromData \ (dnd->display, dnd->root_window, (char *) cursor->image_data, cursor->width, cursor->height); cursor->mask_pixmap = XCreateBitmapFromData \ (dnd->display, dnd->root_window, (char *) cursor->mask_data, cursor->width, cursor->height); cursor->cursor = XCreatePixmapCursor (dnd->display, cursor->image_pixmap, cursor->mask_pixmap, &black, &white, cursor->x, cursor->y); XFreePixmap (dnd->display, cursor->image_pixmap); XFreePixmap (dnd->display, cursor->mask_pixmap); cursor->action = XInternAtom (dnd->display, cursor->_action, False); }}void xdnd_shut (DndClass * dnd){ DndCursor *cursor; for (cursor = &dnd->cursors[0]; cursor->width; cursor++) XFreeCursor (dnd->display, cursor->cursor); memset (dnd, 0, sizeof (*dnd)); return;}/* typelist is a null terminated array */static int array_length (Atom * a){ int n; for (n = 0; a[n]; n++); return n;}void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist){ Window root_return, parent; unsigned int nchildren_return; Window *children_return = 0; int r, s; if (dnd->widget_exists) if (!(*dnd->widget_exists) (dnd, window)) return; s = XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32, PropModeReplace, (unsigned char *) &dnd->version, 1);#if 0 dnd_debug4 ("XChangeProperty() = %d, window = %ld, widget = %s", s, window, (char *) CWidgetOfWindow (window));#endif if (s && typelist) { int n; n = array_length (typelist); if (n) s = XChangeProperty (dnd->display, window, dnd->XdndAware, XA_ATOM, 32, PropModeAppend, (unsigned char *) typelist, n); } r = XQueryTree (dnd->display, window, &root_return, &parent, &children_return, &nchildren_return); if (children_return) XFree (children_return); if (r) xdnd_set_dnd_aware (dnd, parent, typelist);}int xdnd_is_dnd_aware (DndClass * dnd, Window window, int *version, Atom * typelist){ Atom actual; int format; unsigned long count, remaining; unsigned char *data = 0; Atom *types, *t; int result = 1; *version = 0; XGetWindowProperty (dnd->display, window, dnd->XdndAware, 0, 0x8000000L, False, XA_ATOM, &actual, &format, &count, &remaining, &data); if (actual != XA_ATOM || format != 32 || count == 0 || !data) { dnd_debug2 ("XGetWindowProperty failed in xdnd_is_dnd_aware - XdndAware = %ld", dnd->XdndAware); if (data) XFree (data); return 0; } types = (Atom *) data;#if XDND_VERSION >= 3 if (types[0] < 3) { if (data) XFree (data); return 0; }#endif *version = dnd->version < types[0] ? dnd->version : types[0]; /* minimum */ dnd_debug2 ("Using XDND version %d", *version); if (count > 1) { result = 0; for (t = typelist; *t; t++) { int j; for (j = 1; j < count; j++) { if (types[j] == *t) { result = 1; break; } } if (result) break; } } XFree (data); return result;}void xdnd_set_type_list (DndClass * dnd, Window window, Atom * typelist){ int n; n = array_length (typelist); XChangeProperty (dnd->display, window, dnd->XdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char *) typelist, n);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -