added use of non-preemptive keylistener to simple-at test.
[platform/core/uifw/at-spi2-atk.git] / util / magnifier.c
1 #include <popt.h>
2 #include <gdk/gdkwindow.h>
3 #include <bonobo/Bonobo.h>
4 #include "magnifier.h"
5 #include "mag_image.h"
6
7 #define ENV_STRING_MAX_SIZE 128
8
9 /*
10  * Our parent GObject type
11  */
12 #define PARENT_TYPE BONOBO_OBJECT_TYPE
13
14 struct sockaddr_un mag_server = { AF_UNIX ,  "/tmp/magnifier_socket" };
15
16 typedef struct {
17         GdkRectangle extents;
18         GdkRectangle roi;
19         float zoom_x;
20         float zoom_y;
21         int contrast;
22         gboolean is_managed;
23         gboolean is_dirty;
24 } ZoomRegionData;
25
26 typedef struct {
27         gchar *target_display;
28         gchar *source_display;
29         int   vertical_split;
30         int   horizontal_split;
31         int   dual_head;
32         int   fullscreen;
33         int   mouse_follow;
34         int   invert_image;
35         float zoom_factor;
36         int   min_refresh_time;
37         int   no_bonobo;
38         int   fast_cmap_convert;
39         GList *zoom_regions;
40 } MagnifierOptions;
41
42 static MagnifierOptions global_options = { ":0.0",
43                                            ":0.0",
44                                            0,
45                                            0,
46                                            0,
47                                            0,
48                                            0,
49                                            0,
50                                            2.0,
51                                            200,
52                                            0,
53                                            0
54                                          };
55
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}
69 };
70
71 #define MSG_LEN 80
72
73 static gboolean get_commands(GIOChannel* client,
74                              GIOCondition condition,
75                              gpointer data){
76   char msg[MSG_LEN];
77   int desc_client = 0;
78   
79   memset(msg,0,MSG_LEN);
80   
81   if((desc_client = accept(desc,(struct sockaddr*)&client_sockaddr,&size_client)) == -1){
82     perror("Could connect to client");exit(1);
83   }
84   
85   read(desc_client,msg,sizeof(msg));
86   parse_message(msg, data);
87   return TRUE;
88
89 }
90
91 int main (int argc, char** argv){
92   GtkWidget *window;
93   GIOChannel *mag_channel;
94   char *dpyname;
95   char env_string[ENV_STRING_MAX_SIZE];
96
97   /* TODO: finish replacing socket connection IPC with bonobo service. */
98   Magnifier *magnifier;
99   char * obj_id;
100   
101   x_cmap = NULL;
102
103   size_client = sizeof(client_sockaddr);
104
105   image = NULL;
106
107   if (!bonobo_init (&argc, argv))
108     {
109       g_error ("Could not initialize Bonobo");
110     }
111
112   magnifier = magnifier_new (argc, argv);
113   
114   magnifier->mag_data->follow_mouse =
115           global_options.mouse_follow;
116   magnifier->mag_data->color_inverted =
117           global_options.invert_image;
118   magnifier->mag_data->factor_x =
119     (int) global_options.zoom_factor; 
120   magnifier->mag_data->factor_y =
121     (int) global_options.zoom_factor;
122   
123   /* TODO: enable fractional magnifications ? */
124   if (global_options.target_display) {
125     snprintf (env_string, (size_t) (ENV_STRING_MAX_SIZE-1), "DISPLAY=%s", global_options.target_display);
126     putenv (env_string);
127   }
128   gtk_init (&argc, &argv);
129
130   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
131   drawing_area = gtk_drawing_area_new();
132   gtk_container_add (GTK_CONTAINER (window),drawing_area);
133   gtk_widget_add_events(GTK_WIDGET(drawing_area),GDK_BUTTON_PRESS_MASK);
134   gtk_signal_connect (GTK_OBJECT (drawing_area),"expose_event",
135                       GTK_SIGNAL_FUNC(expose_event),NULL);
136   
137   /* Init socket */
138   if (global_options.no_bonobo) {
139     if((desc = socket(AF_UNIX,SOCK_STREAM,0)) == -1){
140       perror("Socket");exit(1);
141     }
142     unlink("/tmp/magnifier_socket");
143
144     if(bind(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1){
145        perror("Bind");exit(1);
146     }
147
148     if(listen(desc,100) == -1){
149        perror("Listen");exit(1);
150     }
151     mag_channel = g_io_channel_unix_new(desc);
152     g_io_add_watch(mag_channel,
153                    G_IO_IN | G_IO_ERR,
154                    get_commands,
155                    magnifier->mag_data);
156
157   }
158   
159   /* init image information */
160   if (!global_options.source_display) global_options.source_display = gdk_get_display();
161   dpyname = global_options.source_display + (strlen(global_options.source_display) - 1);
162   screen_num = atoi(dpyname);
163   if (!global_options.target_display) {
164     if((screen_num == 0) && global_options.dual_head)
165       screen_num++;
166     else if (global_options.dual_head)
167       screen_num--;
168     global_options.target_display =
169             (char *) malloc (strlen (global_options.source_display));
170     strncpy (global_options.target_display,
171              global_options.source_display,
172              strlen(global_options.source_display)-2);
173     global_options.target_display[strlen(global_options.source_display)-2] = 0;
174     sprintf(global_options.target_display, "%s.%d",
175             global_options.target_display, screen_num);
176   }
177
178   printf("displays: source=%s; target=%s\n",
179          global_options.source_display,
180          global_options.target_display);
181   
182   magnifier->mag_data->source_display = XOpenDisplay (global_options.source_display);
183   magnifier->mag_data->target_display = GDK_DISPLAY();
184
185   spi_image_root_window = RootWindow(magnifier->mag_data->source_display, screen_num);
186   gdk_pixbuf_xlib_init (magnifier->mag_data->source_display, screen_num);
187   image = gdk_pixbuf_new        (GDK_COLORSPACE_RGB,FALSE, 8,
188                                 DisplayWidth (magnifier->mag_data->source_display,screen_num)/2,
189                                 DisplayHeight(magnifier->mag_data->source_display,screen_num)/2);
190   scaled_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8,
191                                 DisplayWidth (magnifier->mag_data->target_display,screen_num),
192                                 DisplayHeight(magnifier->mag_data->target_display,screen_num));
193   if (global_options.vertical_split)
194           magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display,screen_num)/2;
195   else
196           magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display, screen_num);
197   if (global_options.horizontal_split)
198           magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display,screen_num)/2;
199   else magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display, screen_num);
200   gtk_widget_show_all (window);
201
202   gdk_window_move(window->window,
203                   gdk_screen_width() - magnifier->mag_data->mag_width,
204                   gdk_screen_height() - magnifier->mag_data->mag_height);
205   gdk_window_resize (window->window, magnifier->mag_data->mag_width, magnifier->mag_data->mag_height);
206   magnifier->mag_data->output_window = window;
207   if (global_options.fullscreen) gdk_window_stick (window->window);
208   gtk_window_set_decorated(GTK_WINDOW (window), FALSE);
209   gdk_window_set_functions(window->window, 0);
210   gdk_window_raise(window->window);
211   
212   gtk_timeout_add(global_options.min_refresh_time, display_image, magnifier->mag_data);
213
214   obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1";
215
216   if (! global_options.no_bonobo)
217     {     
218       bonobo_activation_active_server_register (
219           obj_id,
220           bonobo_object_corba_objref (bonobo_object (magnifier)));
221
222       bonobo_main ();
223     }
224   else
225     {
226       gtk_main ();
227     }
228
229   unlink("magnifier_socket");
230   return 0;
231 }
232
233 static void
234 impl_magnifier_fullscreen (PortableServer_Servant servant,
235                            CORBA_Environment *ev)
236 {
237 }
238                                    
239 static void
240 impl_magnifier_set_extents (PortableServer_Servant servant,
241                             CORBA_long x1,
242                             CORBA_long y1,
243                             CORBA_long x2,
244                             CORBA_long y2,
245                             CORBA_Environment *ev)
246 {
247 }
248
249 static void
250 impl_magnifier_set_follow_mouse (PortableServer_Servant servant,
251                                  const CORBA_boolean follow_mouse,
252                                  CORBA_Environment *ev)
253 {
254   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
255   magnifier->mag_data->follow_mouse = (int) follow_mouse;
256 }
257
258 static void
259 impl_magnifier_set_contrast (PortableServer_Servant servant,
260                              const CORBA_short contrast,
261                              CORBA_Environment *ev)
262 {
263   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
264   magnifier->mag_data->contrast = (int) contrast;
265 }
266
267 static void
268 impl_magnifier_set_source_display (PortableServer_Servant servant,
269                                    const CORBA_char *display,
270                                    CORBA_Environment *ev)
271 {
272   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
273   magnifier->mag_data->source_display =
274           XOpenDisplay (global_options.source_display);
275 }
276
277 static void
278 impl_magnifier_set_target_display (PortableServer_Servant servant,
279                                    const CORBA_char *display,
280                                    CORBA_Environment *ev)
281 {
282   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
283   magnifier->mag_data->target_display = GDK_DISPLAY();
284 }
285
286 static void
287 impl_magnifier_goto (PortableServer_Servant servant,
288                      const CORBA_long x,
289                      const CORBA_long y,
290                      CORBA_Environment *ev)
291 {
292   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
293   magnifier->mag_data->center.x = (int) x;
294   magnifier->mag_data->center.y = (int) y;
295 }
296
297 static void
298 impl_magnifier_set_roi (PortableServer_Servant servant,
299                         const CORBA_short zoom_region,
300                         const CORBA_long x1,
301                         const CORBA_long y1,
302                         const CORBA_long x2,
303                         const CORBA_long y2,
304                         CORBA_Environment *ev)
305 {
306   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
307   magnifier->mag_data->center.x = (int) ((x1 + x2)/2);
308   magnifier->mag_data->center.y = (int) ((y1 + y2)/2);
309 }
310
311 static void
312 impl_magnifier_set_mag_factor (PortableServer_Servant servant,
313                                const CORBA_short zoom_region,
314                                const CORBA_float mag_factor_x,
315                                const CORBA_float mag_factor_y,
316                                CORBA_Environment *ev)
317 {
318   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
319   magnifier->mag_data->factor_x = (float) mag_factor_x;
320   magnifier->mag_data->factor_y = (float) mag_factor_y;
321 }
322
323 static void
324 impl_magnifier_mark_dirty (PortableServer_Servant servant,
325                            const CORBA_short zoom_region,
326                            CORBA_Environment *ev)
327 {
328   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
329 }
330
331 static void
332 impl_magnifier_mark_unmanaged (PortableServer_Servant servant,
333                                const CORBA_short zoom_region,
334                                CORBA_Environment *ev)
335 {
336   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
337 }
338
339 static CORBA_short
340 impl_magnifier_create_zoom_region (PortableServer_Servant servant,
341                                    const CORBA_float zx,
342                                    const CORBA_float zy,
343                                    const CORBA_long x1,
344                                    const CORBA_long y1,
345                                    const CORBA_long x2,
346                                    const CORBA_long y2,
347                                    CORBA_Environment *ev)
348 {
349   Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant));
350   return -1;
351 }
352
353 static CORBA_boolean
354 impl_magnifier_get_zoom_region_params (PortableServer_Servant _servant,
355                                        const CORBA_short zoom_region,
356                                        CORBA_float * zx,
357                                        CORBA_float * zy, CORBA_long * x1,
358                                        CORBA_long * y1, CORBA_long * x2,
359                                        CORBA_long * y2,
360                                        CORBA_Environment * ev)
361 {
362         return CORBA_FALSE;
363 }
364
365 static void
366 impl_magnifier_resize_zoom_region (PortableServer_Servant _servant,
367                                    const CORBA_short zoom_region,
368                                    const CORBA_long x1, const CORBA_long y1,
369                                    const CORBA_long x2, const CORBA_long y2,
370                                    CORBA_Environment * ev)
371 {
372 }
373
374 static void
375 impl_magnifier_destroy_zoom_region (PortableServer_Servant _servant,
376                                     const CORBA_short zoom_region,
377                                     CORBA_Environment * ev)
378 {
379 }
380
381 static void
382 impl_magnifier_clear_all_zoom_regions (PortableServer_Servant _servant,
383                                        CORBA_Environment * ev)
384 {
385 }
386
387 static void
388 impl_magnifier_exit (PortableServer_Servant servant, CORBA_Environment *ev)
389 {
390         ;
391 }
392
393 static void
394 magnifier_class_init (MagnifierClass *klass)
395 {
396         GObjectClass * object_class = (GObjectClass *) klass;
397         POA_Accessibility_Magnifier__epv *epv = &klass->epv;
398 /*
399         object_class->finalize = magnifier_finalize;
400 */
401         epv->_set_SourceDisplay = impl_magnifier_set_source_display;
402         epv->_set_TargetDisplay = impl_magnifier_set_target_display;
403         epv->setROI = impl_magnifier_set_roi;
404         epv->setMagFactor = impl_magnifier_set_mag_factor;
405         epv->markDirty = impl_magnifier_mark_dirty;
406         epv->markUnmanaged = impl_magnifier_mark_unmanaged;
407         epv->createZoomRegion = impl_magnifier_create_zoom_region;
408         epv->getZoomRegionParams = impl_magnifier_get_zoom_region_params;
409         epv->resizeZoomRegion = impl_magnifier_resize_zoom_region;
410         epv->destroyZoomRegion = impl_magnifier_destroy_zoom_region;
411         epv->clearAllZoomRegions = impl_magnifier_clear_all_zoom_regions;
412         epv->exit = impl_magnifier_exit;
413 }
414
415 static void
416 magnifier_init (Magnifier *magnifier)
417 {
418   magnifier->mag_data = (MagnifierData *) g_new0 (MagnifierData, 1);
419   magnifier->mag_data->factor_x = 2;
420   magnifier->mag_data->factor_y = 2;
421   magnifier->mag_data->contrast = 0;
422   magnifier->mag_data->color_inverted = FALSE;
423   magnifier->mag_data->fast_rgb_convert = FALSE;
424   magnifier->mag_data->center.x = 0;
425   magnifier->mag_data->center.y = 0;
426 }
427
428 GType
429 magnifier_get_type (void)
430 {
431         static GType type = 0;
432
433         if (!type) {
434                 static const GTypeInfo tinfo = {
435                         sizeof (MagnifierClass),
436                         (GBaseInitFunc) NULL,
437                         (GBaseFinalizeFunc) NULL,
438                         (GClassInitFunc) magnifier_class_init,
439                         (GClassFinalizeFunc) NULL,
440                         NULL, /* class data */
441                         sizeof (Magnifier),
442                         0, /* n preallocs */
443                         (GInstanceInitFunc) magnifier_init,
444                         NULL /* value table */
445                 };
446                 /*
447                  *   Here we use bonobo_type_unique instead of
448                  * gtk_type_unique, this auto-generates a load of
449                  * CORBA structures for us. All derived types must
450                  * use bonobo_type_unique.
451                  */
452                 type = bonobo_type_unique (
453                         PARENT_TYPE,
454                         POA_Accessibility_Magnifier__init,
455                         NULL,
456                         G_STRUCT_OFFSET (MagnifierClass, epv),
457                         &tinfo,
458                         "Magnifier");
459         }
460
461         return type;
462 }
463
464 Magnifier *
465 magnifier_new(int argc, char **argv)
466 {
467   poptContext ctx;      
468   Magnifier *magnifier =
469           MAGNIFIER (g_object_new (magnifier_get_type(), NULL));
470   ctx = poptGetContext ("magnifier",
471                         argc,
472                         (const char **)argv,
473                         magnifier_options,
474                         0);
475
476   while (poptGetNextOpt (ctx) >= 0)
477         /**/;
478
479   return magnifier;
480 }
481
482
483
484
485
486
487
488
489
490
491
492
493
494     
495
496
497