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