⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdkdnd.c

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1999 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS * file for a list of people on the GTK+ Team.  See the ChangeLog * files for a list of changes.  These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/.  */#include <X11/Xlib.h>#include <X11/Xatom.h>#include <string.h>#include "gdkx.h"#include "gdk/gdkprivate.h"#include "gdk.h"typedef struct _GdkDragContextPrivate GdkDragContextPrivate;typedef enum {  GDK_DRAG_STATUS_DRAG,  GDK_DRAG_STATUS_MOTION_WAIT,  GDK_DRAG_STATUS_ACTION_WAIT,  GDK_DRAG_STATUS_DROP} GtkDragStatus;typedef struct {  guint32 xid;  gint x, y, width, height;  gboolean mapped;} GdkCacheChild;typedef struct {  GList *children;  GHashTable *child_hash;  guint old_event_mask;} GdkWindowCache;/* Structure that holds information about a drag in progress. * this is used on both source and destination sides. */struct _GdkDragContextPrivate {  GdkDragContext context;  GdkAtom motif_selection;  GdkAtom xdnd_selection;  guint   ref_count;  guint16 last_x;		/* Coordinates from last event */  guint16 last_y;  GdkDragAction old_action;	  /* The last action we sent to the source */  GdkDragAction old_actions;	  /* The last actions we sent to the source */  GdkDragAction xdnd_actions;     /* What is currently set in XdndActionList */  Window dest_xid;              /* The last window we looked up */  Window drop_xid;            /* The (non-proxied) window that is receiving drops */  guint xdnd_targets_set : 1;   /* Whether we've already set XdndTypeList */  guint xdnd_actions_set : 1;   /* Whether we've already set XdndActionList */  guint xdnd_have_actions : 1; /* Whether an XdndActionList was provided */  guint motif_targets_set : 1;  /* Whether we've already set motif initiator info */  guint drag_status : 4;	/* current status of drag */  GdkWindowCache *window_cache;};GdkDragContext *current_dest_drag = NULL;/* Forward declarations */static void gdk_window_cache_destroy (GdkWindowCache *cache);static void     motif_read_target_table (void);static GdkFilterReturn motif_dnd_filter (GdkXEvent *xev,					 GdkEvent  *event,					 gpointer   data);static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev,					  GdkEvent  *event,					  gpointer   data);static GdkFilterReturn xdnd_leave_filter (GdkXEvent *xev,					  GdkEvent  *event,					  gpointer   data);static GdkFilterReturn xdnd_position_filter (GdkXEvent *xev,					     GdkEvent  *event,					     gpointer   data);static GdkFilterReturn xdnd_status_filter (GdkXEvent *xev,					   GdkEvent  *event,					   gpointer   data);static GdkFilterReturn xdnd_finished_filter (GdkXEvent *xev,					    GdkEvent  *event,					    gpointer   data);static GdkFilterReturn xdnd_drop_filter (GdkXEvent *xev,					 GdkEvent  *event,					 gpointer   data);static void   xdnd_manage_source_filter (GdkDragContext *context,					 GdkWindow      *window,					 gboolean        add_filter);/* Drag Contexts */static GList *contexts;GdkDragContext *gdk_drag_context_new        (void){  GdkDragContextPrivate *result;  result = g_new0 (GdkDragContextPrivate, 1);  result->ref_count = 1;  contexts = g_list_prepend (contexts, result);  return (GdkDragContext *)result;}void            gdk_drag_context_ref (GdkDragContext *context){  g_return_if_fail (context != NULL);  ((GdkDragContextPrivate *)context)->ref_count++;}void            gdk_drag_context_unref (GdkDragContext *context){  GdkDragContextPrivate *private = (GdkDragContextPrivate *)context;  g_return_if_fail (context != NULL);  g_return_if_fail (private->ref_count > 0);  private->ref_count--;    if (private->ref_count == 0)    {      g_dataset_destroy (private);            g_list_free (context->targets);      if (context->source_window)	{	  if ((context->protocol == GDK_DRAG_PROTO_XDND) &&	      !context->is_source)	    xdnd_manage_source_filter (context, context->source_window, FALSE);	  gdk_window_unref (context->source_window);	}      if (context->dest_window)	gdk_window_unref (context->dest_window);      if (private->window_cache)	gdk_window_cache_destroy (private->window_cache);      contexts = g_list_remove (contexts, private);      g_free (private);    }}static GdkDragContext *gdk_drag_context_find (gboolean is_source,		       Window   source_xid,		       Window   dest_xid){  GList *tmp_list = contexts;  GdkDragContext *context;  GdkDragContextPrivate *private;  Window context_dest_xid;  while (tmp_list)    {      context = (GdkDragContext *)tmp_list->data;      private = (GdkDragContextPrivate *)context;      context_dest_xid = context->dest_window ? 	                   (private->drop_xid ?			      private->drop_xid :			      GDK_WINDOW_XWINDOW (context->dest_window)) :	                   None;      if ((!context->is_source == !is_source) &&	  ((source_xid == None) || (context->source_window &&	    (GDK_WINDOW_XWINDOW (context->source_window) == source_xid))) &&	  ((dest_xid == None) || (context_dest_xid == dest_xid)))	return context;            tmp_list = tmp_list->next;    }    return NULL;}/* Utility functions */static voidgdk_window_cache_add (GdkWindowCache *cache,		      guint32 xid,		      gint x, gint y, gint width, gint height, 		      gboolean mapped){  GdkCacheChild *child = g_new (GdkCacheChild, 1);  child->xid = xid;  child->x = x;  child->y = y;  child->width = width;  child->height = height;  child->mapped = mapped;  cache->children = g_list_prepend (cache->children, child);  g_hash_table_insert (cache->child_hash, GUINT_TO_POINTER (xid), 		       cache->children);}static GdkFilterReturngdk_window_cache_filter (GdkXEvent *xev,			 GdkEvent  *event,			 gpointer   data){  XEvent *xevent = (XEvent *)xev;  GdkWindowCache *cache = data;  switch (xevent->type)    {    case CirculateNotify:      break;    case ConfigureNotify:      {	XConfigureEvent *xce = &xevent->xconfigure;	GList *node;	node = g_hash_table_lookup (cache->child_hash, 				    GUINT_TO_POINTER (xce->window));	if (node) 	  {	    GdkCacheChild *child = node->data;	    child->x = xce->x; 	    child->y = xce->y;	    child->width = xce->width; 	    child->height = xce->height;	    if (xce->above == None && (node->next))	      {		GList *last = g_list_last (cache->children);		cache->children = g_list_remove_link (cache->children, node);		last->next = node;		node->next = NULL;		node->prev = last;	      }	    else	      {		GList *above_node = g_hash_table_lookup (cache->child_hash, 							 GUINT_TO_POINTER (xce->above));		if (above_node && node->prev != above_node)		  {		    cache->children = g_list_remove_link (cache->children, node);		    node->next = above_node->next;		    if (node->next)		      node->next->prev = node;		    node->prev = above_node;		    above_node->next = node;		  }	      }	  }	break;      }    case CreateNotify:      {	XCreateWindowEvent *xcwe = &xevent->xcreatewindow;	if (!g_hash_table_lookup (cache->child_hash, 				  GUINT_TO_POINTER (xcwe->window))) 	  gdk_window_cache_add (cache, xcwe->window, 				xcwe->x, xcwe->y, xcwe->width, xcwe->height,				FALSE);	break;      }    case DestroyNotify:      {	XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;	GList *node;	node = g_hash_table_lookup (cache->child_hash, 				    GUINT_TO_POINTER (xdwe->window));	if (node) 	  {	    g_hash_table_remove (cache->child_hash,				 GUINT_TO_POINTER (xdwe->window));	    cache->children = g_list_remove_link (cache->children, node);	    g_free (node->data);	    g_list_free_1 (node);	  }	break;      }    case MapNotify:      {	XMapEvent *xme = &xevent->xmap;	GList *node;	node = g_hash_table_lookup (cache->child_hash, 				    GUINT_TO_POINTER (xme->window));	if (node) 	  {	    GdkCacheChild *child = node->data;	    child->mapped = TRUE;	  }	break;      }    case ReparentNotify:      break;    case UnmapNotify:      {	XMapEvent *xume = &xevent->xmap;	GList *node;	node = g_hash_table_lookup (cache->child_hash, 				    GUINT_TO_POINTER (xume->window));	if (node) 	  {	    GdkCacheChild *child = node->data;	    child->mapped = FALSE;	  }	break;      }    default:      return GDK_FILTER_CONTINUE;    }  return GDK_FILTER_REMOVE;}static GdkWindowCache *gdk_window_cache_new (void){  XWindowAttributes xwa;  Window root, parent, *children;  unsigned int nchildren;  int i;    gint old_warnings = gdk_error_warnings;    GdkWindowCache *result = g_new (GdkWindowCache, 1);  result->children = NULL;  result->child_hash = g_hash_table_new (g_direct_hash, NULL);  XGetWindowAttributes (gdk_display, gdk_root_window, &xwa);  result->old_event_mask = xwa.your_event_mask;  XSelectInput (gdk_display, gdk_root_window,		result->old_event_mask | SubstructureNotifyMask);  gdk_window_add_filter ((GdkWindow *)&gdk_root_parent, 			 gdk_window_cache_filter, result);    gdk_error_code = 0;  gdk_error_warnings = 0;  if (XQueryTree(gdk_display, gdk_root_window, 		 &root, &parent, &children, &nchildren) == 0)    return result;    for (i = 0; i < nchildren ; i++)    {      XGetWindowAttributes (gdk_display, children[i], &xwa);      gdk_window_cache_add (result, children[i],			    xwa.x, xwa.y, xwa.width, xwa.height,			    xwa.map_state != IsUnmapped);      if (gdk_error_code)	gdk_error_code = 0;      else	{	  gdk_window_cache_add (result, children[i],				xwa.x, xwa.y, xwa.width, xwa.height,				(xwa.map_state != IsUnmapped));	}    }  XFree (children);  gdk_error_warnings = old_warnings;  return result;}static voidgdk_window_cache_destroy (GdkWindowCache *cache){  XSelectInput (gdk_display, gdk_root_window, cache->old_event_mask);  gdk_window_remove_filter ((GdkWindow *)&gdk_root_parent, 			    gdk_window_cache_filter, cache);  g_list_foreach (cache->children, (GFunc)g_free, NULL);  g_list_free (cache->children);  g_hash_table_destroy (cache->child_hash);  g_free (cache);}static Windowget_client_window_at_coords_recurse (Window  win,				     gint    x,				     gint    y){  Window root, tmp_parent, *children;  unsigned int nchildren;  int i;  Window child = None;  Atom type = None;  int format;  unsigned long nitems, after;  unsigned char *data;    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;    }#if 0  /* This is beautiful! Damn Enlightenment and click-to-focus */  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;    }  #else  if (XQueryTree(gdk_display, win,		 &root, &tmp_parent, &children, &nchildren) == 0)    return 0;  if (!gdk_error_code)    {      for (i = nchildren - 1; (i >= 0) && (child == None); i--)	{	  XWindowAttributes xwa;	  	  XGetWindowAttributes (gdk_display, children[i], &xwa);	  	  if (gdk_error_code)	    gdk_error_code = 0;	  else if ((xwa.map_state == IsViewable) && (xwa.class == InputOutput) &&		   (x >= xwa.x) && (x < xwa.x + (gint)xwa.width) &&		   (y >= xwa.y) && (y < xwa.y + (gint)xwa.height))	    {	      x -= xwa.x;	      y -= xwa.y;	      child = children[i];	    }	}            XFree (children);    }  else    gdk_error_code = 0;#endif    if (child)    return get_client_window_at_coords_recurse (child, x, y);  else    return None;}static Window get_client_window_at_coords (GdkWindowCache *cache,			     Window          ignore,			     gint            x_root,			     gint            y_root){  GList *tmp_list;  Window retval = None;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -