00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00087 rectlist = XFixesFetchRegion (damage_client_connection, region, &howmany);
00088 if (rectlist == NULL)
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
00133 if (damage_client_gsource)
00134 g_source_remove (damage_client_gsource);
00135 XCloseDisplay (damage_client_connection);
00136 }
00137
00138 if (magnifier)
00139 {
00140
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