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
00948
00949
00950
00951
00952
00953
00954 if (magnifier->priv->source_drawable) {
00955 g_object_unref (magnifier->priv->source_drawable);
00956 magnifier->priv->source_drawable = NULL;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965 g_unsetenv ("MAGNIFIER_IGNORE_COMPOSITE");
00966
00967
00968
00969 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
00970 magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
00971 magnifier_zoom_regions_restore (magnifier, zoom_region_params);
00972 magnifier_warp_cursor_to_screen (magnifier);
00973 gmag_gs_check_set_struts (magnifier);
00974 }
00975 DBG(fprintf (stderr, "Set source display: \t%s\n", full_display_string));
00976 break;
00977 case MAGNIFIER_TARGET_DISPLAY_PROP:
00978 full_display_string = BONOBO_ARG_GET_STRING (arg);
00979 if (can_open_display (full_display_string))
00980 {
00981 magnifier->target_screen_num =
00982 magnifier_parse_display_name (magnifier,
00983 full_display_string,
00984 NULL);
00985 magnifier->target_display =
00986 gdk_display_open (full_display_string);
00987 magnifier->target_display_name = g_strdup (full_display_string);
00988 if (GTK_IS_WINDOW (magnifier->priv->w))
00989 {
00990 #ifdef REPARENT_GTK_WINDOW_WORKS
00991 gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w),
00992 gdk_display_get_screen (
00993 magnifier->target_display,
00994 magnifier->target_screen_num));
00995 #else
00996 GSList *zoom_region_params = NULL;
00997
00998 g_object_disconnect (magnifier->priv->w,
00999 "any_signal::realize", magnifier_realize, NULL,
01000 "any_signal::size_allocate", magnifier_size_allocate, NULL,
01001 "any_signal::destroy", magnifier_exit, NULL,
01002 NULL);
01003
01004 zoom_region_params = magnifier_zoom_regions_save (magnifier);
01005
01006 gtk_widget_destroy (magnifier->priv->w);
01007
01008 magnifier_init_window (magnifier, gdk_display_get_screen (
01009 magnifier->target_display,
01010 magnifier->target_screen_num));
01011
01012 magnifier_zoom_regions_restore (magnifier, zoom_region_params);
01013 #endif
01014 }
01015 magnifier_get_display_rect_bounds (magnifier, &magnifier->source_bounds, FALSE);
01016 magnifier_init_cursor_set (magnifier, magnifier->cursor_set);
01017 if (magnifier->priv->overlay)
01018 gdk_window_move (magnifier->priv->overlay,
01019 magnifier->target_bounds.x1,
01020 magnifier->target_bounds.y1);
01021 else
01022 gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01023 magnifier->target_bounds.x1,
01024 magnifier->target_bounds.y1);
01025
01026 if ((magnifier->target_bounds.x2 - magnifier->target_bounds.x1 > 0) &&
01027 (magnifier->target_bounds.y2 - magnifier->target_bounds.y1) > 0)
01028 {
01029 if (magnifier->priv->overlay)
01030 gdk_window_resize (
01031 magnifier->priv->overlay,
01032 magnifier->target_bounds.x2 -
01033 magnifier->target_bounds.x1,
01034 magnifier->target_bounds.y2 -
01035 magnifier->target_bounds.y1);
01036 gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01037 magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01038 magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01039 DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n",
01040 magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01041 }
01042
01043
01044
01045 gmag_gs_check_set_struts (magnifier);
01046 }
01047 DBG(fprintf (stderr, "Set target display: \t%s (screen %d)\n",
01048 full_display_string, magnifier->target_screen_num));
01049 break;
01050 case MAGNIFIER_SOURCE_SIZE_PROP:
01051 magnifier->source_bounds = BONOBO_ARG_GET_GENERAL (arg,
01052 TC_GNOME_Magnifier_RectBounds,
01053 GNOME_Magnifier_RectBounds,
01054 NULL);
01055 DBG (fprintf (stderr, "Set source size: \t%d,%d to %d,%d\n",
01056 magnifier->source_bounds.x1, magnifier->source_bounds.y1, magnifier->source_bounds.x2, magnifier->source_bounds.y2));
01057 break;
01058 case MAGNIFIER_TARGET_SIZE_PROP:
01059 magnifier->target_bounds = BONOBO_ARG_GET_GENERAL (arg,
01060 TC_GNOME_Magnifier_RectBounds,
01061 GNOME_Magnifier_RectBounds,
01062
01063 NULL);
01064 if (magnifier->priv->overlay)
01065 gdk_window_move_resize (magnifier->priv->overlay,
01066 magnifier->target_bounds.x1,
01067 magnifier->target_bounds.y1,
01068 magnifier->target_bounds.x2 -
01069 magnifier->target_bounds.x1,
01070 magnifier->target_bounds.y2 -
01071 magnifier->target_bounds.y1);
01072 else
01073 gtk_window_move (GTK_WINDOW (magnifier->priv->w),
01074 magnifier->target_bounds.x1,
01075 magnifier->target_bounds.y1);
01076
01077 gtk_window_resize (GTK_WINDOW (magnifier->priv->w),
01078 magnifier->target_bounds.x2 - magnifier->target_bounds.x1,
01079 magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
01080 gmag_gs_check_set_struts (magnifier);
01081 DBG(fprintf (stderr, "Set target size: \t%d,%d to %d,%d\n",
01082 magnifier->target_bounds.x1, magnifier->target_bounds.y1, magnifier->target_bounds.x2, magnifier->target_bounds.y2));
01083 if (!strcmp (magnifier->target_display_name, magnifier->source_display_name) &&
01084 (magnifier->target_screen_num == magnifier->source_screen_num))
01085 magnifier_adjust_source_size (magnifier);
01086 break;
01087 case MAGNIFIER_CURSOR_SET_PROP:
01088 magnifier_init_cursor_set (magnifier, g_strdup (BONOBO_ARG_GET_STRING (arg)));
01089 DBG (fprintf (stderr, "Setting cursor set: \t%s\n", BONOBO_ARG_GET_STRING (arg)));
01090 break;
01091 case MAGNIFIER_CURSOR_SIZE_PROP:
01092 magnifier->cursor_size_x = BONOBO_ARG_GET_INT (arg);
01093 magnifier->cursor_size_y = BONOBO_ARG_GET_INT (arg);
01094 magnifier_transform_cursor (magnifier);
01095 DBG (fprintf (stderr, "Setting cursor size: \t%d\n", magnifier->cursor_size_x));
01096 break;
01097 case MAGNIFIER_CURSOR_ZOOM_PROP:
01098 magnifier->cursor_scale_factor = BONOBO_ARG_GET_FLOAT (arg);
01099 DBG (fprintf (stderr, "Setting cursor scale factor: \t%f\n", (float) magnifier->cursor_scale_factor));
01100 magnifier_transform_cursor (magnifier);
01101 break;
01102 case MAGNIFIER_CURSOR_COLOR_PROP:
01103 magnifier->cursor_color = BONOBO_ARG_GET_GENERAL (arg,
01104 TC_CORBA_unsigned_long,
01105 CORBA_unsigned_long,
01106 NULL);
01107 magnifier_transform_cursor (magnifier);
01108 DBG (fprintf (stderr, "Setting cursor color: \t%u\n", (unsigned) magnifier->cursor_color));
01109 break;
01110 case MAGNIFIER_CURSOR_HOTSPOT_PROP:
01111 magnifier->cursor_hotspot = BONOBO_ARG_GET_GENERAL (arg,
01112 TC_GNOME_Magnifier_Point,
01113 GNOME_Magnifier_Point,
01114 NULL);
01115
01116
01117 magnifier_transform_cursor (magnifier);
01118 break;
01119 case MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP:
01120 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_ReadOnly);
01121 break;
01122 case MAGNIFIER_CROSSWIRE_SIZE_PROP:
01123 magnifier->crosswire_size = BONOBO_ARG_GET_INT (arg);
01124 DBG (fprintf (stderr, "Setting crosswire size: \t%d\n", magnifier->crosswire_size));
01125
01126 break;
01127 case MAGNIFIER_CROSSWIRE_CLIP_PROP:
01128 magnifier->crosswire_clip = BONOBO_ARG_GET_BOOLEAN (arg);
01129 DBG (fprintf (stderr, "Setting crosswire clip: \t%s\n", magnifier->crosswire_clip ? "true" : "false"));
01130 break;
01131 case MAGNIFIER_CROSSWIRE_COLOR_PROP:
01132 magnifier->crosswire_color = BONOBO_ARG_GET_LONG (arg);
01133 DBG (fprintf (stderr, "Setting crosswire size: \t%ld\n", (long) magnifier->crosswire_color));
01134 break;
01135 default:
01136 bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
01137 break;
01138 };
01139 }
01140
01141 static void
01142 magnifier_do_dispose (Magnifier *magnifier)
01143 {
01144
01145 bonobo_activation_active_server_unregister (
01146 MAGNIFIER_OAFIID, BONOBO_OBJREF (magnifier));
01147
01148 if (magnifier->zoom_regions)
01149 g_list_free (magnifier->zoom_regions);
01150 magnifier->zoom_regions = NULL;
01151
01152 bonobo_main_quit ();
01153 }
01154
01155 static void
01156 magnifier_gobject_dispose (GObject *object)
01157 {
01158 magnifier_do_dispose (MAGNIFIER (object));
01159
01160 BONOBO_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
01161 }
01162
01163 static void
01164 impl_magnifier_set_source_display (PortableServer_Servant servant,
01165 const CORBA_char *display,
01166 CORBA_Environment *ev)
01167 {
01168 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01169 BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01170 gchar *full_display_string;
01171
01172 full_display_string = g_strdup (display);
01173 if (strcmp (full_display_string, "") == 0)
01174 full_display_string = (gchar *) g_getenv ("DISPLAY");
01175
01176 BONOBO_ARG_SET_STRING (arg, full_display_string);
01177
01178 DBG (fprintf (stderr, "Set source display: \t%s\n",
01179 full_display_string));
01180
01181 if (strcmp (full_display_string, magnifier->source_display_name)) {
01182 magnifier_set_property (magnifier->property_bag,
01183 arg,
01184 MAGNIFIER_SOURCE_DISPLAY_PROP,
01185 ev,
01186 magnifier);
01187 }
01188 else
01189 {
01190 DBG (fprintf (stderr, "Attempt to set source to same value as previous: %s\n",
01191 full_display_string));
01192 }
01193 bonobo_arg_release (arg);
01194 }
01195
01196 static void
01197 impl_magnifier_set_target_display (PortableServer_Servant servant,
01198 const CORBA_char *display,
01199 CORBA_Environment *ev)
01200 {
01201 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01202 BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01203 gchar *full_display_string;
01204
01205 full_display_string = g_strdup (display);
01206 if (strcmp (full_display_string, "") == 0)
01207 full_display_string = (gchar *) g_getenv ("DISPLAY");
01208
01209 BONOBO_ARG_SET_STRING (arg, full_display_string);
01210
01211 DBG (fprintf (stderr, "Set target display: \t%s\n",
01212 full_display_string));
01213
01214 if (strcmp (full_display_string, magnifier->target_display_name))
01215 {
01216 magnifier_set_property (magnifier->property_bag,
01217 arg,
01218 MAGNIFIER_TARGET_DISPLAY_PROP,
01219 ev,
01220 magnifier);
01221 }
01222 else
01223 {
01224 DBG (fprintf (stderr, "Attempt to set target to same value as previous: %s\n",
01225 full_display_string));
01226 }
01227 bonobo_arg_release (arg);
01228 }
01229
01230 static
01231 CORBA_string
01232 impl_magnifier_get_source_display (PortableServer_Servant servant,
01233 CORBA_Environment *ev)
01234 {
01235 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01236 DBG (fprintf (stderr, "Get source display: \t%s\n", magnifier->source_display_name));
01237
01238 return CORBA_string_dup (magnifier->source_display_name ? magnifier->source_display_name : "");
01239 }
01240
01241 static
01242 CORBA_string
01243 impl_magnifier_get_target_display (PortableServer_Servant servant,
01244 CORBA_Environment *ev)
01245 {
01246 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01247 DBG (fprintf (stderr, "Get target display: \t%s\n",
01248 magnifier->target_display_name));
01249
01250 return CORBA_string_dup (magnifier->target_display_name ? magnifier->target_display_name : "");
01251 }
01252
01253 static GNOME_Magnifier_ZoomRegion
01254 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
01255 const CORBA_float zx,
01256 const CORBA_float zy,
01257 const GNOME_Magnifier_RectBounds *roi,
01258 const GNOME_Magnifier_RectBounds *viewport,
01259 CORBA_Environment *ev)
01260 {
01261 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01262 CORBA_any viewport_any;
01263 ZoomRegion *zoom_region = zoom_region_new ();
01264 Bonobo_PropertyBag properties;
01265 GNOME_Magnifier_ZoomRegion retval;
01266
01267 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));
01268
01269
01270
01271
01272
01273 DBG(g_message ("creating zoom region with parent %p", magnifier));
01274 zoom_region->priv->parent = magnifier;
01275
01276 retval = BONOBO_OBJREF (zoom_region);
01277
01278
01279 CORBA_exception_init (ev);
01280 GNOME_Magnifier_ZoomRegion_setMagFactor (retval, zx, zy, ev);
01281
01282 if (ev->_major != CORBA_NO_EXCEPTION)
01283 fprintf (stderr, "EXCEPTION setMagFactor\n");
01284
01285 CORBA_exception_init (ev);
01286 properties = GNOME_Magnifier_ZoomRegion_getProperties (retval, ev);
01287 if (ev->_major != CORBA_NO_EXCEPTION)
01288 fprintf (stderr, "EXCEPTION getProperties\n");
01289
01290 viewport_any._type = TC_GNOME_Magnifier_RectBounds;
01291 viewport_any._value = (gpointer) viewport;
01292 Bonobo_PropertyBag_setValue (
01293 properties, "viewport", &viewport_any, ev);
01294
01295 GNOME_Magnifier_ZoomRegion_setROI (retval, roi, ev);
01296 if (ev->_major != CORBA_NO_EXCEPTION)
01297 fprintf (stderr, "EXCEPTION setROI\n");
01298
01299 CORBA_exception_init (ev);
01300
01301 gtk_widget_set_size_request (magnifier->priv->canvas,
01302 viewport->x2 - viewport->x1,
01303 viewport->y2 - viewport->y1);
01304 gtk_widget_show (magnifier->priv->canvas);
01305 gtk_widget_show (magnifier->priv->w);
01306
01307 bonobo_object_release_unref (properties, ev);
01308
01309 return CORBA_Object_duplicate (retval, ev);
01310 }
01311
01312 static
01313 CORBA_boolean
01314 impl_magnifier_add_zoom_region (PortableServer_Servant servant,
01315 const GNOME_Magnifier_ZoomRegion region,
01316 CORBA_Environment * ev)
01317 {
01318 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01319
01320 if (!magnifier->source_initialized)
01321 {
01322 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01323 }
01324
01325
01326 magnifier->zoom_regions = g_list_append (magnifier->zoom_regions, region);
01327 gmag_gs_check_set_struts (magnifier);
01328
01329 return CORBA_TRUE;
01330 }
01331
01332 static Bonobo_PropertyBag
01333 impl_magnifier_get_properties (PortableServer_Servant servant,
01334 CORBA_Environment *ev)
01335 {
01336 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01337 return bonobo_object_dup_ref (
01338 BONOBO_OBJREF (magnifier->property_bag), ev);
01339 }
01340
01341 GNOME_Magnifier_ZoomRegionList *
01342 impl_magnifier_get_zoom_regions (PortableServer_Servant servant,
01343 CORBA_Environment * ev)
01344 {
01345 Magnifier *magnifier =
01346 MAGNIFIER (bonobo_object_from_servant (servant));
01347
01348 GNOME_Magnifier_ZoomRegionList *list;
01349 CORBA_Object objref;
01350 int i, len;
01351
01352 len = g_list_length (magnifier->zoom_regions);
01353 list = GNOME_Magnifier_ZoomRegionList__alloc ();
01354 list->_length = len;
01355 list->_buffer =
01356 GNOME_Magnifier_ZoomRegionList_allocbuf (list->_length);
01357 for (i = 0; i < len; ++i) {
01358 objref = g_list_nth_data (magnifier->zoom_regions, i);
01359 list->_buffer [i] =
01360 CORBA_Object_duplicate (objref, ev);
01361 }
01362 CORBA_sequence_set_release (list, CORBA_TRUE);
01363
01364 DBG (fprintf (stderr, "Get zoom regions: \t%d\n", len));
01365
01366 return list;
01367 }
01368
01369 static void
01370 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant servant,
01371 CORBA_Environment * ev)
01372 {
01373 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01374 fprintf (stderr, "Clear all zoom regions.\n");
01375
01376 g_list_foreach (magnifier->zoom_regions,
01377 magnifier_unref_zoom_region, magnifier);
01378 g_list_free (magnifier->zoom_regions);
01379 magnifier->zoom_regions = NULL;
01380 }
01381
01382 static void
01383 impl_magnifier_dispose (PortableServer_Servant servant,
01384 CORBA_Environment *ev)
01385 {
01386 magnifier_do_dispose (
01387 MAGNIFIER (bonobo_object_from_servant (servant)));
01388 }
01389
01390 static void
01391 magnifier_class_init (MagnifierClass *klass)
01392 {
01393 GObjectClass * object_class = (GObjectClass *) klass;
01394 POA_GNOME_Magnifier_Magnifier__epv *epv = &klass->epv;
01395 parent_class = g_type_class_peek (BONOBO_TYPE_OBJECT);
01396
01397 object_class->dispose = magnifier_gobject_dispose;
01398
01399 epv->_set_SourceDisplay = impl_magnifier_set_source_display;
01400 epv->_set_TargetDisplay = impl_magnifier_set_target_display;
01401 epv->_get_SourceDisplay = impl_magnifier_get_source_display;
01402 epv->_get_TargetDisplay = impl_magnifier_get_target_display;
01403 epv->getProperties = impl_magnifier_get_properties;
01404 epv->getZoomRegions = impl_magnifier_get_zoom_regions;
01405 epv->createZoomRegion = impl_magnifier_create_zoom_region;
01406 epv->addZoomRegion = impl_magnifier_add_zoom_region;
01407 epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
01408 epv->dispose = impl_magnifier_dispose;
01409 }
01410
01411 static void
01412 magnifier_properties_init (Magnifier *magnifier)
01413 {
01414 BonoboArg *def;
01415 GNOME_Magnifier_RectBounds rect_bounds;
01416 gchar *display_env;
01417
01418 magnifier->property_bag =
01419 bonobo_property_bag_new_closure (
01420 g_cclosure_new_object (
01421 G_CALLBACK (magnifier_get_property),
01422 G_OBJECT (magnifier)),
01423 g_cclosure_new_object (
01424 G_CALLBACK (magnifier_set_property),
01425 G_OBJECT (magnifier)));
01426
01427
01428 bonobo_object_add_interface (BONOBO_OBJECT (magnifier),
01429 BONOBO_OBJECT (magnifier->property_bag));
01430
01431 def = bonobo_arg_new (BONOBO_ARG_STRING);
01432 display_env = getenv ("DISPLAY");
01433 BONOBO_ARG_SET_STRING (def, display_env);
01434
01435 bonobo_property_bag_add (magnifier->property_bag,
01436 "source-display-screen",
01437 MAGNIFIER_SOURCE_DISPLAY_PROP,
01438 BONOBO_ARG_STRING,
01439 def,
01440 "source display screen",
01441 Bonobo_PROPERTY_WRITEABLE);
01442
01443 bonobo_property_bag_add (magnifier->property_bag,
01444 "target-display-screen",
01445 MAGNIFIER_TARGET_DISPLAY_PROP,
01446 BONOBO_ARG_STRING,
01447 def,
01448 "target display screen",
01449 Bonobo_PROPERTY_WRITEABLE);
01450
01451 bonobo_arg_release (def);
01452
01453 magnifier_init_display (magnifier, display_env, TRUE);
01454 magnifier_init_display (magnifier, display_env, FALSE);
01455
01456 magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
01457 def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01458
01459 bonobo_property_bag_add (magnifier->property_bag,
01460 "source-display-bounds",
01461 MAGNIFIER_SOURCE_SIZE_PROP,
01462 TC_GNOME_Magnifier_RectBounds,
01463 def,
01464 "source display bounds/size",
01465 Bonobo_PROPERTY_READABLE |
01466 Bonobo_PROPERTY_WRITEABLE);
01467 bonobo_arg_release (def);
01468
01469 magnifier_get_display_rect_bounds (magnifier, &rect_bounds, TRUE);
01470 def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01471
01472 bonobo_property_bag_add (magnifier->property_bag,
01473 "target-display-bounds",
01474 MAGNIFIER_TARGET_SIZE_PROP,
01475 TC_GNOME_Magnifier_RectBounds,
01476 def,
01477 "target display bounds/size",
01478 Bonobo_PROPERTY_READABLE |
01479 Bonobo_PROPERTY_WRITEABLE);
01480 bonobo_arg_release (def);
01481
01482 bonobo_property_bag_add (magnifier->property_bag,
01483 "cursor-set",
01484 MAGNIFIER_CURSOR_SET_PROP,
01485 BONOBO_ARG_STRING,
01486 NULL,
01487 "name of cursor set",
01488 Bonobo_PROPERTY_READABLE |
01489 Bonobo_PROPERTY_WRITEABLE);
01490
01491 def = bonobo_arg_new (BONOBO_ARG_INT);
01492 BONOBO_ARG_SET_INT (def, 64);
01493
01494 bonobo_property_bag_add (magnifier->property_bag,
01495 "cursor-size",
01496 MAGNIFIER_CURSOR_SIZE_PROP,
01497 BONOBO_ARG_INT,
01498 def,
01499 "cursor size, in pixels",
01500 Bonobo_PROPERTY_READABLE |
01501 Bonobo_PROPERTY_WRITEABLE);
01502 bonobo_arg_release (def);
01503
01504 bonobo_property_bag_add (magnifier->property_bag,
01505 "cursor-scale-factor",
01506 MAGNIFIER_CURSOR_ZOOM_PROP,
01507 BONOBO_ARG_FLOAT,
01508 NULL,
01509 "scale factor for cursors (overrides size)",
01510 Bonobo_PROPERTY_READABLE |
01511 Bonobo_PROPERTY_WRITEABLE);
01512
01513 bonobo_property_bag_add (magnifier->property_bag,
01514 "cursor-color",
01515 MAGNIFIER_CURSOR_COLOR_PROP,
01516 TC_CORBA_unsigned_long,
01517 NULL,
01518 "foreground color for 1-bit cursors, as ARGB",
01519 Bonobo_PROPERTY_READABLE |
01520 Bonobo_PROPERTY_WRITEABLE);
01521
01522 bonobo_property_bag_add (magnifier->property_bag,
01523 "cursor-hotspot",
01524 MAGNIFIER_CURSOR_HOTSPOT_PROP,
01525 TC_GNOME_Magnifier_Point,
01526 NULL,
01527 "hotspot relative to cursor's upper-left-corner, at default resolition",
01528 Bonobo_PROPERTY_READABLE |
01529 Bonobo_PROPERTY_WRITEABLE);
01530
01531 bonobo_property_bag_add (magnifier->property_bag,
01532 "cursor-default-size",
01533 MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
01534 BONOBO_ARG_INT,
01535 NULL,
01536 "default size of current cursor set",
01537 Bonobo_PROPERTY_READABLE);
01538
01539 bonobo_property_bag_add (magnifier->property_bag,
01540 "crosswire-size",
01541 MAGNIFIER_CROSSWIRE_SIZE_PROP,
01542 BONOBO_ARG_INT,
01543 NULL,
01544 "thickness of crosswire cursor, in target pixels",
01545 Bonobo_PROPERTY_READABLE |
01546 Bonobo_PROPERTY_WRITEABLE);
01547
01548 bonobo_property_bag_add (magnifier->property_bag,
01549 "crosswire-color",
01550 MAGNIFIER_CROSSWIRE_COLOR_PROP,
01551 BONOBO_ARG_LONG,
01552 NULL,
01553 "color of crosswire, as A-RGB; note that alpha is required. (use 0 for XOR wire)",
01554 Bonobo_PROPERTY_READABLE |
01555 Bonobo_PROPERTY_WRITEABLE);
01556
01557 bonobo_property_bag_add (magnifier->property_bag,
01558 "crosswire-clip",
01559 MAGNIFIER_CROSSWIRE_CLIP_PROP,
01560 BONOBO_ARG_BOOLEAN,
01561 NULL,
01562 "whether to inset the cursor over the crosswire or not",
01563 Bonobo_PROPERTY_READABLE |
01564 Bonobo_PROPERTY_WRITEABLE);
01565 }
01566
01567 static void
01568 magnifier_init_window (Magnifier *magnifier, GdkScreen *screen)
01569 {
01570 GtkWindowType mag_win_type = GTK_WINDOW_TOPLEVEL;
01571 if (_is_override_redirect) mag_win_type = GTK_WINDOW_POPUP;
01572
01573 magnifier->priv->w =
01574 g_object_connect (gtk_widget_new (gtk_window_get_type (),
01575 "user_data", NULL,
01576 "can_focus", FALSE,
01577 "type", mag_win_type,
01578 "title", "magnifier",
01579 "allow_grow", TRUE,
01580 "allow_shrink", TRUE,
01581 "border_width", 0,
01582 NULL),
01583 "signal::realize", magnifier_realize, NULL,
01584 "signal::size_allocate", magnifier_size_allocate, NULL,
01585 "signal::destroy", magnifier_exit, NULL,
01586 NULL);
01587 gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), screen);
01588 magnifier->priv->canvas = gtk_fixed_new ();
01589 gtk_container_add (GTK_CONTAINER (magnifier->priv->w),
01590 magnifier->priv->canvas);
01591 magnifier->priv->root = NULL;
01592 }
01593
01594 static void
01595 magnifier_init (Magnifier *magnifier)
01596 {
01597 magnifier->priv = g_new0 (MagnifierPrivate, 1);
01598 magnifier_properties_init (magnifier);
01599 magnifier->zoom_regions = NULL;
01600 magnifier->source_screen_num = 0;
01601 magnifier->target_screen_num = 0;
01602 magnifier->source_display_name = g_strdup (":0.0");
01603 magnifier->target_display_name = g_strdup (":0.0");
01604 magnifier->cursor_size_x = 0;
01605 magnifier->cursor_size_y = 0;
01606 magnifier->cursor_scale_factor = 1.0F;
01607 magnifier->cursor_color = 0xFF000000;
01608 magnifier->crosswire_size = 1;
01609 magnifier->crosswire_color = 0;
01610 magnifier->crosswire_clip = FALSE;
01611 magnifier->cursor_hotspot.x = 0;
01612 magnifier->cursor_hotspot.y = 0;
01613 magnifier->target_bounds.x1 = 0;
01614 magnifier->target_bounds.y1 = 0;
01615 magnifier->target_bounds.x2 = 0;
01616 magnifier->target_bounds.y2 = 0;
01617 magnifier->priv->cursor = NULL;
01618 magnifier->priv->w = NULL;
01619 magnifier->priv->use_source_cursor = TRUE;
01620 magnifier->priv->cursorlist = NULL;
01621 magnifier->priv->source_drawable = NULL;
01622 magnifier->priv->overlay = NULL;
01623 magnifier_init_window (magnifier,
01624 gdk_display_get_screen (magnifier->target_display,
01625 magnifier->target_screen_num));
01626 magnifier_init_cursor_set (magnifier, "default");
01627
01628 mag_timing.process = g_timer_new ();
01629 mag_timing.frame = g_timer_new ();
01630 mag_timing.scale = g_timer_new ();
01631 mag_timing.idle = g_timer_new ();
01632 #ifdef DEBUG_CLIENT_CALLS
01633 client_debug = (g_getenv ("MAG_CLIENT_DEBUG") != NULL);
01634 #endif
01635 }
01636
01637 GdkDrawable *
01638 magnifier_get_cursor (Magnifier *magnifier)
01639 {
01640 if (magnifier->priv->cursor == NULL) {
01641 if ((fixes_event_base == 0) &&
01642 strcmp (magnifier->cursor_set, "none"))
01643 {
01644 GdkPixbuf *pixbuf;
01645 gchar *default_cursor_filename =
01646 g_strconcat (CURSORSDIR, "/", "default-cursor.xpm", NULL);
01647 pixbuf = gdk_pixbuf_new_from_file (default_cursor_filename, NULL);
01648 if (pixbuf)
01649 {
01650 magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
01651 g_object_unref (pixbuf);
01652 magnifier_transform_cursor (magnifier);
01653 }
01654 g_free (default_cursor_filename);
01655 } else {
01656 GdkPixbuf *cursor_pixbuf = gmag_cursor_get_source_pixbuf (
01657 magnifier);
01658 magnifier_set_cursor_from_pixbuf (magnifier, cursor_pixbuf);
01659 if (cursor_pixbuf) g_object_unref (cursor_pixbuf);
01660 magnifier_transform_cursor (magnifier);
01661 }
01662 }
01663 return magnifier->priv->cursor;
01664 }
01665
01666 Magnifier *
01667 magnifier_new (gboolean override_redirect)
01668 {
01669 Magnifier *mag;
01670 MagLoginHelper *helper;
01671 int ret;
01672
01673 _is_override_redirect = override_redirect;
01674
01675 mag = g_object_new (magnifier_get_type(), NULL);
01676
01677 _this_magnifier = mag;
01678
01679 helper = g_object_new (mag_login_helper_get_type (), NULL);
01680 mag_login_helper_set_magnifier (helper, mag);
01681
01682 bonobo_object_add_interface (bonobo_object (mag),
01683 BONOBO_OBJECT (helper));
01684
01685 ret = bonobo_activation_active_server_register (
01686 MAGNIFIER_OAFIID, BONOBO_OBJREF (mag));
01687 if (ret != Bonobo_ACTIVATION_REG_SUCCESS) {
01688 if ( ret == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE)
01689 {
01690 printf("An instance of magnifier is already active. Exiting Program.\n");
01691 exit(0);
01692 } else
01693 g_error ("Error registering magnifier server.\n");
01694 }
01695
01696 g_timeout_add (500, magnifier_reset_struts_at_idle, mag);
01697 g_timeout_add (500, gmag_gs_reset_overlay_at_idle, mag);
01698
01699 return mag;
01700 }
01701
01702 BONOBO_TYPE_FUNC_FULL (Magnifier,
01703 GNOME_Magnifier_Magnifier,
01704 BONOBO_TYPE_OBJECT,
01705 magnifier)
01706