# 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