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 BONOBO_ARG_SET_STRING (arg, display);
01149
01150 DBG (fprintf (stderr, "Set source display: \t%s\n", display));
01151
01152 if (strcmp (display, magnifier->source_display_name)) {
01153
01154 magnifier_set_property (magnifier->property_bag,
01155 arg,
01156 MAGNIFIER_SOURCE_DISPLAY_PROP,
01157 ev,
01158 magnifier);
01159 }
01160 else
01161 {
01162 DBG (fprintf (stderr, "Attempt to set source to same value as previous: %s\n",
01163 display));
01164 }
01165 bonobo_arg_release (arg);
01166 }
01167
01168 static void
01169 impl_magnifier_set_target_display (PortableServer_Servant servant,
01170 const CORBA_char *display,
01171 CORBA_Environment *ev)
01172 {
01173 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01174 BonoboArg *arg = bonobo_arg_new (BONOBO_ARG_STRING);
01175 BONOBO_ARG_SET_STRING (arg, display);
01176
01177 DBG (fprintf (stderr, "Set target display: \t%s\n", display));
01178
01179 if (strcmp (display, magnifier->target_display_name))
01180 {
01181 magnifier_set_property (magnifier->property_bag,
01182 arg,
01183 MAGNIFIER_TARGET_DISPLAY_PROP,
01184 ev,
01185 magnifier);
01186 }
01187 else
01188 {
01189 DBG (fprintf (stderr, "Attempt to set target to same value as previous: %s\n",
01190 display));
01191 }
01192 bonobo_arg_release (arg);
01193 }
01194
01195 static
01196 CORBA_string
01197 impl_magnifier_get_source_display (PortableServer_Servant servant,
01198 CORBA_Environment *ev)
01199 {
01200 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01201 DBG (fprintf (stderr, "Get source display: \t%s\n", magnifier->source_display_name));
01202
01203 return CORBA_string_dup (magnifier->source_display_name ? magnifier->source_display_name : "");
01204 }
01205
01206 static
01207 CORBA_string
01208 impl_magnifier_get_target_display (PortableServer_Servant servant,
01209 CORBA_Environment *ev)
01210 {
01211 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01212 DBG (fprintf (stderr, "Get target display: \t%s\n",
01213 magnifier->target_display_name));
01214
01215 return CORBA_string_dup (magnifier->target_display_name ? magnifier->target_display_name : "");
01216 }
01217
01218 static GNOME_Magnifier_ZoomRegion
01219 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
01220 const CORBA_float zx,
01221 const CORBA_float zy,
01222 const GNOME_Magnifier_RectBounds *roi,
01223 const GNOME_Magnifier_RectBounds *viewport,
01224 CORBA_Environment *ev)
01225 {
01226 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01227 CORBA_any viewport_any;
01228 ZoomRegion *zoom_region = zoom_region_new ();
01229 Bonobo_PropertyBag properties;
01230 GNOME_Magnifier_ZoomRegion retval;
01231
01232 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));
01233
01234
01235
01236
01237
01238 DBG(g_message ("creating zoom region with parent %p", magnifier));
01239 zoom_region->priv->parent = magnifier;
01240
01241 retval = BONOBO_OBJREF (zoom_region);
01242
01243 CORBA_exception_init (ev);
01244 GNOME_Magnifier_ZoomRegion_setMagFactor (retval, zx, zy, ev);
01245
01246 if (ev->_major != CORBA_NO_EXCEPTION)
01247 fprintf (stderr, "EXCEPTION setMagFactor\n");
01248
01249 CORBA_exception_init (ev);
01250 properties = GNOME_Magnifier_ZoomRegion_getProperties (retval, ev);
01251 if (ev->_major != CORBA_NO_EXCEPTION)
01252 fprintf (stderr, "EXCEPTION getProperties\n");
01253
01254 viewport_any._type = TC_GNOME_Magnifier_RectBounds;
01255 viewport_any._value = (gpointer) viewport;
01256 Bonobo_PropertyBag_setValue (
01257 properties, "viewport", &viewport_any, ev);
01258
01259 GNOME_Magnifier_ZoomRegion_setROI (retval, roi, ev);
01260 if (ev->_major != CORBA_NO_EXCEPTION)
01261 fprintf (stderr, "EXCEPTION setROI\n");
01262
01263 CORBA_exception_init (ev);
01264
01265 gtk_widget_set_size_request (magnifier->priv->canvas,
01266 viewport->x2 - viewport->x1,
01267 viewport->y2 - viewport->y1);
01268 gtk_widget_show (magnifier->priv->canvas);
01269 gtk_widget_show (magnifier->priv->w);
01270
01271 bonobo_object_release_unref (properties, ev);
01272
01273 return CORBA_Object_duplicate (retval, ev);
01274 }
01275
01276 static
01277 CORBA_boolean
01278 impl_magnifier_add_zoom_region (PortableServer_Servant servant,
01279 const GNOME_Magnifier_ZoomRegion region,
01280 CORBA_Environment * ev)
01281 {
01282 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01283
01284 if (!magnifier->source_initialized)
01285 {
01286 magnifier_set_extension_listeners (magnifier, magnifier_get_root (magnifier));
01287 }
01288
01289
01290 magnifier->zoom_regions = g_list_append (magnifier->zoom_regions, region);
01291 gmag_gs_check_set_struts (magnifier);
01292
01293 return CORBA_TRUE;
01294 }
01295
01296 static Bonobo_PropertyBag
01297 impl_magnifier_get_properties (PortableServer_Servant servant,
01298 CORBA_Environment *ev)
01299 {
01300 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01301 return bonobo_object_dup_ref (
01302 BONOBO_OBJREF (magnifier->property_bag), ev);
01303 }
01304
01305 GNOME_Magnifier_ZoomRegionList *
01306 impl_magnifier_get_zoom_regions (PortableServer_Servant servant,
01307 CORBA_Environment * ev)
01308 {
01309 Magnifier *magnifier =
01310 MAGNIFIER (bonobo_object_from_servant (servant));
01311
01312 GNOME_Magnifier_ZoomRegionList *list;
01313 CORBA_Object objref;
01314 int i, len;
01315
01316 len = g_list_length (magnifier->zoom_regions);
01317 list = GNOME_Magnifier_ZoomRegionList__alloc ();
01318 list->_length = len;
01319 list->_buffer =
01320 GNOME_Magnifier_ZoomRegionList_allocbuf (list->_length);
01321 for (i = 0; i < len; ++i) {
01322 objref = g_list_nth_data (magnifier->zoom_regions, i);
01323 list->_buffer [i] =
01324 CORBA_Object_duplicate (objref, ev);
01325 }
01326 CORBA_sequence_set_release (list, CORBA_TRUE);
01327
01328 DBG (fprintf (stderr, "Get zoom regions: \t%d\n", len));
01329
01330 return list;
01331 }
01332
01333 static void
01334 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant servant,
01335 CORBA_Environment * ev)
01336 {
01337 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
01338 fprintf (stderr, "Clear all zoom regions.\n");
01339
01340 g_list_foreach (magnifier->zoom_regions,
01341 magnifier_unref_zoom_region, magnifier);
01342 g_list_free (magnifier->zoom_regions);
01343 magnifier->zoom_regions = NULL;
01344 }
01345
01346 static void
01347 impl_magnifier_dispose (PortableServer_Servant servant,
01348 CORBA_Environment *ev)
01349 {
01350 magnifier_do_dispose (
01351 MAGNIFIER (bonobo_object_from_servant (servant)));
01352 }
01353
01354 static void
01355 magnifier_class_init (MagnifierClass *klass)
01356 {
01357 GObjectClass * object_class = (GObjectClass *) klass;
01358 POA_GNOME_Magnifier_Magnifier__epv *epv = &klass->epv;
01359 parent_class = g_type_class_peek (BONOBO_TYPE_OBJECT);
01360
01361 object_class->dispose = magnifier_gobject_dispose;
01362
01363 epv->_set_SourceDisplay = impl_magnifier_set_source_display;
01364 epv->_set_TargetDisplay = impl_magnifier_set_target_display;
01365 epv->_get_SourceDisplay = impl_magnifier_get_source_display;
01366 epv->_get_TargetDisplay = impl_magnifier_get_target_display;
01367 epv->getProperties = impl_magnifier_get_properties;
01368 epv->getZoomRegions = impl_magnifier_get_zoom_regions;
01369 epv->createZoomRegion = impl_magnifier_create_zoom_region;
01370 epv->addZoomRegion = impl_magnifier_add_zoom_region;
01371 epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
01372 epv->dispose = impl_magnifier_dispose;
01373 }
01374
01375 static void
01376 magnifier_properties_init (Magnifier *magnifier)
01377 {
01378 BonoboArg *def;
01379 GNOME_Magnifier_RectBounds rect_bounds;
01380 gchar *display_env;
01381
01382 magnifier->property_bag =
01383 bonobo_property_bag_new_closure (
01384 g_cclosure_new_object (
01385 G_CALLBACK (magnifier_get_property),
01386 G_OBJECT (magnifier)),
01387 g_cclosure_new_object (
01388 G_CALLBACK (magnifier_set_property),
01389 G_OBJECT (magnifier)));
01390
01391
01392 bonobo_object_add_interface (BONOBO_OBJECT (magnifier),
01393 BONOBO_OBJECT (magnifier->property_bag));
01394
01395 def = bonobo_arg_new (BONOBO_ARG_STRING);
01396 display_env = getenv ("DISPLAY");
01397 BONOBO_ARG_SET_STRING (def, display_env);
01398
01399 bonobo_property_bag_add (magnifier->property_bag,
01400 "source-display-screen",
01401 MAGNIFIER_SOURCE_DISPLAY_PROP,
01402 BONOBO_ARG_STRING,
01403 def,
01404 "source display screen",
01405 Bonobo_PROPERTY_WRITEABLE);
01406
01407 bonobo_property_bag_add (magnifier->property_bag,
01408 "target-display-screen",
01409 MAGNIFIER_TARGET_DISPLAY_PROP,
01410 BONOBO_ARG_STRING,
01411 def,
01412 "target display screen",
01413 Bonobo_PROPERTY_WRITEABLE);
01414
01415 bonobo_arg_release (def);
01416
01417 magnifier_init_display (magnifier, display_env, TRUE);
01418 magnifier_init_display (magnifier, display_env, FALSE);
01419
01420 magnifier_get_display_rect_bounds (magnifier, &rect_bounds, FALSE);
01421 def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01422
01423 bonobo_property_bag_add (magnifier->property_bag,
01424 "source-display-bounds",
01425 MAGNIFIER_SOURCE_SIZE_PROP,
01426 TC_GNOME_Magnifier_RectBounds,
01427 def,
01428 "source display bounds/size",
01429 Bonobo_PROPERTY_READABLE |
01430 Bonobo_PROPERTY_WRITEABLE);
01431 bonobo_arg_release (def);
01432
01433 magnifier_get_display_rect_bounds (magnifier, &rect_bounds, TRUE);
01434 def = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, &rect_bounds);
01435
01436 bonobo_property_bag_add (magnifier->property_bag,
01437 "target-display-bounds",
01438 MAGNIFIER_TARGET_SIZE_PROP,
01439 TC_GNOME_Magnifier_RectBounds,
01440 def,
01441 "target display bounds/size",
01442 Bonobo_PROPERTY_READABLE |
01443 Bonobo_PROPERTY_WRITEABLE);
01444 bonobo_arg_release (def);
01445
01446 bonobo_property_bag_add (magnifier->property_bag,
01447 "cursor-set",
01448 MAGNIFIER_CURSOR_SET_PROP,
01449 BONOBO_ARG_STRING,
01450 NULL,
01451 "name of cursor set",
01452 Bonobo_PROPERTY_READABLE |
01453 Bonobo_PROPERTY_WRITEABLE);
01454
01455 def = bonobo_arg_new (BONOBO_ARG_INT);
01456 BONOBO_ARG_SET_INT (def, 64);
01457
01458 bonobo_property_bag_add (magnifier->property_bag,
01459 "cursor-size",
01460 MAGNIFIER_CURSOR_SIZE_PROP,
01461 BONOBO_ARG_INT,
01462 def,
01463 "cursor size, in pixels",
01464 Bonobo_PROPERTY_READABLE |
01465 Bonobo_PROPERTY_WRITEABLE);
01466 bonobo_arg_release (def);
01467
01468 bonobo_property_bag_add (magnifier->property_bag,
01469 "cursor-scale-factor",
01470 MAGNIFIER_CURSOR_ZOOM_PROP,
01471 BONOBO_ARG_FLOAT,
01472 NULL,
01473 "scale factor for cursors (overrides size)",
01474 Bonobo_PROPERTY_READABLE |
01475 Bonobo_PROPERTY_WRITEABLE);
01476
01477 bonobo_property_bag_add (magnifier->property_bag,
01478 "cursor-color",
01479 MAGNIFIER_CURSOR_COLOR_PROP,
01480 TC_CORBA_unsigned_long,
01481 NULL,
01482 "foreground color for 1-bit cursors, as ARGB",
01483 Bonobo_PROPERTY_READABLE |
01484 Bonobo_PROPERTY_WRITEABLE);
01485
01486 bonobo_property_bag_add (magnifier->property_bag,
01487 "cursor-hotspot",
01488 MAGNIFIER_CURSOR_HOTSPOT_PROP,
01489 TC_GNOME_Magnifier_Point,
01490 NULL,
01491 "hotspot relative to cursor's upper-left-corner, at default resolition",
01492 Bonobo_PROPERTY_READABLE |
01493 Bonobo_PROPERTY_WRITEABLE);
01494
01495 bonobo_property_bag_add (magnifier->property_bag,
01496 "cursor-default-size",
01497 MAGNIFIER_CURSOR_DEFAULT_SIZE_PROP,
01498 BONOBO_ARG_INT,
01499 NULL,
01500 "default size of current cursor set",
01501 Bonobo_PROPERTY_READABLE);
01502
01503 bonobo_property_bag_add (magnifier->property_bag,
01504 "crosswire-size",
01505 MAGNIFIER_CROSSWIRE_SIZE_PROP,
01506 BONOBO_ARG_INT,
01507 NULL,
01508 "thickness of crosswire cursor, in target pixels",
01509 Bonobo_PROPERTY_READABLE |
01510 Bonobo_PROPERTY_WRITEABLE);
01511
01512 bonobo_property_bag_add (magnifier->property_bag,
01513 "crosswire-color",
01514 MAGNIFIER_CROSSWIRE_COLOR_PROP,
01515 BONOBO_ARG_LONG,
01516 NULL,
01517 "color of crosswire, as A-RGB; note that alpha is required. (use 0 for XOR wire)",
01518 Bonobo_PROPERTY_READABLE |
01519 Bonobo_PROPERTY_WRITEABLE);
01520
01521 bonobo_property_bag_add (magnifier->property_bag,
01522 "crosswire-clip",
01523 MAGNIFIER_CROSSWIRE_CLIP_PROP,
01524 BONOBO_ARG_BOOLEAN,
01525 NULL,
01526 "whether to inset the cursor over the crosswire or not",
01527 Bonobo_PROPERTY_READABLE |
01528 Bonobo_PROPERTY_WRITEABLE);
01529 }
01530
01531 static void
01532 magnifier_init_window (Magnifier *magnifier, GdkScreen *screen)
01533 {
01534 GtkWindowType mag_win_type = GTK_WINDOW_TOPLEVEL;
01535 if (_is_override_redirect) mag_win_type = GTK_WINDOW_POPUP;
01536
01537 magnifier->priv->w =
01538 g_object_connect (gtk_widget_new (gtk_window_get_type (),
01539 "user_data", NULL,
01540 "can_focus", FALSE,
01541 "type", mag_win_type,
01542 "title", "magnifier",
01543 "allow_grow", TRUE,
01544 "allow_shrink", TRUE,
01545 "border_width", 0,
01546 NULL),
01547 "signal::realize", magnifier_realize, NULL,
01548 "signal::size_allocate", magnifier_size_allocate, NULL,
01549 "signal::destroy", magnifier_exit, NULL,
01550 NULL);
01551 gtk_window_set_screen (GTK_WINDOW (magnifier->priv->w), screen);
01552 magnifier->priv->canvas = gtk_fixed_new ();
01553 gtk_container_add (GTK_CONTAINER (magnifier->priv->w),
01554 magnifier->priv->canvas);
01555 magnifier->priv->root = NULL;
01556 }
01557
01558 static void
01559 magnifier_init (Magnifier *magnifier)
01560 {
01561 magnifier->priv = g_new0 (MagnifierPrivate, 1);
01562 magnifier_properties_init (magnifier);
01563 magnifier->zoom_regions = NULL;
01564 magnifier->source_screen_num = 0;
01565 magnifier->target_screen_num = 0;
01566 magnifier->source_display_name = g_strdup (":0.0");
01567 magnifier->target_display_name = g_strdup (":0.0");
01568 magnifier->cursor_size_x = 0;
01569 magnifier->cursor_size_y = 0;
01570 magnifier->cursor_scale_factor = 1.0F;
01571 magnifier->cursor_color = 0xFF000000;
01572 magnifier->crosswire_size = 1;
01573 magnifier->crosswire_color = 0;
01574 magnifier->crosswire_clip = FALSE;
01575 magnifier->cursor_hotspot.x = 0;
01576 magnifier->cursor_hotspot.y = 0;
01577 magnifier->target_bounds.x1 = 0;
01578 magnifier->target_bounds.y1 = 0;
01579 magnifier->target_bounds.x2 = 0;
01580 magnifier->target_bounds.y2 = 0;
01581 magnifier->priv->cursor = NULL;
01582 magnifier->priv->w = NULL;
01583 magnifier->priv->use_source_cursor = TRUE;
01584 magnifier->priv->cursorlist = NULL;
01585 magnifier->priv->source_drawable = NULL;
01586 magnifier->priv->overlay = NULL;
01587 magnifier_init_window (magnifier,
01588 gdk_display_get_screen (magnifier->target_display,
01589 magnifier->target_screen_num));
01590 magnifier_init_cursor_set (magnifier, "default");
01591
01592 mag_timing.process = g_timer_new ();
01593 mag_timing.frame = g_timer_new ();
01594 mag_timing.scale = g_timer_new ();
01595 mag_timing.idle = g_timer_new ();
01596 #ifdef DEBUG_CLIENT_CALLS
01597 client_debug = (g_getenv ("MAG_CLIENT_DEBUG") != NULL);
01598 #endif
01599 }
01600
01601 GdkDrawable *
01602 magnifier_get_cursor (Magnifier *magnifier)
01603 {
01604 if (magnifier->priv->cursor == NULL) {
01605 if ((fixes_event_base == 0) &&
01606 strcmp (magnifier->cursor_set, "none"))
01607 {
01608 GdkPixbuf *pixbuf;
01609 gchar *default_cursor_filename =
01610 g_strconcat (CURSORSDIR, "/", "default-cursor.xpm", NULL);
01611 pixbuf = gdk_pixbuf_new_from_file (default_cursor_filename, NULL);
01612 if (pixbuf)
01613 {
01614 magnifier_set_cursor_from_pixbuf (magnifier, pixbuf);
01615 g_object_unref (pixbuf);
01616 magnifier_transform_cursor (magnifier);
01617 }
01618 g_free (default_cursor_filename);
01619 } else {
01620 GdkPixbuf *cursor_pixbuf = gmag_cursor_get_source_pixbuf (
01621 magnifier);
01622 magnifier_set_cursor_from_pixbuf (magnifier, cursor_pixbuf);
01623 if (cursor_pixbuf) g_object_unref (cursor_pixbuf);
01624 magnifier_transform_cursor (magnifier);
01625 }
01626 }
01627 return magnifier->priv->cursor;
01628 }
01629
01630 Magnifier *
01631 magnifier_new (gboolean override_redirect)
01632 {
01633 Magnifier *mag;
01634 MagLoginHelper *helper;
01635 int ret;
01636
01637 _is_override_redirect = override_redirect;
01638
01639 mag = g_object_new (magnifier_get_type(), NULL);
01640
01641 _this_magnifier = mag;
01642
01643 helper = g_object_new (mag_login_helper_get_type (), NULL);
01644 mag_login_helper_set_magnifier (helper, mag);
01645
01646 bonobo_object_add_interface (bonobo_object (mag),
01647 BONOBO_OBJECT (helper));
01648
01649 ret = bonobo_activation_active_server_register (
01650 MAGNIFIER_OAFIID, BONOBO_OBJREF (mag));
01651 if (ret != Bonobo_ACTIVATION_REG_SUCCESS) {
01652 if ( ret == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE) {
01653 printf("An instance of magnifier is already active. " \
01654 "Exiting Program.\n");
01655 exit(0);
01656 }
01657 else
01658 g_error ("Error registering magnifier server.\n");
01659 }
01660
01661 g_idle_add (magnifier_reset_struts_at_idle, mag);
01662 g_idle_add (gmag_gs_reset_overlay_at_idle, mag);
01663
01664 return mag;
01665 }
01666
01667 BONOBO_TYPE_FUNC_FULL (Magnifier,
01668 GNOME_Magnifier_Magnifier,
01669 BONOBO_TYPE_OBJECT,
01670 magnifier)
01671