2 #include <gdk/gdkwindow.h>
7 #define ENV_STRING_MAX_SIZE 128
10 * Our parent GObject type
12 #define PARENT_TYPE BONOBO_OBJECT_TYPE
14 struct sockaddr_un mag_server = { AF_UNIX , "/tmp/magnifier_socket" };
17 gchar *target_display;
18 gchar *source_display;
28 int fast_cmap_convert;
29 int no_initial_region;
32 static MagnifierOptions global_options = { ":0.0",
47 struct poptOption magnifier_options [] = {
48 {"target_display", 't', POPT_ARG_STRING, &global_options.target_display, 't', "specify display on which to show magnified view", NULL},
49 {"source_display", 's', POPT_ARG_STRING, &global_options.source_display, 's', "specify display to magnify", NULL},
50 {"vertical", 'v', POPT_ARG_NONE, &global_options.vertical_split, 'v', "split screen vertically (if target display = source display)", NULL},
51 {"horizontal", 'h', POPT_ARG_NONE, &global_options.horizontal_split, 'h', "split screen horizontally (if target display = source display)", NULL},
52 {"dual-head", 'd', POPT_ARG_NONE, &global_options.dual_head, 'd', "dual-head display mode (maps magnifier to second display)", NULL},
53 {"mouse follow", 'm', POPT_ARG_NONE, &global_options.mouse_follow, 'm', "track mouse movements", NULL},
54 {"refresh time", 'r', POPT_ARG_NONE, &global_options.min_refresh_time, 'r', "minimum refresh time for mouse follow and idle, in ms", NULL},
55 {"zoom (scale) factor", 'z', POPT_ARG_FLOAT, &global_options.zoom_factor, 'z', "zoom (scale) factor used to magnify source display", NULL},
56 /* {"invert image", 'i', POPT_ARG_NONE, &global_options.invert_image, 'i', "invert the image colormap", NULL}, */
57 {"fast-colormap-conversion", 'c', POPT_ARG_NONE, &global_options.fast_cmap_convert, 'c', "use faster colormap conversion algorithm (fails for 6 bit color)", NULL},
58 {"no-bonobo", '\0', POPT_ARG_NONE, &global_options.no_bonobo, '\0', "don't use bonobo for controls, use sockets", NULL},
59 {"no-initial-region", '\0', POPT_ARG_NONE, &global_options.no_initial_region, '\0', "don't create an initial zoom region", NULL},
60 {NULL, 0, 0, NULL, 0, 0}
65 static GtkWidget *window; /* TODO: clean up, with accessor func? */
68 magnifier_realize (GtkWidget *widget)
71 Atom wm_window_protocols[2];
72 static gboolean initialized = FALSE;
76 wm_window_protocols[0] = gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW");
77 wm_window_protocols[1] = gdk_x11_get_xatom_by_name ("_NET_WM_PING");
80 wm_hints.flags = InputHint;
81 wm_hints.input = False;
83 XSetWMHints (GDK_WINDOW_XDISPLAY (widget->window),
84 GDK_WINDOW_XWINDOW (widget->window), &wm_hints);
86 XSetWMProtocols (GDK_WINDOW_XDISPLAY (widget->window),
87 GDK_WINDOW_XWINDOW (widget->window), wm_window_protocols, 2);
96 static gboolean get_commands(GIOChannel* client,
97 GIOCondition condition,
102 memset(msg,0,MSG_LEN);
104 if((desc_client = accept(desc,(struct sockaddr*)&client_sockaddr,&size_client)) == -1){
105 perror("Could connect to client");exit(1);
108 read(desc_client,msg,sizeof(msg));
109 parse_message(msg, data);
115 magnifier_pack_regions (Magnifier *magnifier)
118 * this call prevents resizing, which is a bother, but required to
119 * work around dtwm incompatibilities. Perhaps a better workaround will
120 * be found, or we can make this a runtime option.
122 gtk_widget_set_size_request (magnifier->mag_data->output_window,
123 magnifier->mag_data->mag_width,
124 magnifier->mag_data->mag_height);
126 gdk_window_move(magnifier->mag_data->output_window->window,
127 magnifier->mag_data->mag_x,
128 magnifier->mag_data->mag_y);
132 int main (int argc, char** argv){
133 GIOChannel *mag_channel;
135 char env_string[ENV_STRING_MAX_SIZE];
137 /* TODO: finish replacing socket connection IPC with bonobo service. */
138 Magnifier *magnifier;
140 GdkGeometry geometry;
144 size_client = sizeof(client_sockaddr);
148 if (!bonobo_init (&argc, argv))
150 g_error ("Could not initialize Bonobo");
153 magnifier = magnifier_new (argc, argv);
155 magnifier->mag_data->follow_mouse =
156 global_options.mouse_follow;
157 magnifier->mag_data->color_inverted =
158 global_options.invert_image;
159 if (!global_options.no_initial_region)
161 magnifier->mag_data->zoom_regions =
162 g_list_prepend (magnifier->mag_data->zoom_regions,
163 g_new0 (ZoomRegionData, 1));
164 magnifier->mag_data->factor_x = (int) global_options.zoom_factor;
165 magnifier->mag_data->factor_y = (int) global_options.zoom_factor;
168 g_print ("starting magnifier with no initial zoom region\n");
169 magnifier->mag_data->mag_width = 0;
170 magnifier->mag_data->mag_height = 0;
172 /* TODO: enable fractional magnifications option? */
173 if (global_options.target_display) {
174 snprintf (env_string, (size_t) (ENV_STRING_MAX_SIZE-1), "DISPLAY=%s", global_options.target_display);
177 gtk_init (&argc, &argv);
179 window = g_object_connect (gtk_widget_new (gtk_window_get_type (),
182 "type", GTK_WINDOW_TOPLEVEL,
183 "title", "magnifier",
185 "allow_shrink", FALSE,
188 "signal::realize", magnifier_realize, NULL,
189 "signal::destroy", magnifier_exit, NULL,
192 drawing_area = gtk_drawing_area_new();
193 gtk_container_add (GTK_CONTAINER (window),drawing_area);
194 gtk_widget_add_events(GTK_WIDGET(drawing_area),GDK_BUTTON_PRESS_MASK);
195 gtk_signal_connect (GTK_OBJECT (drawing_area),"expose_event",
196 GTK_SIGNAL_FUNC(expose_event),NULL);
199 if (global_options.no_bonobo) {
200 if((desc = socket(AF_UNIX,SOCK_STREAM,0)) == -1){
201 perror("Socket");exit(1);
203 unlink("/tmp/magnifier_socket");
205 if(bind(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1){
206 perror("Bind");exit(1);
209 if(listen(desc,100) == -1){
210 perror("Listen");exit(1);
212 mag_channel = g_io_channel_unix_new(desc);
213 g_io_add_watch(mag_channel,
216 magnifier->mag_data);
220 /* init image information */
221 if (!global_options.source_display) global_options.source_display = gdk_get_display();
222 dpyname = global_options.source_display + (strlen(global_options.source_display) - 1);
223 screen_num = atoi(dpyname);
224 if (!global_options.target_display) {
225 if((screen_num == 0) && global_options.dual_head)
227 else if (global_options.dual_head)
229 global_options.target_display =
230 (char *) malloc (strlen (global_options.source_display));
231 strncpy (global_options.target_display,
232 global_options.source_display,
233 strlen(global_options.source_display)-2);
234 global_options.target_display[strlen(global_options.source_display)-2] = 0;
235 sprintf(global_options.target_display, "%s.%d",
236 global_options.target_display, screen_num);
239 printf("displays: source=%s; target=%s\n",
240 global_options.source_display,
241 global_options.target_display);
243 magnifier->mag_data->source_display = XOpenDisplay (global_options.source_display);
244 magnifier->mag_data->target_display = GDK_DISPLAY();
246 spi_image_root_window = RootWindow(magnifier->mag_data->source_display, screen_num);
247 gdk_pixbuf_xlib_init (magnifier->mag_data->source_display, screen_num);
248 image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
249 DisplayWidth (magnifier->mag_data->source_display,screen_num)/2,
250 DisplayHeight(magnifier->mag_data->source_display,screen_num)/2);
251 scaled_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
252 DisplayWidth (magnifier->mag_data->target_display,screen_num),
253 DisplayHeight(magnifier->mag_data->target_display,screen_num));
254 if (global_options.vertical_split)
256 magnifier->mag_data->mag_width =
257 DisplayWidth (magnifier->mag_data->target_display,screen_num)/2;
258 magnifier->mag_data->mag_height =
259 DisplayHeight (magnifier->mag_data->target_display, screen_num);
261 else if (global_options.horizontal_split)
263 magnifier->mag_data->mag_width =
264 DisplayWidth (magnifier->mag_data->target_display, screen_num);
265 magnifier->mag_data->mag_height =
266 DisplayHeight (magnifier->mag_data->target_display,screen_num)/2;
268 else if (global_options.fullscreen)
270 magnifier->mag_data->mag_width =
271 DisplayWidth (magnifier->mag_data->target_display, screen_num);
272 magnifier->mag_data->mag_height =
273 DisplayHeight (magnifier->mag_data->target_display,screen_num);
275 magnifier->mag_data->mag_x =
276 DisplayWidth (magnifier->mag_data->target_display, screen_num)
277 - magnifier->mag_data->mag_width;
278 magnifier->mag_data->mag_y =
279 DisplayHeight (magnifier->mag_data->target_display, screen_num)
280 - magnifier->mag_data->mag_height;
282 magnifier->mag_data->output_window = window;
283 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
284 gtk_widget_show_all (window);
286 magnifier_pack_regions (magnifier);
288 /* if (global_options.fullscreen) */
289 gdk_window_stick (window->window);
290 gdk_window_set_functions(window->window, 0);
291 gdk_window_raise(window->window);
293 gtk_timeout_add(global_options.min_refresh_time, display_image, magnifier->mag_data);
295 obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1";
297 if (! global_options.no_bonobo)
299 int ret = bonobo_activation_active_server_register (
300 obj_id, BONOBO_OBJREF (magnifier));
302 if (ret == Bonobo_ACTIVATION_REG_SUCCESS)
312 unlink("magnifier_socket");
317 impl_magnifier_fullscreen (PortableServer_Servant servant,
318 CORBA_Environment *ev)
320 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
321 magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display, screen_num);
322 magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display, screen_num);
326 impl_magnifier_set_extents (PortableServer_Servant servant,
331 CORBA_Environment *ev)
333 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
334 magnifier->mag_data->mag_width = x2 - x1;
335 magnifier->mag_data->mag_height = y2 - y1;
336 gdk_window_move(window->window, x1, y1);
340 impl_magnifier_set_follow_mouse (PortableServer_Servant servant,
341 const CORBA_boolean follow_mouse,
342 CORBA_Environment *ev)
344 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
345 magnifier->mag_data->follow_mouse = (int) follow_mouse;
349 impl_magnifier_set_contrast (PortableServer_Servant servant,
350 const CORBA_short contrast,
351 CORBA_Environment *ev)
353 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
354 magnifier->mag_data->contrast = (int) contrast;
358 impl_magnifier_set_source_display (PortableServer_Servant servant,
359 const CORBA_char *display,
360 CORBA_Environment *ev)
362 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
363 magnifier->mag_data->source_display =
364 XOpenDisplay (global_options.source_display);
368 impl_magnifier_set_target_display (PortableServer_Servant servant,
369 const CORBA_char *display,
370 CORBA_Environment *ev)
372 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
373 magnifier->mag_data->target_display = GDK_DISPLAY();
377 impl_magnifier_goto (PortableServer_Servant servant,
380 CORBA_Environment *ev)
382 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
383 magnifier->mag_data->center.x = (int) x;
384 magnifier->mag_data->center.y = (int) y;
388 impl_magnifier_set_roi (PortableServer_Servant servant,
389 const CORBA_short zoom_region,
394 CORBA_Environment *ev)
396 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
397 magnifier->mag_data->center.x = (int) ((x1 + x2)/2);
398 magnifier->mag_data->center.y = (int) ((y1 + y2)/2);
402 impl_magnifier_set_mag_factor (PortableServer_Servant servant,
403 const CORBA_short zoom_region,
404 const CORBA_float mag_factor_x,
405 const CORBA_float mag_factor_y,
406 CORBA_Environment *ev)
408 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
409 if (zoom_region == (CORBA_short) 0) /* TODO: fix for multi-zoom-regions */
411 magnifier->mag_data->factor_x = (float) mag_factor_x;
412 magnifier->mag_data->factor_y = (float) mag_factor_y;
417 impl_magnifier_mark_dirty (PortableServer_Servant servant,
418 const CORBA_short zoom_region,
423 CORBA_Environment *ev)
425 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
426 /* TODO: implement */
430 impl_magnifier_mark_unmanaged (PortableServer_Servant servant,
431 const CORBA_short zoom_region,
432 CORBA_Environment *ev)
434 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
435 /* TODO: implement */
439 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
440 const CORBA_float zx,
441 const CORBA_float zy,
446 CORBA_Environment *ev)
448 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
449 if (magnifier->mag_data->zoom_regions == NULL)
451 magnifier->mag_data->zoom_regions =
452 g_list_prepend (magnifier->mag_data->zoom_regions,
453 g_new0 (ZoomRegionData, 1));
454 magnifier->mag_data->factor_x = (int) zx;
455 magnifier->mag_data->factor_y = (int) zy;
456 magnifier->mag_data->mag_x = x1;
457 magnifier->mag_data->mag_y = y1;
458 magnifier->mag_data->mag_width = (x2 - x1);
459 magnifier->mag_data->mag_height = (y2 - y1);
460 magnifier_pack_regions (magnifier);
470 impl_magnifier_get_zoom_region_params (PortableServer_Servant servant,
471 const CORBA_short zoom_region,
473 CORBA_float * zy, CORBA_long * x1,
474 CORBA_long * y1, CORBA_long * x2,
476 CORBA_Environment * ev)
478 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
479 if (zoom_region == (CORBA_short) 0)
481 *zx = magnifier->mag_data->factor_x;
482 *zy = magnifier->mag_data->factor_y;
485 *x2 = *x1 + magnifier->mag_data->mag_width;
486 *y2 = *y1 + magnifier->mag_data->mag_height;
489 else return CORBA_FALSE;
493 impl_magnifier_resize_zoom_region (PortableServer_Servant servant,
494 const CORBA_short zoom_region,
495 const CORBA_long x1, const CORBA_long y1,
496 const CORBA_long x2, const CORBA_long y2,
497 CORBA_Environment * ev)
499 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
500 if (zoom_region == 0)
502 magnifier->mag_data->mag_x = x1;
503 magnifier->mag_data->mag_y = y1;
504 magnifier->mag_data->mag_width = (x2 - x1);
505 magnifier->mag_data->mag_height = (y2 - y1);
506 magnifier_pack_regions (magnifier);
511 impl_magnifier_destroy_zoom_region (PortableServer_Servant servant,
512 const CORBA_short zoom_region,
513 CORBA_Environment * ev)
515 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
516 if (zoom_region == 0)
518 g_list_free (magnifier->mag_data->zoom_regions);
523 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant servant,
524 CORBA_Environment * ev)
526 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
527 g_list_free (magnifier->mag_data->zoom_regions);
528 magnifier->mag_data->zoom_regions = NULL;
532 impl_magnifier_exit (PortableServer_Servant servant, CORBA_Environment *ev)
538 magnifier_class_init (MagnifierClass *klass)
540 GObjectClass * object_class = (GObjectClass *) klass;
541 POA_Accessibility_Magnifier__epv *epv = &klass->epv;
543 object_class->finalize = magnifier_finalize;
545 epv->_set_SourceDisplay = impl_magnifier_set_source_display;
546 epv->_set_TargetDisplay = impl_magnifier_set_target_display;
547 epv->setROI = impl_magnifier_set_roi;
548 epv->setMagFactor = impl_magnifier_set_mag_factor;
549 epv->markDirty = impl_magnifier_mark_dirty;
550 epv->markUnmanaged = impl_magnifier_mark_unmanaged;
551 epv->createZoomRegion = impl_magnifier_create_zoom_region;
552 epv->getZoomRegionParams = impl_magnifier_get_zoom_region_params;
553 epv->resizeZoomRegion = impl_magnifier_resize_zoom_region;
554 epv->destroyZoomRegion = impl_magnifier_destroy_zoom_region;
555 epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
556 epv->exit = impl_magnifier_exit;
560 magnifier_init (Magnifier *magnifier)
562 magnifier->mag_data = (MagnifierData *) g_new0 (MagnifierData, 1);
563 magnifier->mag_data->factor_x = 2;
564 magnifier->mag_data->factor_y = 2;
565 magnifier->mag_data->contrast = 0;
566 magnifier->mag_data->color_inverted = FALSE;
567 magnifier->mag_data->fast_rgb_convert = FALSE;
568 magnifier->mag_data->center.x = 0;
569 magnifier->mag_data->center.y = 0;
570 magnifier->mag_data->zoom_regions = NULL;
574 magnifier_get_type (void)
576 static GType type = 0;
579 static const GTypeInfo tinfo = {
580 sizeof (MagnifierClass),
581 (GBaseInitFunc) NULL,
582 (GBaseFinalizeFunc) NULL,
583 (GClassInitFunc) magnifier_class_init,
584 (GClassFinalizeFunc) NULL,
585 NULL, /* class data */
588 (GInstanceInitFunc) magnifier_init,
589 NULL /* value table */
592 * Here we use bonobo_type_unique instead of
593 * gtk_type_unique, this auto-generates a load of
594 * CORBA structures for us. All derived types must
595 * use bonobo_type_unique.
597 type = bonobo_type_unique (
599 POA_Accessibility_Magnifier__init,
601 G_STRUCT_OFFSET (MagnifierClass, epv),
610 magnifier_new (int argc, char **argv)
613 Magnifier *magnifier =
614 MAGNIFIER (g_object_new (magnifier_get_type(), NULL));
615 ctx = poptGetContext ("magnifier",
621 while (poptGetNextOpt (ctx) >= 0)