📄 gdkdnd.c
字号:
gint old_warnings = gdk_error_warnings; gdk_error_code = 0; gdk_error_warnings = 0; tmp_list = cache->children; while (tmp_list && !retval) { GdkCacheChild *child = tmp_list->data; if ((child->xid != ignore) && (child->mapped)) { if ((x_root >= child->x) && (x_root < child->x + child->width) && (y_root >= child->y) && (y_root < child->y + child->height)) { retval = get_client_window_at_coords_recurse (child->xid, x_root - child->x, y_root - child->y); if (!retval) retval = child->xid; } } tmp_list = tmp_list->next; } gdk_error_warnings = old_warnings; if (retval) return retval; else return gdk_root_window;}#if 0static Windowget_client_window_at_coords_recurse (Window win, gint x_root, gint y_root){ Window child; Atom type = None; int format; unsigned long nitems, after; unsigned char *data; int dest_x, dest_y; static Atom wm_state_atom = None; if (!wm_state_atom) wm_state_atom = gdk_atom_intern ("WM_STATE", FALSE); XGetWindowProperty (gdk_display, win, wm_state_atom, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data); if (gdk_error_code) { gdk_error_code = 0; return None; } if (type != None) { XFree (data); return win; } XTranslateCoordinates (gdk_display, gdk_root_window, win, x_root, y_root, &dest_x, &dest_y, &child); if (gdk_error_code) { gdk_error_code = 0; return None; } if (child) return get_client_window_at_coords_recurse (child, x_root, y_root); else return None;}static Window get_client_window_at_coords (Window ignore, gint x_root, gint y_root){ Window root, parent, *children; unsigned int nchildren; int i; Window retval = None; gint old_warnings = gdk_error_warnings; gdk_error_code = 0; gdk_error_warnings = 0; if (XQueryTree(gdk_display, gdk_root_window, &root, &parent, &children, &nchildren) == 0) return 0; for (i = nchildren - 1; (i >= 0) && (retval == None); i--) { if (children[i] != ignore) { XWindowAttributes xwa; XGetWindowAttributes (gdk_display, children[i], &xwa); if (gdk_error_code) gdk_error_code = 0; else if ((xwa.map_state == IsViewable) && (x_root >= xwa.x) && (x_root < xwa.x + (gint)xwa.width) && (y_root >= xwa.y) && (y_root < xwa.y + (gint)xwa.height)) { retval = get_client_window_at_coords_recurse (children[i], x_root, y_root); if (!retval) retval = children[i]; } } } XFree (children); gdk_error_warnings = old_warnings; if (retval) return retval; else return gdk_root_window;}#endif/************************************************************* ***************************** MOTIF ************************* *************************************************************//* values used in the message type for Motif DND */enum { XmTOP_LEVEL_ENTER, XmTOP_LEVEL_LEAVE, XmDRAG_MOTION, XmDROP_SITE_ENTER, XmDROP_SITE_LEAVE, XmDROP_START, XmDROP_FINISH, XmDRAG_DROP_FINISH, XmOPERATION_CHANGED};/* Values used to specify type of protocol to use */enum { XmDRAG_NONE, XmDRAG_DROP_ONLY, XmDRAG_PREFER_PREREGISTER, XmDRAG_PREREGISTER, XmDRAG_PREFER_DYNAMIC, XmDRAG_DYNAMIC, XmDRAG_PREFER_RECEIVER};/* Operation codes */enum { XmDROP_NOOP, XmDROP_MOVE = 0x01, XmDROP_COPY = 0x02, XmDROP_LINK = 0x04};/* Drop site status */enum { XmNO_DROP_SITE = 0x01, XmDROP_SITE_INVALID = 0x02, XmDROP_SITE_VALID = 0x03};/* completion status */enum { XmDROP, XmDROP_HELP, XmDROP_CANCEL, XmDROP_INTERRUPT};/* Static data for MOTIF DND */static GList **motif_target_lists = NULL;static gint motif_n_target_lists = -1;/* Byte swapping routines. The motif specification leaves it * up to us to save a few bytes in the client messages */static gchar local_byte_order = '\0';#ifdef G_ENABLE_DEBUGstatic voidprint_target_list (GList *targets){ while (targets) { gchar *name = gdk_atom_name (GPOINTER_TO_INT (targets->data)); g_message ("\t%s", name); g_free (name); targets = targets->next; }}#endif /* G_ENABLE_DEBUG */static voidinit_byte_order (void){ guint32 myint = 0x01020304; local_byte_order = (*(gchar *)&myint == 1) ? 'B' : 'l';}static guint16card16_to_host (guint16 x, gchar byte_order) { if (byte_order == local_byte_order) return x; else return (x << 8) | (x >> 8);}static guint32card32_to_host (guint32 x, gchar byte_order) { if (byte_order == local_byte_order) return x; else return (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);}/* Motif packs together fields of varying length into the * client message. We can't rely on accessing these * through data.s[], data.l[], etc, because on some architectures * (i.e., Alpha) these won't be valid for format == 8. */#define MOTIF_XCLIENT_BYTE(xevent,i) \ (xevent)->xclient.data.b[i]#define MOTIF_XCLIENT_SHORT(xevent,i) \ ((gint16 *)&((xevent)->xclient.data.b[0]))[i]#define MOTIF_XCLIENT_LONG(xevent,i) \ ((gint32 *)&((xevent)->xclient.data.b[0]))[i]#define MOTIF_UNPACK_BYTE(xevent,i) MOTIF_XCLIENT_BYTE(xevent,i)#define MOTIF_UNPACK_SHORT(xevent,i) \ card16_to_host (MOTIF_XCLIENT_SHORT(xevent,i), MOTIF_XCLIENT_BYTE(xevent, 1))#define MOTIF_UNPACK_LONG(xevent,i) \ card32_to_host (MOTIF_XCLIENT_LONG(xevent,i), MOTIF_XCLIENT_BYTE(xevent, 1))/***** Dest side ***********//* Property placed on source windows */typedef struct _MotifDragInitiatorInfo { guint8 byte_order; guint8 protocol_version; guint16 targets_index; guint32 selection_atom;} MotifDragInitiatorInfo;/* Header for target table on the drag window */typedef struct _MotifTargetTableHeader { guchar byte_order; guchar protocol_version; guint16 n_lists; guint32 total_size;} MotifTargetTableHeader;/* Property placed on target windows */typedef struct _MotifDragReceiverInfo { guint8 byte_order; guint8 protocol_version; guint8 protocol_style; guint8 pad; guint32 proxy_window; guint16 num_drop_sites; guint16 padding; guint32 total_size;} MotifDragReceiverInfo;static Window motif_drag_window = None;static GdkWindow *motif_drag_gdk_window = NULL;static GdkAtom motif_drag_targets_atom = GDK_NONE;static GdkAtom motif_drag_receiver_info_atom = GDK_NONE;/* Target table handling */GdkFilterReturnmotif_drag_window_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data){ XEvent *xev = (XEvent *)xevent; switch (xev->xany.type) { case DestroyNotify: motif_drag_window = None; motif_drag_gdk_window = NULL; break; case PropertyNotify: if (motif_target_lists && motif_drag_targets_atom && (xev->xproperty.atom == motif_drag_targets_atom)) motif_read_target_table(); break; } return GDK_FILTER_REMOVE;}static Atom motif_drag_window_atom = GDK_NONE;static Windowmotif_lookup_drag_window (Display *display){ Window retval = None; gulong bytes_after, nitems; GdkAtom type; gint format; guchar *data; XGetWindowProperty (gdk_display, gdk_root_window, motif_drag_window_atom, 0, 1, FALSE, XA_WINDOW, &type, &format, &nitems, &bytes_after, &data); if ((format == 32) && (nitems == 1) && (bytes_after == 0)) { retval = *(Window *)data; GDK_NOTE(DND, g_message ("Found drag window %#lx\n", motif_drag_window)); } if (type != None) XFree (data); return retval;}/* Finds the window where global Motif drag information is stored. * If it doesn't exist and 'create' is TRUE, create one. */Window motif_find_drag_window (gboolean create){ if (!motif_drag_window) { if (!motif_drag_window_atom) motif_drag_window_atom = gdk_atom_intern ("_MOTIF_DRAG_WINDOW", TRUE); motif_drag_window = motif_lookup_drag_window (gdk_display); if (!motif_drag_window && create) { /* Create a persistant window. (Copied from LessTif) */ Display *display; XSetWindowAttributes attr; display = XOpenDisplay (gdk_display_name); XSetCloseDownMode (display, RetainPermanent); XGrabServer (display); motif_drag_window = motif_lookup_drag_window (display); if (!motif_drag_window) { attr.override_redirect = True; attr.event_mask = PropertyChangeMask; motif_drag_window = XCreateWindow(display, DefaultRootWindow(display), -100, -100, 10, 10, 0, 0, InputOnly, CopyFromParent, (CWOverrideRedirect | CWEventMask), &attr); GDK_NOTE (DND, g_message ("Created drag window %#lx\n", motif_drag_window)); XChangeProperty (display, gdk_root_window, motif_drag_window_atom, XA_WINDOW, 32, PropModeReplace, (guchar *)&motif_drag_window_atom, 1); } XUngrabServer (display); XCloseDisplay (display); } /* There is a miniscule race condition here if the drag window * gets destroyed exactly now. */ if (motif_drag_window) { motif_drag_gdk_window = gdk_window_foreign_new (motif_drag_window); gdk_window_add_filter (motif_drag_gdk_window, motif_drag_window_filter, NULL); } } return motif_drag_window;}static void motif_read_target_table (void){ gulong bytes_after, nitems; GdkAtom type; gint format; gint i, j; if (!motif_drag_targets_atom) motif_drag_targets_atom = gdk_atom_intern ("_MOTIF_DRAG_TARGETS", FALSE); if (motif_target_lists) { for (i=0; i<motif_n_target_lists; i++) g_list_free (motif_target_lists[i]); g_free (motif_target_lists); motif_target_lists = NULL; motif_n_target_lists = 0; } if (motif_find_drag_window (FALSE)) { MotifTargetTableHeader *header = NULL; guchar *target_bytes = NULL; guchar *p; gboolean success = FALSE; XGetWindowProperty (gdk_display, motif_drag_window, motif_drag_targets_atom, 0, (sizeof(MotifTargetTableHeader)+3)/4, FALSE, motif_drag_targets_atom, &type, &format, &nitems, &bytes_after, (guchar **)&header); if ((format != 8) || (nitems < sizeof (MotifTargetTableHeader))) goto error; header->n_lists = card16_to_host (header->n_lists, header->byte_order); header->total_size = card32_to_host (header->total_size, header->byte_order); XGetWindowProperty (gdk_display, motif_drag_window, motif_drag_targets_atom, (sizeof(MotifTargetTableHeader)+3)/4, (header->total_size + 3)/4 - (sizeof(MotifTargetTableHeader) + 3)/4, FALSE, motif_drag_targets_atom, &type, &format, &nitems, &bytes_after, &target_bytes); if ((format != 8) || (bytes_after != 0) || (nitems != header->total_size - sizeof(MotifTargetTableHeader))) goto error; motif_n_target_lists = header->n_lists; motif_target_lists = g_new0 (GList *, motif_n_target_lists); p = target_bytes; for (i=0; i<header->n_lists; i++) { gint n_targets; guint32 *targets; if (p + sizeof(guint16) - target_bytes > nitems) goto error; n_targets = card16_to_host (*(gushort *)p, header->byte_order); /* We need to make a copy of the targets, since it may * be unaligned */ targets = g_new (guint32, n_targets); memcpy (targets, p + sizeof(guint16), sizeof(guint32) * n_targets); p += sizeof(guint16) + n_targets * sizeof(guint32); if (p - target_bytes > nitems) goto error; for (j=0; j<n_targets; j++) motif_target_lists[i] = g_list_prepend (motif_target_lists[i], GUINT_TO_POINTER (card32_to_host (targets[j], header->byte_order))); g_free (targets); motif_target_lists[i] = g_list_reverse (motif_target_lists[i]); } success = TRUE; error: if (header) XFree (header); if (target_bytes) XFree (target_bytes); if (!success) { if (motif_target_lists) { g_free (motif_target_lists); motif_target_lists = NULL; motif_n_target_lists = 0; } g_warning ("Error reading Motif target table\n"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -