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

Generated on Fri Mar 9 14:08:10 2007 for gnome-mag by  doxygen 1.4.7