magnifier.c

Go to the documentation of this file.
00001 /*
00002  * AT-SPI - Assistive Technology Service Provider Interface
00003  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
00004  *
00005  * Copyright 2001 Sun Microsystems Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Library General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Library General Public
00018  * License along with this library; if not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020  * Boston, MA 02111-1307, USA.
00021  */
00022 
00023 #include "config.h"
00024 #include "magnifier.h"
00025 #include "magnifier-private.h"
00026 #include "zoom-region.h"
00027 #include "zoom-region-private.h"
00028 #include "gmag-cursor.h"
00029 #include "gmag-graphical-server.h"
00030 #include "GNOME_Magnifier.h"
00031 #include "magnifier-server.h"
00032 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <strings.h>
00036 
00037 #include <libbonobo.h>
00038 #include <login-helper/login-helper.h>
00039 
00040 #include <dbus/dbus-glib-bindings.h>
00041 
00042 #include <gdk-pixbuf/gdk-pixbuf.h>
00043 #include <gdk/gdkx.h>
00044 #include <gdk/gdk.h>
00045 #include <gtk/gtk.h>
00046 
00047 /* if you #define this, don't forget to set MAG_CLIENT_DEBUG env variable */
00048 #define DEBUG_CLIENT_CALLS
00049 
00050 #ifdef DEBUG_CLIENT_CALLS
00051 static gboolean client_debug = FALSE;
00052 #define DBG(a) if (client_debug) { (a); }
00053 #else
00054 #define DBG(a)
00055 #endif
00056 
00057 typedef struct
00058 {
00059     LoginHelper parent;
00060     Magnifier *mag;
00061 } MagLoginHelper;
00062 
00063 typedef struct 
00064 {
00065     LoginHelperClass parent_class;
00066 } MagLoginHelperClass;
00067 
00068 static GObjectClass *parent_class = NULL;
00069 
00070 enum {
00071         MAGNIFIER_SOURCE_DISPLAY_PROP,
00072         MAGNIFIER_TARGET_DISPLAY_PROP,
00073         MAGNIFIER_SOURCE_SIZE_PROP,
00074         MAGNIFIER_TARGET_SIZE_PROP,
00075         MAGNIFIER_CURSOR_SET_PROP,
00076         MAGNIFIER_CURSOR_SIZE_PROP,
00077         MAGNIFIER_CURSOR_ZOOM_PROP,
00078         MAGNIFIER_CURSOR_COLOR_PROP,
00079         MAGNIFIER_CURSOR_HOTSPOT_PROP,
00080         MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
00081         MAGNIFIER_CROSSWIRE_SIZE_PROP,
00082         MAGNIFIER_CROSSWIRE_LENGTH_PROP,
00083         MAGNIFIER_CROSSWIRE_CLIP_PROP,
00084         MAGNIFIER_CROSSWIRE_COLOR_PROP
00085 } PropIdx;
00086 
00087 typedef struct
00088 {
00089         GNOME_Magnifier_RectBounds rectbounds;
00090         RectBounds dbus_rectbounds;
00091         GNOME_Magnifier_RectBounds viewport;
00092         RectBounds dbus_viewport;
00093         gboolean   is_managed;
00094         gint       scroll_policy;
00095         gfloat     contrast;
00096         gfloat     zx;
00097         gfloat     zy;
00098         gint32     xalign;
00099         gint32     yalign;
00100         guint32    border_color;
00101         gint32     border_size;
00102         gchar     *smoothing_type;
00103         gboolean   inverse;
00104 } MagnifierZoomRegionSaveProps;
00105 
00106 #ifdef DEBUG_CLIENT_CALLS
00107 gchar* mag_prop_names[MAGNIFIER_CROSSWIRE_COLOR_PROP + 1] = {
00108     "SOURCE_DISPLAY",
00109     "TARGET_DISPLAY",
00110     "SOURCE_SIZE",
00111     "TARGET_SIZE",
00112     "CURSOR_SET",
00113     "CURSOR_SIZE",
00114     "CURSOR_ZOOM",
00115     "CURSOR_COLOR",
00116     "CURSOR_HOTSPOT",
00117     "CURSOR_DEFAULT_SIZE",
00118     "CROSSWIRE_SIZE",
00119     "CROSSWIRE_LENGTH",
00120     "CROSSWIRE_CLIP",
00121     "CROSSWIRE_COLOR"
00122 };
00123 #endif
00124 
00125 static Magnifier *_this_magnifier = NULL;
00126 extern gint       fixes_event_base;
00127 
00128 static void magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set);
00129 static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);
00130 static gboolean magnifier_reset_struts_at_idle (gpointer data);
00131 static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);
00132 static void magnifier_adjust_source_size (Magnifier *magnifier);
00133 static gboolean _is_override_redirect = FALSE;
00134 
00135 static GHashTable *zoom_hash = NULL;
00136 
00137 static Window*
00138 mag_login_helper_get_raise_windows (LoginHelper *helper)
00139 {
00140     Window *mainwin = NULL;
00141     MagLoginHelper *mag_helper = (MagLoginHelper *) helper;
00142     Magnifier *magnifier = MAGNIFIER (mag_helper->mag);
00143 
00144     if (magnifier && magnifier->priv && magnifier->priv->w)
00145     {
00146         mainwin = g_new0 (Window, 2);
00147         mainwin[0] = GDK_WINDOW_XWINDOW (magnifier->priv->w->window);
00148         mainwin[1] = None;
00149     }
00150     return mainwin;
00151 }
00152 
00153 static LoginHelperDeviceReqFlags
00154 mag_login_helper_get_device_reqs (LoginHelper *helper)
00155 {
00156     /* means "don't grab the xserver or core pointer", 
00157        and "we need to raise windows" */
00158     return LOGIN_HELPER_GUI_EVENTS | 
00159         LOGIN_HELPER_POST_WINDOWS | 
00160         LOGIN_HELPER_CORE_POINTER;
00161 }
00162 
00163 static gboolean
00164 mag_login_helper_set_safe (LoginHelper *helper, gboolean ignored)
00165 {
00166     return TRUE;
00167 }
00168 
00169 static void
00170 mag_login_helper_class_init (MagLoginHelperClass *klass)
00171 {
00172         LoginHelperClass *login_helper_class = LOGIN_HELPER_CLASS(klass);
00173         login_helper_class->get_raise_windows = mag_login_helper_get_raise_windows;
00174         login_helper_class->get_device_reqs = mag_login_helper_get_device_reqs;
00175         login_helper_class->set_safe = mag_login_helper_set_safe;
00176 }
00177 
00178 static void
00179 mag_login_helper_init (MagLoginHelper *helper)
00180 {
00181     helper->mag = NULL; /* we set this with mag_login_helper_set_magnifier */
00182 }
00183 
00184 static void
00185 mag_login_helper_set_magnifier (MagLoginHelper *helper, Magnifier *mag)
00186 {
00187     if (helper) 
00188         helper->mag = mag;
00189 }
00190 
00191 BONOBO_TYPE_FUNC (MagLoginHelper, 
00192                   LOGIN_HELPER_TYPE,
00193                   mag_login_helper)
00194 
00195 static gboolean
00196 can_open_display (gchar *display_name)
00197 {
00198     Display *d;
00199     if ((d = XOpenDisplay (display_name)))
00200     {
00201         XCloseDisplay (d);
00202         return TRUE;
00203     }
00204     return FALSE;
00205 }
00206 
00207 static void
00208 magnifier_warp_cursor_to_screen (Magnifier *magnifier)
00209 {
00210         int x, y, unused_x, unused_y;
00211         unsigned int mask;
00212         Window root_return, child_return;
00213 
00214         if (magnifier->source_display)
00215         {
00216             if (!XQueryPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display), 
00217                                 GDK_WINDOW_XWINDOW (magnifier->priv->root), 
00218                                 &root_return,
00219                                 &child_return,
00220                                 &x, &y,
00221                                 &unused_x, &unused_y,
00222                                 &mask))
00223             {
00224                 XWarpPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display),
00225                               None,
00226                               GDK_WINDOW_XWINDOW (magnifier->priv->root),
00227                               0, 0, 0, 0,
00228                               x, y);
00229                 XSync (GDK_DISPLAY_XDISPLAY (magnifier->source_display), FALSE);
00230             }
00231         }
00232 }
00233 
00234 void
00235 magnifier_zoom_regions_update_pointer (Magnifier *magnifier)
00236 {
00237         GList *list;
00238 
00239         g_assert (magnifier);
00240 
00241         list = magnifier->zoom_regions;
00242         while (list) {
00243                 /* propagate the expose events to the zoom regions */
00244                 GNOME_Magnifier_ZoomRegion zoom_region;
00245                 CORBA_Environment ev;
00246                 zoom_region = list->data;
00247                 CORBA_exception_init (&ev);
00248                 if (zoom_region)
00249                         GNOME_Magnifier_ZoomRegion_updatePointer (
00250                                 CORBA_Object_duplicate (zoom_region, &ev), &ev);
00251                 list = g_list_next (list);
00252         }
00253 }
00254 
00255 static void
00256 magnifier_zoom_regions_mark_dirty (Magnifier *magnifier, GNOME_Magnifier_RectBounds rect_bounds)
00257 {
00258         GList *list;
00259 
00260         g_assert (magnifier);
00261 
00262         list = magnifier->zoom_regions;
00263         while (list) 
00264         {
00265                 /* propagate the expose events to the zoom regions */
00266                 GNOME_Magnifier_ZoomRegion zoom_region;
00267                 CORBA_Environment ev;
00268                 zoom_region = list->data;
00269                 CORBA_exception_init (&ev);
00270                 if (zoom_region)
00271                         GNOME_Magnifier_ZoomRegion_markDirty (CORBA_Object_duplicate (zoom_region, &ev),
00272                                                               &rect_bounds,
00273                                                               &ev);
00274                 list = g_list_next (list);
00275         }
00276 }
00277 
00278 void
00279 magnifier_set_cursor_from_pixbuf (Magnifier *magnifier,
00280                                   GdkPixbuf *cursor_pixbuf)
00281 {
00282         GdkPixmap *pixmap, *mask;
00283         gint width, height;
00284         GdkGC *gc;
00285         GdkDrawable *drawable = magnifier->priv->w->window;
00286 
00287         if (magnifier->priv->cursor) {
00288                 g_object_unref (magnifier->priv->cursor);
00289                 magnifier->priv->cursor = NULL;
00290         }
00291         if (drawable && cursor_pixbuf) {
00292                 const gchar *xhot_string = NULL, *yhot_string = NULL;
00293                 width = gdk_pixbuf_get_width (cursor_pixbuf);
00294                 height = gdk_pixbuf_get_height (cursor_pixbuf);
00295                 pixmap = gdk_pixmap_new (drawable, width, height, -1);
00296                 gc = gdk_gc_new (pixmap);
00297                 if (GDK_IS_DRAWABLE (pixmap))
00298                         gdk_draw_pixbuf (pixmap, gc, cursor_pixbuf, 0, 0, 0, 0,
00299                                          width, height, GDK_RGB_DITHER_NONE,
00300                                          0, 0);
00301                 else
00302                         DBG (g_warning ("empty cursor pixmap created."));
00303                 mask = gdk_pixmap_new (drawable, width, height, 1);
00304                 gdk_pixbuf_render_threshold_alpha (cursor_pixbuf, mask,
00305                                                    0, 0, 0, 0, 
00306                                                    width, height,
00307                                                    200);
00308                 g_object_unref (gc);
00309                 magnifier->priv->cursor = pixmap;
00310                 magnifier->priv->cursor_mask = mask;
00311 
00312                 xhot_string = g_object_get_data (cursor_pixbuf, "x_hot");
00313                 yhot_string = g_object_get_data (cursor_pixbuf, "y_hot");
00314 
00315                 if (xhot_string)
00316                         magnifier->cursor_hotspot.x = atoi (xhot_string);
00317                 if (yhot_string)
00318                         magnifier->cursor_hotspot.y = atoi (yhot_string);
00319                 if (pixmap) {
00320                         gdk_drawable_get_size (
00321                                 pixmap,
00322                                 &magnifier->priv->cursor_default_size_x,
00323                                 &magnifier->priv->cursor_default_size_y);
00324                         magnifier->priv->cursor_hotspot_x =
00325                                 magnifier->cursor_hotspot.x;
00326                         magnifier->priv->cursor_hotspot_y =
00327                                 magnifier->cursor_hotspot.y;
00328                 }
00329         }
00330 }
00331 
00332 
00333 GdkPixbuf *
00334 magnifier_get_pixbuf_for_name (Magnifier *magnifier, const gchar *cursor_name)
00335 {
00336     GdkPixbuf *retval = NULL;
00337     if (magnifier->priv->cursorlist) 
00338             retval = g_hash_table_lookup (magnifier->priv->cursorlist, cursor_name);
00339     if (retval) 
00340             g_object_ref (retval);
00341     return retval;
00342 }
00343 
00344 void
00345 magnifier_set_cursor_pixmap_by_name (Magnifier *magnifier,
00346                                      const gchar *cursor_name, 
00347                                      gboolean source_fallback)
00348 {
00349         GdkPixbuf *pixbuf;
00350         /* search local table; if not found, use source screen's cursor if source_fallback is TRUE */
00351         if ((pixbuf = magnifier_get_pixbuf_for_name (magnifier, cursor_name)) == NULL) {
00352                 if (source_fallback == TRUE)
00353                 {
00354                         pixbuf = gmag_cursor_get_source_pixbuf (magnifier);
00355                 }
00356                 else
00357                 {
00358                         pixbuf = magnifier_get_pixbuf_for_name (magnifier, "default");
00359                 }
00360         }
00361         magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
00362         if (pixbuf) g_object_unref (pixbuf);
00363 }
00364 
00365 void
00366 magnifier_notify_damage (Magnifier *magnifier, GdkRectangle *rect)
00367 {
00368         GNOME_Magnifier_RectBounds rect_bounds;
00369         rect_bounds.x1 = rect->x;
00370         rect_bounds.y1 = rect->y;
00371         rect_bounds.x2 = rect->x + rect->width;
00372         rect_bounds.y2 = rect->y + rect->height;
00373 #undef DEBUG_DAMAGE
00374 #ifdef DEBUG_DAMAGE
00375         g_message ("damage");
00376         g_message ("dirty %d, %d to %d, %d", rect_bounds.x1, rect_bounds.y1,
00377                    rect_bounds.x2, rect_bounds.y2);
00378 #endif
00379         magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);
00380 }
00381 
00382 static void
00383 magnifier_set_extension_listeners (Magnifier *magnifier, GdkWindow *root)
00384 {
00385         gmag_gs_client_init (magnifier);
00386         magnifier->source_initialized = TRUE;
00387 }
00388 
00389 static void
00390 magnifier_size_allocate (GtkWidget *widget)
00391 {
00392         gmag_gs_check_set_struts (_this_magnifier);
00393 }
00394 
00395 static void
00396 magnifier_realize (GtkWidget *widget)
00397 {
00398         gmag_gs_magnifier_realize (widget);
00399 }
00400 
00401 GdkWindow*
00402 magnifier_get_root (Magnifier *magnifier)
00403 {
00404     if (!magnifier->priv->root && magnifier->source_display) {
00405         magnifier->priv->root = gdk_screen_get_root_window (
00406             gdk_display_get_screen (magnifier->source_display,
00407                                     magnifier->source_screen_num));
00408     }
00409     return magnifier->priv->root;
00410 }
00411 
00412 static gint
00413 magnifier_parse_display_name (Magnifier *magnifier, gchar *full_display_string,
00414                               gchar **display_name)
00415 {
00416         gchar *screen_ptr;
00417         gchar **strings;
00418         
00419         if (display_name != NULL) {
00420                 strings = g_strsplit (full_display_string, ":", 2);
00421                 *display_name = strings [0];
00422                 if (strings [1] != NULL)
00423                         g_free (strings [1]);
00424         }
00425 
00426         screen_ptr = rindex (full_display_string, '.');
00427         if (screen_ptr != NULL) {
00428                 return (gint) strtol (++screen_ptr, NULL, 10);
00429         }
00430         return 0;
00431 }
00432 
00433 static void
00434 magnifier_get_display_rect_bounds (Magnifier *magnifier, GNOME_Magnifier_RectBounds *rect_bounds, gboolean is_target)
00435 {
00436     if (is_target)
00437     {
00438         rect_bounds->x1 = 0;
00439         rect_bounds->x2 = gdk_screen_get_width (
00440             gdk_display_get_screen (magnifier->target_display,
00441                                     magnifier->target_screen_num));
00442         rect_bounds->y1 = 0;
00443         rect_bounds->y2 = gdk_screen_get_height (
00444             gdk_display_get_screen (magnifier->target_display,
00445                                     magnifier->target_screen_num));
00446 
00447     }
00448     else 
00449     {
00450         rect_bounds->x1 = 0;
00451         rect_bounds->x2 = gdk_screen_get_width (
00452             gdk_display_get_screen (magnifier->source_display,
00453                                     magnifier->source_screen_num));
00454         rect_bounds->y1 = 0;
00455         rect_bounds->y2 = gdk_screen_get_height (
00456             gdk_display_get_screen (magnifier->source_display,
00457                                     magnifier->source_screen_num));
00458 
00459     }
00460 }
00461 
00462 gboolean
00463 magnifier_full_screen_capable (Magnifier *magnifier)
00464 {
00465         if ((strcmp (magnifier->source_display_name,
00466                      magnifier->target_display_name) != 0) ||
00467                 gmag_gs_use_compositor (magnifier))
00468                 return TRUE;
00469 
00470         return FALSE;
00471 }
00472 
00473 static void
00474 magnifier_adjust_source_size (Magnifier *magnifier)
00475 {
00476         GNOME_Magnifier_RectBounds rect_bounds; 
00477         gdouble vfract_top, vfract_bottom, hfract_left, hfract_right;
00478 
00479         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
00480 
00481         hfract_left = (double) (magnifier->target_bounds.x1) /
00482                 (double) rect_bounds.x2;
00483         vfract_top = (double) (magnifier->target_bounds.y1) /
00484                 (double) rect_bounds.y2;
00485         hfract_right = (double) (rect_bounds.x2 -
00486                                  magnifier->target_bounds.x2) /
00487                 (double) rect_bounds.x2;
00488         vfract_bottom = (double) (rect_bounds.y2 -
00489                                   magnifier->target_bounds.y2) /
00490                 (double) rect_bounds.y2;
00491 
00492         if (magnifier_full_screen_capable (magnifier)) {
00493         /* we make our 'source' rectangle the largest available subsection which we aren't occupying */
00494                 magnifier->source_bounds = rect_bounds;
00495         } else if (MAX (hfract_left, hfract_right) >
00496                    MAX (vfract_top, vfract_bottom)) {  /* vertical split,
00497                                                         * approximately */
00498                 if (hfract_right > hfract_left) {
00499                         magnifier->source_bounds.x1 =
00500                                 magnifier->target_bounds.x2;
00501                         magnifier->source_bounds.x2 = rect_bounds.x2;
00502                 } else  {
00503                         magnifier->source_bounds.x1 = rect_bounds.x1;
00504                         magnifier->source_bounds.x2 =
00505                                 magnifier->target_bounds.x1;
00506                 }
00507                 magnifier->source_bounds.y1 = rect_bounds.y1;
00508                 magnifier->source_bounds.y2 = rect_bounds.y2;
00509         } else { /* more-or-less horizontally split */
00510                 if (vfract_bottom > vfract_top) {
00511                         magnifier->source_bounds.y1 =
00512                                 magnifier->target_bounds.y2;
00513                         magnifier->source_bounds.y2 = rect_bounds.y2;
00514                 } else {
00515                         magnifier->source_bounds.y1 = rect_bounds.y1;
00516                         magnifier->source_bounds.y2 =
00517                                 magnifier->target_bounds.y1;
00518                 }
00519                 magnifier->source_bounds.x1 = rect_bounds.x1;
00520                 magnifier->source_bounds.x2 = rect_bounds.x2;
00521         }
00522         g_message ("set source bounds to %d,%d; %d,%d", 
00523                    magnifier->source_bounds.x1, magnifier->source_bounds.y1,
00524                    magnifier->source_bounds.x2, magnifier->source_bounds.y2);
00525 }
00526 
00527 static void
00528 magnifier_unref_zoom_region (gpointer data, gpointer user_data)
00529 {
00530 /*      Magnifier *magnifier = user_data; NOT USED */
00531         CORBA_Environment ev;
00532         GNOME_Magnifier_ZoomRegion zoom_region = data;
00533         CORBA_exception_init (&ev);
00534         
00535         DBG(g_message ("unreffing zoom region"));
00536 
00537         GNOME_Magnifier_ZoomRegion_dispose (zoom_region, &ev);
00538         if (!BONOBO_EX (&ev))
00539             Bonobo_Unknown_unref (zoom_region, &ev);
00540 }
00541 
00542 static void
00543 magnifier_dbus_unref_zoom_region (gpointer data, gpointer user_data)
00544 {
00545 /*      Magnifier *magnifier = user_data; NOT USED */
00546         ZoomRegion *zoom_region = data;
00547         
00548         DBG(g_message ("unreffing zoom region"));
00549 
00550         impl_dbus_zoom_region_dispose (zoom_region);
00551 }
00552 
00553 static GSList*
00554 magnifier_zoom_regions_save (Magnifier *magnifier)
00555 {
00556     GList *list;
00557     GSList *save_props = NULL;
00558     
00559     g_assert (magnifier);
00560     list = magnifier->zoom_regions;
00561 
00562     DBG(g_message ("saving %d regions", g_list_length (list)));
00563 
00564     while (list) 
00565     {
00566         GNOME_Magnifier_ZoomRegion zoom_region;
00567         CORBA_Environment ev;
00568         zoom_region = list->data;
00569         CORBA_exception_init (&ev);
00570         if (zoom_region)
00571         {
00572             Bonobo_PropertyBag properties;
00573             CORBA_any *value;
00574             MagnifierZoomRegionSaveProps *zoomer_props = g_new0 (MagnifierZoomRegionSaveProps, 1);
00575 
00576             zoomer_props->rectbounds = GNOME_Magnifier_ZoomRegion_getROI (zoom_region, &ev);
00577             properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev);
00578             value = bonobo_pbclient_get_value (properties, "viewport", TC_GNOME_Magnifier_RectBounds, &ev);
00579             memcpy (&zoomer_props->viewport, value->_value, sizeof (GNOME_Magnifier_RectBounds));
00580             CORBA_free (value);
00581             zoomer_props->is_managed = bonobo_pbclient_get_boolean (properties, "is-managed", NULL);
00582             zoomer_props->scroll_policy = bonobo_pbclient_get_short (properties, "smooth-scroll-policy", NULL);
00583             zoomer_props->contrast = bonobo_pbclient_get_float (properties, "contrast", NULL);
00584             zoomer_props->zx = bonobo_pbclient_get_float (properties, "mag-factor-x", NULL);
00585             zoomer_props->zy = bonobo_pbclient_get_float (properties, "mag-factor-y", NULL);
00586             zoomer_props->xalign = bonobo_pbclient_get_long (properties, "x-alignment", NULL);
00587             zoomer_props->yalign = bonobo_pbclient_get_long (properties, "y-alignment", NULL);
00588             zoomer_props->border_color = bonobo_pbclient_get_long (properties, "border-color", NULL); 
00589             zoomer_props->border_size = bonobo_pbclient_get_long (properties, "border-size", NULL);
00590             zoomer_props->smoothing_type = bonobo_pbclient_get_string (properties, "smoothing-type", NULL); 
00591             zoomer_props->inverse = bonobo_pbclient_get_boolean (properties, "inverse-video", NULL); 
00592 
00593             bonobo_object_release_unref (properties, &ev);
00594             magnifier_unref_zoom_region ((gpointer) zoom_region, NULL);
00595             save_props = g_slist_append (save_props, zoomer_props);
00596         }
00597         list = g_list_next (list);
00598     }   
00599 
00600     magnifier->zoom_regions = NULL;
00601     magnifier->zoom_regions_dbus = NULL;
00602 
00603     return save_props;
00604 }
00605 
00606 static void
00607 magnifier_zoom_regions_restore (Magnifier *magnifier, GSList *region_params)
00608 {
00609         GSList *list = region_params;
00610 
00611         while (list)
00612         {
00613                 CORBA_Environment ev;
00614                 MagnifierZoomRegionSaveProps *zoomer_props = list->data;
00615                 GNOME_Magnifier_ZoomRegion new_region;
00616                 Bonobo_PropertyBag new_properties;
00617 
00618                 CORBA_exception_init (&ev);
00619                 new_region = GNOME_Magnifier_Magnifier_createZoomRegion (BONOBO_OBJREF (magnifier), zoomer_props->zx, zoomer_props->zy, &zoomer_props->rectbounds, &zoomer_props->viewport, &ev);
00620                 new_properties = GNOME_Magnifier_ZoomRegion_getProperties (new_region, &ev);
00621                 bonobo_pbclient_set_boolean (new_properties, "is-managed", 
00622                                              zoomer_props->is_managed, NULL);
00623                 bonobo_pbclient_set_short (new_properties, "smooth-scroll-policy", 
00624                                            zoomer_props->scroll_policy, NULL);
00625                 bonobo_pbclient_set_float (new_properties, "contrast", 
00626                                            zoomer_props->contrast, NULL);
00627 /* NOT YET USED
00628                 bonobo_pbclient_set_long (new_properties, "x-alignment", 
00629                                              zoomer_props->xalign, NULL);
00630                 bonobo_pbclient_set_long (new_properties, "y-alignment", 
00631                                              zoomer_props->yalign, NULL);
00632 */
00633                 bonobo_pbclient_set_long (new_properties, "border-color", 
00634                                              zoomer_props->border_color, NULL);
00635                 bonobo_pbclient_set_long (new_properties, "border-size", 
00636                                              zoomer_props->border_size, NULL);
00637                 bonobo_pbclient_set_string (new_properties, "smoothing-type", 
00638                                              zoomer_props->smoothing_type, NULL);
00639                 bonobo_pbclient_set_boolean (new_properties, "inverse-video", 
00640                                              zoomer_props->inverse, NULL);
00641                 GNOME_Magnifier_Magnifier_addZoomRegion (BONOBO_OBJREF (magnifier), new_region, &ev);
00642                 g_free (zoomer_props->smoothing_type);
00643                 g_free (zoomer_props);
00644                 bonobo_object_release_unref (new_properties, &ev);
00645                 list = g_slist_next (list);
00646         }
00647         g_slist_free (region_params);
00648 }
00649 
00650 static void
00651 magnifier_init_display (Magnifier *magnifier, gchar *display_name, gboolean is_target)
00652 {
00653     if (!can_open_display (display_name))
00654         return;
00655 
00656     if (is_target)
00657     {
00658         magnifier->target_screen_num =
00659             magnifier_parse_display_name (magnifier,
00660                                           display_name,
00661                                           NULL);
00662         magnifier->target_display =
00663             gdk_display_open (display_name);
00664         if (magnifier->target_display_name) g_free (magnifier->target_display_name);
00665         magnifier->target_display_name = g_strdup (display_name);
00666         magnifier->priv->root =
00667             gdk_screen_get_root_window (
00668                 gdk_display_get_screen (
00669                     magnifier->target_display,
00670                     magnifier->target_screen_num));
00671     }
00672     else 
00673     {
00674         magnifier->source_screen_num =
00675             magnifier_parse_display_name (magnifier,
00676                                           display_name,
00677                                           NULL);
00678         magnifier->source_display =
00679             gdk_display_open (display_name);
00680         if (magnifier->source_display)
00681         {
00682             if (magnifier->source_display_name) g_free (magnifier->source_display_name);
00683             magnifier->source_display_name = g_strdup (display_name);
00684             magnifier->priv->root =
00685                 gdk_screen_get_root_window (
00686                     gdk_display_get_screen (
00687                         magnifier->source_display,
00688                         magnifier->source_screen_num));
00689         }
00690     }
00691 }
00692 
00693 static void
00694 magnifier_exit (GtkObject *object)
00695 {
00696         gtk_main_quit ();
00697         exit (0);
00698 }
00699 
00700 #define GET_PIXEL(a,i,j,s,b) \
00701 (*(guint32 *)(memcpy (b,(a) + ((j) * s + (i) * pixel_size_t), pixel_size_t)))
00702 
00703 #define PUT_PIXEL(a,i,j,s,b) \
00704 (memcpy (a + ((j) * s + (i) * pixel_size_t), &(b), pixel_size_t))
00705 
00706 static void
00707 magnifier_recolor_pixbuf (Magnifier *magnifier, GdkPixbuf *pixbuf)
00708 {
00709         int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
00710         int i, j;
00711         int w = gdk_pixbuf_get_width (pixbuf);
00712         int h = gdk_pixbuf_get_height (pixbuf);
00713         guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
00714         guint32 pixval = 0, cursor_color = 0;
00715         size_t pixel_size_t = 3; /* FIXME: invalid assumption ? */
00716 
00717         cursor_color = ((magnifier->cursor_color & 0xFF0000) >> 16) +
00718                 (magnifier->cursor_color & 0x00FF00) +
00719                 ((magnifier->cursor_color & 0x0000FF) << 16);
00720         for (j = 0; j < h; ++j) {
00721                 for (i = 0; i < w; ++i) {
00722                         pixval = GET_PIXEL (pixels, i, j, rowstride, &pixval);
00723                         if ((pixval & 0x808080) == 0)
00724                         {
00725                                 pixval = cursor_color;
00726                                 PUT_PIXEL (pixels, i, j, rowstride,
00727                                            pixval);
00728                         }
00729                 }
00730         }
00731 }
00732 
00733 void
00734 magnifier_transform_cursor (Magnifier *magnifier)
00735 {
00736         if (magnifier->priv->cursor) /* don't do this if cursor isn't intialized yet */
00737         {
00738                 int width, height;
00739                 int size_x, size_y;
00740                 GdkPixbuf *scaled_cursor_pixbuf;
00741                 GdkPixbuf *scaled_mask_pixbuf;
00742                 GdkPixbuf *scaled_mask_pixbuf_alpha;
00743                 GdkPixbuf *cursor_pixbuf;
00744                 GdkPixbuf *mask_pixbuf;
00745                 GdkPixmap *cursor_pixmap = magnifier->priv->cursor;
00746                 GdkPixmap *mask_pixmap = magnifier->priv->cursor_mask;
00747                 GdkGC *cgc;
00748                 GdkGC *mgc;
00749 
00750                 if (magnifier->cursor_size_x)
00751                 {
00752                         size_x = magnifier->cursor_size_x;
00753                         size_y = magnifier->cursor_size_y;
00754                 }
00755                 else
00756                 {
00757                         size_x = magnifier->priv->cursor_default_size_x * 
00758                                magnifier->cursor_scale_factor;
00759                         size_y = magnifier->priv->cursor_default_size_y * 
00760                                magnifier->cursor_scale_factor;
00761                 }
00762                 gdk_drawable_get_size (magnifier->priv->cursor, &width, &height);
00763                 if ((size_x == width) && (size_y == height) 
00764                     && (magnifier->cursor_color == 0xFF000000)) {
00765                         return; /* nothing changes */
00766                 }
00767                 cgc = gdk_gc_new (cursor_pixmap);
00768                 mgc = gdk_gc_new (mask_pixmap);
00769                 cursor_pixbuf = gdk_pixbuf_get_from_drawable (NULL, cursor_pixmap,
00770                                                               NULL, 0, 0, 0, 0,
00771                                                               width, height);
00772                 if (magnifier->cursor_color != 0xFF000000)
00773                         magnifier_recolor_pixbuf (magnifier, cursor_pixbuf);
00774                 mask_pixbuf = gdk_pixbuf_get_from_drawable (NULL,
00775                                                             mask_pixmap,
00776                                                             NULL, 0, 0, 0, 0,
00777                                                             width, height);
00778                 scaled_cursor_pixbuf = gdk_pixbuf_scale_simple (
00779                         cursor_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
00780                 
00781                 magnifier->cursor_hotspot.x = magnifier->priv->cursor_hotspot_x * size_x 
00782                                             / magnifier->priv->cursor_default_size_x;
00783                 magnifier->cursor_hotspot.y = magnifier->priv->cursor_hotspot_y * size_y 
00784                                             / magnifier->priv->cursor_default_size_y;
00785                                             
00786                 scaled_mask_pixbuf = gdk_pixbuf_scale_simple (
00787                         mask_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
00788                 g_object_unref (cursor_pixbuf);
00789                 g_object_unref (mask_pixbuf);
00790                 g_object_unref (cursor_pixmap);
00791                 g_object_unref (mask_pixmap);
00792                 magnifier->priv->cursor = gdk_pixmap_new (
00793                         magnifier->priv->w->window,
00794                         size_x, size_y,
00795                         -1);
00796                 if (!GDK_IS_DRAWABLE (magnifier->priv->cursor)) 
00797                 {
00798                     DBG (g_warning ("NULL magnifier cursor pixmap."));
00799                     return;
00800                 }
00801                 magnifier->priv->cursor_mask = gdk_pixmap_new (
00802                         magnifier->priv->w->window,
00803                         size_x, size_y,
00804                         1);
00805                 if (GDK_IS_DRAWABLE (magnifier->priv->cursor)) {
00806                     gdk_draw_pixbuf (magnifier->priv->cursor,
00807                                      cgc,
00808                                      scaled_cursor_pixbuf,
00809                                      0, 0, 0, 0, size_x, size_y,
00810                                      GDK_RGB_DITHER_NONE, 0, 0 );
00811                 }
00812                 else
00813                     DBG (g_warning ("cursor pixmap is non-drawable."));
00814                 scaled_mask_pixbuf_alpha = gdk_pixbuf_add_alpha (
00815                         scaled_mask_pixbuf, True, 0, 0, 0);
00816                 gdk_pixbuf_render_threshold_alpha (scaled_mask_pixbuf_alpha,
00817                                                    magnifier->priv->cursor_mask,
00818                                                    0, 0, 0, 0, size_x, size_y,
00819                                                    0x80);
00820                 g_object_unref (scaled_mask_pixbuf_alpha);
00821                 g_object_unref (scaled_cursor_pixbuf);
00822                 g_object_unref (scaled_mask_pixbuf);
00823                 g_object_unref (mgc);
00824                 g_object_unref (cgc);
00825         }       
00826 }
00827 
00828 static void
00829 magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
00830 {
00831         /*
00832          * we check the cursor-set property string here,
00833          * and create/apply the appropriate cursor settings
00834          */
00835         magnifier->cursor_set = cursor_set;
00836         magnifier->priv->use_source_cursor = 
00837             (!strcmp (cursor_set, "default") && 
00838              (fixes_event_base != 0));
00839         if (magnifier->priv->use_source_cursor) return;
00840 
00841         if (!strcmp (magnifier->cursor_set, "none")) {
00842                 magnifier->priv->cursor = NULL;
00843                 return;
00844         }
00845         else 
00846         {
00847                 GDir *cursor_dir;
00848                 const gchar *filename;
00849                 gchar *cursor_dirname;
00850 
00851                 if (magnifier->priv->cursorlist)
00852                 {
00853                         g_hash_table_destroy (magnifier->priv->cursorlist);
00854                 }
00855                 magnifier->priv->cursorlist = g_hash_table_new_full (g_str_hash, g_str_equal,
00856                                                                      g_free, g_object_unref);
00857 
00858                 cursor_dirname = g_strconcat (CURSORSDIR, "/", magnifier->cursor_set, NULL);
00859                 cursor_dir = g_dir_open (cursor_dirname, 0, NULL);
00860                 /* assignment, not comparison, is intentional */
00861                 while (cursor_dir && (filename = g_dir_read_name (cursor_dir)) != NULL) 
00862                 {
00863                         if (filename) 
00864                         {
00865                                 gchar *path = g_strconcat (cursor_dirname, "/", filename, NULL);
00866                                 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path, NULL);
00867                                 if (pixbuf)
00868                                 {
00869                                         /* add this pixbuf and its name to our list */
00870                                         gchar **sv, *cname;
00871                                         cname = g_path_get_basename (filename);
00872                                         sv = g_strsplit (cname, ".", 2);
00873                                         g_hash_table_insert (magnifier->priv->cursorlist, 
00874                                                              g_strdup (sv[0]),
00875                                                              pixbuf);
00876                                         g_free (cname);
00877                                         g_strfreev (sv);
00878                                 }
00879                                 g_free (path);
00880                         }
00881                 } 
00882                 g_free (cursor_dirname);
00883                 if (cursor_dir) g_dir_close (cursor_dir);
00884         }
00885         /* don't fallover to source cursor here, we haven't initialized X yet */
00886         magnifier_set_cursor_pixmap_by_name (magnifier, "default", FALSE);
00887         magnifier_transform_cursor (magnifier);
00888 }
00889 
00890 static gboolean 
00891 magnifier_reset_struts_at_idle (gpointer data)
00892 {
00893         if (data)
00894         {
00895                 Magnifier *magnifier = MAGNIFIER (data);
00896 #if GTK_CHECK_VERSION (2,19,5)
00897                 if (magnifier->priv &&
00898                     gtk_widget_get_realized (magnifier->priv->w) &&
00899                     gmag_gs_check_set_struts (magnifier)) {
00900                         return FALSE;
00901                 }
00902 #else
00903                 if (magnifier->priv &&
00904                     GTK_WIDGET_REALIZED (magnifier->priv->w) && 
00905                     gmag_gs_check_set_struts (magnifier)) {
00906                         return FALSE;
00907                 }
00908 #endif
00909         }
00910         return TRUE;
00911 }
00912 
00913 static void
00914 magnifier_get_property (BonoboPropertyBag *bag,
00915                         BonoboArg *arg,
00916                         guint arg_id,
00917                         CORBA_Environment *ev,
00918                         gpointer user_data)
00919 {
00920         Magnifier *magnifier = user_data;
00921         int csize = 0;
00922 
00923         DBG (fprintf (stderr, "Get property: \t%s\n", mag_prop_names[arg_id]));
00924         
00925         switch (arg_id) {
00926         case MAGNIFIER_SOURCE_SIZE_PROP:
00927                 BONOBO_ARG_SET_GENERAL (arg, magnifier->source_bounds,
00928                                         TC_GNOME_Magnifier_RectBounds,
00929                                         GNOME_Magnifier_RectBounds, NULL);
00930                 break;
00931         case MAGNIFIER_TARGET_SIZE_PROP:
00932                 BONOBO_ARG_SET_GENERAL (arg, magnifier->target_bounds,
00933                                         TC_GNOME_Magnifier_RectBounds,
00934                                         GNOME_Magnifier_RectBounds, NULL);
00935 
00936                 break;
00937         case MAGNIFIER_CURSOR_SET_PROP:
00938                 BONOBO_ARG_SET_STRING (arg, magnifier->cursor_set);
00939                 break;
00940         case MAGNIFIER_CURSOR_SIZE_PROP:
00941                 BONOBO_ARG_SET_INT (arg, magnifier->cursor_size_x);
00942                 BONOBO_ARG_SET_INT (arg, magnifier->cursor_size_y);
00943                 break;
00944         case MAGNIFIER_CURSOR_ZOOM_PROP:
00945                 BONOBO_ARG_SET_FLOAT (arg, magnifier->cursor_scale_factor);
00946                 break;
00947         case MAGNIFIER_CURSOR_COLOR_PROP:
00948                 BONOBO_ARG_SET_GENERAL (arg, magnifier->cursor_color,
00949                                         TC_CORBA_unsigned_long,
00950                                         CORBA_unsigned_long, NULL);
00951                 break;
00952         case MAGNIFIER_CURSOR_HOTSPOT_PROP:
00953                 BONOBO_ARG_SET_GENERAL (arg, magnifier->cursor_hotspot,
00954                                         TC_GNOME_Magnifier_Point,
00955                                         GNOME_Magnifier_Point, NULL);
00956 
00957                 break;
00958         case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP:
00959                 if (magnifier->priv->cursor)
00960                         gdk_drawable_get_size (magnifier->priv->cursor,
00961                                                &csize, &csize);
00962                 BONOBO_ARG_SET_INT (arg, csize);
00963                 break;
00964         case MAGNIFIER_CROSSWIRE_SIZE_PROP:
00965                 BONOBO_ARG_SET_INT (arg, magnifier->crosswire_size);
00966                 break;
00967         case MAGNIFIER_CROSSWIRE_LENGTH_PROP:
00968                 BONOBO_ARG_SET_INT (arg, magnifier->crosswire_length);
00969                 break;
00970         case MAGNIFIER_CROSSWIRE_CLIP_PROP:
00971                 BONOBO_ARG_SET_BOOLEAN (arg, magnifier->crosswire_clip);
00972                 break;
00973         case MAGNIFIER_CROSSWIRE_COLOR_PROP:
00974                 BONOBO_ARG_SET_LONG (arg, magnifier->crosswire_color);
00975                 break;
00976         case MAGNIFIER_SOURCE_DISPLAY_PROP:
00977                 BONOBO_ARG_SET_STRING (arg, magnifier->source_display_name);
00978                 break;
00979         case MAGNIFIER_TARGET_DISPLAY_PROP:
00980                 BONOBO_ARG_SET_STRING (arg, magnifier->target_display_name);
00981                 break;
00982         default:
00983                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
00984         };
00985 }
00986 
00987 gboolean
00988 impl_dbus_magnifier_set_source_display (Magnifier *magnifier, gchar *source_display)
00989 {
00990         gchar *full_display_string = source_display;
00991         if (can_open_display (full_display_string))
00992         {
00993             GSList *zoom_region_params = NULL;
00994             magnifier->source_screen_num =
00995                 magnifier_parse_display_name (magnifier,
00996                                               full_display_string,
00997                                               NULL);
00998             magnifier->source_display =
00999                 gdk_display_open (full_display_string);
01000             magnifier->source_display_name = g_strdup (full_display_string);
01001             zoom_region_params = magnifier_zoom_regions_save (magnifier);
01002             magnifier->priv->root =
01003                 gdk_screen_get_root_window (
01004                     gdk_display_get_screen (
01005                         magnifier->source_display,
01006                         magnifier->source_screen_num));
01007 
01008             /* remove the source_drawable, since in the new display the
01009              * composite can be unavailable and the source_drawable is
01010              * where the desktop screen is composed. If this is not
01011              * freed it will be used even if the display doesn't use
01012              * composite what will lead to wrong behavior and crashes.
01013              * If composite is used in the new display this variable is
01014              * re-created */
01015             if (magnifier->priv->source_drawable) {
01016                     g_object_unref (magnifier->priv->source_drawable);
01017                     magnifier->priv->source_drawable = NULL;
01018             }
01019 
01020             /* attach listeners for DAMAGE, "dirty region", XFIXES
01021              * cursor changes */
01022             magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01023             magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01024             magnifier_adjust_source_size (magnifier);
01025             magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01026             magnifier_warp_cursor_to_screen (magnifier);
01027             gmag_gs_check_set_struts (magnifier);
01028             gmag_gs_reset_overlay_at_idle (magnifier);
01029         }
01030         DBG(fprintf (stderr, "Set source display: \t%s\n", full_display_string));
01031         
01032         return TRUE;
01033 }
01034 
01035 gchar*
01036 impl_dbus_magnifier_get_source_display (Magnifier *magnifier)
01037 {
01038         return g_strdup (magnifier->source_display_name);
01039 }
01040 
01041 gboolean
01042 impl_dbus_magnifier_set_target_display (Magnifier *magnifier, gchar *target_display)
01043 {
01044         gchar *full_display_string = target_display;
01045         if (can_open_display (full_display_string))
01046         {
01047             magnifier->target_screen_num =
01048                 magnifier_parse_display_name (magnifier,
01049                                               full_display_string,
01050                                               NULL);
01051             magnifier->target_display =
01052                 gdk_display_open (full_display_string);
01053             magnifier->target_display_name = g_strdup (full_display_string);
01054             if (GTK_IS_WINDOW (magnifier->priv->w)) 
01055             {
01056 #ifdef REPARENT_GTK_WINDOW_WORKS
01057                 gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), 
01058                                        gdk_display_get_screen (
01059                                            magnifier->target_display,
01060                                            magnifier->target_screen_num));
01061 #else
01062                 GSList *zoom_region_params = NULL;
01063                 /* disconnect from the old window's destroy signal */
01064                 g_object_disconnect (magnifier->priv->w,
01065                           "any_signal::realize", magnifier_realize, NULL,
01066                           "any_signal::size_allocate", magnifier_size_allocate, NULL,
01067                           "any_signal::destroy", magnifier_exit, NULL,
01068                           NULL);
01069                 /* save the old zoom region state */
01070                 zoom_region_params = magnifier_zoom_regions_save (magnifier);
01071                 /* destroy the old window */
01072                 gtk_widget_destroy (magnifier->priv->w);
01073                 /* and re-initialize... */
01074                 magnifier_init_window (magnifier, gdk_display_get_screen (
01075                                            magnifier->target_display,
01076                                            magnifier->target_screen_num));
01077                 /* restore the zoom regions in their new host magnifier window */
01078                 magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01079 #endif
01080             }
01081             magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01082             magnifier_init_cursor_set (magnifier, magnifier->cursor_set); /* needed to reset pixmaps */
01083             if (magnifier->priv->overlay)
01084                     gdk_window_move (magnifier->priv->overlay,
01085                                      magnifier->target_bounds.x1,
01086                                      magnifier->target_bounds.y1);
01087             else
01088                     gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01089                                      magnifier->target_bounds.x1,
01090                                      magnifier->target_bounds.y1);
01091             
01092             if ((magnifier->target_bounds.x2 - magnifier->target_bounds.x1 > 0) &&
01093                 (magnifier->target_bounds.y2 - magnifier->target_bounds.y1) > 0)
01094             {
01095                     if (magnifier->priv->overlay)
01096                             gdk_window_resize (
01097                                     magnifier->priv->overlay,
01098                                     magnifier->target_bounds.x2 -
01099                                     magnifier->target_bounds.x1,
01100                                     magnifier->target_bounds.y2 -
01101                                     magnifier->target_bounds.y1);
01102                 gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01103                                magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01104                                magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01105             DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01106                      magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01107             }
01108             /* N. B. we don't reset the target bounds to the limits of the new display, because */
01109             /* doing so would override the client-specified magnifier size */
01110             /* magnifier_get_display_rect_bounds (magnifier, &magnifier->target_bounds, TRUE); */
01111             gmag_gs_check_set_struts (magnifier);
01112         }
01113         DBG(fprintf (stderr, "Set target display: \t%s (screen %d)\n", 
01114                       full_display_string, magnifier->target_screen_num));
01115                       
01116         return TRUE;
01117 }
01118 
01119 gchar*
01120 impl_dbus_magnifier_get_target_display (Magnifier *magnifier)
01121 {
01122         return g_strdup (magnifier->target_display_name);
01123 }
01124 
01125 gboolean
01126 impl_dbus_magnifier_set_source_size (Magnifier *magnifier, gint32 **bounds)
01127 {
01128         magnifier->source_bounds.x1 = (*bounds)[0];
01129         magnifier->source_bounds.y1 = (*bounds)[1];
01130         magnifier->source_bounds.x2 = (*bounds)[2];
01131         magnifier->source_bounds.y2 = (*bounds)[3];
01132         DBG (fprintf (stderr, "Set source size: \t%d,%d to %d,%d\n", 
01133                       magnifier->source_bounds.x1, magnifier->source_bounds.y1, magnifier->source_bounds.x2, magnifier->source_bounds.y2));
01134                       
01135         return TRUE;
01136 }
01137 
01138 GArray*
01139 impl_dbus_magnifier_get_source_size (Magnifier *magnifier)
01140 {
01141         GArray *ret = g_array_new (FALSE, FALSE, sizeof (gint32));
01142         
01143         g_array_append_val (ret, magnifier->source_bounds.x1);
01144         g_array_append_val (ret, magnifier->source_bounds.y1);
01145         g_array_append_val (ret, magnifier->source_bounds.x2);
01146         g_array_append_val (ret, magnifier->source_bounds.y2);
01147         
01148         return ret;
01149 }
01150 
01151 gboolean
01152 impl_dbus_magnifier_set_target_size (Magnifier *magnifier, gint32 **bounds)
01153 {
01154         magnifier->target_bounds.x1 = (*bounds)[0];
01155         magnifier->target_bounds.y1 = (*bounds)[1];
01156         magnifier->target_bounds.x2 = (*bounds)[2];
01157         magnifier->target_bounds.y2 = (*bounds)[3];
01158 
01159         if (magnifier->priv->overlay)
01160                 gdk_window_move_resize (magnifier->priv->overlay,
01161                                         magnifier->target_bounds.x1,
01162                                         magnifier->target_bounds.y1,
01163                                         magnifier->target_bounds.x2 -
01164                                         magnifier->target_bounds.x1,
01165                                         magnifier->target_bounds.y2 -
01166                                         magnifier->target_bounds.y1);
01167         else
01168                 gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01169                                  magnifier->target_bounds.x1,
01170                                  magnifier->target_bounds.y1);
01171         
01172         gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01173                            magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01174                            magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01175         gmag_gs_check_set_struts (magnifier);
01176         DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01177                       magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01178         if (!strcmp (magnifier->target_display_name, magnifier->source_display_name) && 
01179             (magnifier->target_screen_num == magnifier->source_screen_num)) 
01180             magnifier_adjust_source_size (magnifier);
01181             
01182         return TRUE;
01183 }
01184 
01185 GArray*
01186 impl_dbus_magnifier_get_target_size (Magnifier *magnifier)
01187 {
01188         GArray *ret = g_array_new (FALSE, FALSE, sizeof (gint32));
01189         
01190         g_array_append_val (ret, magnifier->target_bounds.x1);
01191         g_array_append_val (ret, magnifier->target_bounds.y1);
01192         g_array_append_val (ret, magnifier->target_bounds.x2);
01193         g_array_append_val (ret, magnifier->target_bounds.y2);
01194         
01195         return ret;
01196 }
01197 
01198 gboolean
01199 impl_dbus_magnifier_set_cursor_set (Magnifier *magnifier, gchar *cursor_set)
01200 {
01201         magnifier_init_cursor_set (magnifier, g_strdup (cursor_set));
01202         DBG (fprintf (stderr, "Setting cursor set: \t%s\n", cursor_set));
01203         
01204         return TRUE;
01205 }
01206 
01207 gchar*
01208 impl_dbus_magnifier_get_cursor_set (Magnifier *magnifier)
01209 {
01210         return g_strdup (magnifier->cursor_set);
01211 }
01212 
01213 gboolean
01214 impl_dbus_magnifier_set_cursor_size (Magnifier *magnifier, gint x, gint y)
01215 {
01216         magnifier->cursor_size_x = x;
01217         magnifier->cursor_size_y = y;
01218         magnifier_transform_cursor (magnifier);
01219         DBG (fprintf (stderr, "Setting cursor size: \t%d\n", magnifier->cursor_size_x));
01220         
01221         return TRUE;
01222 }
01223 
01224 GArray*
01225 impl_dbus_magnifier_get_cursor_size (Magnifier *magnifier)
01226 {
01227         GArray *ret = g_array_new (FALSE, FALSE, sizeof (gint));
01228         
01229         g_array_append_val (ret, magnifier->cursor_size_x);
01230         g_array_append_val (ret, magnifier->cursor_size_y);
01231         
01232         return ret;
01233 }
01234 
01235 gboolean
01236 impl_dbus_magnifier_set_cursor_zoom (Magnifier *magnifier, double factor)
01237 {
01238         magnifier->cursor_scale_factor = factor;
01239         DBG (fprintf (stderr, "Setting cursor scale factor: \t%f\n", magnifier->cursor_scale_factor));
01240         magnifier_transform_cursor (magnifier);
01241         
01242         return TRUE;
01243 }
01244 
01245 double
01246 impl_dbus_magnifier_get_cursor_zoom (Magnifier *magnifier)
01247 {
01248         return magnifier->cursor_scale_factor;
01249 }
01250 
01251 gboolean
01252 impl_dbus_magnifier_set_cursor_color (Magnifier *magnifier, guint32 color)
01253 {
01254         magnifier->cursor_color = color;
01255         magnifier_transform_cursor (magnifier);
01256         DBG (fprintf (stderr, "Setting cursor color: \t%u\n", (unsigned) magnifier->cursor_color));
01257         
01258         return TRUE;
01259 }
01260 
01261 guint32
01262 impl_dbus_magnifier_get_cursor_color (Magnifier *magnifier)
01263 {
01264         return magnifier->cursor_color;
01265 }
01266 
01267 gboolean
01268 impl_dbus_magnifier_set_cursor_hotspot (Magnifier *magnifier, gint32 x, gint32 y)
01269 {
01270         magnifier->cursor_hotspot.x = x;
01271         magnifier->cursor_hotspot.y = y;
01272         magnifier_transform_cursor (magnifier);
01273         
01274         return TRUE;
01275 }
01276 
01277 GArray*
01278 impl_dbus_magnifier_get_cursor_hotspot (Magnifier *magnifier)
01279 {
01280         GArray *ret = g_array_new (FALSE, FALSE, sizeof (gint32));
01281         
01282         g_array_append_val (ret, magnifier->cursor_hotspot.x);
01283         g_array_append_val (ret, magnifier->cursor_hotspot.y);
01284         
01285         return ret;
01286 }
01287 
01288 gint32
01289 impl_dbus_magnifier_get_cursor_default_size (Magnifier *magnifier)
01290 {
01291         gint32 csize;
01292         
01293         if (magnifier->priv->cursor) {
01294                 gdk_drawable_get_size (magnifier->priv->cursor, &csize, &csize);
01295         }
01296         
01297         return csize;
01298 }
01299 
01300 gboolean
01301 impl_dbus_magnifier_set_crosswire_size (Magnifier *magnifier, gint size)
01302 {
01303         magnifier->crosswire_size = size;
01304         DBG (fprintf (stderr, "Setting crosswire size: \t%d\n", magnifier->crosswire_size));
01305         magnifier_zoom_regions_update_pointer (magnifier);
01306         
01307         return TRUE;
01308 }
01309 
01310 gint
01311 impl_dbus_magnifier_get_crosswire_size (Magnifier *magnifier)
01312 {
01313         return magnifier->crosswire_size;
01314 }
01315 
01316 gboolean
01317 impl_dbus_magnifier_set_crosswire_length (Magnifier *magnifier, gint length)
01318 {
01319         GNOME_Magnifier_RectBounds rect_bounds;
01320         rect_bounds.x1 = 0;
01321         rect_bounds.y1 = 0;
01322         rect_bounds.x2 = 4096;
01323         rect_bounds.y2 = 4096;
01324 
01325         magnifier->crosswire_length = length;
01326         DBG (fprintf (stderr, "Setting crosswire length: \t%d\n", magnifier->crosswire_length));
01327         magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);
01328         
01329         return TRUE;
01330 }
01331 
01332 gboolean
01333 impl_dbus_magnifier_set_crosswire_clip (Magnifier *magnifier, gboolean clip)
01334 {
01335         magnifier->crosswire_clip = clip;
01336         DBG (fprintf (stderr, "Setting crosswire clip: \t%s\n", magnifier->crosswire_clip ? "true" : "false"));
01337         magnifier_zoom_regions_update_pointer (magnifier);
01338         
01339         return TRUE;
01340 }
01341 
01342 gboolean
01343 impl_dbus_magnifier_get_crosswire_clip (Magnifier *magnifier)
01344 {
01345         return magnifier->crosswire_clip;
01346 }
01347 
01348 gint
01349 impl_dbus_magnifier_get_crosswire_length (Magnifier *magnifier) {
01350         return magnifier->crosswire_length;
01351 }
01352 
01353 gboolean
01354 impl_dbus_magnifier_set_crosswire_color (Magnifier *magnifier, guint32 color)
01355 {
01356         magnifier->crosswire_color = color;
01357         DBG (fprintf (stderr, "Setting crosswire color: \t%ld\n", (long) magnifier->crosswire_color));
01358         
01359         return TRUE;
01360 }
01361 
01362 guint32
01363 impl_dbus_magnifier_get_crosswire_color (Magnifier *magnifier)
01364 {
01365         return magnifier->crosswire_color;
01366 }
01367 
01368 static void
01369 magnifier_set_property (BonoboPropertyBag *bag,
01370                         BonoboArg *arg,
01371                         guint arg_id,
01372                         CORBA_Environment *ev,
01373                         gpointer user_data)
01374 {
01375         Magnifier *magnifier = user_data;
01376         gchar *full_display_string;
01377 
01378         GNOME_Magnifier_RectBounds rect_bounds;
01379         rect_bounds.x1 = 0;
01380         rect_bounds.y1 = 0;
01381         rect_bounds.x2 = 4096;
01382         rect_bounds.y2 = 4096;
01383 
01384         switch (arg_id) {
01385         case MAGNIFIER_SOURCE_DISPLAY_PROP:
01386                 full_display_string = BONOBO_ARG_GET_STRING (arg);
01387                 if (can_open_display (full_display_string))
01388                 {
01389                     GSList *zoom_region_params = NULL;
01390                     magnifier->source_screen_num =
01391                         magnifier_parse_display_name (magnifier,
01392                                                       full_display_string,
01393                                                       NULL);
01394                     magnifier->source_display =
01395                         gdk_display_open (full_display_string);
01396                     magnifier->source_display_name = g_strdup (full_display_string);
01397                     zoom_region_params = magnifier_zoom_regions_save (magnifier);
01398                     magnifier->priv->root =
01399                         gdk_screen_get_root_window (
01400                             gdk_display_get_screen (
01401                                 magnifier->source_display,
01402                                 magnifier->source_screen_num));
01403 
01404                     /* remove the source_drawable, since in the new display the
01405                      * composite can be unavailable and the source_drawable is
01406                      * where the desktop screen is composed. If this is not
01407                      * freed it will be used even if the display doesn't use
01408                      * composite what will lead to wrong behavior and crashes.
01409                      * If composite is used in the new display this variable is
01410                      * re-created */
01411                     if (magnifier->priv->source_drawable) {
01412                             g_object_unref (magnifier->priv->source_drawable);
01413                             magnifier->priv->source_drawable = NULL;
01414                     }
01415 
01416                     /* attach listeners for DAMAGE, "dirty region", XFIXES
01417                      * cursor changes */
01418                     magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01419                     magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01420                     magnifier_adjust_source_size (magnifier);
01421                     magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01422                     magnifier_warp_cursor_to_screen (magnifier);
01423                     gmag_gs_check_set_struts (magnifier);
01424                     gmag_gs_reset_overlay_at_idle (magnifier);
01425                 }
01426                 DBG(fprintf (stderr, "Set source display: \t%s\n", full_display_string));
01427                 break;
01428         case MAGNIFIER_TARGET_DISPLAY_PROP:
01429                 full_display_string = BONOBO_ARG_GET_STRING (arg);
01430                 if (can_open_display (full_display_string))
01431                 {
01432                     magnifier->target_screen_num =
01433                         magnifier_parse_display_name (magnifier,
01434                                                       full_display_string,
01435                                                       NULL);
01436                     magnifier->target_display =
01437                         gdk_display_open (full_display_string);
01438                     magnifier->target_display_name = g_strdup (full_display_string);
01439                     if (GTK_IS_WINDOW (magnifier->priv->w)) 
01440                     {
01441 #ifdef REPARENT_GTK_WINDOW_WORKS
01442                         gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), 
01443                                                gdk_display_get_screen (
01444                                                    magnifier->target_display,
01445                                                    magnifier->target_screen_num));
01446 #else
01447                         GSList *zoom_region_params = NULL;
01448                         /* disconnect from the old window's destroy signal */
01449                         g_object_disconnect (magnifier->priv->w,
01450                                   "any_signal::realize", magnifier_realize, NULL,
01451                                   "any_signal::size_allocate", magnifier_size_allocate, NULL,
01452                                   "any_signal::destroy", magnifier_exit, NULL,
01453                                   NULL);
01454                         /* save the old zoom region state */
01455                         zoom_region_params = magnifier_zoom_regions_save (magnifier);
01456                         /* destroy the old window */
01457                         gtk_widget_destroy (magnifier->priv->w);
01458                         /* and re-initialize... */
01459                         magnifier_init_window (magnifier, gdk_display_get_screen (
01460                                                    magnifier->target_display,
01461                                                    magnifier->target_screen_num));
01462                         /* restore the zoom regions in their new host magnifier window */
01463                         magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01464 #endif
01465                     }
01466                     magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01467                     magnifier_init_cursor_set (magnifier, magnifier->cursor_set); /* needed to reset pixmaps */
01468                     if (magnifier->priv->overlay)
01469                             gdk_window_move (magnifier->priv->overlay,
01470                                              magnifier->target_bounds.x1,
01471                                              magnifier->target_bounds.y1);
01472                     else
01473                             gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01474                                              magnifier->target_bounds.x1,
01475                                              magnifier->target_bounds.y1);
01476                     
01477                     if ((magnifier->target_bounds.x2 - magnifier->target_bounds.x1 > 0) &&
01478                         (magnifier->target_bounds.y2 - magnifier->target_bounds.y1) > 0)
01479                     {
01480                             if (magnifier->priv->overlay)
01481                                     gdk_window_resize (
01482                                             magnifier->priv->overlay,
01483                                             magnifier->target_bounds.x2 -
01484                                             magnifier->target_bounds.x1,
01485                                             magnifier->target_bounds.y2 -
01486                                             magnifier->target_bounds.y1);
01487                         gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01488                                        magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01489                                        magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01490                     DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01491                              magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01492                     }
01493                     /* N. B. we don't reset the target bounds to the limits of the new display, because */
01494                     /* doing so would override the client-specified magnifier size */
01495                     /* magnifier_get_display_rect_bounds (magnifier, &magnifier->target_bounds, TRUE); */
01496                     gmag_gs_check_set_struts (magnifier);
01497                 }
01498                 DBG(fprintf (stderr, "Set target display: \t%s (screen %d)\n", 
01499                               full_display_string, magnifier->target_screen_num));
01500                 break;
01501         case MAGNIFIER_SOURCE_SIZE_PROP:
01502                 magnifier->source_bounds = BONOBO_ARG_GET_GENERAL (arg,
01503                                                                    TC_GNOME_Magnifier_RectBounds,
01504                                                                    GNOME_Magnifier_RectBounds,
01505                                                                    NULL);
01506                 DBG (fprintf (stderr, "Set source size: \t%d,%d to %d,%d\n", 
01507                               magnifier->source_bounds.x1, magnifier->source_bounds.y1, magnifier->source_bounds.x2, magnifier->source_bounds.y2));
01508                 break;
01509         case MAGNIFIER_TARGET_SIZE_PROP:
01510                 magnifier->target_bounds = BONOBO_ARG_GET_GENERAL (arg,
01511                                                                    TC_GNOME_Magnifier_RectBounds,
01512                                                                    GNOME_Magnifier_RectBounds,
01513                                 
01514                                    NULL);
01515                 if (magnifier->priv->overlay)
01516                         gdk_window_move_resize (magnifier->priv->overlay,
01517                                                 magnifier->target_bounds.x1,
01518                                                 magnifier->target_bounds.y1,
01519                                                 magnifier->target_bounds.x2 -
01520                                                 magnifier->target_bounds.x1,
01521                                                 magnifier->target_bounds.y2 -
01522                                                 magnifier->target_bounds.y1);
01523                 else
01524                         gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01525                                          magnifier->target_bounds.x1,
01526                                          magnifier->target_bounds.y1);
01527                 
01528                 gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01529                                    magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01530                                    magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01531                 gmag_gs_check_set_struts (magnifier);
01532                 DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01533                               magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01534                 if (!strcmp (magnifier->target_display_name, magnifier->source_display_name) && 
01535                     (magnifier->target_screen_num == magnifier->source_screen_num)) 
01536                     magnifier_adjust_source_size (magnifier);
01537                 break;
01538         case MAGNIFIER_CURSOR_SET_PROP:
01539                 magnifier_init_cursor_set (magnifier, g_strdup (BONOBO_ARG_GET_STRING (arg)));
01540                 DBG (fprintf (stderr, "Setting cursor set: \t%s\n", BONOBO_ARG_GET_STRING (arg)));
01541                 break;
01542         case MAGNIFIER_CURSOR_SIZE_PROP:
01543                 magnifier->cursor_size_x = BONOBO_ARG_GET_INT (arg);
01544                 magnifier->cursor_size_y = BONOBO_ARG_GET_INT (arg);
01545                 magnifier_transform_cursor (magnifier);
01546                 DBG (fprintf (stderr, "Setting cursor size: \t%d\n", magnifier->cursor_size_x));
01547                 break;
01548         case MAGNIFIER_CURSOR_ZOOM_PROP:
01549                 magnifier->cursor_scale_factor = BONOBO_ARG_GET_FLOAT (arg);
01550                 DBG (fprintf (stderr, "Setting cursor scale factor: \t%f\n", (float) magnifier->cursor_scale_factor));
01551                 magnifier_transform_cursor (magnifier);
01552                 break;
01553         case MAGNIFIER_CURSOR_COLOR_PROP:
01554                 magnifier->cursor_color = BONOBO_ARG_GET_GENERAL (arg,
01555                                                                   TC_CORBA_unsigned_long, 
01556                                                                   CORBA_unsigned_long, 
01557                                                                   NULL);
01558                 magnifier_transform_cursor (magnifier);
01559                 DBG (fprintf (stderr, "Setting cursor color: \t%u\n", (unsigned) magnifier->cursor_color));
01560                 break;
01561         case MAGNIFIER_CURSOR_HOTSPOT_PROP:
01562                 magnifier->cursor_hotspot = BONOBO_ARG_GET_GENERAL (arg,
01563                                                                     TC_GNOME_Magnifier_Point,
01564                                                                     GNOME_Magnifier_Point,
01565                                                                     NULL);
01566                 /* TODO: notify zoomers */
01567                 /* FIXME: don't call init_cursor, it overwrites this property! */
01568                 magnifier_transform_cursor (magnifier); 
01569                 break;
01570         case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP:
01571                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_ReadOnly);
01572                 break;
01573         case MAGNIFIER_CROSSWIRE_SIZE_PROP:
01574                 magnifier->crosswire_size = BONOBO_ARG_GET_INT (arg);
01575                 DBG (fprintf (stderr, "Setting crosswire size: \t%d\n", magnifier->crosswire_size));
01576                 magnifier_zoom_regions_update_pointer (magnifier);
01577                 break;
01578         case MAGNIFIER_CROSSWIRE_LENGTH_PROP:
01579                 magnifier->crosswire_length = BONOBO_ARG_GET_INT (arg);
01580                 DBG (fprintf (stderr, "Setting crosswire length: \t%d\n", magnifier->crosswire_length));
01581                 /* FIXME: The call below forces the repaint of all the screen,
01582                  * but I can't figure a better solution right now to the case
01583                  * where the crosswire lenght decrease */
01584                 magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);
01585                 break;
01586         case MAGNIFIER_CROSSWIRE_CLIP_PROP:
01587                 magnifier->crosswire_clip = BONOBO_ARG_GET_BOOLEAN (arg);
01588                 DBG (fprintf (stderr, "Setting crosswire clip: \t%s\n", magnifier->crosswire_clip ? "true" : "false"));
01589                 magnifier_zoom_regions_update_pointer (magnifier);
01590                 break;
01591         case MAGNIFIER_CROSSWIRE_COLOR_PROP:
01592                 magnifier->crosswire_color = BONOBO_ARG_GET_LONG (arg);
01593                 DBG (fprintf (stderr, "Setting crosswire size: \t%ld\n", (long) magnifier->crosswire_color));
01594                 break;
01595         default:
01596                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
01597                 break;
01598         };
01599 }
01600 
01601 static void
01602 magnifier_do_dispose (Magnifier *magnifier)
01603 {
01604         /* FIXME: this is dead ropey code structuring */
01605         bonobo_activation_active_server_unregister (
01606                 MAGNIFIER_OAFIID, BONOBO_OBJREF (magnifier));
01607 
01608         if (magnifier->zoom_regions_dbus)
01609                 g_list_free (magnifier->zoom_regions_dbus);
01610         if (magnifier->zoom_regions)
01611                 g_list_free (magnifier->zoom_regions);
01612         magnifier->zoom_regions = NULL;
01613         magnifier->zoom_regions_dbus = NULL;
01614         
01615         bonobo_main_quit ();
01616 }
01617 
01618 static void
01619 magnifier_gobject_dispose (GObject *object)
01620 {
01621         magnifier_do_dispose (MAGNIFIER (object));
01622 
01623         BONOBO_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
01624 }
01625 
01626 static
01627 CORBA_boolean
01628 impl_magnifier_support_colorblind_filters (Magnifier *magnifier)
01629 {
01630 #ifdef HAVE_COLORBLIND
01631         return CORBA_TRUE;
01632 #else
01633         return CORBA_FALSE;
01634 #endif
01635 }
01636 
01637 static void
01638 impl_magnifier_hide_cursor (PortableServer_Servant servant,
01639                         CORBA_Environment *ev)
01640 {
01641         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01642 
01643         gmag_gs_hide_cursor (magnifier);
01644 }
01645 
01646 static void
01647 impl_magnifier_show_cursor (PortableServer_Servant servant,
01648                             CORBA_Environment *ev)
01649 {
01650         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01651 
01652         gmag_gs_show_cursor (magnifier);
01653 }
01654 
01655 static
01656 CORBA_boolean
01657 impl_magnifier_full_screen_capable (PortableServer_Servant servant,
01658                                     CORBA_Environment * ev)
01659 {
01660         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01661 
01662         if ((strcmp (magnifier->source_display_name,
01663                      magnifier->target_display_name) != 0) ||
01664                 gmag_gs_use_compositor (magnifier))
01665                 return CORBA_TRUE;
01666 
01667         return CORBA_FALSE;
01668 }
01669 
01670 gboolean
01671 impl_dbus_magnifier_full_screen_capable (Magnifier *magnifier)
01672 {
01673         if ((strcmp (magnifier->source_display_name,
01674                      magnifier->target_display_name) != 0) ||
01675                 gmag_gs_use_compositor (magnifier)) {
01676                 return TRUE;
01677         }
01678 
01679         return FALSE;
01680 }
01681 
01682 gboolean
01683 impl_dbus_magnifier_hide_cursor (Magnifier *magnifier)
01684 {
01685         gmag_gs_hide_cursor (magnifier);
01686         
01687         return TRUE;
01688 }
01689 
01690 gboolean
01691 impl_dbus_magnifier_show_cursor (Magnifier *magnifier)
01692 {
01693         gmag_gs_show_cursor (magnifier);
01694 
01695         return TRUE;
01696 }
01697 
01698 gboolean
01699 impl_dbus_magnifier_support_colorblind_filters (Magnifier *magnifier)
01700 {
01701 #ifdef HAVE_COLORBLIND
01702         return TRUE;
01703 #else
01704         return FALSE;
01705 #endif
01706 }
01707 
01708 gchar*
01709 impl_dbus_magnifier_create_zoom_region (Magnifier *magnifier,
01710                                         const double zx,
01711                                         const double zy,
01712                                         const gint32 **roi,
01713                                         const gint32 **viewport)
01714 {
01715         ZoomRegion *zoom_region = zoom_region_new();
01716 
01717         DBG (fprintf (stderr, "Create zoom region: \tzoom %f,%f, viewport %d,%d to %d,%d\n", (float) zx, (float) zy, (*viewport)[0]/*x1*/, (*viewport)[1]/*y1*/, (*viewport)[2]/*x2*/, (*viewport)[3]/*y3*/));
01718 
01719         /* FIXME:
01720          * shouldn't do this here, since it causes the region to get
01721          * mapped onto the parent, if if it's not explicitly added!
01722          */
01723         DBG(g_message ("creating zoom region with parent %p", magnifier));
01724         zoom_region->priv->parent = magnifier;
01725 
01726         impl_dbus_zoom_region_set_mag_factor (zoom_region, zx, zy);
01727         
01728         impl_dbus_zoom_region_move_resize (zoom_region, viewport);
01729 
01730         impl_dbus_zoom_region_set_roi (zoom_region, roi);
01731 
01732         gtk_widget_set_size_request (magnifier->priv->canvas,
01733                                      (*viewport)[2] - (*viewport)[0],
01734                                      (*viewport)[3] - (*viewport)[1]);
01735         gtk_widget_show (magnifier->priv->canvas);
01736         gtk_widget_show (magnifier->priv->w);
01737         
01738         g_hash_table_insert (zoom_hash, g_strdup(zoom_region->object_path), zoom_region);
01739 
01740         return g_strdup (zoom_region->object_path);
01741 }
01742 
01743 gchar**
01744 impl_dbus_magnifier_get_zoom_regions (Magnifier *magnifier)
01745 {
01746         ZoomRegion *zoom_region;
01747         gchar **list;
01748         int i, len;
01749 
01750         len = g_list_length (magnifier->zoom_regions);
01751         list = g_malloc0 (sizeof (gchar *) * len);
01752         for (i = 0; i < len; ++i) {
01753                 zoom_region = g_list_nth_data (magnifier->zoom_regions_dbus, i);
01754                 list[i] = g_strdup (zoom_region->object_path);
01755         }
01756 
01757         DBG (fprintf (stderr, "Get zoom regions: \t%d\n", len));
01758         
01759         return list; 
01760 }
01761 
01762 gboolean
01763 impl_dbus_magnifier_add_zoom_region (Magnifier *magnifier, gchar *zoom_region_path)
01764 {
01765         if (!magnifier->source_initialized) 
01766         {
01767                 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01768         }
01769 
01770         /* FIXME: this needs proper lifecycle management */
01771         ZoomRegion *zoom_region = g_hash_table_lookup (zoom_hash, zoom_region_path);
01772         magnifier->zoom_regions = g_list_append (magnifier->zoom_regions, BONOBO_OBJREF (zoom_region));
01773         magnifier->zoom_regions_dbus = g_list_append (magnifier->zoom_regions_dbus, zoom_region);
01774         g_hash_table_remove (zoom_hash, zoom_region_path);
01775         gmag_gs_check_set_struts (magnifier);
01776 
01777         return TRUE;
01778 }
01779 
01780 gboolean
01781 impl_dbus_magnifier_clear_all_zoom_regions (Magnifier *magnifier)
01782 {
01783         g_list_foreach (magnifier->zoom_regions_dbus,
01784                         magnifier_dbus_unref_zoom_region, magnifier);
01785         g_list_foreach (magnifier->zoom_regions,
01786                         magnifier_unref_zoom_region, magnifier);
01787         g_list_free (magnifier->zoom_regions);
01788         g_list_free (magnifier->zoom_regions_dbus);
01789         magnifier->zoom_regions = NULL;
01790         magnifier->zoom_regions_dbus = NULL;
01791 
01792         return TRUE;
01793 }
01794 
01795 gboolean
01796 impl_dbus_magnifier_dispose (Magnifier *magnifier)
01797 {
01798         magnifier_do_dispose (magnifier);
01799         
01800         return TRUE;
01801 }
01802 
01803 static void
01804 impl_magnifier_set_source_display (PortableServer_Servant servant,
01805                                    const CORBA_char *display,
01806                                    CORBA_Environment *ev)
01807 {
01808         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01809         BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01810         gchar *full_display_string;
01811 
01812         full_display_string = g_strdup (display);
01813         if (strcmp (full_display_string, "") == 0)
01814                 full_display_string = (gchar *) g_getenv ("DISPLAY");
01815 
01816         BONOBO_ARG_SET_STRING (arg, full_display_string);
01817         
01818         DBG (fprintf (stderr, "Set source display: \t%s\n",
01819                       full_display_string));
01820 
01821         if (strcmp (full_display_string, magnifier->source_display_name)) {
01822             magnifier_set_property (magnifier->property_bag,
01823                                     arg,
01824                                     MAGNIFIER_SOURCE_DISPLAY_PROP,
01825                                     ev,
01826                                     magnifier);
01827         }
01828         else
01829         {
01830             DBG (fprintf (stderr, "Attempt to set source to same value as previous: %s\n",
01831                           full_display_string));
01832         }
01833         bonobo_arg_release (arg);
01834 }
01835 
01836 static void
01837 impl_magnifier_set_target_display (PortableServer_Servant servant,
01838                                    const CORBA_char *display,
01839                                    CORBA_Environment *ev)
01840 {
01841         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01842         BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01843         gchar *full_display_string;
01844 
01845         full_display_string = g_strdup (display);
01846         if (strcmp (full_display_string, "") == 0)
01847                 full_display_string = (gchar *) g_getenv ("DISPLAY");
01848 
01849         BONOBO_ARG_SET_STRING (arg, full_display_string);
01850         
01851         DBG (fprintf (stderr, "Set target display: \t%s\n",
01852                       full_display_string));
01853 
01854         if (strcmp (full_display_string, magnifier->target_display_name)) 
01855         {
01856             magnifier_set_property (magnifier->property_bag,
01857                                     arg,
01858                                     MAGNIFIER_TARGET_DISPLAY_PROP,
01859                                     ev,
01860                                     magnifier);
01861         }
01862         else
01863         {
01864             DBG (fprintf (stderr, "Attempt to set target to same value as previous: %s\n",
01865                           full_display_string));
01866         }
01867         bonobo_arg_release (arg);
01868 }
01869 
01870 static 
01871 CORBA_string
01872 impl_magnifier_get_source_display (PortableServer_Servant servant,
01873                                    CORBA_Environment *ev)
01874 {
01875         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01876         DBG (fprintf (stderr, "Get source display: \t%s\n", magnifier->source_display_name));
01877 
01878         return CORBA_string_dup (magnifier->source_display_name ? magnifier->source_display_name : "");
01879 }
01880 
01881 static 
01882 CORBA_string
01883 impl_magnifier_get_target_display (PortableServer_Servant servant,
01884                                    CORBA_Environment *ev)
01885 {
01886         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01887         DBG (fprintf (stderr, "Get target display: \t%s\n", 
01888                       magnifier->target_display_name));
01889 
01890         return CORBA_string_dup (magnifier->target_display_name ? magnifier->target_display_name : "");
01891 }
01892 
01893 static GNOME_Magnifier_ZoomRegion
01894 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
01895                                    const CORBA_float zx,
01896                                    const CORBA_float zy,
01897                                    const GNOME_Magnifier_RectBounds *roi,
01898                                    const GNOME_Magnifier_RectBounds *viewport,
01899                                    CORBA_Environment *ev)
01900 {
01901         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01902         CORBA_any viewport_any;
01903         ZoomRegion *zoom_region = zoom_region_new ();
01904         Bonobo_PropertyBag properties;
01905         GNOME_Magnifier_ZoomRegion retval;
01906 
01907         DBG (fprintf (stderr, "Create zoom region: \tzoom %f,%f, viewport %d,%d to %d,%d\n", (float) zx, (float) zy, viewport->x1, viewport->y1, viewport->x2, viewport->y2));
01908 
01909         /* FIXME:
01910          * shouldn't do this here, since it causes the region to get
01911          * mapped onto the parent, if if it's not explicitly added!
01912          */
01913         DBG(g_message ("creating zoom region with parent %p", magnifier));
01914         zoom_region->priv->parent = magnifier;
01915 
01916         retval = BONOBO_OBJREF (zoom_region);
01917 
01918         /* XXX: should check ev after each call, below */
01919         CORBA_exception_init (ev);
01920         GNOME_Magnifier_ZoomRegion_setMagFactor (retval, zx, zy, ev);
01921 
01922         if (ev->_major != CORBA_NO_EXCEPTION)
01923                 fprintf (stderr, "EXCEPTION setMagFactor\n");
01924 
01925         CORBA_exception_init (ev);
01926         properties = GNOME_Magnifier_ZoomRegion_getProperties (retval, ev);
01927         if (ev->_major != CORBA_NO_EXCEPTION)
01928                 fprintf (stderr, "EXCEPTION getProperties\n");
01929 
01930         viewport_any._type = TC_GNOME_Magnifier_RectBounds;
01931         viewport_any._value = (gpointer) viewport;
01932         Bonobo_PropertyBag_setValue (
01933                 properties, "viewport", &viewport_any, ev);
01934 
01935         GNOME_Magnifier_ZoomRegion_setROI (retval, roi, ev);
01936         if (ev->_major != CORBA_NO_EXCEPTION)
01937                 fprintf (stderr, "EXCEPTION setROI\n");
01938 
01939         CORBA_exception_init (ev);
01940 
01941         gtk_widget_set_size_request (magnifier->priv->canvas,
01942                            viewport->x2 - viewport->x1,
01943                            viewport->y2 - viewport->y1);
01944         gtk_widget_show (magnifier->priv->canvas);
01945         gtk_widget_show (magnifier->priv->w);
01946 
01947         bonobo_object_release_unref (properties, ev);
01948         
01949         return CORBA_Object_duplicate (retval, ev);
01950 }
01951 
01952 static
01953 CORBA_boolean
01954 impl_magnifier_add_zoom_region (PortableServer_Servant servant,
01955                                 const GNOME_Magnifier_ZoomRegion region,
01956                                 CORBA_Environment * ev)
01957 {
01958         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01959 
01960         if (!magnifier->source_initialized) 
01961         {
01962                 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01963         }
01964 
01965         /* FIXME: this needs proper lifecycle management */
01966         magnifier->zoom_regions = g_list_append (magnifier->zoom_regions, region);
01967         gmag_gs_check_set_struts (magnifier);
01968 
01969         return CORBA_TRUE;
01970 }
01971 
01972 static Bonobo_PropertyBag
01973 impl_magnifier_get_properties (PortableServer_Servant servant,
01974                                CORBA_Environment *ev)
01975 {
01976         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01977         return bonobo_object_dup_ref (
01978                 BONOBO_OBJREF (magnifier->property_bag), ev);
01979 }
01980 
01981 GNOME_Magnifier_ZoomRegionList *
01982 impl_magnifier_get_zoom_regions (PortableServer_Servant servant,
01983                                  CORBA_Environment * ev)
01984 {
01985         Magnifier *magnifier =
01986                 MAGNIFIER (bonobo_object_from_servant (servant));
01987 
01988         GNOME_Magnifier_ZoomRegionList *list;
01989         CORBA_Object objref;
01990         int i, len;
01991 
01992         len = g_list_length (magnifier->zoom_regions);
01993         list = GNOME_Magnifier_ZoomRegionList__alloc ();
01994         list->_length = len;
01995         list->_buffer =
01996                 GNOME_Magnifier_ZoomRegionList_allocbuf (list->_length);
01997         for (i = 0; i < len; ++i) {
01998                 objref = g_list_nth_data (magnifier->zoom_regions, i);
01999                 list->_buffer [i] =
02000                         CORBA_Object_duplicate (objref, ev);
02001         }
02002         CORBA_sequence_set_release (list, CORBA_TRUE);
02003 
02004         DBG (fprintf (stderr, "Get zoom regions: \t%d\n", len));
02005         
02006         return list; 
02007 }
02008 
02009 static void
02010 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant servant,
02011                                        CORBA_Environment * ev)
02012 {
02013         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
02014         fprintf (stderr, "Clear all zoom regions.\n");
02015 
02016         g_list_foreach (magnifier->zoom_regions,
02017                         magnifier_unref_zoom_region, magnifier);
02018         g_list_free (magnifier->zoom_regions);
02019         magnifier->zoom_regions = NULL;
02020         magnifier->zoom_regions_dbus = NULL;
02021 }
02022 
02023 static void
02024 impl_magnifier_dispose (PortableServer_Servant servant,
02025                         CORBA_Environment *ev)
02026 {
02027         magnifier_do_dispose (
02028                 MAGNIFIER (bonobo_object_from_servant (servant)));
02029 }
02030 
02031 static void
02032 magnifier_class_init (MagnifierClass *klass)
02033 {
02034         GObjectClass * object_class = (GObjectClass *) klass;
02035         POA_GNOME_Magnifier_Magnifier__epv *epv = &klass->epv;
02036         parent_class = g_type_class_peek (BONOBO_TYPE_OBJECT); /* needed by BONOBO_CALL_PARENT! */
02037 
02038         object_class->dispose = magnifier_gobject_dispose;
02039 
02040         epv->fullScreenCapable = impl_magnifier_full_screen_capable;
02041         epv->hideCursor = impl_magnifier_hide_cursor;
02042         epv->showCursor = impl_magnifier_show_cursor;
02043         epv->supportColorblindFilters = impl_magnifier_support_colorblind_filters;
02044         epv->_set_SourceDisplay = impl_magnifier_set_source_display;
02045         epv->_set_TargetDisplay = impl_magnifier_set_target_display;
02046         epv->_get_SourceDisplay = impl_magnifier_get_source_display;
02047         epv->_get_TargetDisplay = impl_magnifier_get_target_display;
02048         epv->getProperties = impl_magnifier_get_properties;
02049         epv->getZoomRegions = impl_magnifier_get_zoom_regions;
02050         epv->createZoomRegion = impl_magnifier_create_zoom_region;
02051         epv->addZoomRegion = impl_magnifier_add_zoom_region;
02052         epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
02053         epv->dispose = impl_magnifier_dispose;
02054 }
02055 
02056 static void
02057 magnifier_properties_init (Magnifier *magnifier)
02058 {
02059         BonoboArg *def;
02060         GNOME_Magnifier_RectBounds rect_bounds;
02061         gchar *display_env;
02062 
02063         magnifier->property_bag =
02064                 bonobo_property_bag_new_closure (
02065                         g_cclosure_new_object (
02066                                 G_CALLBACK (magnifier_get_property),
02067                                 G_OBJECT (magnifier)),
02068                         g_cclosure_new_object (
02069                                 G_CALLBACK (magnifier_set_property),
02070                                 G_OBJECT (magnifier)));
02071         /* Aggregate so magnifier implements Bonobo_PropertyBag */
02072         bonobo_object_add_interface (BONOBO_OBJECT (magnifier),
02073                                      BONOBO_OBJECT (magnifier->property_bag));
02074 
02075         def = bonobo_arg_new (BONOBO_ARG_STRING);
02076         display_env = getenv ("DISPLAY");
02077         BONOBO_ARG_SET_STRING (def, display_env);
02078 
02079         bonobo_property_bag_add (magnifier->property_bag,
02080                                  "source-display-screen",
02081                                  MAGNIFIER_SOURCE_DISPLAY_PROP,
02082                                  BONOBO_ARG_STRING,
02083                                  def,
02084                                  "source display screen",
02085                                  Bonobo_PROPERTY_WRITEABLE);
02086 
02087         bonobo_property_bag_add (magnifier->property_bag,
02088                                  "target-display-screen",
02089                                  MAGNIFIER_TARGET_DISPLAY_PROP,
02090                                  BONOBO_ARG_STRING,
02091                                  def,
02092                                  "target display screen",
02093                                  Bonobo_PROPERTY_WRITEABLE);
02094 
02095         bonobo_arg_release (def);
02096 
02097         magnifier_init_display (magnifier, display_env, TRUE);
02098         magnifier_init_display (magnifier, display_env, FALSE);
02099 
02100         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
02101         def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
02102         
02103         bonobo_property_bag_add (magnifier->property_bag,
02104                                  "source-display-bounds",
02105                                  MAGNIFIER_SOURCE_SIZE_PROP,
02106                                  TC_GNOME_Magnifier_RectBounds,
02107                                  def,
02108                                  "source display bounds/size",
02109                                  Bonobo_PROPERTY_READABLE |
02110                                  Bonobo_PROPERTY_WRITEABLE);
02111         bonobo_arg_release (def);
02112         
02113         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, TRUE);
02114         def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
02115 
02116         bonobo_property_bag_add (magnifier->property_bag,
02117                                  "target-display-bounds",
02118                                  MAGNIFIER_TARGET_SIZE_PROP,
02119                                  TC_GNOME_Magnifier_RectBounds,
02120                                  def,
02121                                  "target display bounds/size",
02122                                  Bonobo_PROPERTY_READABLE |
02123                                  Bonobo_PROPERTY_WRITEABLE);
02124         bonobo_arg_release (def);
02125 
02126         bonobo_property_bag_add (magnifier->property_bag,
02127                                  "cursor-set",
02128                                  MAGNIFIER_CURSOR_SET_PROP,
02129                                  BONOBO_ARG_STRING,
02130                                  NULL,
02131                                  "name of cursor set",
02132                                  Bonobo_PROPERTY_READABLE |
02133                                  Bonobo_PROPERTY_WRITEABLE);
02134 
02135         def = bonobo_arg_new (BONOBO_ARG_INT);
02136         BONOBO_ARG_SET_INT (def, 64);
02137         
02138         bonobo_property_bag_add (magnifier->property_bag,
02139                                  "cursor-size",
02140                                  MAGNIFIER_CURSOR_SIZE_PROP,
02141                                  BONOBO_ARG_INT,
02142                                  def,
02143                                  "cursor size, in pixels",
02144                                  Bonobo_PROPERTY_READABLE |
02145                                  Bonobo_PROPERTY_WRITEABLE);
02146         bonobo_arg_release (def);
02147         
02148         bonobo_property_bag_add (magnifier->property_bag,
02149                                  "cursor-scale-factor",
02150                                  MAGNIFIER_CURSOR_ZOOM_PROP,
02151                                  BONOBO_ARG_FLOAT,
02152                                  NULL,
02153                                  "scale factor for cursors (overrides size)",
02154                                  Bonobo_PROPERTY_READABLE |
02155                                  Bonobo_PROPERTY_WRITEABLE);
02156         
02157         bonobo_property_bag_add (magnifier->property_bag,
02158                                  "cursor-color",
02159                                  MAGNIFIER_CURSOR_COLOR_PROP,
02160                                  TC_CORBA_unsigned_long,
02161                                  NULL,
02162                                  "foreground color for 1-bit cursors, as ARGB",
02163                                  Bonobo_PROPERTY_READABLE |
02164                                  Bonobo_PROPERTY_WRITEABLE);    
02165 
02166         bonobo_property_bag_add (magnifier->property_bag,
02167                                  "cursor-hotspot",
02168                                  MAGNIFIER_CURSOR_HOTSPOT_PROP,
02169                                  TC_GNOME_Magnifier_Point,
02170                                  NULL,
02171                                  "hotspot relative to cursor's upper-left-corner, at default resolition",
02172                                  Bonobo_PROPERTY_READABLE |
02173                                  Bonobo_PROPERTY_WRITEABLE);
02174         
02175         bonobo_property_bag_add (magnifier->property_bag,
02176                                  "cursor-default-size",
02177                                  MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
02178                                  BONOBO_ARG_INT,
02179                                  NULL,
02180                                  "default size of current cursor set",
02181                                  Bonobo_PROPERTY_READABLE);
02182 
02183         bonobo_property_bag_add (magnifier->property_bag,
02184                                  "crosswire-size",
02185                                  MAGNIFIER_CROSSWIRE_SIZE_PROP,
02186                                  BONOBO_ARG_INT,
02187                                  NULL,
02188                                  "thickness of crosswire cursor, in target pixels",
02189                                  Bonobo_PROPERTY_READABLE |
02190                                  Bonobo_PROPERTY_WRITEABLE);
02191 
02192         bonobo_property_bag_add (magnifier->property_bag,
02193                                  "crosswire-length",
02194                                  MAGNIFIER_CROSSWIRE_LENGTH_PROP,
02195                                  BONOBO_ARG_INT,
02196                                  NULL,
02197                                  "length of crosswire cursor, in target pixels",
02198                                  Bonobo_PROPERTY_READABLE |
02199                                  Bonobo_PROPERTY_WRITEABLE);
02200         
02201         bonobo_property_bag_add (magnifier->property_bag,
02202                                  "crosswire-color",
02203                                  MAGNIFIER_CROSSWIRE_COLOR_PROP,
02204                                  BONOBO_ARG_LONG,
02205                                  NULL,
02206                                  "color of crosswire, as A-RGB; note that alpha is required. (use 0 for XOR wire)",
02207                                  Bonobo_PROPERTY_READABLE |
02208                                  Bonobo_PROPERTY_WRITEABLE);
02209 
02210         bonobo_property_bag_add (magnifier->property_bag,
02211                                  "crosswire-clip",
02212                                  MAGNIFIER_CROSSWIRE_CLIP_PROP,
02213                                  BONOBO_ARG_BOOLEAN,
02214                                  NULL,
02215                                  "whether to inset the cursor over the crosswire or not",
02216                                  Bonobo_PROPERTY_READABLE |
02217                                  Bonobo_PROPERTY_WRITEABLE);
02218 }
02219 
02220 static void
02221 magnifier_init_window (Magnifier *magnifier, GdkScreen *screen)
02222 {
02223         GtkWindowType mag_win_type = GTK_WINDOW_TOPLEVEL;
02224         if (_is_override_redirect || gmag_gs_use_compositor (magnifier))
02225                 mag_win_type = GTK_WINDOW_POPUP;
02226 
02227         magnifier->priv->w =
02228                 g_object_connect (gtk_widget_new (gtk_window_get_type (),
02229                                                   "user_data", NULL,
02230                                                   "can_focus", FALSE,
02231                                                   "type", mag_win_type,  
02232                                                   "title", "magnifier",
02233                                                   "allow_grow", TRUE,
02234                                                   "allow_shrink", TRUE,
02235                                                   "border_width", 0,
02236                                                   NULL),
02237                                   "signal::realize", magnifier_realize, NULL,
02238                                   "signal::size_allocate", magnifier_size_allocate, NULL,
02239                                   "signal::destroy", magnifier_exit, NULL,
02240                                   NULL);
02241         gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), screen);
02242         magnifier->priv->canvas = gtk_fixed_new ();
02243         gtk_container_add (GTK_CONTAINER (magnifier->priv->w),
02244                            magnifier->priv->canvas);
02245         magnifier->priv->root = NULL;
02246 }
02247 
02248 static void
02249 magnifier_init (Magnifier *magnifier)
02250 {
02251         magnifier->priv = g_new0 (MagnifierPrivate, 1);
02252         magnifier_properties_init (magnifier);
02253         magnifier->zoom_regions = NULL;
02254         magnifier->zoom_regions_dbus = NULL;
02255         magnifier->source_screen_num = 0;
02256         magnifier->target_screen_num = 0;
02257         magnifier->source_display_name = g_strdup (":0.0");
02258         magnifier->target_display_name = g_strdup (":0.0");
02259         magnifier->cursor_size_x = 0;
02260         magnifier->cursor_size_y = 0;
02261         magnifier->cursor_scale_factor = 1.0F;
02262         magnifier->cursor_color = 0xFF000000;
02263         magnifier->crosswire_size = 1;
02264         magnifier->crosswire_length = 0;
02265         magnifier->crosswire_color = 0;
02266         magnifier->crosswire_clip = FALSE;
02267         magnifier->cursor_hotspot.x = 0;
02268         magnifier->cursor_hotspot.y = 0;
02269         magnifier->target_bounds.x1 = 0;
02270         magnifier->target_bounds.y1 = 0;
02271         magnifier->target_bounds.x2 = 0;
02272         magnifier->target_bounds.y2 = 0;
02273         magnifier->priv->cursor = NULL;
02274         magnifier->priv->w = NULL;
02275         magnifier->priv->use_source_cursor = TRUE;
02276         magnifier->priv->cursorlist = NULL;
02277         magnifier->priv->source_drawable = NULL;
02278         magnifier->priv->overlay = NULL;
02279         magnifier_init_window (magnifier, 
02280                                gdk_display_get_screen (magnifier->target_display, 
02281                                                        magnifier->target_screen_num));
02282         magnifier_init_cursor_set (magnifier, "default");
02283 
02284         mag_timing.process = g_timer_new ();
02285         mag_timing.frame = g_timer_new ();
02286         mag_timing.scale = g_timer_new ();
02287         mag_timing.idle = g_timer_new ();
02288 #ifdef DEBUG_CLIENT_CALLS
02289         client_debug = (g_getenv ("MAG_CLIENT_DEBUG") != NULL);
02290 #endif
02291 
02292         zoom_hash = g_hash_table_new (g_str_hash, g_str_equal);
02293 }
02294 
02295 GdkDrawable *
02296 magnifier_get_cursor (Magnifier *magnifier)
02297 {
02298         if (magnifier->priv->cursor == NULL) {
02299             if ((fixes_event_base == 0) && 
02300                 strcmp (magnifier->cursor_set, "none")) 
02301             {
02302                 GdkPixbuf *pixbuf;
02303                 gchar *default_cursor_filename = 
02304                     g_strconcat (CURSORSDIR, "/", "default-cursor.xpm", NULL);
02305                 pixbuf = gdk_pixbuf_new_from_file (default_cursor_filename, NULL);
02306                 if (pixbuf) 
02307                 {
02308                     magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
02309                     g_object_unref (pixbuf);
02310                     magnifier_transform_cursor (magnifier);
02311                 }
02312                 g_free (default_cursor_filename);
02313             } else {
02314                 GdkPixbuf *cursor_pixbuf = gmag_cursor_get_source_pixbuf (
02315                         magnifier);
02316                 magnifier_set_cursor_from_pixbuf (magnifier, cursor_pixbuf);
02317                 if (cursor_pixbuf) g_object_unref (cursor_pixbuf);
02318                 magnifier_transform_cursor (magnifier);
02319             }
02320         }
02321         return magnifier->priv->cursor;
02322 }
02323 
02324 Magnifier *
02325 magnifier_new (gboolean override_redirect)
02326 {
02327         Magnifier *mag;
02328         MagLoginHelper *helper;
02329         GError *error = NULL;
02330         MagnifierClass *klass = NULL;
02331         DBusGProxy *driver_proxy;
02332         guint request_req;
02333         int ret;
02334 
02335         _is_override_redirect = override_redirect;
02336 
02337         mag = g_object_new (magnifier_get_type(), NULL);
02338 
02339         _this_magnifier = mag; /* FIXME what about multiple instances? */
02340 
02341         helper = g_object_new (mag_login_helper_get_type (), NULL);
02342         mag_login_helper_set_magnifier (helper, mag);
02343 
02344         bonobo_object_add_interface (bonobo_object (mag), 
02345                                      BONOBO_OBJECT (helper));
02346         
02347         ret = bonobo_activation_active_server_register (
02348                 MAGNIFIER_OAFIID, BONOBO_OBJREF (mag));
02349         if (ret != Bonobo_ACTIVATION_REG_SUCCESS) {
02350             if ( ret == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE)
02351             {
02352                 printf("An instance of magnifier is already active. Exiting Program.\n");
02353                 exit(0);
02354             } else
02355                 g_error ("Error registering magnifier server.\n");
02356         }
02357         
02358         klass = MAGNIFIER_GET_CLASS (mag);
02359         
02360         klass->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
02361         if (klass->connection == NULL) {
02362                 g_warning ("Unable to connect to dbus: %s", error->message);
02363                 g_error_free (error);
02364                 return NULL;
02365         }
02366         
02367         dbus_g_object_type_install_info (MAGNIFIER_TYPE, &dbus_glib_impl_dbus_magnifier_object_info);
02368         
02369         dbus_g_connection_register_g_object (klass->connection, "/org/freedesktop/gnome/Magnifier",
02370                                              G_OBJECT (_this_magnifier));
02371         
02372         driver_proxy = dbus_g_proxy_new_for_name (klass->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
02373                                                   DBUS_INTERFACE_DBUS);
02374                                                   
02375         if (!org_freedesktop_DBus_request_name (driver_proxy, "org.freedesktop.gnome.Magnifier", 0, &request_req,
02376                                                 &error)) {
02377                 g_warning ("Unable to register service: %s", error->message);
02378                 g_error_free (error);                                   
02379         }
02380 
02381         g_timeout_add (500, magnifier_reset_struts_at_idle, mag);
02382         g_timeout_add (500, gmag_gs_reset_overlay_at_idle, mag);
02383         
02384         return mag;
02385 }
02386 
02387 BONOBO_TYPE_FUNC_FULL (Magnifier, 
02388                        GNOME_Magnifier_Magnifier,
02389                        BONOBO_TYPE_OBJECT,
02390                        magnifier)
02391 
Generated on Sat Jun 19 11:00:30 2010 for gnome-mag by  doxygen 1.6.3