# magnifier.c

Go to the documentation of this file.

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