eventqueue.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* Metacity X event source for main loop */
00004 
00005 /* 
00006  * Copyright (C) 2001 Havoc Pennington (based on GDK code (C) Owen
00007  * Taylor, Red Hat Inc.)
00008  * 
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License as
00011  * published by the Free Software Foundation; either version 2 of the
00012  * License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful, but
00015  * WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00022  * 02111-1307, USA.  */
00023 
00024 #include "eventqueue.h"
00025 #include <X11/Xlib.h>
00026 
00027 static gboolean eq_prepare  (GSource     *source,
00028                              gint        *timeout);
00029 static gboolean eq_check    (GSource     *source);
00030 static gboolean eq_dispatch (GSource     *source,
00031                              GSourceFunc  callback,
00032                              gpointer     user_data);
00033 static void     eq_destroy  (GSource     *source);
00034 
00035 static GSourceFuncs eq_funcs = {
00036   eq_prepare,
00037   eq_check,
00038   eq_dispatch,
00039   eq_destroy
00040 };
00041 
00042 struct _MetaEventQueue
00043 {
00044   GSource source;
00045 
00046   Display *display;
00047   GPollFD poll_fd;
00048   int connection_fd;
00049   GQueue *events;
00050 };
00051 
00052 MetaEventQueue*
00053 meta_event_queue_new (Display *display, MetaEventQueueFunc func, gpointer data)
00054 {
00055   GSource *source;
00056   MetaEventQueue *eq;
00057 
00058   source = g_source_new (&eq_funcs, sizeof (MetaEventQueue));
00059   eq = (MetaEventQueue*) source;
00060   
00061   eq->connection_fd = ConnectionNumber (display);
00062   eq->poll_fd.fd = eq->connection_fd;
00063   eq->poll_fd.events = G_IO_IN;
00064 
00065   eq->events = g_queue_new ();
00066 
00067   eq->display = display;
00068   
00069   g_source_set_priority (source, G_PRIORITY_DEFAULT);
00070   g_source_add_poll (source, &eq->poll_fd);
00071   g_source_set_can_recurse (source, TRUE);
00072 
00073   g_source_set_callback (source, (GSourceFunc) func, data, NULL);
00074   
00075   g_source_attach (source, NULL);
00076   g_source_unref (source);
00077 
00078   return eq;
00079 }
00080 
00081 void
00082 meta_event_queue_free (MetaEventQueue *eq)
00083 {
00084   GSource *source;
00085 
00086   source = (GSource*) eq;
00087   
00088   g_source_destroy (source);
00089 }
00090 
00091 static gboolean
00092 eq_events_pending (MetaEventQueue *eq)
00093 {
00094   return eq->events->length > 0 || XPending (eq->display);
00095 }
00096 
00097 static void
00098 eq_queue_events (MetaEventQueue *eq)
00099 {
00100   XEvent xevent;
00101 
00102   while (XPending (eq->display))
00103     {
00104       XEvent *copy;
00105       
00106       XNextEvent (eq->display, &xevent);
00107 
00108       copy = g_new (XEvent, 1);
00109       *copy = xevent;
00110 
00111       g_queue_push_tail (eq->events, copy);
00112     }
00113 }
00114 
00115 static gboolean  
00116 eq_prepare (GSource *source, gint *timeout)
00117 {
00118   MetaEventQueue *eq;
00119 
00120   eq = (MetaEventQueue*) source;
00121   
00122   *timeout = -1;
00123 
00124   return eq_events_pending (eq);
00125 }
00126 
00127 static gboolean  
00128 eq_check (GSource  *source) 
00129 {
00130   MetaEventQueue *eq;
00131 
00132   eq = (MetaEventQueue*) source;
00133 
00134   if (eq->poll_fd.revents & G_IO_IN)
00135     return eq_events_pending (eq);
00136   else
00137     return FALSE;
00138 }
00139 
00140 static gboolean  
00141 eq_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
00142 {
00143   MetaEventQueue *eq;
00144 
00145   eq = (MetaEventQueue*) source;
00146   
00147   eq_queue_events (eq);
00148 
00149   if (eq->events->length > 0)
00150     {
00151       XEvent *event;
00152       MetaEventQueueFunc func;
00153 
00154       event = g_queue_pop_head (eq->events);
00155       func = (MetaEventQueueFunc) callback;
00156       
00157       (* func) (event, user_data);
00158 
00159       g_free (event);
00160     }
00161   
00162   return TRUE;
00163 }
00164 
00165 static void
00166 eq_destroy (GSource *source)
00167 {
00168   MetaEventQueue *eq;
00169 
00170   eq = (MetaEventQueue*) source;
00171 
00172   while (eq->events->length > 0)
00173     {
00174       XEvent *event;
00175       
00176       event = g_queue_pop_head (eq->events);
00177 
00178       g_free (event);
00179     }
00180 
00181   g_queue_free (eq->events);
00182 
00183   /* source itself is freed by glib */
00184 }

Generated on Sat Aug 23 22:04:16 2008 for metacity by  doxygen 1.5.5