Main Page | Namespace List | Data Structures | Directories | File List | Namespace Members | Data Fields | Globals

damage-client.c

Go to the documentation of this file.
00001 /*
00002  * GNOME-MAG Magnification service for GNOME
00003  *
00004  * Copyright 2004 Sun Microsystems Inc.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public
00017  * License along with this library; if not, write to the
00018  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA 02111-1307, USA.
00020  */
00021 
00022 #include "config.h"
00023 #include <gdk/gdkx.h>
00024 #include <gtk/gtk.h>
00025 #include <X11/Xlib.h>
00026 #ifdef HAVE_DAMAGE
00027 #include <X11/extensions/Xdamage.h>
00028 #endif
00029 #ifdef HAVE_XFIXES
00030 #include <X11/extensions/Xfixes.h>
00031 #endif
00032 #include "magnifier.h"
00033 #include "magnifier-private.h"
00034 
00035 Display *damage_client_connection = NULL;
00036 guint   damage_client_gsource = 0;
00037 
00038 #ifdef HAVE_DAMAGE
00039 Damage _magnifier_client_damage;
00040 #endif
00041 int damage_event_base, damage_error_base;
00042 
00043 #ifdef HAVE_XFIXES
00044 XserverRegion region;
00045 #endif
00046 
00047 gboolean
00048 magnifier_damage_reset (gpointer data)
00049 {
00050 #ifdef HAVE_DAMAGE
00051 #ifdef HAVE_XFIXES
00052   XDamageSubtract (damage_client_connection, _magnifier_client_damage, None, region);
00053   XFlush (damage_client_connection);
00054 #endif
00055 #endif
00056     return FALSE;
00057 }
00058 
00059 gboolean
00060 magnifier_damage_handler (GIOChannel *source, GIOCondition condition, gpointer data)
00061 {
00062 #ifdef HAVE_DAMAGE
00063   XEvent ev;
00064   Magnifier *magnifier = (Magnifier *) data;
00065 #ifdef HAVE_XFIXES
00066   XRectangle *rectlist;
00067 
00068   do
00069   {
00070       XNextEvent(damage_client_connection, &ev);
00071       if (ev.type == damage_event_base + XDamageNotify) 
00072       {
00073           XDamageNotifyEvent  *dev = (XDamageNotifyEvent *) &ev;
00074 #ifdef DEBUG_DAMAGE
00075           g_message ("Damage %3d, %3d x %3d, %3d\n",
00076                      (int) dev->area.x, (int) dev->area.x + dev->area.width,
00077                      (int) dev->area.y, (int) dev->area.y + dev->area.height);
00078 #endif
00079       }
00080   } while (XPending (damage_client_connection));
00081   XDamageSubtract (damage_client_connection, _magnifier_client_damage, None, region);
00082   
00083   if (magnifier)
00084   {
00085       int i, howmany;
00086       /* TODO: maintain this list on the client instead, to avoid the roundtrip below */
00087       rectlist = XFixesFetchRegion (damage_client_connection, region, &howmany);
00088       if (rectlist == NULL) /* no reply from fetch */
00089           return TRUE;
00090       for (i=0; i < howmany; ++i) {
00091           magnifier_notify_damage (magnifier, &rectlist[i]);
00092       }
00093       XFree (rectlist);
00094   }
00095 
00096   XFlush (damage_client_connection);
00097 #endif
00098 
00099   return TRUE;
00100 #else
00101   return FALSE;
00102 #endif
00103 }
00104 
00105 gboolean
00106 magnifier_source_has_damage_extension (Magnifier *magnifier)
00107 {
00108         int event_base, error_base;
00109         Display *dpy;
00110         g_assert (magnifier);
00111 #ifdef HAVE_DAMAGE
00112         dpy = GDK_DISPLAY_XDISPLAY (magnifier->source_display);
00113         if (g_getenv ("MAGNIFIER_IGNORE_DAMAGE"))
00114                 return FALSE;
00115         if (XDamageQueryExtension (dpy, &event_base, &error_base))
00116                 return TRUE;
00117 #endif
00118         return FALSE;
00119 }
00120 
00121 gboolean
00122 magnifier_damage_client_init (Magnifier *magnifier)
00123 {
00124 #ifdef HAVE_DAMAGE
00125     GIOChannel *ioc;
00126     int fd;
00127     Display *dpy;
00128     Window rootwin;
00129 
00130     if (damage_client_connection)
00131     {
00132         /* remove the old watch */
00133         if (damage_client_gsource) 
00134           g_source_remove (damage_client_gsource);
00135         XCloseDisplay (damage_client_connection);
00136     }
00137 
00138     if (magnifier)
00139     {
00140         /* we need our own connection here to keep from gumming up the works */
00141         damage_client_connection = 
00142           XOpenDisplay (magnifier->source_display_name); 
00143         rootwin = GDK_WINDOW_XWINDOW (magnifier->priv->root);
00144     }
00145     else 
00146     {
00147         dpy = GDK_DISPLAY ();
00148         damage_client_connection = XOpenDisplay (NULL);
00149         rootwin = RootWindow (damage_client_connection, DefaultScreen (damage_client_connection));
00150         g_message ("warning - using DefaultScreen for DAMAGE connection.");
00151     }
00152 
00153     if (!XDamageQueryExtension (damage_client_connection, 
00154                                 &damage_event_base, &damage_error_base))
00155     {
00156         g_warning ("Damage extension not currently active.\n");
00157         return FALSE;
00158     }
00159     else if (g_getenv ("MAGNIFIER_IGNORE_DAMAGE"))
00160     {
00161         g_warning ("Damage extension being ignored at user request.");
00162         return FALSE;
00163     }
00164     else
00165     {
00166         _magnifier_client_damage = XDamageCreate (damage_client_connection, 
00167                                                   rootwin,
00168                                                   XDamageReportDeltaRectangles);
00169 #ifdef HAVE_XFIXES
00170         region = XFixesCreateRegion (damage_client_connection, 
00171                                      0, 0);
00172 #else
00173         return FALSE;
00174 #endif
00175         fd = ConnectionNumber (damage_client_connection);
00176         ioc = g_io_channel_unix_new (fd);
00177         damage_client_gsource = 
00178           g_io_add_watch (ioc, G_IO_IN | G_IO_HUP | G_IO_PRI | G_IO_ERR, magnifier_damage_handler, 
00179                           magnifier);
00180         g_io_channel_unref (ioc); 
00181         g_message ("added event source to damage connection");
00182         g_idle_add (magnifier_damage_reset, NULL);
00183     }
00184     return TRUE;
00185 #else
00186     g_warning ("this copy of gnome-mag was built without damage extension support.\n");
00187     return FALSE;
00188 #endif
00189 }
00190 

Generated on Mon May 15 16:14:02 2006 for gnome-mag by  doxygen 1.4.4