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 = { NULL,
00073 NULL,
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 } else {
00383 global_options.target_display = getenv ("DISPLAY");
00384 if (!global_options.target_display) {
00385 fprintf (stderr, _("Can't open display, DISPLAY is not set"));
00386 exit (1);
00387 }
00388 }
00389
00390 if (!global_options.source_display) {
00391 global_options.source_display = global_options.target_display;
00392 }
00393
00394 if (global_options.timing_pan_rate && global_options.timing_iterations == 0)
00395 {
00396 g_error ("Must specify timing_iterations when running pan test");
00397 }
00398
00399
00400 gtk_init (&argc, &argv);
00401
00402 if (global_options.ignore_damage)
00403 {
00404 g_setenv ("MAGNIFIER_IGNORE_DAMAGE", "1", TRUE);
00405 }
00406
00407 magnifier = magnifier_new (global_options.is_override_redirect);
00408
00409 properties = GNOME_Magnifier_Magnifier_getProperties (
00410 BONOBO_OBJREF (magnifier), &ev);
00411 if (ev._major != CORBA_NO_EXCEPTION) fprintf (stderr, "EXCEPTION\n");
00412
00413 if (global_options.source_display)
00414 bonobo_pbclient_set_string (properties, "source-display-screen",
00415 global_options.source_display, NULL);
00416
00417 if (global_options.target_display)
00418 bonobo_pbclient_set_string (properties, "target-display-screen",
00419 global_options.target_display, NULL);
00420
00421 if (global_options.cursor_set)
00422 bonobo_pbclient_set_string (properties, "cursor-set",
00423 global_options.cursor_set, NULL);
00424
00425 if (global_options.cursor_size)
00426 bonobo_pbclient_set_long (properties, "cursor-size",
00427 global_options.cursor_size, NULL);
00428
00429 else if (global_options.cursor_scale_factor != 0.0F)
00430 bonobo_pbclient_set_float (properties, "cursor-scale-factor",
00431 global_options.cursor_scale_factor, NULL);
00432 else
00433 bonobo_pbclient_set_float (properties, "cursor-scale-factor",
00434 global_options.zoom_factor, NULL);
00435
00436 if (global_options.cursor_color)
00437 bonobo_pbclient_set_ulong (properties, "cursor-color",
00438 global_options.cursor_color,
00439 NULL);
00440
00441 fullwidth = screen_width = gdk_screen_get_width (
00442 gdk_display_get_screen (magnifier->target_display,
00443 magnifier->target_screen_num));
00444 fullheight = screen_height = gdk_screen_get_height (
00445 gdk_display_get_screen (magnifier->target_display,
00446 magnifier->target_screen_num));
00447
00448 if (global_options.vertical_split) {
00449 screen_width /= 2;
00450 x = screen_width;
00451 }
00452 if (global_options.horizontal_split) {
00453 screen_height /= 2;
00454 }
00455
00456 fprintf (stderr, "initial viewport %d %d\n", (int) screen_width,
00457 (int) screen_height);
00458
00459 init_rect_bounds (viewport, x, y, x + screen_width, y + screen_height);
00460 viewport_any = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, viewport);
00461
00462 bonobo_pbclient_set_value (properties, "target-display-bounds",
00463 viewport_any,
00464 &ev);
00465 bonobo_arg_release (viewport_any);
00466
00467 if (global_options.vertical_split || global_options.horizontal_split)
00468 {
00469 init_rect_bounds (viewport, 0, 0, fullwidth-x, fullheight-y);
00470 viewport_any = bonobo_arg_new_from (TC_GNOME_Magnifier_RectBounds, viewport);
00471 bonobo_pbclient_set_value (properties, "source-display-bounds",
00472 viewport_any,
00473 &ev);
00474
00475 bonobo_arg_release (viewport_any);
00476 }
00477
00478 bonobo_object_release_unref (properties, NULL);
00479 properties = NULL;
00480
00481 if (global_options.vertical_split ||
00482 global_options.horizontal_split ||
00483 global_options.fullscreen)
00484 {
00485 int scroll_policy;
00486
00487 init_rect_bounds (roi, 0, 0, 100, 100);
00488 init_rect_bounds (viewport, 0, 0, screen_width, screen_height);
00489 zoom_region =
00490 GNOME_Magnifier_Magnifier_createZoomRegion (
00491 BONOBO_OBJREF (magnifier),
00492 global_options.zoom_factor,
00493 global_options.zoom_factor,
00494 roi,
00495 viewport,
00496 &ev);
00497
00498 properties = GNOME_Magnifier_ZoomRegion_getProperties (zoom_region, &ev);
00499 if (BONOBO_EX (&ev))
00500 fprintf (stderr, "EXCEPTION\n");
00501
00502 scroll_policy = global_options.smooth_scroll ?
00503 GNOME_Magnifier_ZoomRegion_SCROLL_SMOOTHEST :
00504 GNOME_Magnifier_ZoomRegion_SCROLL_FASTEST;
00505
00506 bonobo_pbclient_set_long (properties, "timing-iterations",
00507 global_options.timing_iterations, &ev);
00508 bonobo_pbclient_set_boolean (properties, "timing-output",
00509 global_options.timing_output, &ev);
00510 bonobo_pbclient_set_long (properties, "timing-pan-rate",
00511 global_options.timing_pan_rate, &ev);
00512 bonobo_pbclient_set_long (properties, "border-size",
00513 global_options.border_width, &ev);
00514 bonobo_pbclient_set_long (properties, "border-color",
00515 global_options.border_color, &ev);
00516 bonobo_pbclient_set_short (properties, "smooth-scroll-policy",
00517 (short) scroll_policy, &ev);
00518 bonobo_pbclient_set_boolean (properties, "use-test-pattern",
00519 global_options.test_pattern, &ev);
00520
00521 if (strcmp (global_options.smoothing_type, "none"))
00522 bonobo_pbclient_set_string (properties, "smoothing-type",
00523 global_options.smoothing_type, &ev);
00524
00525 if (global_options.invert_image)
00526 bonobo_pbclient_set_boolean (properties, "inverse-video",
00527 global_options.invert_image, NULL);
00528
00529 GNOME_Magnifier_Magnifier_addZoomRegion (
00530 BONOBO_OBJREF (magnifier),
00531 zoom_region,
00532 &ev);
00533
00534 bonobo_object_release_unref (properties, &ev);
00535 properties = NULL;
00536 }
00537
00538 if (global_options.timing_pan_rate)
00539 {
00540 GNOME_Magnifier_ZoomRegionList *zoom_regions;
00541 GNOME_Magnifier_RectBounds roi;
00542 roi.x1 = 100;
00543 roi.x2 = 100 + (screen_width / global_options.zoom_factor);
00544 roi.y1 = 0;
00545 roi.y2 = screen_height / global_options.zoom_factor;
00546
00547 zoom_regions = GNOME_Magnifier_Magnifier_getZoomRegions (
00548 BONOBO_OBJREF (magnifier), &ev);
00549
00550 if (zoom_regions && (zoom_regions->_length > 0))
00551 {
00552 GNOME_Magnifier_ZoomRegion_setROI (
00553 zoom_regions->_buffer[0], &roi, &ev);
00554 }
00555 }
00556 else if (global_options.timing_iterations)
00557 {
00558 refresh_handle = g_timeout_add (global_options.refresh_time,
00559 magnifier_main_test_image,
00560 magnifier);
00561 }
00562 else
00563 {
00564 if (global_options.ignore_damage ||
00565 !magnifier_source_has_damage_extension (magnifier))
00566 {
00567 refresh_handle = g_timeout_add (
00568 global_options.refresh_time,
00569 magnifier_main_refresh_all, magnifier);
00570 }
00571
00572 pan_handle = g_timeout_add (
00573 global_options.mouse_poll_time,
00574 magnifier_main_pan_image, magnifier);
00575 }
00576
00577 bonobo_main ();
00578
00579 if (refresh_handle)
00580 g_source_remove (refresh_handle);
00581
00582 if (pan_handle)
00583 g_source_remove (pan_handle);
00584
00585 return 0;
00586 }