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 
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <strings.h>
00035 
00036 #include <libbonobo.h>
00037 #include <login-helper/login-helper.h>
00038 
00039 #include <gdk-pixbuf/gdk-pixbuf.h>
00040 #include <gdk/gdkx.h>
00041 #include <gdk/gdk.h>
00042 #include <gtk/gtk.h>
00043 
00044 /* if you #define this, don't forget to set MAG_CLIENT_DEBUG env variable */
00045 #define DEBUG_CLIENT_CALLS
00046 
00047 #ifdef DEBUG_CLIENT_CALLS
00048 static gboolean client_debug = FALSE;
00049 #define DBG(a) if (client_debug) { (a); }
00050 #else
00051 #define DBG(a)
00052 #endif
00053 
00054 typedef struct
00055 {
00056     LoginHelper parent;
00057     Magnifier *mag;
00058 } MagLoginHelper;
00059 
00060 typedef struct 
00061 {
00062     LoginHelperClass parent_class;
00063 } MagLoginHelperClass;
00064 
00065 static GObjectClass *parent_class = NULL;
00066 
00067 enum {
00068         MAGNIFIER_SOURCE_DISPLAY_PROP,
00069         MAGNIFIER_TARGET_DISPLAY_PROP,
00070         MAGNIFIER_SOURCE_SIZE_PROP,
00071         MAGNIFIER_TARGET_SIZE_PROP,
00072         MAGNIFIER_CURSOR_SET_PROP,
00073         MAGNIFIER_CURSOR_SIZE_PROP,
00074         MAGNIFIER_CURSOR_ZOOM_PROP,
00075         MAGNIFIER_CURSOR_COLOR_PROP,
00076         MAGNIFIER_CURSOR_HOTSPOT_PROP,
00077         MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
00078         MAGNIFIER_CROSSWIRE_SIZE_PROP,
00079         MAGNIFIER_CROSSWIRE_LENGTH_PROP,
00080         MAGNIFIER_CROSSWIRE_CLIP_PROP,
00081         MAGNIFIER_CROSSWIRE_COLOR_PROP
00082 } PropIdx;
00083 
00084 typedef struct
00085 {
00086         GNOME_Magnifier_RectBounds rectbounds;
00087         GNOME_Magnifier_RectBounds viewport;
00088         gboolean is_managed;
00089         gint scroll_policy;
00090         gfloat contrast;
00091         gfloat zx;
00092         gfloat zy;
00093         gint32 xalign;
00094         gint32 yalign;
00095         guint32 border_color;
00096         gint32 border_size;
00097         gchar *smoothing_type;
00098         gboolean inverse;
00099 
00100 } MagnifierZoomRegionSaveProps;
00101 
00102 #ifdef DEBUG_CLIENT_CALLS
00103 gchar* mag_prop_names[MAGNIFIER_CROSSWIRE_COLOR_PROP + 1] = {
00104     "SOURCE_DISPLAY",
00105     "TARGET_DISPLAY",
00106     "SOURCE_SIZE",
00107     "TARGET_SIZE",
00108     "CURSOR_SET",
00109     "CURSOR_SIZE",
00110     "CURSOR_ZOOM",
00111     "CURSOR_COLOR",
00112     "CURSOR_HOTSPOT",
00113     "CURSOR_DEFAULT_SIZE",
00114     "CROSSWIRE_SIZE",
00115     "CROSSWIRE_LENGTH",
00116     "CROSSWIRE_CLIP",
00117     "CROSSWIRE_COLOR"
00118 };
00119 #endif
00120 
00121 static Magnifier *_this_magnifier = NULL;
00122 extern gint       fixes_event_base;
00123 
00124 static void magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set);
00125 static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);
00126 static gboolean magnifier_reset_struts_at_idle (gpointer data);
00127 static void magnifier_init_window (Magnifier *magnifier, GdkScreen *screen);
00128 static void magnifier_adjust_source_size (Magnifier *magnifier);
00129 static gboolean _is_override_redirect = FALSE;
00130 
00131 static Window*
00132 mag_login_helper_get_raise_windows (LoginHelper *helper)
00133 {
00134     Window *mainwin = NULL;
00135     MagLoginHelper *mag_helper = (MagLoginHelper *) helper;
00136     Magnifier *magnifier = MAGNIFIER (mag_helper->mag);
00137 
00138     if (magnifier && magnifier->priv && magnifier->priv->w)
00139     {
00140         mainwin = g_new0 (Window, 2);
00141         mainwin[0] = GDK_WINDOW_XWINDOW (magnifier->priv->w->window);
00142         mainwin[1] = None;
00143     }
00144     return mainwin;
00145 }
00146 
00147 static LoginHelperDeviceReqFlags
00148 mag_login_helper_get_device_reqs (LoginHelper *helper)
00149 {
00150     /* means "don't grab the xserver or core pointer", 
00151        and "we need to raise windows" */
00152 
00153     return LOGIN_HELPER_GUI_EVENTS | 
00154         LOGIN_HELPER_POST_WINDOWS | 
00155         LOGIN_HELPER_CORE_POINTER;
00156 }
00157 
00158 static gboolean
00159 mag_login_helper_set_safe (LoginHelper *helper, gboolean ignored)
00160 {
00161     return TRUE;
00162 }
00163 
00164 static void
00165 mag_login_helper_class_init (MagLoginHelperClass *klass)
00166 {
00167         LoginHelperClass *login_helper_class = LOGIN_HELPER_CLASS(klass);
00168         login_helper_class->get_raise_windows = mag_login_helper_get_raise_windows;
00169         login_helper_class->get_device_reqs = mag_login_helper_get_device_reqs;
00170         login_helper_class->set_safe = mag_login_helper_set_safe;
00171 }
00172 
00173 static void
00174 mag_login_helper_init (MagLoginHelper *helper)
00175 {
00176     helper->mag = NULL; /* we set this with mag_login_helper_set_magnifier */
00177 }
00178 
00179 static void
00180 mag_login_helper_set_magnifier (MagLoginHelper *helper, Magnifier *mag)
00181 {
00182     if (helper) 
00183         helper->mag = mag;
00184 }
00185 
00186 BONOBO_TYPE_FUNC (MagLoginHelper, 
00187                   LOGIN_HELPER_TYPE,
00188                   mag_login_helper)
00189 
00190 static gboolean
00191 can_open_display (gchar *display_name)
00192 {
00193     Display *d;
00194     if ((d = XOpenDisplay (display_name)))
00195     {
00196         XCloseDisplay (d);
00197         return TRUE;
00198     }
00199     return FALSE;
00200 }
00201 
00202 static void
00203 magnifier_warp_cursor_to_screen (Magnifier *magnifier)
00204 {
00205         int x, y, unused_x, unused_y;
00206         unsigned int mask;
00207         Window root_return, child_return;
00208 
00209         if (magnifier->source_display)
00210         {
00211             if (!XQueryPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display), 
00212                                 GDK_WINDOW_XWINDOW (magnifier->priv->root), 
00213                                 &root_return,
00214                                 &child_return,
00215                                 &x, &y,
00216                                 &unused_x, &unused_y,
00217                                 &mask))
00218             {
00219                 XWarpPointer (GDK_DISPLAY_XDISPLAY (magnifier->source_display),
00220                               None,
00221                               GDK_WINDOW_XWINDOW (magnifier->priv->root),
00222                               0, 0, 0, 0,
00223                               x, y);
00224                 XSync (GDK_DISPLAY_XDISPLAY (magnifier->source_display), FALSE);
00225             }
00226         }
00227 }
00228 
00229 void
00230 magnifier_zoom_regions_update_pointer (Magnifier *magnifier)
00231 {
00232         GList *list;
00233 
00234         g_assert (magnifier);
00235 
00236         list = magnifier->zoom_regions;
00237         while (list) {
00238                 /* propagate the expose events to the zoom regions */
00239                 GNOME_Magnifier_ZoomRegion zoom_region;
00240                 CORBA_Environment ev;
00241                 zoom_region = list->data;
00242                 CORBA_exception_init (&ev);
00243                 if (zoom_region)
00244                         GNOME_Magnifier_ZoomRegion_updatePointer (
00245                                 CORBA_Object_duplicate (zoom_region, &ev), &ev);
00246                 list = g_list_next (list);
00247         }
00248 }
00249 
00250 static void
00251 magnifier_zoom_regions_mark_dirty (Magnifier *magnifier, GNOME_Magnifier_RectBounds rect_bounds)
00252 {
00253         GList *list;
00254 
00255         g_assert (magnifier);
00256 
00257         list = magnifier->zoom_regions;
00258         while (list) 
00259         {
00260                 /* propagate the expose events to the zoom regions */
00261                 GNOME_Magnifier_ZoomRegion zoom_region;
00262                 CORBA_Environment ev;
00263                 zoom_region = list->data;
00264                 CORBA_exception_init (&ev);
00265                 if (zoom_region)
00266                         GNOME_Magnifier_ZoomRegion_markDirty (CORBA_Object_duplicate (zoom_region, &ev),
00267                                                               &rect_bounds,
00268                                                               &ev);
00269                 list = g_list_next (list);
00270         }
00271 }
00272 
00273 void
00274 magnifier_set_cursor_from_pixbuf (Magnifier *magnifier,
00275                                   GdkPixbuf *cursor_pixbuf)
00276 {
00277         GdkPixmap *pixmap, *mask;
00278         gint width, height;
00279         GdkGC *gc;
00280         GdkDrawable *drawable = magnifier->priv->w->window;
00281 
00282         if (magnifier->priv->cursor) {
00283                 g_object_unref (magnifier->priv->cursor);
00284                 magnifier->priv->cursor = NULL;
00285         }
00286         if (drawable && cursor_pixbuf) {
00287                 const gchar *xhot_string = NULL, *yhot_string = NULL;
00288                 width = gdk_pixbuf_get_width (cursor_pixbuf);
00289                 height = gdk_pixbuf_get_height (cursor_pixbuf);
00290                 pixmap = gdk_pixmap_new (drawable, width, height, -1);
00291                 gc = gdk_gc_new (pixmap);
00292                 if (GDK_IS_DRAWABLE (pixmap))
00293                         gdk_draw_pixbuf (pixmap, gc, cursor_pixbuf, 0, 0, 0, 0,
00294                                          width, height, GDK_RGB_DITHER_NONE,
00295                                          0, 0);
00296                 else
00297                         DBG (g_warning ("empty cursor pixmap created."));
00298                 mask = gdk_pixmap_new (drawable, width, height, 1);
00299                 gdk_pixbuf_render_threshold_alpha (cursor_pixbuf, mask,
00300                                                    0, 0, 0, 0, 
00301                                                    width, height,
00302                                                    200);
00303                 g_object_unref (gc);
00304                 magnifier->priv->cursor = pixmap;
00305                 magnifier->priv->cursor_mask = mask;
00306 
00307                 xhot_string = g_object_get_data (cursor_pixbuf, "x_hot");
00308                 yhot_string = g_object_get_data (cursor_pixbuf, "y_hot");
00309 
00310                 if (xhot_string)
00311                         magnifier->cursor_hotspot.x = atoi (xhot_string);
00312                 if (yhot_string)
00313                         magnifier->cursor_hotspot.y = atoi (yhot_string);
00314                 if (pixmap) {
00315                         gdk_drawable_get_size (
00316                                 pixmap,
00317                                 &magnifier->priv->cursor_default_size_x,
00318                                 &magnifier->priv->cursor_default_size_y);
00319                         magnifier->priv->cursor_hotspot_x =
00320                                 magnifier->cursor_hotspot.x;
00321                         magnifier->priv->cursor_hotspot_y =
00322                                 magnifier->cursor_hotspot.y;
00323                 }
00324         }
00325 }
00326 
00327 
00328 GdkPixbuf *
00329 magnifier_get_pixbuf_for_name (Magnifier *magnifier, const gchar *cursor_name)
00330 {
00331     GdkPixbuf *retval = NULL;
00332     if (magnifier->priv->cursorlist) 
00333             retval = g_hash_table_lookup (magnifier->priv->cursorlist, cursor_name);
00334     if (retval) 
00335             g_object_ref (retval);
00336     return retval;
00337 }
00338 
00339 void
00340 magnifier_set_cursor_pixmap_by_name (Magnifier *magnifier,
00341                                      const gchar *cursor_name, 
00342                                      gboolean source_fallback)
00343 {
00344         GdkPixbuf *pixbuf;
00345         /* search local table; if not found, use source screen's cursor if source_fallback is TRUE */
00346         if ((pixbuf = magnifier_get_pixbuf_for_name (magnifier, cursor_name)) == NULL) {
00347                 if (source_fallback == TRUE)
00348                 {
00349                         pixbuf = gmag_cursor_get_source_pixbuf (magnifier);
00350                 }
00351                 else
00352                 {
00353                         pixbuf = magnifier_get_pixbuf_for_name (magnifier, "default");
00354                 }
00355         }
00356         magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
00357         if (pixbuf) g_object_unref (pixbuf);
00358 }
00359 
00360 void
00361 magnifier_notify_damage (Magnifier *magnifier, GdkRectangle *rect)
00362 {
00363         GNOME_Magnifier_RectBounds rect_bounds;
00364         rect_bounds.x1 = rect->x;
00365         rect_bounds.y1 = rect->y;
00366         rect_bounds.x2 = rect->x + rect->width;
00367         rect_bounds.y2 = rect->y + rect->height;
00368 #undef DEBUG_DAMAGE
00369 #ifdef DEBUG_DAMAGE
00370         g_message ("damage");
00371         g_message ("dirty %d, %d to %d, %d", rect_bounds.x1, rect_bounds.y1,
00372                    rect_bounds.x2, rect_bounds.y2);
00373 #endif
00374         magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);
00375 }
00376 
00377 static void
00378 magnifier_set_extension_listeners (Magnifier *magnifier, GdkWindow *root)
00379 {
00380         gmag_gs_client_init (magnifier);
00381         magnifier->source_initialized = TRUE;
00382 }
00383 
00384 static void
00385 magnifier_size_allocate (GtkWidget *widget)
00386 {
00387         gmag_gs_check_set_struts (_this_magnifier);
00388 }
00389 
00390 static void
00391 magnifier_realize (GtkWidget *widget)
00392 {
00393         gmag_gs_magnifier_realize (widget);
00394 }
00395 
00396 GdkWindow*
00397 magnifier_get_root (Magnifier *magnifier)
00398 {
00399     if (!magnifier->priv->root && magnifier->source_display) {
00400         magnifier->priv->root = gdk_screen_get_root_window (
00401             gdk_display_get_screen (magnifier->source_display,
00402                                     magnifier->source_screen_num));
00403     }
00404     return magnifier->priv->root;
00405 }
00406 
00407 static gint
00408 magnifier_parse_display_name (Magnifier *magnifier, gchar *full_display_string,
00409                               gchar **display_name)
00410 {
00411         gchar *screen_ptr;
00412         gchar **strings;
00413         
00414         if (display_name != NULL) {
00415                 strings = g_strsplit (full_display_string, ":", 2);
00416                 *display_name = strings [0];
00417                 if (strings [1] != NULL)
00418                         g_free (strings [1]);
00419         }
00420 
00421         screen_ptr = rindex (full_display_string, '.');
00422         if (screen_ptr != NULL) {
00423                 return (gint) strtol (++screen_ptr, NULL, 10);
00424         }
00425         return 0;
00426 }
00427 
00428 static void
00429 magnifier_get_display_rect_bounds (Magnifier *magnifier, GNOME_Magnifier_RectBounds *rect_bounds, gboolean is_target)
00430 {
00431     if (is_target)
00432     {
00433         rect_bounds->x1 = 0;
00434         rect_bounds->x2 = gdk_screen_get_width (
00435             gdk_display_get_screen (magnifier->target_display,
00436                                     magnifier->target_screen_num));
00437         rect_bounds->y1 = 0;
00438         rect_bounds->y2 = gdk_screen_get_height (
00439             gdk_display_get_screen (magnifier->target_display,
00440                                     magnifier->target_screen_num));
00441 
00442     }
00443     else 
00444     {
00445         rect_bounds->x1 = 0;
00446         rect_bounds->x2 = gdk_screen_get_width (
00447             gdk_display_get_screen (magnifier->source_display,
00448                                     magnifier->source_screen_num));
00449         rect_bounds->y1 = 0;
00450         rect_bounds->y2 = gdk_screen_get_height (
00451             gdk_display_get_screen (magnifier->source_display,
00452                                     magnifier->source_screen_num));
00453 
00454     }
00455 }
00456 
00457 gboolean
00458 magnifier_full_screen_capable (Magnifier *magnifier)
00459 {
00460         if ((strcmp (magnifier->source_display_name,
00461                      magnifier->target_display_name) != 0) ||
00462                 gmag_gs_use_compositor (magnifier))
00463                 return TRUE;
00464 
00465         return FALSE;
00466 }
00467 
00468 static void
00469 magnifier_adjust_source_size (Magnifier *magnifier)
00470 {
00471         GNOME_Magnifier_RectBounds rect_bounds; 
00472         gdouble vfract_top, vfract_bottom, hfract_left, hfract_right;
00473 
00474         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
00475 
00476         hfract_left = (double) (magnifier->target_bounds.x1) /
00477                 (double) rect_bounds.x2;
00478         vfract_top = (double) (magnifier->target_bounds.y1) /
00479                 (double) rect_bounds.y2;
00480         hfract_right = (double) (rect_bounds.x2 -
00481                                  magnifier->target_bounds.x2) /
00482                 (double) rect_bounds.x2;
00483         vfract_bottom = (double) (rect_bounds.y2 -
00484                                   magnifier->target_bounds.y2) /
00485                 (double) rect_bounds.y2;
00486 
00487         /* we make our 'source' rectangle the largest available subsection which we aren't occupying */
00488         if (magnifier_full_screen_capable (magnifier)) {
00489                 magnifier->source_bounds = rect_bounds;
00490         } else if (MAX (hfract_left, hfract_right) >
00491                    MAX (vfract_top, vfract_bottom)) {  /* vertical split,
00492                                                         * approximately */
00493                 if (hfract_right > hfract_left) {
00494                         magnifier->source_bounds.x1 =
00495                                 magnifier->target_bounds.x2;
00496                         magnifier->source_bounds.x2 = rect_bounds.x2;
00497                 } else  {
00498                         magnifier->source_bounds.x1 = rect_bounds.x1;
00499                         magnifier->source_bounds.x2 =
00500                                 magnifier->target_bounds.x1;
00501                 }
00502                 magnifier->source_bounds.y1 = rect_bounds.y1;
00503                 magnifier->source_bounds.y2 = rect_bounds.y2;
00504         } else { /* more-or-less horizontally split */
00505                 if (vfract_bottom > vfract_top) {
00506                         magnifier->source_bounds.y1 =
00507                                 magnifier->target_bounds.y2;
00508                         magnifier->source_bounds.y2 = rect_bounds.y2;
00509                 } else {
00510                         magnifier->source_bounds.y1 = rect_bounds.y1;
00511                         magnifier->source_bounds.y2 =
00512                                 magnifier->target_bounds.y1;
00513                 }
00514                 magnifier->source_bounds.x1 = rect_bounds.x1;
00515                 magnifier->source_bounds.x2 = rect_bounds.x2;
00516         }
00517         g_message ("set source bounds to %d,%d; %d,%d", 
00518                    magnifier->source_bounds.x1, magnifier->source_bounds.y1,
00519                    magnifier->source_bounds.x2, magnifier->source_bounds.y2);
00520 }
00521 
00522 static void
00523 magnifier_unref_zoom_region (gpointer data, gpointer user_data)
00524 {
00525 /*      Magnifier *magnifier = user_data; NOT USED */
00526         CORBA_Environment ev;
00527         GNOME_Magnifier_ZoomRegion zoom_region = data;
00528         CORBA_exception_init (&ev);
00529         
00530         DBG(g_message ("unreffing zoom region"));
00531 
00532         GNOME_Magnifier_ZoomRegion_dispose (zoom_region, &ev);
00533         if (!BONOBO_EX (&ev))
00534             Bonobo_Unknown_unref (zoom_region, &ev);
00535 }
00536 
00537 static GSList*
00538 magnifier_zoom_regions_save (Magnifier *magnifier)
00539 {
00540     GList *list;
00541     GSList *save_props = NULL;
00542     
00543     g_assert (magnifier);
00544     list = magnifier->zoom_regions;
00545 
00546     DBG(g_message ("saving %d regions", g_list_length (list)));
00547 
00548     while (list) 
00549     {
00550         GNOME_Magnifier_ZoomRegion zoom_region;
00551         CORBA_Environment ev;
00552         zoom_region = list->data;
00553         CORBA_exception_init (&ev);
00554         if (zoom_region)
00555         {
00556             Bonobo_PropertyBag properties;
00557             CORBA_any *value;
00558             MagnifierZoomRegionSaveProps *zoomer_props = g_new0 (MagnifierZoomRegionSaveProps, 1);
00559 
00560             zoomer_props->rectbounds = GNOME_Magnifier_ZoomRegion_getROI (zoom_region, &ev);
00561             properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev);
00562             value = bonobo_pbclient_get_value (properties, "viewport", TC_GNOME_Magnifier_RectBounds, &ev);
00563             memcpy (&zoomer_props->viewport, value->_value, sizeof (GNOME_Magnifier_RectBounds));
00564             CORBA_free (value);
00565             zoomer_props->is_managed = bonobo_pbclient_get_boolean (properties, "is-managed", NULL);
00566             zoomer_props->scroll_policy = bonobo_pbclient_get_short (properties, "smooth-scroll-policy", NULL);
00567             zoomer_props->contrast = bonobo_pbclient_get_float (properties, "contrast", NULL);
00568             zoomer_props->zx = bonobo_pbclient_get_float (properties, "mag-factor-x", NULL);
00569             zoomer_props->zy = bonobo_pbclient_get_float (properties, "mag-factor-y", NULL);
00570             zoomer_props->xalign = bonobo_pbclient_get_long (properties, "x-alignment", NULL);
00571             zoomer_props->yalign = bonobo_pbclient_get_long (properties, "y-alignment", NULL);
00572             zoomer_props->border_color = bonobo_pbclient_get_long (properties, "border-color", NULL); 
00573             zoomer_props->border_size = bonobo_pbclient_get_long (properties, "border-size", NULL);
00574             zoomer_props->smoothing_type = bonobo_pbclient_get_string (properties, "smoothing-type", NULL); 
00575             zoomer_props->inverse = bonobo_pbclient_get_boolean (properties, "inverse-video", NULL); 
00576 
00577             bonobo_object_release_unref (properties, &ev);
00578             magnifier_unref_zoom_region ((gpointer) zoom_region, NULL);
00579             save_props = g_slist_append (save_props, zoomer_props);
00580         }
00581         list = g_list_next (list);
00582     }   
00583 
00584     magnifier->zoom_regions = NULL;
00585 
00586     return save_props;
00587 }
00588 
00589 static void
00590 magnifier_zoom_regions_restore (Magnifier *magnifier, GSList *region_params)
00591 {
00592         GSList *list = region_params;
00593 
00594         while (list)
00595         {
00596                 CORBA_Environment ev;
00597                 MagnifierZoomRegionSaveProps *zoomer_props = list->data;
00598                 GNOME_Magnifier_ZoomRegion new_region;
00599                 Bonobo_PropertyBag new_properties;
00600 
00601                 CORBA_exception_init (&ev);
00602                 new_region = GNOME_Magnifier_Magnifier_createZoomRegion (BONOBO_OBJREF (magnifier), zoomer_props->zx, zoomer_props->zy, &zoomer_props->rectbounds, &zoomer_props->viewport, &ev);
00603                 new_properties = GNOME_Magnifier_ZoomRegion_getProperties (new_region, &ev);
00604                 bonobo_pbclient_set_boolean (new_properties, "is-managed", 
00605                                              zoomer_props->is_managed, NULL);
00606                 bonobo_pbclient_set_short (new_properties, "smooth-scroll-policy", 
00607                                            zoomer_props->scroll_policy, NULL);
00608                 bonobo_pbclient_set_float (new_properties, "contrast", 
00609                                            zoomer_props->contrast, NULL);
00610 /* NOT YET USED
00611                 bonobo_pbclient_set_long (new_properties, "x-alignment", 
00612                                              zoomer_props->xalign, NULL);
00613                 bonobo_pbclient_set_long (new_properties, "y-alignment", 
00614                                              zoomer_props->yalign, NULL);
00615 */
00616                 bonobo_pbclient_set_long (new_properties, "border-color", 
00617                                              zoomer_props->border_color, NULL);
00618                 bonobo_pbclient_set_long (new_properties, "border-size", 
00619                                              zoomer_props->border_size, NULL);
00620                 bonobo_pbclient_set_string (new_properties, "smoothing-type", 
00621                                              zoomer_props->smoothing_type, NULL);
00622                 bonobo_pbclient_set_boolean (new_properties, "inverse-video", 
00623                                              zoomer_props->inverse, NULL);
00624                 GNOME_Magnifier_Magnifier_addZoomRegion (BONOBO_OBJREF (magnifier), new_region, &ev);
00625                 g_free (zoomer_props->smoothing_type);
00626                 g_free (zoomer_props);
00627                 bonobo_object_release_unref (new_properties, &ev);
00628                 list = g_slist_next (list);
00629         }
00630         g_slist_free (region_params);
00631 }
00632 
00633 static void
00634 magnifier_init_display (Magnifier *magnifier, gchar *display_name, gboolean is_target)
00635 {
00636     if (!can_open_display (display_name))
00637         return;
00638 
00639     if (is_target)
00640     {
00641         magnifier->target_screen_num =
00642             magnifier_parse_display_name (magnifier,
00643                                           display_name,
00644                                           NULL);
00645         magnifier->target_display =
00646             gdk_display_open (display_name);
00647         if (magnifier->target_display_name) g_free (magnifier->target_display_name);
00648         magnifier->target_display_name = g_strdup (display_name);
00649         magnifier->priv->root =
00650             gdk_screen_get_root_window (
00651                 gdk_display_get_screen (
00652                     magnifier->target_display,
00653                     magnifier->target_screen_num));
00654     }
00655     else 
00656     {
00657         magnifier->source_screen_num =
00658             magnifier_parse_display_name (magnifier,
00659                                           display_name,
00660                                           NULL);
00661         magnifier->source_display =
00662             gdk_display_open (display_name);
00663         if (magnifier->source_display)
00664         {
00665             if (magnifier->source_display_name) g_free (magnifier->source_display_name);
00666             magnifier->source_display_name = g_strdup (display_name);
00667             magnifier->priv->root =
00668                 gdk_screen_get_root_window (
00669                     gdk_display_get_screen (
00670                         magnifier->source_display,
00671                         magnifier->source_screen_num));
00672         }
00673     }
00674 }
00675 
00676 static void
00677 magnifier_exit (GtkObject *object)
00678 {
00679         gtk_main_quit ();
00680         exit (0);
00681 }
00682 
00683 #define GET_PIXEL(a,i,j,s,b) \
00684 (*(guint32 *)(memcpy (b,(a) + ((j) * s + (i) * pixel_size_t), pixel_size_t)))
00685 
00686 #define PUT_PIXEL(a,i,j,s,b) \
00687 (memcpy (a + ((j) * s + (i) * pixel_size_t), &(b), pixel_size_t))
00688 
00689 static void
00690 magnifier_recolor_pixbuf (Magnifier *magnifier, GdkPixbuf *pixbuf)
00691 {
00692         int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
00693         int i, j;
00694         int w = gdk_pixbuf_get_width (pixbuf);
00695         int h = gdk_pixbuf_get_height (pixbuf);
00696         guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
00697         guint32 pixval = 0, cursor_color = 0;
00698         size_t pixel_size_t = 3; /* FIXME: invalid assumption ? */
00699 
00700         cursor_color = ((magnifier->cursor_color & 0xFF0000) >> 16) +
00701                 (magnifier->cursor_color & 0x00FF00) +
00702                 ((magnifier->cursor_color & 0x0000FF) << 16);
00703         for (j = 0; j < h; ++j) {
00704                 for (i = 0; i < w; ++i) {
00705                         pixval = GET_PIXEL (pixels, i, j, rowstride, &pixval);
00706                         if ((pixval & 0x808080) == 0)
00707                         {
00708                                 pixval = cursor_color;
00709                                 PUT_PIXEL (pixels, i, j, rowstride,
00710                                            pixval);
00711                         }
00712                 }
00713         }
00714 }
00715 
00716 void
00717 magnifier_transform_cursor (Magnifier *magnifier)
00718 {
00719         if (magnifier->priv->cursor) /* don't do this if cursor isn't intialized yet */
00720         {
00721                 int width, height;
00722                 int size_x, size_y;
00723                 GdkPixbuf *scaled_cursor_pixbuf;
00724                 GdkPixbuf *scaled_mask_pixbuf;
00725                 GdkPixbuf *scaled_mask_pixbuf_alpha;
00726                 GdkPixbuf *cursor_pixbuf;
00727                 GdkPixbuf *mask_pixbuf;
00728                 GdkPixmap *cursor_pixmap = magnifier->priv->cursor;
00729                 GdkPixmap *mask_pixmap = magnifier->priv->cursor_mask;
00730                 GdkGC *cgc;
00731                 GdkGC *mgc;
00732 
00733                 if (magnifier->cursor_size_x)
00734                 {
00735                         size_x = magnifier->cursor_size_x;
00736                         size_y = magnifier->cursor_size_y;
00737                 }
00738                 else
00739                 {
00740                         size_x = magnifier->priv->cursor_default_size_x * 
00741                                magnifier->cursor_scale_factor;
00742                         size_y = magnifier->priv->cursor_default_size_y * 
00743                                magnifier->cursor_scale_factor;
00744                 }
00745                 gdk_drawable_get_size (magnifier->priv->cursor, &width, &height);
00746                 if ((size_x == width) && (size_y == height) 
00747                     && (magnifier->cursor_color == 0xFF000000)) {
00748                         return; /* nothing changes */
00749                 }
00750                 cgc = gdk_gc_new (cursor_pixmap);
00751                 mgc = gdk_gc_new (mask_pixmap);
00752                 cursor_pixbuf = gdk_pixbuf_get_from_drawable (NULL, cursor_pixmap,
00753                                                               NULL, 0, 0, 0, 0,
00754                                                               width, height);
00755                 if (magnifier->cursor_color != 0xFF000000)
00756                         magnifier_recolor_pixbuf (magnifier, cursor_pixbuf);
00757                 mask_pixbuf = gdk_pixbuf_get_from_drawable (NULL,
00758                                                             mask_pixmap,
00759                                                             NULL, 0, 0, 0, 0,
00760                                                             width, height);
00761                 scaled_cursor_pixbuf = gdk_pixbuf_scale_simple (
00762                         cursor_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
00763                 
00764                 magnifier->cursor_hotspot.x = magnifier->priv->cursor_hotspot_x * size_x 
00765                                             / magnifier->priv->cursor_default_size_x;
00766                 magnifier->cursor_hotspot.y = magnifier->priv->cursor_hotspot_y * size_y 
00767                                             / magnifier->priv->cursor_default_size_y;
00768                                             
00769                 scaled_mask_pixbuf = gdk_pixbuf_scale_simple (
00770                         mask_pixbuf, size_x, size_y, GDK_INTERP_NEAREST);
00771                 g_object_unref (cursor_pixbuf);
00772                 g_object_unref (mask_pixbuf);
00773                 g_object_unref (cursor_pixmap);
00774                 g_object_unref (mask_pixmap);
00775                 magnifier->priv->cursor = gdk_pixmap_new (
00776                         magnifier->priv->w->window,
00777                         size_x, size_y,
00778                         -1);
00779                 if (!GDK_IS_DRAWABLE (magnifier->priv->cursor)) 
00780                 {
00781                     DBG (g_warning ("NULL magnifier cursor pixmap."));
00782                     return;
00783                 }
00784                 magnifier->priv->cursor_mask = gdk_pixmap_new (
00785                         magnifier->priv->w->window,
00786                         size_x, size_y,
00787                         1);
00788                 if (GDK_IS_DRAWABLE (magnifier->priv->cursor)) {
00789                     gdk_draw_pixbuf (magnifier->priv->cursor,
00790                                      cgc,
00791                                      scaled_cursor_pixbuf,
00792                                      0, 0, 0, 0, size_x, size_y,
00793                                      GDK_RGB_DITHER_NONE, 0, 0 );
00794                 }
00795                 else
00796                     DBG (g_warning ("cursor pixmap is non-drawable."));
00797                 scaled_mask_pixbuf_alpha = gdk_pixbuf_add_alpha (
00798                         scaled_mask_pixbuf, True, 0, 0, 0);
00799                 gdk_pixbuf_render_threshold_alpha (scaled_mask_pixbuf_alpha,
00800                                                    magnifier->priv->cursor_mask,
00801                                                    0, 0, 0, 0, size_x, size_y,
00802                                                    0x80);
00803                 g_object_unref (scaled_mask_pixbuf_alpha);
00804                 g_object_unref (scaled_cursor_pixbuf);
00805                 g_object_unref (scaled_mask_pixbuf);
00806                 g_object_unref (mgc);
00807                 g_object_unref (cgc);
00808         }       
00809 }
00810 
00811 static void
00812 magnifier_init_cursor_set (Magnifier *magnifier, gchar *cursor_set)
00813 {
00814         /*
00815          * we check the cursor-set property string here,
00816          * and create/apply the appropriate cursor settings
00817          */
00818         magnifier->cursor_set = cursor_set;
00819         magnifier->priv->use_source_cursor = 
00820             (!strcmp (cursor_set, "default") && 
00821              (fixes_event_base != 0));
00822         if (magnifier->priv->use_source_cursor) return;
00823 
00824         if (!strcmp (magnifier->cursor_set, "none")) {
00825                 magnifier->priv->cursor = NULL;
00826                 return;
00827         }
00828         else 
00829         {
00830                 GDir *cursor_dir;
00831                 const gchar *filename;
00832                 gchar *cursor_dirname;
00833 
00834                 if (magnifier->priv->cursorlist)
00835                 {
00836                         g_hash_table_destroy (magnifier->priv->cursorlist);
00837                 }
00838                 magnifier->priv->cursorlist = g_hash_table_new_full (g_str_hash, g_str_equal,
00839                                                                      g_free, g_object_unref);
00840 
00841                 cursor_dirname = g_strconcat (CURSORSDIR, "/", magnifier->cursor_set, NULL);
00842                 cursor_dir = g_dir_open (cursor_dirname, 0, NULL);
00843                 /* assignment, not comparison, is intentional */
00844                 while (cursor_dir && (filename = g_dir_read_name (cursor_dir)) != NULL) 
00845                 {
00846                         if (filename) 
00847                         {
00848                                 gchar *path = g_strconcat (cursor_dirname, "/", filename, NULL);
00849                                 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path, NULL);
00850                                 if (pixbuf)
00851                                 {
00852                                         /* add this pixbuf and its name to our list */
00853                                         gchar **sv, *cname;
00854                                         cname = g_path_get_basename (filename);
00855                                         sv = g_strsplit (cname, ".", 2);
00856                                         g_hash_table_insert (magnifier->priv->cursorlist, 
00857                                                              g_strdup (sv[0]),
00858                                                              pixbuf);
00859                                         g_free (cname);
00860                                         g_strfreev (sv);
00861                                 }
00862                                 g_free (path);
00863                         }
00864                 } 
00865                 g_free (cursor_dirname);
00866                 if (cursor_dir) g_dir_close (cursor_dir);
00867         }
00868         /* don't fallover to source cursor here, we haven't initialized X yet */
00869         magnifier_set_cursor_pixmap_by_name (magnifier, "default", FALSE);
00870         magnifier_transform_cursor (magnifier);
00871 }
00872 
00873 static gboolean 
00874 magnifier_reset_struts_at_idle (gpointer data)
00875 {
00876         if (data)
00877         {
00878                 Magnifier *magnifier = MAGNIFIER (data);
00879                 if (magnifier->priv &&
00880                     GTK_WIDGET_REALIZED (magnifier->priv->w) && 
00881                     gmag_gs_check_set_struts (magnifier)) {
00882                         return FALSE;
00883                 }
00884         }
00885         return TRUE;
00886 }
00887 
00888 static void
00889 magnifier_get_property (BonoboPropertyBag *bag,
00890                         BonoboArg *arg,
00891                         guint arg_id,
00892                         CORBA_Environment *ev,
00893                         gpointer user_data)
00894 {
00895         Magnifier *magnifier = user_data;
00896         int csize = 0;
00897 
00898         DBG (fprintf (stderr, "Get property: \t%s\n", mag_prop_names[arg_id]));
00899         
00900         switch (arg_id) {
00901         case MAGNIFIER_SOURCE_SIZE_PROP:
00902                 BONOBO_ARG_SET_GENERAL (arg, magnifier->source_bounds,
00903                                         TC_GNOME_Magnifier_RectBounds,
00904                                         GNOME_Magnifier_RectBounds, NULL);
00905                 break;
00906         case MAGNIFIER_TARGET_SIZE_PROP:
00907                 BONOBO_ARG_SET_GENERAL (arg, magnifier->target_bounds,
00908                                         TC_GNOME_Magnifier_RectBounds,
00909                                         GNOME_Magnifier_RectBounds, NULL);
00910 
00911                 break;
00912         case MAGNIFIER_CURSOR_SET_PROP:
00913                 BONOBO_ARG_SET_STRING (arg, magnifier->cursor_set);
00914                 break;
00915         case MAGNIFIER_CURSOR_SIZE_PROP:
00916                 BONOBO_ARG_SET_INT (arg, magnifier->cursor_size_x);
00917                 BONOBO_ARG_SET_INT (arg, magnifier->cursor_size_y);
00918                 break;
00919         case MAGNIFIER_CURSOR_ZOOM_PROP:
00920                 BONOBO_ARG_SET_FLOAT (arg, magnifier->cursor_scale_factor);
00921                 break;
00922         case MAGNIFIER_CURSOR_COLOR_PROP:
00923                 BONOBO_ARG_SET_GENERAL (arg, magnifier->cursor_color,
00924                                         TC_CORBA_unsigned_long,
00925                                         CORBA_unsigned_long, NULL);
00926                 break;
00927         case MAGNIFIER_CURSOR_HOTSPOT_PROP:
00928                 BONOBO_ARG_SET_GENERAL (arg, magnifier->cursor_hotspot,
00929                                         TC_GNOME_Magnifier_Point,
00930                                         GNOME_Magnifier_Point, NULL);
00931 
00932                 break;
00933         case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP:
00934                 if (magnifier->priv->cursor)
00935                         gdk_drawable_get_size (magnifier->priv->cursor,
00936                                                &csize, &csize);
00937                 BONOBO_ARG_SET_INT (arg, csize);
00938                 break;
00939         case MAGNIFIER_CROSSWIRE_SIZE_PROP:
00940                 BONOBO_ARG_SET_INT (arg, magnifier->crosswire_size);
00941                 break;
00942         case MAGNIFIER_CROSSWIRE_LENGTH_PROP:
00943                 BONOBO_ARG_SET_INT (arg, magnifier->crosswire_length);
00944                 break;
00945         case MAGNIFIER_CROSSWIRE_CLIP_PROP:
00946                 BONOBO_ARG_SET_BOOLEAN (arg, magnifier->crosswire_clip);
00947                 break;
00948         case MAGNIFIER_CROSSWIRE_COLOR_PROP:
00949                 BONOBO_ARG_SET_LONG (arg, magnifier->crosswire_color);
00950                 break;
00951         case MAGNIFIER_SOURCE_DISPLAY_PROP:
00952                 BONOBO_ARG_SET_STRING (arg, magnifier->source_display_name);
00953                 break;
00954         case MAGNIFIER_TARGET_DISPLAY_PROP:
00955                 BONOBO_ARG_SET_STRING (arg, magnifier->target_display_name);
00956                 break;
00957         default:
00958                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
00959         };
00960 }
00961 
00962 static void
00963 magnifier_set_property (BonoboPropertyBag *bag,
00964                         BonoboArg *arg,
00965                         guint arg_id,
00966                         CORBA_Environment *ev,
00967                         gpointer user_data)
00968 {
00969         Magnifier *magnifier = user_data;
00970         gchar *full_display_string;
00971 
00972         GNOME_Magnifier_RectBounds rect_bounds;
00973         rect_bounds.x1 = 0;
00974         rect_bounds.y1 = 0;
00975         rect_bounds.x2 = 4096;
00976         rect_bounds.y2 = 4096;
00977 
00978         switch (arg_id) {
00979         case MAGNIFIER_SOURCE_DISPLAY_PROP:
00980                 full_display_string = BONOBO_ARG_GET_STRING (arg);
00981                 if (can_open_display (full_display_string))
00982                 {
00983                     GSList *zoom_region_params = NULL;
00984                     magnifier->source_screen_num =
00985                         magnifier_parse_display_name (magnifier,
00986                                                       full_display_string,
00987                                                       NULL);
00988                     magnifier->source_display =
00989                         gdk_display_open (full_display_string);
00990                     magnifier->source_display_name = g_strdup (full_display_string);
00991                     zoom_region_params = magnifier_zoom_regions_save (magnifier);
00992                     magnifier->priv->root =
00993                         gdk_screen_get_root_window (
00994                             gdk_display_get_screen (
00995                                 magnifier->source_display,
00996                                 magnifier->source_screen_num));
00997 
00998                     /* remove the source_drawable, since in the new display the
00999                      * composite can be unavailable and the source_drawable is
01000                      * where the desktop screen is composed. If this is not
01001                      * freed it will be used even if the display doesn't use
01002                      * composite what will lead to wrong behavior and crashes.
01003                      * If composite is used in the new display this variable is
01004                      * re-created */
01005                     if (magnifier->priv->source_drawable) {
01006                             g_object_unref (magnifier->priv->source_drawable);
01007                             magnifier->priv->source_drawable = NULL;
01008                     }
01009 
01010                     /* attach listeners for DAMAGE, "dirty region", XFIXES
01011                      * cursor changes */
01012                     magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01013                     magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01014                     magnifier_adjust_source_size (magnifier);
01015                     magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01016                     magnifier_warp_cursor_to_screen (magnifier);
01017                     gmag_gs_check_set_struts (magnifier);
01018                     gmag_gs_reset_overlay_at_idle (magnifier);
01019                 }
01020                 DBG(fprintf (stderr, "Set source display: \t%s\n", full_display_string));
01021                 break;
01022         case MAGNIFIER_TARGET_DISPLAY_PROP:
01023                 full_display_string = BONOBO_ARG_GET_STRING (arg);
01024                 if (can_open_display (full_display_string))
01025                 {
01026                     magnifier->target_screen_num =
01027                         magnifier_parse_display_name (magnifier,
01028                                                       full_display_string,
01029                                                       NULL);
01030                     magnifier->target_display =
01031                         gdk_display_open (full_display_string);
01032                     magnifier->target_display_name = g_strdup (full_display_string);
01033                     if (GTK_IS_WINDOW (magnifier->priv->w)) 
01034                     {
01035 #ifdef REPARENT_GTK_WINDOW_WORKS
01036                         gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), 
01037                                                gdk_display_get_screen (
01038                                                    magnifier->target_display,
01039                                                    magnifier->target_screen_num));
01040 #else
01041                         GSList *zoom_region_params = NULL;
01042                         /* disconnect from the old window's destroy signal */
01043                         g_object_disconnect (magnifier->priv->w,
01044                                   "any_signal::realize", magnifier_realize, NULL,
01045                                   "any_signal::size_allocate", magnifier_size_allocate, NULL,
01046                                   "any_signal::destroy", magnifier_exit, NULL,
01047                                   NULL);
01048                         /* save the old zoom region state */
01049                         zoom_region_params = magnifier_zoom_regions_save (magnifier);
01050                         /* destroy the old window */
01051                         gtk_widget_destroy (magnifier->priv->w);
01052                         /* and re-initialize... */
01053                         magnifier_init_window (magnifier, gdk_display_get_screen (
01054                                                    magnifier->target_display,
01055                                                    magnifier->target_screen_num));
01056                         /* restore the zoom regions in their new host magnifier window */
01057                         magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01058 #endif
01059                     }
01060                     magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01061                     magnifier_init_cursor_set (magnifier, magnifier->cursor_set); /* needed to reset pixmaps */
01062                     if (magnifier->priv->overlay)
01063                             gdk_window_move (magnifier->priv->overlay,
01064                                              magnifier->target_bounds.x1,
01065                                              magnifier->target_bounds.y1);
01066                     else
01067                             gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01068                                              magnifier->target_bounds.x1,
01069                                              magnifier->target_bounds.y1);
01070                     
01071                     if ((magnifier->target_bounds.x2 - magnifier->target_bounds.x1 > 0) &&
01072                         (magnifier->target_bounds.y2 - magnifier->target_bounds.y1) > 0)
01073                     {
01074                             if (magnifier->priv->overlay)
01075                                     gdk_window_resize (
01076                                             magnifier->priv->overlay,
01077                                             magnifier->target_bounds.x2 -
01078                                             magnifier->target_bounds.x1,
01079                                             magnifier->target_bounds.y2 -
01080                                             magnifier->target_bounds.y1);
01081                         gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01082                                        magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01083                                        magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01084                     DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01085                              magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01086                     }
01087                     /* N. B. we don't reset the target bounds to the limits of the new display, because */
01088                     /* doing so would override the client-specified magnifier size */
01089                     /* magnifier_get_display_rect_bounds (magnifier, &magnifier->target_bounds, TRUE); */
01090                     gmag_gs_check_set_struts (magnifier);
01091                 }
01092                 DBG(fprintf (stderr, "Set target display: \t%s (screen %d)\n", 
01093                               full_display_string, magnifier->target_screen_num));
01094                 break;
01095         case MAGNIFIER_SOURCE_SIZE_PROP:
01096                 magnifier->source_bounds = BONOBO_ARG_GET_GENERAL (arg,
01097                                                                    TC_GNOME_Magnifier_RectBounds,
01098                                                                    GNOME_Magnifier_RectBounds,
01099                                                                    NULL);
01100                 DBG (fprintf (stderr, "Set source size: \t%d,%d to %d,%d\n", 
01101                               magnifier->source_bounds.x1, magnifier->source_bounds.y1, magnifier->source_bounds.x2, magnifier->source_bounds.y2));
01102                 break;
01103         case MAGNIFIER_TARGET_SIZE_PROP:
01104                 magnifier->target_bounds = BONOBO_ARG_GET_GENERAL (arg,
01105                                                                    TC_GNOME_Magnifier_RectBounds,
01106                                                                    GNOME_Magnifier_RectBounds,
01107                                 
01108                                    NULL);
01109                 if (magnifier->priv->overlay)
01110                         gdk_window_move_resize (magnifier->priv->overlay,
01111                                                 magnifier->target_bounds.x1,
01112                                                 magnifier->target_bounds.y1,
01113                                                 magnifier->target_bounds.x2 -
01114                                                 magnifier->target_bounds.x1,
01115                                                 magnifier->target_bounds.y2 -
01116                                                 magnifier->target_bounds.y1);
01117                 else
01118                         gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01119                                          magnifier->target_bounds.x1,
01120                                          magnifier->target_bounds.y1);
01121                 
01122                 gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01123                                    magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01124                                    magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01125                 gmag_gs_check_set_struts (magnifier);
01126                 DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n", 
01127                               magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01128                 if (!strcmp (magnifier->target_display_name, magnifier->source_display_name) && 
01129                     (magnifier->target_screen_num == magnifier->source_screen_num)) 
01130                     magnifier_adjust_source_size (magnifier);
01131                 break;
01132         case MAGNIFIER_CURSOR_SET_PROP:
01133                 magnifier_init_cursor_set (magnifier, g_strdup (BONOBO_ARG_GET_STRING (arg)));
01134                 DBG (fprintf (stderr, "Setting cursor set: \t%s\n", BONOBO_ARG_GET_STRING (arg)));
01135                 break;
01136         case MAGNIFIER_CURSOR_SIZE_PROP:
01137                 magnifier->cursor_size_x = BONOBO_ARG_GET_INT (arg);
01138                 magnifier->cursor_size_y = BONOBO_ARG_GET_INT (arg);
01139                 magnifier_transform_cursor (magnifier);
01140                 DBG (fprintf (stderr, "Setting cursor size: \t%d\n", magnifier->cursor_size_x));
01141                 break;
01142         case MAGNIFIER_CURSOR_ZOOM_PROP:
01143                 magnifier->cursor_scale_factor = BONOBO_ARG_GET_FLOAT (arg);
01144                 DBG (fprintf (stderr, "Setting cursor scale factor: \t%f\n", (float) magnifier->cursor_scale_factor));
01145                 magnifier_transform_cursor (magnifier);
01146                 break;
01147         case MAGNIFIER_CURSOR_COLOR_PROP:
01148                 magnifier->cursor_color = BONOBO_ARG_GET_GENERAL (arg,
01149                                                                   TC_CORBA_unsigned_long, 
01150                                                                   CORBA_unsigned_long, 
01151                                                                   NULL);
01152                 magnifier_transform_cursor (magnifier);
01153                 DBG (fprintf (stderr, "Setting cursor color: \t%u\n", (unsigned) magnifier->cursor_color));
01154                 break;
01155         case MAGNIFIER_CURSOR_HOTSPOT_PROP:
01156                 magnifier->cursor_hotspot = BONOBO_ARG_GET_GENERAL (arg,
01157                                                                     TC_GNOME_Magnifier_Point,
01158                                                                     GNOME_Magnifier_Point,
01159                                                                     NULL);
01160                 /* TODO: notify zoomers */
01161                 /* FIXME: don't call init_cursor, it overwrites this property! */
01162                 magnifier_transform_cursor (magnifier); 
01163                 break;
01164         case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP:
01165                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_ReadOnly);
01166                 break;
01167         case MAGNIFIER_CROSSWIRE_SIZE_PROP:
01168                 magnifier->crosswire_size = BONOBO_ARG_GET_INT (arg);
01169                 DBG (fprintf (stderr, "Setting crosswire size: \t%d\n", magnifier->crosswire_size));
01170                 magnifier_zoom_regions_update_pointer (magnifier);
01171                 break;
01172         case MAGNIFIER_CROSSWIRE_LENGTH_PROP:
01173                 magnifier->crosswire_length = BONOBO_ARG_GET_INT (arg);
01174                 DBG (fprintf (stderr, "Setting crosswire length: \t%d\n", magnifier->crosswire_length));
01175                 /* FIXME: The call below forces the repaint of all the screen,
01176                  * but I can't figure a better solution right now to the case
01177                  * where the crosswire lenght decrease */
01178                 magnifier_zoom_regions_mark_dirty (magnifier, rect_bounds);
01179                 break;
01180         case MAGNIFIER_CROSSWIRE_CLIP_PROP:
01181                 magnifier->crosswire_clip = BONOBO_ARG_GET_BOOLEAN (arg);
01182                 DBG (fprintf (stderr, "Setting crosswire clip: \t%s\n", magnifier->crosswire_clip ? "true" : "false"));
01183                 magnifier_zoom_regions_update_pointer (magnifier);
01184                 break;
01185         case MAGNIFIER_CROSSWIRE_COLOR_PROP:
01186                 magnifier->crosswire_color = BONOBO_ARG_GET_LONG (arg);
01187                 DBG (fprintf (stderr, "Setting crosswire size: \t%ld\n", (long) magnifier->crosswire_color));
01188                 break;
01189         default:
01190                 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
01191                 break;
01192         };
01193 }
01194 
01195 static void
01196 magnifier_do_dispose (Magnifier *magnifier)
01197 {
01198         /* FIXME: this is dead ropey code structuring */
01199         bonobo_activation_active_server_unregister (
01200                 MAGNIFIER_OAFIID, BONOBO_OBJREF (magnifier));
01201 
01202         if (magnifier->zoom_regions)
01203                 g_list_free (magnifier->zoom_regions);
01204         magnifier->zoom_regions = NULL;
01205         
01206         bonobo_main_quit ();
01207 }
01208 
01209 static void
01210 magnifier_gobject_dispose (GObject *object)
01211 {
01212         magnifier_do_dispose (MAGNIFIER (object));
01213 
01214         BONOBO_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
01215 }
01216 
01217 static
01218 CORBA_boolean
01219 impl_magnifier_support_colorblind_filters (Magnifier *magnifier)
01220 {
01221 #ifdef HAVE_COLORBLIND
01222         return CORBA_TRUE;
01223 #else
01224         return CORBA_FALSE;
01225 #endif
01226 }
01227 
01228 static void
01229 impl_magnifier_hide_cursor (PortableServer_Servant servant,
01230                         CORBA_Environment *ev)
01231 {
01232         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01233 
01234         gmag_gs_hide_cursor (magnifier);
01235 }
01236 
01237 static void
01238 impl_magnifier_show_cursor (PortableServer_Servant servant,
01239                             CORBA_Environment *ev)
01240 {
01241         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01242 
01243         gmag_gs_show_cursor (magnifier);
01244 }
01245 
01246 static
01247 CORBA_boolean
01248 impl_magnifier_full_screen_capable (PortableServer_Servant servant,
01249                                     CORBA_Environment * ev)
01250 {
01251         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01252 
01253         if ((strcmp (magnifier->source_display_name,
01254                      magnifier->target_display_name) != 0) ||
01255                 gmag_gs_use_compositor (magnifier))
01256                 return CORBA_TRUE;
01257 
01258         return CORBA_FALSE;
01259 }
01260 
01261 static void
01262 impl_magnifier_set_source_display (PortableServer_Servant servant,
01263                                    const CORBA_char *display,
01264                                    CORBA_Environment *ev)
01265 {
01266         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01267         BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01268         gchar *full_display_string;
01269 
01270         full_display_string = g_strdup (display);
01271         if (strcmp (full_display_string, "") == 0)
01272                 full_display_string = (gchar *) g_getenv ("DISPLAY");
01273 
01274         BONOBO_ARG_SET_STRING (arg, full_display_string);
01275         
01276         DBG (fprintf (stderr, "Set source display: \t%s\n",
01277                       full_display_string));
01278 
01279         if (strcmp (full_display_string, magnifier->source_display_name)) {
01280             magnifier_set_property (magnifier->property_bag,
01281                                     arg,
01282                                     MAGNIFIER_SOURCE_DISPLAY_PROP,
01283                                     ev,
01284                                     magnifier);
01285         }
01286         else
01287         {
01288             DBG (fprintf (stderr, "Attempt to set source to same value as previous: %s\n",
01289                           full_display_string));
01290         }
01291         bonobo_arg_release (arg);
01292 }
01293 
01294 static void
01295 impl_magnifier_set_target_display (PortableServer_Servant servant,
01296                                    const CORBA_char *display,
01297                                    CORBA_Environment *ev)
01298 {
01299         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01300         BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01301         gchar *full_display_string;
01302 
01303         full_display_string = g_strdup (display);
01304         if (strcmp (full_display_string, "") == 0)
01305                 full_display_string = (gchar *) g_getenv ("DISPLAY");
01306 
01307         BONOBO_ARG_SET_STRING (arg, full_display_string);
01308         
01309         DBG (fprintf (stderr, "Set target display: \t%s\n",
01310                       full_display_string));
01311 
01312         if (strcmp (full_display_string, magnifier->target_display_name)) 
01313         {
01314             magnifier_set_property (magnifier->property_bag,
01315                                     arg,
01316                                     MAGNIFIER_TARGET_DISPLAY_PROP,
01317                                     ev,
01318                                     magnifier);
01319         }
01320         else
01321         {
01322             DBG (fprintf (stderr, "Attempt to set target to same value as previous: %s\n",
01323                           full_display_string));
01324         }
01325         bonobo_arg_release (arg);
01326 }
01327 
01328 static 
01329 CORBA_string
01330 impl_magnifier_get_source_display (PortableServer_Servant servant,
01331                                    CORBA_Environment *ev)
01332 {
01333         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01334         DBG (fprintf (stderr, "Get source display: \t%s\n", magnifier->source_display_name));
01335 
01336         return CORBA_string_dup (magnifier->source_display_name ? magnifier->source_display_name : "");
01337 }
01338 
01339 static 
01340 CORBA_string
01341 impl_magnifier_get_target_display (PortableServer_Servant servant,
01342                                    CORBA_Environment *ev)
01343 {
01344         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01345         DBG (fprintf (stderr, "Get target display: \t%s\n", 
01346                       magnifier->target_display_name));
01347 
01348         return CORBA_string_dup (magnifier->target_display_name ? magnifier->target_display_name : "");
01349 }
01350 
01351 static GNOME_Magnifier_ZoomRegion
01352 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
01353                                    const CORBA_float zx,
01354                                    const CORBA_float zy,
01355                                    const GNOME_Magnifier_RectBounds *roi,
01356                                    const GNOME_Magnifier_RectBounds *viewport,
01357                                    CORBA_Environment *ev)
01358 {
01359         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01360         CORBA_any viewport_any;
01361         ZoomRegion *zoom_region = zoom_region_new ();
01362         Bonobo_PropertyBag properties;
01363         GNOME_Magnifier_ZoomRegion retval;
01364 
01365         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));
01366 
01367         /* FIXME:
01368          * shouldn't do this here, since it causes the region to get
01369          * mapped onto the parent, if if it's not explicitly added!
01370          */
01371         DBG(g_message ("creating zoom region with parent %p", magnifier));
01372         zoom_region->priv->parent = magnifier;
01373 
01374         retval = BONOBO_OBJREF (zoom_region);
01375 
01376         /* XXX: should check ev after each call, below */
01377         CORBA_exception_init (ev);
01378         GNOME_Magnifier_ZoomRegion_setMagFactor (retval, zx, zy, ev);
01379 
01380         if (ev->_major != CORBA_NO_EXCEPTION)
01381                 fprintf (stderr, "EXCEPTION setMagFactor\n");
01382 
01383         CORBA_exception_init (ev);
01384         properties = GNOME_Magnifier_ZoomRegion_getProperties (retval, ev);
01385         if (ev->_major != CORBA_NO_EXCEPTION)
01386                 fprintf (stderr, "EXCEPTION getProperties\n");
01387 
01388         viewport_any._type = TC_GNOME_Magnifier_RectBounds;
01389         viewport_any._value = (gpointer) viewport;
01390         Bonobo_PropertyBag_setValue (
01391                 properties, "viewport", &viewport_any, ev);
01392 
01393         GNOME_Magnifier_ZoomRegion_setROI (retval, roi, ev);
01394         if (ev->_major != CORBA_NO_EXCEPTION)
01395                 fprintf (stderr, "EXCEPTION setROI\n");
01396 
01397         CORBA_exception_init (ev);
01398 
01399         gtk_widget_set_size_request (magnifier->priv->canvas,
01400                            viewport->x2 - viewport->x1,
01401                            viewport->y2 - viewport->y1);
01402         gtk_widget_show (magnifier->priv->canvas);
01403         gtk_widget_show (magnifier->priv->w);
01404 
01405         bonobo_object_release_unref (properties, ev);
01406         
01407         return CORBA_Object_duplicate (retval, ev);
01408 }
01409 
01410 static
01411 CORBA_boolean
01412 impl_magnifier_add_zoom_region (PortableServer_Servant servant,
01413                                 const GNOME_Magnifier_ZoomRegion region,
01414                                 CORBA_Environment * ev)
01415 {
01416         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01417 
01418         if (!magnifier->source_initialized) 
01419         {
01420                 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01421         }
01422 
01423         /* FIXME: this needs proper lifecycle management */
01424         magnifier->zoom_regions = g_list_append (magnifier->zoom_regions, region);
01425         gmag_gs_check_set_struts (magnifier);
01426 
01427         return CORBA_TRUE;
01428 }
01429 
01430 static Bonobo_PropertyBag
01431 impl_magnifier_get_properties (PortableServer_Servant servant,
01432                                CORBA_Environment *ev)
01433 {
01434         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01435         return bonobo_object_dup_ref (
01436                 BONOBO_OBJREF (magnifier->property_bag), ev);
01437 }
01438 
01439 GNOME_Magnifier_ZoomRegionList *
01440 impl_magnifier_get_zoom_regions (PortableServer_Servant servant,
01441                                  CORBA_Environment * ev)
01442 {
01443         Magnifier *magnifier =
01444                 MAGNIFIER (bonobo_object_from_servant (servant));
01445 
01446         GNOME_Magnifier_ZoomRegionList *list;
01447         CORBA_Object objref;
01448         int i, len;
01449 
01450         len = g_list_length (magnifier->zoom_regions);
01451         list = GNOME_Magnifier_ZoomRegionList__alloc ();
01452         list->_length = len;
01453         list->_buffer =
01454                 GNOME_Magnifier_ZoomRegionList_allocbuf (list->_length);
01455         for (i = 0; i < len; ++i) {
01456                 objref = g_list_nth_data (magnifier->zoom_regions, i);
01457                 list->_buffer [i] =
01458                         CORBA_Object_duplicate (objref, ev);
01459         }
01460         CORBA_sequence_set_release (list, CORBA_TRUE);
01461 
01462         DBG (fprintf (stderr, "Get zoom regions: \t%d\n", len));
01463         
01464         return list; 
01465 }
01466 
01467 static void
01468 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant servant,
01469                                        CORBA_Environment * ev)
01470 {
01471         Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01472         fprintf (stderr, "Clear all zoom regions.\n");
01473 
01474         g_list_foreach (magnifier->zoom_regions,
01475                         magnifier_unref_zoom_region, magnifier);
01476         g_list_free (magnifier->zoom_regions);
01477         magnifier->zoom_regions = NULL;
01478 }
01479 
01480 static void
01481 impl_magnifier_dispose (PortableServer_Servant servant,
01482                         CORBA_Environment *ev)
01483 {
01484         magnifier_do_dispose (
01485                 MAGNIFIER (bonobo_object_from_servant (servant)));
01486 }
01487 
01488 static void
01489 magnifier_class_init (MagnifierClass *klass)
01490 {
01491         GObjectClass * object_class = (GObjectClass *) klass;
01492         POA_GNOME_Magnifier_Magnifier__epv *epv = &klass->epv;
01493         parent_class = g_type_class_peek (BONOBO_TYPE_OBJECT); /* needed by BONOBO_CALL_PARENT! */
01494 
01495         object_class->dispose = magnifier_gobject_dispose;
01496 
01497         epv->fullScreenCapable = impl_magnifier_full_screen_capable;
01498         epv->hideCursor = impl_magnifier_hide_cursor;
01499         epv->showCursor = impl_magnifier_show_cursor;
01500         epv->supportColorblindFilters =
01501                 impl_magnifier_support_colorblind_filters;
01502         epv->_set_SourceDisplay = impl_magnifier_set_source_display;
01503         epv->_set_TargetDisplay = impl_magnifier_set_target_display;
01504         epv->_get_SourceDisplay = impl_magnifier_get_source_display;
01505         epv->_get_TargetDisplay = impl_magnifier_get_target_display;
01506         epv->getProperties = impl_magnifier_get_properties;
01507         epv->getZoomRegions = impl_magnifier_get_zoom_regions;
01508         epv->createZoomRegion = impl_magnifier_create_zoom_region;
01509         epv->addZoomRegion = impl_magnifier_add_zoom_region;
01510         epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
01511         epv->dispose = impl_magnifier_dispose;
01512 }
01513 
01514 static void
01515 magnifier_properties_init (Magnifier *magnifier)
01516 {
01517         BonoboArg *def;
01518         GNOME_Magnifier_RectBounds rect_bounds;
01519         gchar *display_env;
01520 
01521         magnifier->property_bag =
01522                 bonobo_property_bag_new_closure (
01523                         g_cclosure_new_object (
01524                                 G_CALLBACK (magnifier_get_property),
01525                                 G_OBJECT (magnifier)),
01526                         g_cclosure_new_object (
01527                                 G_CALLBACK (magnifier_set_property),
01528                                 G_OBJECT (magnifier)));
01529 
01530         /* Aggregate so magnifier implements Bonobo_PropertyBag */
01531         bonobo_object_add_interface (BONOBO_OBJECT (magnifier),
01532                                      BONOBO_OBJECT (magnifier->property_bag));
01533 
01534         def = bonobo_arg_new (BONOBO_ARG_STRING);
01535         display_env = getenv ("DISPLAY");
01536         BONOBO_ARG_SET_STRING (def, display_env);
01537 
01538         bonobo_property_bag_add (magnifier->property_bag,
01539                                  "source-display-screen",
01540                                  MAGNIFIER_SOURCE_DISPLAY_PROP,
01541                                  BONOBO_ARG_STRING,
01542                                  def,
01543                                  "source display screen",
01544                                  Bonobo_PROPERTY_WRITEABLE);
01545 
01546         bonobo_property_bag_add (magnifier->property_bag,
01547                                  "target-display-screen",
01548                                  MAGNIFIER_TARGET_DISPLAY_PROP,
01549                                  BONOBO_ARG_STRING,
01550                                  def,
01551                                  "target display screen",
01552                                  Bonobo_PROPERTY_WRITEABLE);
01553 
01554         bonobo_arg_release (def);
01555 
01556         magnifier_init_display (magnifier, display_env, TRUE);
01557         magnifier_init_display (magnifier, display_env, FALSE);
01558 
01559         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
01560         def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01561         
01562         bonobo_property_bag_add (magnifier->property_bag,
01563                                  "source-display-bounds",
01564                                  MAGNIFIER_SOURCE_SIZE_PROP,
01565                                  TC_GNOME_Magnifier_RectBounds,
01566                                  def,
01567                                  "source display bounds/size",
01568                                  Bonobo_PROPERTY_READABLE |
01569                                  Bonobo_PROPERTY_WRITEABLE);
01570         bonobo_arg_release (def);
01571         
01572         magnifier_get_display_rect_bounds (magnifier, &rect_bounds, TRUE);
01573         def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01574 
01575         bonobo_property_bag_add (magnifier->property_bag,
01576                                  "target-display-bounds",
01577                                  MAGNIFIER_TARGET_SIZE_PROP,
01578                                  TC_GNOME_Magnifier_RectBounds,
01579                                  def,
01580                                  "target display bounds/size",
01581                                  Bonobo_PROPERTY_READABLE |
01582                                  Bonobo_PROPERTY_WRITEABLE);
01583         bonobo_arg_release (def);
01584 
01585         bonobo_property_bag_add (magnifier->property_bag,
01586                                  "cursor-set",
01587                                  MAGNIFIER_CURSOR_SET_PROP,
01588                                  BONOBO_ARG_STRING,
01589                                  NULL,
01590                                  "name of cursor set",
01591                                  Bonobo_PROPERTY_READABLE |
01592                                  Bonobo_PROPERTY_WRITEABLE);
01593 
01594         def = bonobo_arg_new (BONOBO_ARG_INT);
01595         BONOBO_ARG_SET_INT (def, 64);
01596         
01597         bonobo_property_bag_add (magnifier->property_bag,
01598                                  "cursor-size",
01599                                  MAGNIFIER_CURSOR_SIZE_PROP,
01600                                  BONOBO_ARG_INT,
01601                                  def,
01602                                  "cursor size, in pixels",
01603                                  Bonobo_PROPERTY_READABLE |
01604                                  Bonobo_PROPERTY_WRITEABLE);
01605         bonobo_arg_release (def);
01606         
01607         bonobo_property_bag_add (magnifier->property_bag,
01608                                  "cursor-scale-factor",
01609                                  MAGNIFIER_CURSOR_ZOOM_PROP,
01610                                  BONOBO_ARG_FLOAT,
01611                                  NULL,
01612                                  "scale factor for cursors (overrides size)",
01613                                  Bonobo_PROPERTY_READABLE |
01614                                  Bonobo_PROPERTY_WRITEABLE);
01615         
01616         bonobo_property_bag_add (magnifier->property_bag,
01617                                  "cursor-color",
01618                                  MAGNIFIER_CURSOR_COLOR_PROP,
01619                                  TC_CORBA_unsigned_long,
01620                                  NULL,
01621                                  "foreground color for 1-bit cursors, as ARGB",
01622                                  Bonobo_PROPERTY_READABLE |
01623                                  Bonobo_PROPERTY_WRITEABLE);    
01624 
01625         bonobo_property_bag_add (magnifier->property_bag,
01626                                  "cursor-hotspot",
01627                                  MAGNIFIER_CURSOR_HOTSPOT_PROP,
01628                                  TC_GNOME_Magnifier_Point,
01629                                  NULL,
01630                                  "hotspot relative to cursor's upper-left-corner, at default resolition",
01631                                  Bonobo_PROPERTY_READABLE |
01632                                  Bonobo_PROPERTY_WRITEABLE);
01633         
01634         bonobo_property_bag_add (magnifier->property_bag,
01635                                  "cursor-default-size",
01636                                  MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
01637                                  BONOBO_ARG_INT,
01638                                  NULL,
01639                                  "default size of current cursor set",
01640                                  Bonobo_PROPERTY_READABLE);
01641 
01642         bonobo_property_bag_add (magnifier->property_bag,
01643                                  "crosswire-size",
01644                                  MAGNIFIER_CROSSWIRE_SIZE_PROP,
01645                                  BONOBO_ARG_INT,
01646                                  NULL,
01647                                  "thickness of crosswire cursor, in target pixels",
01648                                  Bonobo_PROPERTY_READABLE |
01649                                  Bonobo_PROPERTY_WRITEABLE);
01650 
01651         bonobo_property_bag_add (magnifier->property_bag,
01652                                  "crosswire-length",
01653                                  MAGNIFIER_CROSSWIRE_LENGTH_PROP,
01654                                  BONOBO_ARG_INT,
01655                                  NULL,
01656                                  "length of crosswire cursor, in target pixels",
01657                                  Bonobo_PROPERTY_READABLE |
01658                                  Bonobo_PROPERTY_WRITEABLE);
01659         
01660         bonobo_property_bag_add (magnifier->property_bag,
01661                                  "crosswire-color",
01662                                  MAGNIFIER_CROSSWIRE_COLOR_PROP,
01663                                  BONOBO_ARG_LONG,
01664                                  NULL,
01665                                  "color of crosswire, as A-RGB; note that alpha is required. (use 0 for XOR wire)",
01666                                  Bonobo_PROPERTY_READABLE |
01667                                  Bonobo_PROPERTY_WRITEABLE);
01668 
01669         bonobo_property_bag_add (magnifier->property_bag,
01670                                  "crosswire-clip",
01671                                  MAGNIFIER_CROSSWIRE_CLIP_PROP,
01672                                  BONOBO_ARG_BOOLEAN,
01673                                  NULL,
01674                                  "whether to inset the cursor over the crosswire or not",
01675                                  Bonobo_PROPERTY_READABLE |
01676                                  Bonobo_PROPERTY_WRITEABLE);
01677 }
01678 
01679 static void
01680 magnifier_init_window (Magnifier *magnifier, GdkScreen *screen)
01681 {
01682         GtkWindowType mag_win_type = GTK_WINDOW_TOPLEVEL;
01683         if (_is_override_redirect || gmag_gs_use_compositor (magnifier))
01684                 mag_win_type = GTK_WINDOW_POPUP;
01685 
01686         magnifier->priv->w =
01687                 g_object_connect (gtk_widget_new (gtk_window_get_type (),
01688                                                   "user_data", NULL,
01689                                                   "can_focus", FALSE,
01690                                                   "type", mag_win_type,  
01691                                                   "title", "magnifier",
01692                                                   "allow_grow", TRUE,
01693                                                   "allow_shrink", TRUE,
01694                                                   "border_width", 0,
01695                                                   NULL),
01696                                   "signal::realize", magnifier_realize, NULL,
01697                                   "signal::size_allocate", magnifier_size_allocate, NULL,
01698                                   "signal::destroy", magnifier_exit, NULL,
01699                                   NULL);
01700         gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), screen);
01701         magnifier->priv->canvas = gtk_fixed_new ();
01702         gtk_container_add (GTK_CONTAINER (magnifier->priv->w),
01703                            magnifier->priv->canvas);
01704         magnifier->priv->root = NULL;
01705 }
01706 
01707 static void
01708 magnifier_init (Magnifier *magnifier)
01709 {
01710         magnifier->priv = g_new0 (MagnifierPrivate, 1);
01711         magnifier_properties_init (magnifier);
01712         magnifier->zoom_regions = NULL;
01713         magnifier->source_screen_num = 0;
01714         magnifier->target_screen_num = 0;
01715         magnifier->source_display_name = g_strdup (":0.0");
01716         magnifier->target_display_name = g_strdup (":0.0");
01717         magnifier->cursor_size_x = 0;
01718         magnifier->cursor_size_y = 0;
01719         magnifier->cursor_scale_factor = 1.0F;
01720         magnifier->cursor_color = 0xFF000000;
01721         magnifier->crosswire_size = 1;
01722         magnifier->crosswire_length = 0;
01723         magnifier->crosswire_color = 0;
01724         magnifier->crosswire_clip = FALSE;
01725         magnifier->cursor_hotspot.x = 0;
01726         magnifier->cursor_hotspot.y = 0;
01727         magnifier->target_bounds.x1 = 0;
01728         magnifier->target_bounds.y1 = 0;
01729         magnifier->target_bounds.x2 = 0;
01730         magnifier->target_bounds.y2 = 0;
01731         magnifier->priv->cursor = NULL;
01732         magnifier->priv->w = NULL;
01733         magnifier->priv->use_source_cursor = TRUE;
01734         magnifier->priv->cursorlist = NULL;
01735         magnifier->priv->source_drawable = NULL;
01736         magnifier->priv->overlay = NULL;
01737         magnifier_init_window (magnifier, 
01738                                gdk_display_get_screen (magnifier->target_display, 
01739                                                        magnifier->target_screen_num));
01740         magnifier_init_cursor_set (magnifier, "default");
01741 
01742         mag_timing.process = g_timer_new ();
01743         mag_timing.frame = g_timer_new ();
01744         mag_timing.scale = g_timer_new ();
01745         mag_timing.idle = g_timer_new ();
01746 #ifdef DEBUG_CLIENT_CALLS
01747         client_debug = (g_getenv ("MAG_CLIENT_DEBUG") != NULL);
01748 #endif
01749 }
01750 
01751 GdkDrawable *
01752 magnifier_get_cursor (Magnifier *magnifier)
01753 {
01754         if (magnifier->priv->cursor == NULL) {
01755             if ((fixes_event_base == 0) && 
01756                 strcmp (magnifier->cursor_set, "none")) 
01757             {
01758                 GdkPixbuf *pixbuf;
01759                 gchar *default_cursor_filename = 
01760                     g_strconcat (CURSORSDIR, "/", "default-cursor.xpm", NULL);
01761                 pixbuf = gdk_pixbuf_new_from_file (default_cursor_filename, NULL);
01762                 if (pixbuf) 
01763                 {
01764                     magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
01765                     g_object_unref (pixbuf);
01766                     magnifier_transform_cursor (magnifier);
01767                 }
01768                 g_free (default_cursor_filename);
01769             } else {
01770                 GdkPixbuf *cursor_pixbuf = gmag_cursor_get_source_pixbuf (
01771                         magnifier);
01772                 magnifier_set_cursor_from_pixbuf (magnifier, cursor_pixbuf);
01773                 if (cursor_pixbuf) g_object_unref (cursor_pixbuf);
01774                 magnifier_transform_cursor (magnifier);
01775             }
01776         }
01777         return magnifier->priv->cursor;
01778 }
01779 
01780 Magnifier *
01781 magnifier_new (gboolean override_redirect)
01782 {
01783         Magnifier *mag;
01784         MagLoginHelper *helper;
01785         int ret;
01786 
01787         _is_override_redirect = override_redirect;
01788 
01789         mag = g_object_new (magnifier_get_type(), NULL);
01790 
01791         _this_magnifier = mag; /* FIXME what about multiple instances? */
01792 
01793         helper = g_object_new (mag_login_helper_get_type (), NULL);
01794         mag_login_helper_set_magnifier (helper, mag);
01795 
01796         bonobo_object_add_interface (bonobo_object (mag), 
01797                                      BONOBO_OBJECT (helper));
01798         
01799         ret = bonobo_activation_active_server_register (
01800                 MAGNIFIER_OAFIID, BONOBO_OBJREF (mag));
01801         if (ret != Bonobo_ACTIVATION_REG_SUCCESS) {
01802             if ( ret == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE)
01803             {
01804                 printf("An instance of magnifier is already active. Exiting Program.\n");
01805                 exit(0);
01806             } else
01807                 g_error ("Error registering magnifier server.\n");
01808         }
01809 
01810         g_timeout_add (500, magnifier_reset_struts_at_idle, mag);
01811         g_timeout_add (500, gmag_gs_reset_overlay_at_idle, mag);
01812 
01813         return mag;
01814 }
01815 
01816 BONOBO_TYPE_FUNC_FULL (Magnifier, 
01817                        GNOME_Magnifier_Magnifier,
01818                        BONOBO_TYPE_OBJECT,
01819                        magnifier)
01820 

Generated on Sun Aug 9 20:57:28 2009 for gnome-mag by  doxygen 1.5.4