00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <popt.h>
00026 #include <sys/time.h>
00027 #include <gdk/gdkwindow.h>
00028 #include <gdk/gdkx.h>
00029 #include <gtk/gtk.h>
00030 #include <libbonobo.h>
00031 #include "magnifier.h"
00032 #include "magnifier-private.h"
00033 #include "zoom-region.h"
00034 #include "GNOME_Magnifier.h"
00035
00036 #define ENV_STRING_MAX_SIZE 128
00037
00038 GNOME_Magnifier_ZoomRegion zoom_region;
00039
00040 typedef struct {
00041 gchar *target_display;
00042 gchar *source_display;
00043 gchar *cursor_set;
00044 gchar *smoothing_type;
00045 float zoom_factor;
00046 float zoom_factor_x;
00047 float zoom_factor_y;
00048 int refresh_time;
00049 int mouse_poll_time;
00050 int cursor_size;
00051 float cursor_scale_factor;
00052 guint32 cursor_color;
00053 int vertical_split;
00054 int horizontal_split;
00055 int fullscreen;
00056 int mouse_follow;
00057 int invert_image;
00058 int no_initial_region;
00059 int timing_iterations;
00060 int timing_output;
00061 int timing_delta_x;
00062 int timing_delta_y;
00063 int timing_pan_rate;
00064 int smooth_scroll;
00065 int border_width;
00066 unsigned long border_color;
00067 int test_pattern;
00068 int is_override_redirect;
00069 int ignore_damage;
00070 } MagnifierOptions;
00071
00072 static MagnifierOptions global_options = { ":0.0",
00073 ":0.0",
00074 "default",
00075 "none",
00076 2.0,
00077 0.0,
00078 0.0,
00079 500,
00080 50,
00081 0,
00082 0.0F,
00083 0xFF000000,
00084 0,
00085 0,
00086 0,
00087 0,
00088 0,
00089 0,
00090 0,
00091 0,
00092 10,
00093 10,
00094 0,
00095 1,
00096 0,
00097 0,
00098 0,
00099 0,
00100 0
00101 };
00102
00103 struct poptOption magnifier_options [] = {
00104 {"target-display", 't', POPT_ARG_STRING, &global_options.target_display, 't', "specify display on which to show magnified view", NULL},
00105 {"source-display", 's', POPT_ARG_STRING, &global_options.source_display, 's', "specify display to magnify", NULL},
00106 {"cursor-set", '\0', POPT_ARG_STRING, &global_options.cursor_set, '\0', "cursor set to use in target display", NULL},
00107 {"cursor-size", '\0', POPT_ARG_INT, &global_options.cursor_size, '\0', "cursor size to use (overrides cursor-scale-factor)", NULL},
00108 {"cursor-scale-factor", '\0', POPT_ARG_FLOAT, &global_options.cursor_scale_factor, '\0', "cursor scale factor", NULL},
00109 {"cursor-color", '\0', POPT_ARG_LONG, &global_options.cursor_color, '\0', "cursor color (applied to \'black\' pixels", NULL},
00110 {"vertical", 'v', POPT_ARG_NONE, &global_options.vertical_split, 'v', "split screen vertically (if target display = source display)", NULL},
00111 {"horizontal", 'h', POPT_ARG_NONE, &global_options.horizontal_split, 'h', "split screen horizontally (if target display = source display)", NULL},
00112 {"mouse-follow", 'm', POPT_ARG_NONE, &global_options.mouse_follow, 'm', "track mouse movements", NULL},
00113 {"refresh-time", 'r', POPT_ARG_INT, &global_options.refresh_time, 'r', "minimum refresh time for idle, in ms", NULL},
00114 {"mouse-latency", '\0', POPT_ARG_INT, &global_options.mouse_poll_time, '\0', "maximum mouse latency time, in ms", NULL},
00115 {"zoom-factor", 'z', POPT_ARG_FLOAT, &global_options.zoom_factor, 'z', "zoom (scale) factor used to magnify source display", NULL},
00116 {"invert-image", 'i', POPT_ARG_NONE, &global_options.invert_image, 'i', "invert the image colormap", NULL},
00117 {"no-initial-region", '\0', POPT_ARG_NONE, &global_options.no_initial_region, '\0', "don't create an initial zoom region", NULL},
00118 {"timing-iterations", '\0', POPT_ARG_INT, &global_options.timing_iterations, '\0', "iterations to run timing benchmark test (0=continuous)", NULL},
00119 {"timing-output", '\0', POPT_ARG_NONE, &global_options.timing_output, '\0', "display performance ouput", NULL},
00120 {"timing-pan-rate", '\0', POPT_ARG_INT, &global_options.timing_pan_rate, '\0', "timing pan rate in lines per frame", NULL},
00121 {"timing-delta-x", '\0', POPT_ARG_INT, &global_options.timing_delta_x, '\0', "pixels to pan in x-dimension each frame in timing update test", NULL},
00122 {"timing-delta-y", '\0', POPT_ARG_INT, &global_options.timing_delta_y, '\0', "pixels to pan in y-dimension each frame in timing update test", NULL},
00123 {"smoothing-type", '\0', POPT_ARG_STRING, &global_options.smoothing_type, '\0', "image smoothing algorithm to apply (bilinear-interpolation | none)", NULL},
00124 {"fullscreen", 'f', POPT_ARG_NONE, &global_options.fullscreen, '\0', "fullscreen magnification, covers entire target display [REQUIRES --source-display and --target-display]", NULL},
00125 {"smooth-scrolling", '\0', POPT_ARG_NONE, &global_options.smooth_scroll, '\0', "use smooth scrolling", NULL},
00126 {"border-size", 'b', POPT_ARG_INT, &global_options.border_width, '\0', "width of border", NULL},
00127 {"border-color", 'c', POPT_ARG_LONG, &global_options.border_color, '\0', "border color specified as (A)RGB 23-bit value, Alpha-MSB", NULL},
00128 {"use-test-pattern", '\0', POPT_ARG_NONE, &global_options.test_pattern, '\0', "use test pattern as source", NULL},
00129 {"override-redirect", '\0', POPT_ARG_NONE, &global_options.is_override_redirect, '\0', "make the magnifier window totally unmanaged by the window manager", NULL},
00130 {"ignore-damage", '\0', POPT_ARG_NONE, &global_options.ignore_damage, '\0', "ignore the X server DAMAGE extension, if present", NULL},
00131 POPT_AUTOHELP
00132 {NULL, 0, 0, NULL, 0, 0}
00133 };
00134
00135 static void
00136 init_rect_bounds (GNOME_Magnifier_RectBounds *bounds,
00137 long x1, long y1, long x2, long y2)
00138 {
00139 bounds->x1 = x1;
00140 bounds->y1 = y1;
00141 bounds->x2 = x2;
00142 bounds->y2 = y2;
00143 }
00144
00145 static int screen_width, screen_height;
00146
00147 static int
00148 magnifier_main_test_image (gpointer data)
00149 {
00150 static long timing_counter = 0;
00151 static int timing_x_pos = 0;
00152 static int timing_y_pos = 0;
00153 static int x_direction = 1;
00154 static int y_direction = 1;
00155 Magnifier *magnifier = (Magnifier *) data;
00156 GNOME_Magnifier_ZoomRegionList *zoom_regions;
00157 Bonobo_PropertyBag properties;
00158 CORBA_Environment ev;
00159 GNOME_Magnifier_RectBounds roi;
00160 int x_roi, y_roi;
00161
00162
00163 if (global_options.timing_iterations > 0) {
00164 if (timing_counter > global_options.timing_iterations) {
00165 CORBA_exception_init (&ev);
00166 properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev);
00167 if (BONOBO_EX (&ev))
00168 fprintf (stderr, "EXCEPTION\n");
00169
00170 bonobo_pbclient_set_boolean (properties, "exit-magnifier",
00171 TRUE, &ev);
00172 }
00173 }
00174
00175 CORBA_exception_init (&ev);
00176
00177 x_roi = global_options.timing_delta_x * timing_x_pos;
00178 roi.x1 = x_roi;
00179 roi.x2 = (screen_width / global_options.zoom_factor) + roi.x1;
00180 x_roi = global_options.timing_delta_x * (timing_x_pos + x_direction);
00181
00182
00183 if (x_roi + (screen_width / global_options.zoom_factor) > screen_width)
00184 x_direction = -1;
00185 else if (x_roi < 0)
00186 x_direction = 1;
00187
00188 timing_x_pos += x_direction;
00189
00190 y_roi = global_options.timing_delta_y * timing_y_pos;
00191
00192
00193 if (global_options.horizontal_split)
00194 roi.y1 = y_roi + screen_height;
00195 else
00196 roi.y1 = y_roi;
00197 roi.y2 = (screen_height / global_options.zoom_factor) + roi.y1;
00198
00199 y_roi = global_options.timing_delta_y * (timing_y_pos + y_direction);
00200
00201
00202 if (y_roi + (screen_height / global_options.zoom_factor) > screen_height) {
00203 timing_counter++;
00204 y_direction = -1;
00205 }
00206 else if (y_roi < 0) {
00207 timing_counter++;
00208 y_direction = 1;
00209 }
00210
00211 timing_y_pos += y_direction;
00212
00213 if (!IS_MAGNIFIER (magnifier))
00214 return FALSE;
00215
00216 magnifier->priv->cursor_x = (roi.x2 + roi.x1) / 2;
00217 magnifier->priv->cursor_y = (roi.y2 + roi.y1) / 2;
00218
00219 zoom_regions =
00220 GNOME_Magnifier_Magnifier_getZoomRegions (
00221 BONOBO_OBJREF (magnifier),
00222 &ev);
00223
00224 if (zoom_regions && (zoom_regions->_length > 0)) {
00225
00226 GNOME_Magnifier_ZoomRegion_setROI (
00227 zoom_regions->_buffer[0], &roi, &ev);
00228 }
00229
00230 return TRUE;
00231 }
00232
00233 static int last_x = 0, last_y = 0;
00234
00235 static int
00236 magnifier_main_pan_image (gpointer data)
00237 {
00238 Magnifier *magnifier = (Magnifier *) data;
00239 GNOME_Magnifier_ZoomRegionList *zoom_regions;
00240 GNOME_Magnifier_ZoomRegion zoom_region;
00241 CORBA_Environment ev;
00242 GNOME_Magnifier_RectBounds roi;
00243 int mouse_x_return, mouse_y_return;
00244 int w, h;
00245 GdkModifierType mask_return;
00246
00247 CORBA_exception_init (&ev);
00248
00249 if (global_options.mouse_follow && IS_MAGNIFIER (magnifier))
00250 {
00251 gdk_window_get_pointer (
00252 magnifier_get_root (magnifier),
00253 &mouse_x_return,
00254 &mouse_y_return,
00255 &mask_return);
00256
00257 if (last_x != mouse_x_return || last_y != mouse_y_return)
00258 {
00259 last_x = mouse_x_return;
00260 last_y = mouse_y_return;
00261 w = (magnifier->target_bounds.x2 - magnifier->target_bounds.x1);
00262 h = (magnifier->target_bounds.y2 - magnifier->target_bounds.y1);
00263 roi.x1 = mouse_x_return;
00264 roi.y1 = mouse_y_return;
00265 roi.x2 = roi.x1 + 1;
00266 roi.y2 = roi.y1 + 1;
00267
00268 zoom_regions =
00269 GNOME_Magnifier_Magnifier_getZoomRegions (
00270 BONOBO_OBJREF (magnifier),
00271 &ev);
00272 if (zoom_regions && (zoom_regions->_length > 0))
00273 {
00274 int i;
00275 for (i = 0; i < zoom_regions->_length; ++i)
00276 {
00277
00278 zoom_region =
00279 CORBA_Object_duplicate (
00280 ( (CORBA_Object *)
00281 (zoom_regions->_buffer))[i], &ev);
00282 if (zoom_region != CORBA_OBJECT_NIL) {
00283 GNOME_Magnifier_ZoomRegion_setROI (zoom_region,
00284 &roi,
00285 &ev);
00286 } else fprintf (stderr, "nil region!\n");
00287 }
00288 }
00289 }
00290 return TRUE;
00291 }
00292
00293 return FALSE;
00294 }
00295
00296 static int
00297 magnifier_main_refresh_all (gpointer data)
00298 {
00299 int i;
00300 Magnifier *magnifier = data;
00301 CORBA_any *dirty_bounds_any;
00302 CORBA_Environment ev;
00303 Bonobo_PropertyBag properties;
00304 GNOME_Magnifier_RectBounds *dirty_bounds;
00305 GNOME_Magnifier_ZoomRegionList *regions;
00306
00307 CORBA_exception_init (&ev);
00308
00309 if (!IS_MAGNIFIER (magnifier))
00310 return FALSE;
00311
00312 regions = GNOME_Magnifier_Magnifier_getZoomRegions (
00313 BONOBO_OBJREF (magnifier),
00314 &ev);
00315
00316 #ifdef DEBUG_REFRESH
00317 fprintf (stderr, "refreshing %d regions\n", regions->_length);
00318 #endif
00319
00320 properties = GNOME_Magnifier_Magnifier_getProperties (BONOBO_OBJREF (magnifier), &ev);
00321
00322 dirty_bounds_any = Bonobo_PropertyBag_getValue (properties, "source-display-bounds", &ev);
00323 if (BONOBO_EX (&ev)) {
00324 g_warning ("Error getting source-display-bounds");
00325 bonobo_main_quit ();
00326 return FALSE;
00327 }
00328
00329 dirty_bounds = (GNOME_Magnifier_RectBounds *) dirty_bounds_any->_value;
00330
00331 fprintf (stderr, "region to update: %d %d %d %d\n",
00332 dirty_bounds->x1, dirty_bounds->y1, dirty_bounds->x2, dirty_bounds->y2);
00333
00334 for (i = 0; i < regions->_length; ++i)
00335 GNOME_Magnifier_ZoomRegion_markDirty (
00336 regions->_buffer [i], dirty_bounds, &ev);
00337
00338 bonobo_object_release_unref (properties, NULL);
00339
00340 return TRUE;
00341 }
00342
00343 int
00344 main (int argc, char** argv)
00345 {
00346 poptContext ctx;
00347 GNOME_Magnifier_RectBounds *roi = GNOME_Magnifier_RectBounds__alloc();
00348 GNOME_Magnifier_RectBounds *viewport = GNOME_Magnifier_RectBounds__alloc();
00349 CORBA_any *viewport_any;
00350 int x = 0, y = 0, fullwidth, fullheight;
00351 guint pan_handle = 0, refresh_handle = 0;
00352 CORBA_Environment ev;
00353 Bonobo_PropertyBag properties;
00354
00355 Magnifier *magnifier;
00356
00357 if (!bonobo_init (&argc, argv)) {
00358 g_error ("Could not initialize Bonobo");
00359 }
00360 CORBA_exception_init (&ev);
00361
00362 ctx = poptGetContext ("magnifier",
00363 argc,
00364 (const char **)argv,
00365 magnifier_options,
00366 0);
00367
00368 while (poptGetNextOpt (ctx) >= 0)
00369 ;
00370
00371 poptFreeContext (ctx);
00372
00378 if (global_options.target_display) {
00379 gchar *string;
00380 string = g_strconcat ("DISPLAY=", global_options.target_display, NULL);
00381 putenv (string);
00382 }
00383
00384 if (global_options.timing_pan_rate && global_options.timing_iterations == 0)
00385 {
00386 g_error ("Must specify timing_iterations when running pan test");
00387 }
00388
00389
00390 gtk_init (&argc, &argv);
00391
00392 if (global_options.ignore_damage)
00393 {
00394 g_setenv ("MAGNIFIER_IGNORE_DAMAGE", "1", TRUE);
00395 }
00396
00397 magnifier = magnifier_new (global_options.is_override_redirect);
00398
00399 properties = GNOME_Magnifier_Magnifier_getProperties (
00400 BONOBO_OBJREF (magnifier), &ev);
00401 if (ev._major != CORBA_NO_EXCEPTION) fprintf (stderr, "EXCEPTION\n");
00402
00403 if (global_options.source_display)
00404 bonobo_pbclient_set_string (properties, "source-display-screen",
00405 global_options.source_display, NULL);
00406
00407 if (global_options.target_display)
00408 bonobo_pbclient_set_string (properties, "target-display-screen",
00409 global_options.target_display, NULL);
00410
00411 if (global_options.cursor_set)
00412 bonobo_pbclient_set_string (properties, "cursor-set",
00413 global_options.cursor_set, NULL);
00414
00415 if (global_options.cursor_size)
00416 bonobo_pbclient_set_long (properties, "cursor-size",
00417 global_options.cursor_size, NULL);
00418
00419 else if (global_options.cursor_scale_factor != 0.0F)
00420 bonobo_pbclient_set_float (properties, "cursor-scale-factor",
00421 global_options.cursor_scale_factor, NULL);
00422 else
00423 bonobo_pbclient_set_float (properties, "cursor-scale-factor",
00424 global_options.zoom_factor, NULL);
00425
00426 if (global_options.cursor_color)
00427 bonobo_pbclient_set_ulong (properties, "cursor-color",
00428 global_options.cursor_color,
00429 NULL);
00430
00431 fullwidth = screen_width = gdk_screen_get_width (
00432 gdk_display_get_screen (magnifier->target_display,
00433 magnifier->target_screen_num));
00434 fullheight = screen_height = gdk_screen_get_height (
00435 gdk_display_get_screen (magnifier->target_display,
00436 magnifier->target_screen_num));
00437
00438 if (global_options.vertical_split) {
00439 screen_width /= 2;
00440 x = screen_width;
00441 }
00442 if (global_options.horizontal_split) {
00443 screen_height /= 2;
00444 }
00445
00446 fprintf (stderr, "initial viewport %d %d\n", (int) screen_width,
00447 (int) screen_height);
00448
00449 init_rect_bounds (viewport, x, y, x + screen_width, y + screen_height);
00450 viewport_any = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, viewport);
00451
00452 bonobo_pbclient_set_value (properties, "target-display-bounds",
00453 viewport_any,
00454 &ev);
00455 bonobo_arg_release (viewport_any);
00456
00457 if (global_options.vertical_split || global_options.horizontal_split)
00458 {
00459 init_rect_bounds (viewport, 0, 0, fullwidth-x, fullheight-y);
00460 viewport_any = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, viewport);
00461 bonobo_pbclient_set_value (properties, "source-display-bounds",
00462 viewport_any,
00463 &ev);
00464
00465 bonobo_arg_release (viewport_any);
00466 }
00467
00468 bonobo_object_release_unref (properties, NULL);
00469 properties = NULL;
00470
00471 if (global_options.vertical_split ||
00472 global_options.horizontal_split ||
00473 global_options.fullscreen)
00474 {
00475 int scroll_policy;
00476
00477 init_rect_bounds (roi, 0, 0, 100, 100);
00478 init_rect_bounds (viewport, 0, 0, screen_width, screen_height);
00479 zoom_region =
00480 GNOME_Magnifier_Magnifier_createZoomRegion (
00481 BONOBO_OBJREF (magnifier),
00482 global_options.zoom_factor,
00483 global_options.zoom_factor,
00484 roi,
00485 viewport,
00486 &ev);
00487
00488 properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev);
00489 if (BONOBO_EX (&ev))
00490 fprintf (stderr, "EXCEPTION\n");
00491
00492 scroll_policy = global_options.smooth_scroll ?
00493 GNOME_Magnifier_ZoomRegion_SCROLL_SMOOTHEST :
00494 GNOME_Magnifier_ZoomRegion_SCROLL_FASTEST;
00495
00496 bonobo_pbclient_set_long (properties, "timing-iterations",
00497 global_options.timing_iterations, &ev);
00498 bonobo_pbclient_set_boolean (properties, "timing-output",
00499 global_options.timing_output, &ev);
00500 bonobo_pbclient_set_long (properties, "timing-pan-rate",
00501 global_options.timing_pan_rate, &ev);
00502 bonobo_pbclient_set_long (properties, "border-size",
00503 global_options.border_width, &ev);
00504 bonobo_pbclient_set_long (properties, "border-color",
00505 global_options.border_color, &ev);
00506 bonobo_pbclient_set_short (properties, "smooth-scroll-policy",
00507 (short) scroll_policy, &ev);
00508 bonobo_pbclient_set_boolean (properties, "use-test-pattern",
00509 global_options.test_pattern, &ev);
00510
00511 if (strcmp (global_options.smoothing_type, "none"))
00512 bonobo_pbclient_set_string (properties, "smoothing-type",
00513 global_options.smoothing_type, &ev);
00514
00515 if (global_options.invert_image)
00516 bonobo_pbclient_set_boolean (properties, "inverse-video",
00517 global_options.invert_image, NULL);
00518
00519 GNOME_Magnifier_Magnifier_addZoomRegion (
00520 BONOBO_OBJREF (magnifier),
00521 zoom_region,
00522 &ev);
00523
00524 bonobo_object_release_unref (properties, &ev);
00525 properties = NULL;
00526 }
00527
00528 if (global_options.timing_pan_rate)
00529 {
00530 GNOME_Magnifier_ZoomRegionList *zoom_regions;
00531 GNOME_Magnifier_RectBounds roi;
00532 roi.x1 = 100;
00533 roi.x2 = 100 + (screen_width / global_options.zoom_factor);
00534 roi.y1 = 0;
00535 roi.y2 = screen_height / global_options.zoom_factor;
00536
00537 zoom_regions = GNOME_Magnifier_Magnifier_getZoomRegions (
00538 BONOBO_OBJREF (magnifier), &ev);
00539
00540 if (zoom_regions && (zoom_regions->_length > 0))
00541 {
00542 GNOME_Magnifier_ZoomRegion_setROI (
00543 zoom_regions->_buffer[0], &roi, &ev);
00544 }
00545 }
00546 else if (global_options.timing_iterations)
00547 {
00548 refresh_handle = g_timeout_add (global_options.refresh_time,
00549 magnifier_main_test_image,
00550 magnifier);
00551 }
00552 else
00553 {
00554 if (global_options.ignore_damage ||
00555 !magnifier_source_has_damage_extension (magnifier))
00556 {
00557 refresh_handle = g_timeout_add (
00558 global_options.refresh_time,
00559 magnifier_main_refresh_all, magnifier);
00560 }
00561
00562 pan_handle = g_timeout_add (
00563 global_options.mouse_poll_time,
00564 magnifier_main_pan_image, magnifier);
00565 }
00566
00567 bonobo_main ();
00568
00569 if (refresh_handle)
00570 g_source_remove (refresh_handle);
00571
00572 if (pan_handle)
00573 g_source_remove (pan_handle);
00574
00575 return 0;
00576 }