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