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