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

📄 gdkevents.c

📁 gtk是linux一款强大的夸平台的图形化开发工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 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 "gdk.h"#include "gdkx.h"#include "gdkprivate.h"#include "gdkkeysyms.h"#if HAVE_CONFIG_H#  include <config.h>#  if STDC_HEADERS#    include <string.h>#  endif#endif#include "gdkinput.h"typedef struct _GdkIOClosure GdkIOClosure;typedef struct _GdkEventPrivate GdkEventPrivate;#define DOUBLE_CLICK_TIME      250#define TRIPLE_CLICK_TIME      500#define DOUBLE_CLICK_DIST      5#define TRIPLE_CLICK_DIST      5typedef enum{  /* Following flag is set for events on the event queue during   * translation and cleared afterwards.   */  GDK_EVENT_PENDING = 1 << 0} GdkEventFlags;struct _GdkIOClosure{  GdkInputFunction function;  GdkInputCondition condition;  GdkDestroyNotify notify;  gpointer data;};struct _GdkEventPrivate{  GdkEvent event;  guint    flags;};/*  * Private function declarations */static GdkEvent *gdk_event_new		(void);static gint	 gdk_event_apply_filters (XEvent   *xevent,					  GdkEvent *event,					  GList    *filters);static gint	 gdk_event_translate	 (GdkEvent *event, 					  XEvent   *xevent);#if 0static Bool	 gdk_event_get_type	(Display   *display, 					 XEvent	   *xevent, 					 XPointer   arg);#endifstatic void      gdk_events_queue       (void);static GdkEvent* gdk_event_unqueue      (void);static gboolean  gdk_event_prepare      (gpointer   source_data, 				 	 GTimeVal  *current_time,					 gint      *timeout,					 gpointer   user_data);static gboolean  gdk_event_check        (gpointer   source_data,				 	 GTimeVal  *current_time,					 gpointer   user_data);static gboolean  gdk_event_dispatch     (gpointer   source_data,					 GTimeVal  *current_time,					 gpointer   user_data);static void	 gdk_synthesize_click	(GdkEvent  *event, 					 gint	    nclicks);GdkFilterReturn gdk_wm_protocols_filter (GdkXEvent *xev,					 GdkEvent  *event,					 gpointer   data);/* Private variable declarations */static int connection_number = 0;	    /* The file descriptor number of our					     *	connection to the X server. This					     *	is used so that we may determine					     *	when events are pending by using					     *	the "select" system call.					     */static guint32 button_click_time[2];	    /* The last 2 button click times. Used					     *	to determine if the latest button click					     *	is part of a double or triple click.					     */static GdkWindow *button_window[2];	    /* The last 2 windows to receive button presses.					     *	Also used to determine if the latest button					     *	click is part of a double or triple click.					     */static guint button_number[2];		    /* The last 2 buttons to be pressed.					     */static GdkEventFunc   event_func = NULL;    /* Callback for events */static gpointer       event_data = NULL;static GDestroyNotify event_notify = NULL;static GList *client_filters;	            /* Filters for client messages *//* FIFO's for event queue, and for events put back using * gdk_event_put(). */static GList *queued_events = NULL;static GList *queued_tail = NULL;static GSourceFuncs event_funcs = {  gdk_event_prepare,  gdk_event_check,  gdk_event_dispatch,  (GDestroyNotify)g_free};GPollFD event_poll_fd;/********************************************* * Functions for maintaining the event queue * *********************************************//************************************************************* * gdk_event_queue_find_first: *     Find the first event on the queue that is not still *     being filled in. *   arguments: *      *   results: *     Pointer to the list node for that event, or NULL *************************************************************/static GList*gdk_event_queue_find_first (void){  GList *tmp_list = queued_events;  while (tmp_list)    {      GdkEventPrivate *event = tmp_list->data;      if (!(event->flags & GDK_EVENT_PENDING))	return tmp_list;      tmp_list = g_list_next (tmp_list);    }  return NULL;}/************************************************************* * gdk_event_queue_remove_link: *     Remove a specified list node from the event queue. *   arguments: *     node: Node to remove. *   results: *************************************************************/static voidgdk_event_queue_remove_link (GList *node){  if (node->prev)    node->prev->next = node->next;  else    queued_events = node->next;    if (node->next)    node->next->prev = node->prev;  else    queued_tail = node->prev;  }/************************************************************* * gdk_event_queue_append: *     Append an event onto the tail of the event queue. *   arguments: *     event: Event to append. *   results: *************************************************************/static voidgdk_event_queue_append (GdkEvent *event){  queued_tail = g_list_append (queued_tail, event);    if (!queued_events)    queued_events = queued_tail;  else    queued_tail = queued_tail->next;}void gdk_events_init (void){  connection_number = ConnectionNumber (gdk_display);  GDK_NOTE (MISC,	    g_message ("connection number: %d", connection_number));  g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);  event_poll_fd.fd = connection_number;  event_poll_fd.events = G_IO_IN;    g_main_add_poll (&event_poll_fd, GDK_PRIORITY_EVENTS);  button_click_time[0] = 0;  button_click_time[1] = 0;  button_window[0] = NULL;  button_window[1] = NULL;  button_number[0] = -1;  button_number[1] = -1;  gdk_add_client_message_filter (gdk_wm_protocols, 				 gdk_wm_protocols_filter, NULL);}/* *-------------------------------------------------------------- * gdk_events_pending * *   Returns if events are pending on the queue. * * Arguments: * * Results: *   Returns TRUE if events are pending * * Side effects: * *-------------------------------------------------------------- */gbooleangdk_events_pending (void){  return (gdk_event_queue_find_first() || XPending (gdk_display));}/* *-------------------------------------------------------------- * gdk_event_get_graphics_expose * *   Waits for a GraphicsExpose or NoExpose event * * Arguments: * * Results:  *   For GraphicsExpose events, returns a pointer to the event *   converted into a GdkEvent Otherwise, returns NULL. * * Side effects: * *-------------------------------------------------------------- */static Boolgraphics_expose_predicate (Display  *display,			   XEvent   *xevent,			   XPointer  arg){  GdkWindowPrivate *private = (GdkWindowPrivate*) arg;    g_return_val_if_fail (private != NULL, False);    if (xevent->xany.window == private->xwindow &&      (xevent->xany.type == GraphicsExpose ||       xevent->xany.type == NoExpose))    return True;  else    return False;}GdkEvent*gdk_event_get_graphics_expose (GdkWindow *window){  XEvent xevent;  GdkEvent *event;    g_return_val_if_fail (window != NULL, NULL);    XIfEvent (gdk_display, &xevent, graphics_expose_predicate, (XPointer) window);    if (xevent.xany.type == GraphicsExpose)    {      event = gdk_event_new ();            if (gdk_event_translate (event, &xevent))	return event;      else	gdk_event_free (event);    }    return NULL;	}/************************ * Exposure compression * ************************//* * The following implements simple exposure compression. It is * modelled after the way Xt does exposure compression - in * particular compress_expose = XtExposeCompressMultiple. * It compress consecutive sequences of exposure events, * but not sequences that cross other events. (This is because * if it crosses a ConfigureNotify, we could screw up and * mistakenly compress the exposures generated for the new * size - could we just check for ConfigureNotify?) * * Xt compresses to a region / bounding rectangle, we compress * to two rectangles, and try find the two rectangles of minimal * area for this - this is supposed to handle the typical * L-shaped regions generated by OpaqueMove. *//* Given three rectangles, find the two rectangles that cover * them with the smallest area. */static voidgdk_add_rect_to_rects (GdkRectangle *rect1,		       GdkRectangle *rect2, 		       GdkRectangle *new_rect){  GdkRectangle t1, t2, t3;  gint size1, size2, size3;  gdk_rectangle_union (rect1, rect2, &t1);  gdk_rectangle_union (rect1, new_rect, &t2);  gdk_rectangle_union (rect2, new_rect, &t3);  size1 = t1.width * t1.height + new_rect->width * new_rect->height;  size2 = t2.width * t2.height + rect2->width * rect2->height;  size3 = t1.width * t1.height + rect1->width * rect1->height;  if (size1 < size2)    {      if (size1 < size3)	{	  *rect1 = t1;	  *rect2 = *new_rect;	}      else	*rect2 = t3;    }  else    {      if (size2 < size3)	*rect1 = t2;      else	*rect2 = t3;    }}typedef struct _GdkExposeInfo GdkExposeInfo;struct _GdkExposeInfo{  Window window;  gboolean seen_nonmatching;};static Boolexpose_predicate (Display *display,		  XEvent  *xevent,		  XPointer arg){  GdkExposeInfo *info = (GdkExposeInfo*) arg;  /* Compressing across GravityNotify events is safe, because   * we completely ignore them, so they can't change what   * we are going to draw. Compressing across GravityNotify   * events is necessay because during window-unshading animation   * we'll get a whole bunch of them interspersed with   * expose events.   */  if (xevent->xany.type != Expose &&       xevent->xany.type != GravityNotify)    {      info->seen_nonmatching = TRUE;    }  if (info->seen_nonmatching ||      xevent->xany.type != Expose ||      xevent->xany.window != info->window)    return FALSE;  else    return TRUE;}voidgdk_compress_exposures (XEvent    *xevent,			GdkWindow *window){  gint nrects = 1;  gint count = 0;  GdkRectangle rect1;  GdkRectangle rect2;  GdkRectangle tmp_rect;  XEvent tmp_event;  GdkFilterReturn result;  GdkExposeInfo info;  GdkEvent event;  info.window = xevent->xany.window;  info.seen_nonmatching = FALSE;    rect1.x = xevent->xexpose.x;  rect1.y = xevent->xexpose.y;  rect1.width = xevent->xexpose.width;  rect1.height = xevent->xexpose.height;  event.any.type = GDK_EXPOSE;  event.any.window = None;  event.any.send_event = FALSE;    while (1)    {      if (count == 0)	{	  if (!XCheckIfEvent (gdk_display, 			      &tmp_event, 			      expose_predicate, 			      (XPointer)&info))	    break;	}      else	XIfEvent (gdk_display, 		  &tmp_event, 		  expose_predicate, 		  (XPointer)&info);      event.any.window = window;            /* We apply filters here, and if it was filtered, completely       * ignore the return       */      result = gdk_event_apply_filters (xevent, &event,					window ? 					  ((GdkWindowPrivate *)window)->filters					  : gdk_default_filters);            if (result != GDK_FILTER_CONTINUE)	{	  if (result == GDK_FILTER_TRANSLATE)	    gdk_event_put (&event);	  continue;	}      if (nrects == 1)	{	  rect2.x = tmp_event.xexpose.x;	  rect2.y = tmp_event.xexpose.y;	  rect2.width = tmp_event.xexpose.width;	  rect2.height = tmp_event.xexpose.height;	  nrects++;	}      else	{	  tmp_rect.x = tmp_event.xexpose.x;	  tmp_rect.y = tmp_event.xexpose.y;	  tmp_rect.width = tmp_event.xexpose.width;	  tmp_rect.height = tmp_event.xexpose.height;	  gdk_add_rect_to_rects (&rect1, &rect2, &tmp_rect);	}      count = tmp_event.xexpose.count;    }  if (nrects == 2)    {      gdk_rectangle_union (&rect1, &rect2, &tmp_rect);      if ((tmp_rect.width * tmp_rect.height) <	  2 * (rect1.height * rect1.width +	       rect2.height * rect2.width))	{	  rect1 = tmp_rect;	  nrects = 1;	}    }  if (nrects == 2)    {      event.expose.type = GDK_EXPOSE;      event.expose.window = window;      event.expose.area.x = rect2.x;      event.expose.area.y = rect2.y;      event.expose.area.width = rect2.width;      event.expose.area.height = rect2.height;      event.expose.count = 0;      gdk_event_put (&event);    }  xevent->xexpose.count = nrects - 1;  xevent->xexpose.x = rect1.x;  xevent->xexpose.y = rect1.y;  xevent->xexpose.width = rect1.width;  xevent->xexpose.height = rect1.height;}/************************************************************* * gdk_event_handler_set: *      *   arguments: *     func: Callback function to be called for each event. *     data: Data supplied to the function *     notify: function called when function is no longer needed *  *   results: *************************************************************/void gdk_event_handler_set (GdkEventFunc   func,		       gpointer       data,		       GDestroyNotify notify){  if (event_notify)    (*event_notify) (event_data);  event_func = func;  event_data = data;  event_notify = notify;}/* *-------------------------------------------------------------- * gdk_event_get * *   Gets the next event. * * Arguments: * * Results: *   If an event is waiting that we care about, returns  *   a pointer to that event, to be freed with gdk_event_free. *   Otherwise, returns NULL. * * Side effects: * *-------------------------------------------------------------- */

⌨️ 快捷键说明

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