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" };
27 gchar *target_display;
28 gchar *source_display;
38 int fast_cmap_convert;
42 static MagnifierOptions global_options = { ":0.0",
56 struct poptOption magnifier_options [] = {
57 {"target_display", 't', POPT_ARG_STRING, &global_options.target_display, 't', "specify display on which to show magnified view", NULL},
58 {"source_display", 's', POPT_ARG_STRING, &global_options.source_display, 's', "specify display to magnify", NULL},
59 {"vertical", 'v', POPT_ARG_NONE, &global_options.vertical_split, 'v', "split screen vertically (if target display = source display)", NULL},
60 {"horizontal", 'h', POPT_ARG_NONE, &global_options.horizontal_split, 'h', "split screen horizontally (if target display = source display)", NULL},
61 {"dual-head", 'd', POPT_ARG_NONE, &global_options.dual_head, 'd', "dual-head display mode (maps magnifier to second display)", NULL},
62 {"mouse follow", 'm', POPT_ARG_NONE, &global_options.mouse_follow, 'm', "track mouse movements", NULL},
63 {"refresh time", 'r', POPT_ARG_NONE, &global_options.min_refresh_time, 'r', "minimum refresh time for mouse follow and idle, in ms", NULL},
64 {"zoom (scale) factor", 'z', POPT_ARG_FLOAT, &global_options.zoom_factor, 'z', "zoom (scale) factor used to magnify source display", NULL},
65 /* {"invert image", 'i', POPT_ARG_NONE, &global_options.invert_image, 'i', "invert the image colormap", NULL}, */
66 {"fast-colormap-conversion", 'c', POPT_ARG_NONE, &global_options.fast_cmap_convert, 'c', "use faster colormap conversion algorithm (fails for 6 bit color)", NULL},
67 {"no-bonobo", '\0', POPT_ARG_NONE, &global_options.no_bonobo, '\0', "don't use bonobo for controls, use sockets", NULL},
68 {NULL, 0, 0, NULL, 0, 0}
73 static GtkWidget *window; /* TODO: clean up, with accessor func? */
76 magnifier_realize (GtkWidget *widget)
79 Atom wm_window_protocols[2];
80 static gboolean initialized = FALSE;
84 wm_window_protocols[0] = gdk_x11_get_xatom_by_name ("WM_DELETE_WINDOW");
85 wm_window_protocols[1] = gdk_x11_get_xatom_by_name ("_NET_WM_PING");
88 wm_hints.flags = InputHint;
89 wm_hints.input = False;
91 XSetWMHints (GDK_WINDOW_XDISPLAY (widget->window),
92 GDK_WINDOW_XWINDOW (widget->window), &wm_hints);
94 XSetWMProtocols (GDK_WINDOW_XDISPLAY (widget->window),
95 GDK_WINDOW_XWINDOW (widget->window), wm_window_protocols, 2);
104 static gboolean get_commands(GIOChannel* client,
105 GIOCondition condition,
110 memset(msg,0,MSG_LEN);
112 if((desc_client = accept(desc,(struct sockaddr*)&client_sockaddr,&size_client)) == -1){
113 perror("Could connect to client");exit(1);
116 read(desc_client,msg,sizeof(msg));
117 parse_message(msg, data);
122 int main (int argc, char** argv){
123 GIOChannel *mag_channel;
125 char env_string[ENV_STRING_MAX_SIZE];
127 /* TODO: finish replacing socket connection IPC with bonobo service. */
128 Magnifier *magnifier;
130 GdkGeometry geometry;
134 size_client = sizeof(client_sockaddr);
138 if (!bonobo_init (&argc, argv))
140 g_error ("Could not initialize Bonobo");
143 magnifier = magnifier_new (argc, argv);
145 magnifier->mag_data->follow_mouse =
146 global_options.mouse_follow;
147 magnifier->mag_data->color_inverted =
148 global_options.invert_image;
149 magnifier->mag_data->factor_x =
150 (int) global_options.zoom_factor;
151 magnifier->mag_data->factor_y =
152 (int) global_options.zoom_factor;
154 /* TODO: enable fractional magnifications ? */
155 if (global_options.target_display) {
156 snprintf (env_string, (size_t) (ENV_STRING_MAX_SIZE-1), "DISPLAY=%s", global_options.target_display);
159 gtk_init (&argc, &argv);
161 window = g_object_connect (gtk_widget_new (gtk_window_get_type (),
164 "type", GTK_WINDOW_TOPLEVEL,
165 "title", "magnifier",
167 "allow_shrink", FALSE,
170 "signal::realize", magnifier_realize, NULL,
171 "signal::destroy", magnifier_exit, NULL,
174 drawing_area = gtk_drawing_area_new();
175 gtk_container_add (GTK_CONTAINER (window),drawing_area);
176 gtk_widget_add_events(GTK_WIDGET(drawing_area),GDK_BUTTON_PRESS_MASK);
177 gtk_signal_connect (GTK_OBJECT (drawing_area),"expose_event",
178 GTK_SIGNAL_FUNC(expose_event),NULL);
181 if (global_options.no_bonobo) {
182 if((desc = socket(AF_UNIX,SOCK_STREAM,0)) == -1){
183 perror("Socket");exit(1);
185 unlink("/tmp/magnifier_socket");
187 if(bind(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1){
188 perror("Bind");exit(1);
191 if(listen(desc,100) == -1){
192 perror("Listen");exit(1);
194 mag_channel = g_io_channel_unix_new(desc);
195 g_io_add_watch(mag_channel,
198 magnifier->mag_data);
202 /* init image information */
203 if (!global_options.source_display) global_options.source_display = gdk_get_display();
204 dpyname = global_options.source_display + (strlen(global_options.source_display) - 1);
205 screen_num = atoi(dpyname);
206 if (!global_options.target_display) {
207 if((screen_num == 0) && global_options.dual_head)
209 else if (global_options.dual_head)
211 global_options.target_display =
212 (char *) malloc (strlen (global_options.source_display));
213 strncpy (global_options.target_display,
214 global_options.source_display,
215 strlen(global_options.source_display)-2);
216 global_options.target_display[strlen(global_options.source_display)-2] = 0;
217 sprintf(global_options.target_display, "%s.%d",
218 global_options.target_display, screen_num);
221 printf("displays: source=%s; target=%s\n",
222 global_options.source_display,
223 global_options.target_display);
225 magnifier->mag_data->source_display = XOpenDisplay (global_options.source_display);
226 magnifier->mag_data->target_display = GDK_DISPLAY();
228 spi_image_root_window = RootWindow(magnifier->mag_data->source_display, screen_num);
229 gdk_pixbuf_xlib_init (magnifier->mag_data->source_display, screen_num);
230 image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
231 DisplayWidth (magnifier->mag_data->source_display,screen_num)/2,
232 DisplayHeight(magnifier->mag_data->source_display,screen_num)/2);
233 scaled_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
234 DisplayWidth (magnifier->mag_data->target_display,screen_num),
235 DisplayHeight(magnifier->mag_data->target_display,screen_num));
236 if (global_options.vertical_split)
237 magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display,screen_num)/2;
239 magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display, screen_num);
240 if (global_options.horizontal_split)
241 magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display,screen_num)/2;
242 else magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display, screen_num);
243 gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
246 * this call prevents resizing, which is a bother, but required to
247 * work around dtwm incompatibilities. Perhaps a better workaround will
248 * be found, or we can make this a runtime option.
250 gtk_widget_set_size_request (window,
251 magnifier->mag_data->mag_width,
252 magnifier->mag_data->mag_height);
253 gtk_widget_show_all (window);
255 gdk_window_move(window->window,
256 gdk_screen_width() - magnifier->mag_data->mag_width,
257 gdk_screen_height() - magnifier->mag_data->mag_height);
259 magnifier->mag_data->output_window = window;
260 if (global_options.fullscreen) gdk_window_stick (window->window);
261 gdk_window_set_functions(window->window, 0);
262 gdk_window_raise(window->window);
264 gtk_timeout_add(global_options.min_refresh_time, display_image, magnifier->mag_data);
266 obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1";
268 if (! global_options.no_bonobo)
270 int ret = bonobo_activation_active_server_register (
271 obj_id, BONOBO_OBJREF (magnifier));
273 if (ret == Bonobo_ACTIVATION_REG_SUCCESS)
283 unlink("magnifier_socket");
288 impl_magnifier_fullscreen (PortableServer_Servant servant,
289 CORBA_Environment *ev)
291 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
292 magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display, screen_num);
293 magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display, screen_num);
297 impl_magnifier_set_extents (PortableServer_Servant servant,
302 CORBA_Environment *ev)
304 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
305 magnifier->mag_data->mag_width = x2 - x1;
306 magnifier->mag_data->mag_height = y2 - y1;
307 gdk_window_move(window->window, x1, y1);
311 impl_magnifier_set_follow_mouse (PortableServer_Servant servant,
312 const CORBA_boolean follow_mouse,
313 CORBA_Environment *ev)
315 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
316 magnifier->mag_data->follow_mouse = (int) follow_mouse;
320 impl_magnifier_set_contrast (PortableServer_Servant servant,
321 const CORBA_short contrast,
322 CORBA_Environment *ev)
324 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
325 magnifier->mag_data->contrast = (int) contrast;
329 impl_magnifier_set_source_display (PortableServer_Servant servant,
330 const CORBA_char *display,
331 CORBA_Environment *ev)
333 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
334 magnifier->mag_data->source_display =
335 XOpenDisplay (global_options.source_display);
339 impl_magnifier_set_target_display (PortableServer_Servant servant,
340 const CORBA_char *display,
341 CORBA_Environment *ev)
343 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
344 magnifier->mag_data->target_display = GDK_DISPLAY();
348 impl_magnifier_goto (PortableServer_Servant servant,
351 CORBA_Environment *ev)
353 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
354 magnifier->mag_data->center.x = (int) x;
355 magnifier->mag_data->center.y = (int) y;
359 impl_magnifier_set_roi (PortableServer_Servant servant,
360 const CORBA_short zoom_region,
365 CORBA_Environment *ev)
367 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
368 magnifier->mag_data->center.x = (int) ((x1 + x2)/2);
369 magnifier->mag_data->center.y = (int) ((y1 + y2)/2);
373 impl_magnifier_set_mag_factor (PortableServer_Servant servant,
374 const CORBA_short zoom_region,
375 const CORBA_float mag_factor_x,
376 const CORBA_float mag_factor_y,
377 CORBA_Environment *ev)
379 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
380 if (zoom_region == (CORBA_short) 0) /* TODO: fix for multi-zoom-regions */
382 magnifier->mag_data->factor_x = (float) mag_factor_x;
383 magnifier->mag_data->factor_y = (float) mag_factor_y;
388 impl_magnifier_mark_dirty (PortableServer_Servant servant,
389 const CORBA_short zoom_region,
390 CORBA_Environment *ev)
392 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
393 /* TODO: implement */
397 impl_magnifier_mark_unmanaged (PortableServer_Servant servant,
398 const CORBA_short zoom_region,
399 CORBA_Environment *ev)
401 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
402 /* TODO: implement */
406 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
407 const CORBA_float zx,
408 const CORBA_float zy,
413 CORBA_Environment *ev)
415 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
420 impl_magnifier_get_zoom_region_params (PortableServer_Servant servant,
421 const CORBA_short zoom_region,
423 CORBA_float * zy, CORBA_long * x1,
424 CORBA_long * y1, CORBA_long * x2,
426 CORBA_Environment * ev)
428 Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
429 if (zoom_region == (CORBA_short) 0)
431 *zx = magnifier->mag_data->factor_x;
432 *zy = magnifier->mag_data->factor_y;
435 *x2 = *x1 + magnifier->mag_data->mag_width;
436 *y2 = *y1 + magnifier->mag_data->mag_height;
439 else return CORBA_FALSE;
443 impl_magnifier_resize_zoom_region (PortableServer_Servant _servant,
444 const CORBA_short zoom_region,
445 const CORBA_long x1, const CORBA_long y1,
446 const CORBA_long x2, const CORBA_long y2,
447 CORBA_Environment * ev)
452 impl_magnifier_destroy_zoom_region (PortableServer_Servant _servant,
453 const CORBA_short zoom_region,
454 CORBA_Environment * ev)
459 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant _servant,
460 CORBA_Environment * ev)
465 impl_magnifier_exit (PortableServer_Servant servant, CORBA_Environment *ev)
471 magnifier_class_init (MagnifierClass *klass)
473 GObjectClass * object_class = (GObjectClass *) klass;
474 POA_Accessibility_Magnifier__epv *epv = &klass->epv;
476 object_class->finalize = magnifier_finalize;
478 epv->_set_SourceDisplay = impl_magnifier_set_source_display;
479 epv->_set_TargetDisplay = impl_magnifier_set_target_display;
480 epv->setROI = impl_magnifier_set_roi;
481 epv->setMagFactor = impl_magnifier_set_mag_factor;
482 epv->markDirty = impl_magnifier_mark_dirty;
483 epv->markUnmanaged = impl_magnifier_mark_unmanaged;
484 epv->createZoomRegion = impl_magnifier_create_zoom_region;
485 epv->getZoomRegionParams = impl_magnifier_get_zoom_region_params;
486 epv->resizeZoomRegion = impl_magnifier_resize_zoom_region;
487 epv->destroyZoomRegion = impl_magnifier_destroy_zoom_region;
488 epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
489 epv->exit = impl_magnifier_exit;
493 magnifier_init (Magnifier *magnifier)
495 magnifier->mag_data = (MagnifierData *) g_new0 (MagnifierData, 1);
496 magnifier->mag_data->factor_x = 2;
497 magnifier->mag_data->factor_y = 2;
498 magnifier->mag_data->contrast = 0;
499 magnifier->mag_data->color_inverted = FALSE;
500 magnifier->mag_data->fast_rgb_convert = FALSE;
501 magnifier->mag_data->center.x = 0;
502 magnifier->mag_data->center.y = 0;
506 magnifier_get_type (void)
508 static GType type = 0;
511 static const GTypeInfo tinfo = {
512 sizeof (MagnifierClass),
513 (GBaseInitFunc) NULL,
514 (GBaseFinalizeFunc) NULL,
515 (GClassInitFunc) magnifier_class_init,
516 (GClassFinalizeFunc) NULL,
517 NULL, /* class data */
520 (GInstanceInitFunc) magnifier_init,
521 NULL /* value table */
524 * Here we use bonobo_type_unique instead of
525 * gtk_type_unique, this auto-generates a load of
526 * CORBA structures for us. All derived types must
527 * use bonobo_type_unique.
529 type = bonobo_type_unique (
531 POA_Accessibility_Magnifier__init,
533 G_STRUCT_OFFSET (MagnifierClass, epv),
542 magnifier_new (int argc, char **argv)
545 Magnifier *magnifier =
546 MAGNIFIER (g_object_new (magnifier_get_type(), NULL));
547 ctx = poptGetContext ("magnifier",
553 while (poptGetNextOpt (ctx) >= 0)