From 11e760ebf21a1d27d740f6b4a904d36959f587dc Mon Sep 17 00:00:00 2001 From: billh Date: Thu, 27 Sep 2001 21:34:47 +0000 Subject: [PATCH] Added directory 'util' for accessibility-related utilities that use at-spi, and services used by at-spi clients. Added an onscreen magnifier that can be controlled via bonobo (also can use plain sockets). Modified at-spi to send commands to this magnifier if environment variable 'MAGNIFIER' is non-null. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@64 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 45 ++ Makefile.am | 2 +- at-bridge/Makefile.am | 6 +- atk-bridge/Makefile.am | 6 +- configure.in | 16 +- cspi/spi.h | 6 +- libspi/accessible.h | 2 +- test/Makefile.am | 7 +- test/simple-at.c | 62 +- util/Accessibility_Util.server.in | 10 + util/Makefile.am | 56 ++ util/idl/Magnifier.idl | 69 +++ util/mag_client.c | 70 +++ util/mag_client.h | 37 ++ util/mag_control.c | 91 +++ util/mag_image.c | 1205 +++++++++++++++++++++++++++++++++++++ util/mag_image.h | 76 +++ util/magnifier.c | 405 +++++++++++++ util/magnifier.h | 55 ++ 19 files changed, 2164 insertions(+), 62 deletions(-) create mode 100644 util/Accessibility_Util.server.in create mode 100644 util/Makefile.am create mode 100644 util/idl/Magnifier.idl create mode 100644 util/mag_client.c create mode 100644 util/mag_client.h create mode 100644 util/mag_control.c create mode 100644 util/mag_image.c create mode 100644 util/mag_image.h create mode 100644 util/magnifier.c create mode 100644 util/magnifier.h diff --git a/ChangeLog b/ChangeLog index b3fa812..b1580f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +<2001-09-27 Bill Haneman + + * util: + * util/Makefile.am: + Created a new directory for + accessibility-related utilities, primarily for + testing and demo purposes, but with possible + end-user utility. + + * util/magnifier.c: + * util/magnifier.h: + * util/mag_image.c: + * util/mag_image.h: + Onscreen magnifier utility that + is implemented as a bonobo service. + + * util/mag_client.c: + * util/mag_client.h: + Client-side support (simple C bindings) + for Magnification service + + * util/mag_control.c: + Client program example for + Magnification service + + * util/Accessibility_Magnifier.server.in: + Bonobo-activation file for the + Magnification service. + + * util/idl: + * util/idl/Magnifier.idl: + IDL defining the bonobo Magnification + service interface. + + * test/simple-at.c: + Modifications to use the bonobo-activated magnifier + above, in place of trying to connect to an existing + magnifier that uses socket-listening IPC. + + If env variable MAGNIFIER is set, a magnifier service + will be started if one does not exist. + <2001-09-25 Bill Haneman * at-bridge/bridge.c: applied patch from Marc to build and run @@ -7,6 +49,9 @@ made festival-server support turned off by default. Added support for a simple magnifier (off by default) which will be added to a 'util' directory later. + * at-bridge/Makefile.am: + Changed "application.h" header from a 'source' + to a 'dependency' of libat-bridge. <2001-09-12 Marc Mulcahy * cspi/Makefile.am: diff --git a/Makefile.am b/Makefile.am index 99b9331..1a58c83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,3 @@ -SUBDIRS=po docs idl libspi registryd at-bridge cspi test +SUBDIRS=po docs idl libspi registryd at-bridge cspi util test EXTRA_DIST= xml-i18n-extract.in xml-i18n-merge.in xml-i18n-update.in diff --git a/at-bridge/Makefile.am b/at-bridge/Makefile.am index c5d984e..1543657 100644 --- a/at-bridge/Makefile.am +++ b/at-bridge/Makefile.am @@ -1,8 +1,10 @@ lib_LTLIBRARIES = libat-bridge.la libat_bridge_la_SOURCES = \ - bridge.c \ - application.h + bridge.c + +libat_bridge_la_DEPENDENCIES = \ + $(top_srcdir)/libspi/application.h INCLUDES = -I $(top_srcdir) \ -I $(top_builddir) \ diff --git a/atk-bridge/Makefile.am b/atk-bridge/Makefile.am index c5d984e..1543657 100644 --- a/atk-bridge/Makefile.am +++ b/atk-bridge/Makefile.am @@ -1,8 +1,10 @@ lib_LTLIBRARIES = libat-bridge.la libat_bridge_la_SOURCES = \ - bridge.c \ - application.h + bridge.c + +libat_bridge_la_DEPENDENCIES = \ + $(top_srcdir)/libspi/application.h INCLUDES = -I $(top_srcdir) \ -I $(top_builddir) \ diff --git a/configure.in b/configure.in index ea63427..1f1dcbf 100644 --- a/configure.in +++ b/configure.in @@ -87,10 +87,6 @@ PKG_CHECK_MODULES(LIBSPI, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 AC_SUBST(LIBSPI_LIBS) AC_SUBST(LIBSPI_CFLAGS) -PKG_CHECK_MODULES(LIBCSPI, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94 atk >= 0.2) -AC_SUBST(LIBCSPI_LIBS) -AC_SUBST(LIBCSPI_CFLAGS) - PKG_CHECK_MODULES(REGISTRYD, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 atk >= 0.2) AC_SUBST(REGISTRYD_LIBS) AC_SUBST(REGISTRYD_CFLAGS) @@ -99,10 +95,18 @@ PKG_CHECK_MODULES(TESTS, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 AC_SUBST(TESTS_LIBS) AC_SUBST(TESTS_CFLAGS) +PKG_CHECK_MODULES(UTILS, gtk+-2.0 >= 1.3.0 gdk-pixbuf-2.0 >= 1.3.0 bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94) +AC_SUBST(UTILS_LIBS) +AC_SUBST(UTILS_CFLAGS) + PKG_CHECK_MODULES(AT_BRIDGE, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94 atk >= 0.2) AC_SUBST(AT_BRIDGE_LIBS) AC_SUBST(AT_BRIDGE_CFLAGS) +PKG_CHECK_MODULES(LIBCSPI, bonobo-activation-2.0 >= 0.9.1 libbonobo-2.0 >= 1.97.0 ORBit-2.0 >= 2.3.94 atk >= 0.2) +AC_SUBST(LIBCSPI_LIBS) +AC_SUBST(LIBCSPI_CFLAGS) + dnl orbit-idl. ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`" AC_SUBST(ORBIT_IDL) @@ -117,6 +121,9 @@ AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) +AC_CHECK_LIB(popt, poptDupArgv,, +AC_MSG_ERROR([You must have popt 1.5 or greater to compile the utilities.])) + AC_OUTPUT([ Makefile po/Makefile.in @@ -128,6 +135,7 @@ registryd/Accessibility_Registry.server at-bridge/Makefile test/Makefile cspi/Makefile +util/Makefile ]) echo "AT-SPI setup: diff --git a/cspi/spi.h b/cspi/spi.h index 7c7b66a..414ebaf 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -51,10 +51,10 @@ typedef enum } RELATION_TYPE; - +/* don't change the order of these ! */ typedef enum _AccessibleCoordType { - COORD_TYPE_WINDOW, - COORD_TYPE_SCREEN + COORD_TYPE_SCREEN, + COORD_TYPE_WINDOW } AccessibleCoordType; diff --git a/libspi/accessible.h b/libspi/accessible.h index a8876fb..acb2123 100644 --- a/libspi/accessible.h +++ b/libspi/accessible.h @@ -1,4 +1,4 @@ -/* ATK - Accessibility Toolkit +/* AT-SPI : Assistive Technology Service Provider Interface * Copyright 2001 Sun Microsystems Inc. * * This library is free software; you can redistribute it and/or diff --git a/test/Makefile.am b/test/Makefile.am index 52c3020..d9a3ade 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,7 +6,7 @@ at_SOURCES = at.c app_SOURCES = app.c -simple_at_SOURCES = simple-at.c +simple_at_SOURCES = simple-at.c INCLUDES = -I$(top_srcdir) \ -I$(top_builddir) \ @@ -20,4 +20,7 @@ DEBUG_CFLAGS=-DSPI_DEBUG CFLAGS += $(TESTS_CFLAGS) $(DEBUG_CFLAGS) -LDADD = ../libspi/libspi.la ../cspi/libcspi.la $(TESTS_LIBS) +LDADD = ../util/libat-util.la ../libspi/libspi.la ../cspi/libcspi.la $(TESTS_LIBS) + + + diff --git a/test/simple-at.c b/test/simple-at.c index 2a8fc24..904218a 100644 --- a/test/simple-at.c +++ b/test/simple-at.c @@ -25,22 +25,18 @@ #include #include "spi.h" -void report_focus_event (void *fp); - -void report_button_press (void *fp); +static void report_focus_event (void *fp); +static void report_button_press (void *fp); +static void get_environment_vars (void); static int _festival_init (); static void _festival_say (const char *text, const char *voice, boolean shutup); static void _festival_write (const char *buff, int fd); -static void _send_to_magnifier (int x, int y, int w, int h); static boolean use_magnifier = FALSE; static boolean use_festival = FALSE; static boolean festival_chatty = FALSE; -static struct sockaddr_un mag_server = { AF_UNIX , "/tmp/magnifier_socket" }; -static struct sockaddr_un client = { AF_UNIX, "/tmp/mag_client"}; - int main(int argc, char **argv) { @@ -80,7 +76,15 @@ main(int argc, char **argv) fprintf (stderr, "app %d name: %s\n", j, Accessible_getName (application)); } } - + + get_environment_vars(); + + SPI_event_main(FALSE); +} + +static void +get_environment_vars() +{ if (getenv ("FESTIVAL")) { use_festival = TRUE; @@ -93,8 +97,6 @@ main(int argc, char **argv) { use_magnifier = TRUE; } - - SPI_event_main(FALSE); } void @@ -117,13 +119,13 @@ report_focus_event (void *p) { long x, y, width, height; AccessibleComponent *component = Accessible_getComponent (&ev->source); - fprintf (stderr, "Source implements IDL:Accessibility/Component:1.0\n"); AccessibleComponent_getExtents (component, &x, &y, &width, &height, COORD_TYPE_SCREEN); fprintf (stderr, "Bounding box: (%ld, %ld) ; (%ld, %ld)\n", x, y, x+width, y+height); - if (use_magnifier) - _send_to_magnifier (x, y, width, height); + if (use_magnifier) { + magnifier_set_roi (x, y, width, height); + } } } @@ -214,37 +216,3 @@ static void _festival_write (const gchar *command_string, int fd) write(fd, command_string, strlen(command_string)); } -static void -_send_to_magnifier(int x, int y, int w, int h) -{ - int desc, length_msg; - gchar buff[100]; - - sprintf (buff, "~5:%d,%d:", x+w/2, y+h/2); - -#ifdef MAG_DEBUG - g_print ("sending magnifier: %s\n", buff); -#endif - - if((desc=socket(AF_UNIX,SOCK_STREAM,0)) == -1){ - perror("socket"); - return; - } - unlink("/tmp/mag_client"); - - if (bind(desc, (struct sockaddr*)&client, sizeof(client)) == -1) - { - perror("bind"); - return; - } - - if (connect(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1) - { - perror("connect"); - return; - } - - length_msg = write(desc,buff,strlen(buff)); - unlink("/tmp/mag_client"); - return; -} diff --git a/util/Accessibility_Util.server.in b/util/Accessibility_Util.server.in new file mode 100644 index 0000000..1eb2214 --- /dev/null +++ b/util/Accessibility_Util.server.in @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/util/Makefile.am b/util/Makefile.am new file mode 100644 index 0000000..2bd92c2 --- /dev/null +++ b/util/Makefile.am @@ -0,0 +1,56 @@ +NULL= + +lib_LTLIBRARIES = libat-util.la + +bin_PROGRAMS = magnifier + +noinst_PROGRAMS = mag_control + +libat_util_la_SOURCES = \ + mag_client.c \ + mag_client.h \ + Magnifier-common.c \ + Magnifier-stubs.c + +libat_util_la_DEPENDENCIES = \ + Magnifier.h + +magnifier_SOURCES = magnifier.c \ + mag_image.c mag_image.h Magnifier.h \ + Magnifier-skels.c \ + Magnifier-common.c + +mag_control_SOURCES = mag_control.c mag_client.h\ + Magnifier-common.c \ + Magnifier-stubs.c + +INCLUDES = \ + $(UTILS_CFLAGS) \ + -I$(top_srcdir)/util/idl + +CFLAGS += $(UTILS_CFLAGS) + +IDL_OUT = Magnifier.h Magnifier-skels.c Magnifier-stubs.c Magnifier-common.c + +IDL = $(top_srcdir)/util/idl/Magnifier.idl + +BUILT_SOURCES = $(IDL_OUT) +CLEANFILES+=$(IDL_OUT) + +IDLFLAGS = -I$(BONOBO_ACTIVATION_IDL_DIR) \ + -I$(LIBBONOBO_IDL_DIR) \ + -I$(top_srcdir)/util/idl + +orbittypelibdir = $(libdir)/orbit + +LDADD = $(UTILS_LIBS) -L$(prefix)/lib -lgdk_pixbuf_xlib-1.3 + +serverinfodir = $(libdir)/bonobo/servers +serverinfo_DATA = Accessibility_Util.server + +@XML_I18N_MERGE_SERVER_RULE@ + +EXTRA_DIST = Accessibility_Util.server.in $(serverinfo_DATA) + +$(IDL_OUT) : $(IDL) $(ORBIT_IDL) + $(ORBIT_IDL) $(IDLFLAGS) $(IDL) diff --git a/util/idl/Magnifier.idl b/util/idl/Magnifier.idl new file mode 100644 index 0000000..d585c61 --- /dev/null +++ b/util/idl/Magnifier.idl @@ -0,0 +1,69 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ACCESSIBILITY_MAGNIFIER_IDL +#define _ACCESSIBILITY_MAGNIFIER_IDL + +#include + +module Accessibility { + + interface Magnifier : Bonobo::Unknown { + + /** + * #attribute MagFactor: a float indicating the current x and y magnification ratio. + **/ + attribute float MagFactor; + + /** + * #attribute SourceDisplay: a @string containing the X display name + * containing the region to be magnified. + **/ + attribute string SourceDisplay; + + /** + * #attribute TargetDisplay: a @string containing the X display name + * where the magnifier pixels are to be displayed. + **/ + attribute string TargetDisplay; + + /** + * oneway void setROI: + * Sets the region of interest for the magnifier. + * @x1: the minimum X coordinate of the ROI bounding box + * @x2: the maximum X coordinate of the ROI bounding box + * @y1: the minimum Y coordinate of the ROI bounding box + * @y2: the maximum Y coordinate of the ROI bounding box + **/ + oneway void setROI (in long x1, in long y1, in long x2, in long y2); + + /** + * void exit: + * Unmap the current magnifier from the display. + **/ + void exit (); + + }; +}; + +#endif + diff --git a/util/mag_client.c b/util/mag_client.c new file mode 100644 index 0000000..9829e44 --- /dev/null +++ b/util/mag_client.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include "Magnifier.h" +#include "mag_client.h" + +static CORBA_Environment ev; + +Accessibility_Magnifier +get_magnifier() +{ + static Accessibility_Magnifier magnifier = NULL; + static gboolean is_error = FALSE; + CORBA_Object oclient; + char *obj_id; + + if (!magnifier && !is_error) + { + CORBA_exception_init (&ev); + obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1"; + + oclient = bonobo_activation_activate_from_id (obj_id, 0, NULL, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + fprintf (stderr, + ("Activation error: during magnifier activation: %s\n"), + CORBA_exception_id(&ev)); + CORBA_exception_free(&ev); + is_error = TRUE; + } + + if (CORBA_Object_is_nil (oclient, &ev)) + { + g_error ("Could not locate magnifier"); + is_error = TRUE; + } + + magnifier = (Accessibility_Magnifier) oclient; + + /* bonobo_activate (); ? */ + } + + return magnifier; +} + +void +magnifier_set_roi(int x, int y, int w, int h) +{ + Accessibility_Magnifier magnifier = get_magnifier(); + + if (magnifier) + Accessibility_Magnifier_setROI (magnifier, + (const CORBA_long) x, + (const CORBA_long) y, + (const CORBA_long) x+w, + (const CORBA_long) y+h, + &ev); +} + +void +magnifier_set_magnification (float mag_factor) +{ + Accessibility_Magnifier magnifier = get_magnifier(); + + if (magnifier) + Accessibility_Magnifier__set_MagFactor (magnifier, + (const CORBA_short) + ((short) mag_factor), + &ev); +} + diff --git a/util/mag_client.h b/util/mag_client.h new file mode 100644 index 0000000..1287bdb --- /dev/null +++ b/util/mag_client.h @@ -0,0 +1,37 @@ +/* AT-SPI : Assistive Technology Service Provider Interface + * Copyright 2001 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MAG_CLIENT_H_ +#define MAG_CLIENT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +Accessibility_Magnifier get_magnifier(void); +void magnifier_set_roi (int x1, int y1, int x2, int y2); +void magnifier_set_magnification (float mag_factor); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MAG_CLIENT_H_ */ + diff --git a/util/mag_control.c b/util/mag_control.c new file mode 100644 index 0000000..5fde4fd --- /dev/null +++ b/util/mag_control.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include "Magnifier.h" +#include "mag_client.h" + +static CORBA_Environment ev; + +int main(int argc, char ** argv){ + + if (!bonobo_init (&argc, argv)) + { + g_error ("Could not initialize Bonobo"); + } + + CORBA_exception_init (&ev); + + if(argc == 1){ + get_magnifier (); + } + + else { + printf ("setting mag factor to %f\n", (float) atof (argv[1])); + magnifier_set_magnification ((float) atof (argv[1])); + } + sleep (4); + return 0; +} + +Accessibility_Magnifier +get_magnifier() +{ + static Accessibility_Magnifier magnifier = NULL; + static gboolean is_error = FALSE; + CORBA_Object oclient; + char *obj_id; + + if (!magnifier && !is_error) + { + CORBA_exception_init (&ev); + obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1"; + + oclient = bonobo_activation_activate_from_id (obj_id, 0, NULL, &ev); + if (ev._major != CORBA_NO_EXCEPTION) { + fprintf (stderr, + ("Activation error: during magnifier activation: %s\n"), + CORBA_exception_id(&ev)); + CORBA_exception_free(&ev); + is_error = TRUE; + } + + if (CORBA_Object_is_nil (oclient, &ev)) + { + g_error ("Could not locate magnifier"); + is_error = TRUE; + } + + magnifier = (Accessibility_Magnifier) oclient; + + /* bonobo_activate (); ? */ + } + + return magnifier; +} + +void +magnifier_set_roi(int x, int y, int w, int h) +{ + Accessibility_Magnifier magnifier = get_magnifier(); + + if (magnifier) + Accessibility_Magnifier_setROI (magnifier, + (const CORBA_long) x, + (const CORBA_long) y, + (const CORBA_long) x+w, + (const CORBA_long) y+h, + &ev); +} + +void +magnifier_set_magnification (float mag_factor) +{ + Accessibility_Magnifier magnifier = get_magnifier(); + + if (magnifier) + Accessibility_Magnifier__set_MagFactor (magnifier, + (const CORBA_short) + ((short) mag_factor), + &ev); +} + diff --git a/util/mag_image.c b/util/mag_image.c new file mode 100644 index 0000000..a8619ab --- /dev/null +++ b/util/mag_image.c @@ -0,0 +1,1205 @@ +#include "mag_image.h" + + +static int get_num(char* msg); +static void get_coord(char* msg,point *p); +static void get_rect(char* msg, point *p1, point *p2); +static void compute_center_coord(point p1, point p2, point *center); +static xlib_colormap * xlib_get_colormap (Colormap id, Visual *visual, MagnifierData *data); +static guint32 mask_table[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +void parse_message(char *msg, MagnifierData *data){ + + int type; + point roi_pos, roi_size; + point mag_pos, mag_size; + + printf("%s\n",msg); + if(msg[0] != '~'){ + fprintf(stderr,"corrupted message, discarding\n"); + return; + } + type = atoi((char*)&msg[1]); + switch (type){ + case FACTOR : + old_factor = data->factor; + data->factor = get_num(msg); + printf("FACTOR = %d\n",data->factor); + break; + case CONTRAST : + data->contrast = get_num(msg); + printf("CONTRAST = %d\n",data->contrast); + break; + case FOLLOW_MOUSE : + data->follow_mouse = get_num(msg); + printf("FOLLOW_MOUSE = %d\n",data->follow_mouse); + break; + case COLOR_INVERTED : + data->color_inverted = get_num(msg); + printf("COLOR_INVERTED = %d\n",data->color_inverted); + break; + case GOTO : + get_coord(msg, &data->center); + printf("GOTO = (%d,%d)\n", data->center.x, data->center.y); + break; + case SET_ROI: + get_rect (msg, &roi_pos, &roi_size); + printf("ROI = (%d,%d; %d,%d)\n", roi_pos.x, roi_pos.y, roi_size.x, roi_size.y); + compute_center_coord (roi_pos, roi_size, &data->center); + break; + case SET_EXTENTS: + get_rect (msg, &mag_pos, &mag_size); + printf("EXTENTS = (%d,%d; %d,%d)\n", mag_pos.x, mag_pos.y, mag_size.x, mag_size.y); + data->mag_width = mag_size.x; + data->mag_height = mag_size.y; + gdk_window_move_resize (data->output_window->window, mag_pos.x, + mag_pos.y, + data->mag_width, data->mag_height); + break; + case STOP : + printf("STOP\n"); + gtk_main_quit(); + break; + default: + break; + } +} + + +static int get_num(char* msg){ + int type,num; + sscanf(msg,"~%d:%d:",&type,&num); + return num; +} + +static void get_coord(char* msg,point *p){ + int type; + sscanf(msg,"~%d:%d,%d:",&type,&p->x,&p->y); +} + +static void get_rect(char* msg, point *p1, point *p2){ + int type; + sscanf(msg,"~%d:%d,%d;%d,%d:",&type, &p1->x, &p1->y, &p2->x, &p2->y); +} + +static void compute_center_coord (point pos, point size, point *center) { + center->x = pos.x + (size.x/2); + center->y = pos.y + (size.y/2); +} + +int display_image(gpointer data) +{ + MagnifierData *mag_data = (MagnifierData *)data; + update_image(mag_data); + gdk_pixbuf_scale(image, + scaled_image, + 0, + 0, + DisplayWidth (mag_data->target_display,screen_num), + DisplayHeight(mag_data->target_display,screen_num), + 0, + 0, + mag_data->factor, + mag_data->factor, + GDK_INTERP_NEAREST); + + gdk_pixbuf_render_to_drawable (scaled_image, + drawing_area->window, + drawing_area->style->fg_gc[GTK_STATE_NORMAL], + 0,0,0,0,DisplayWidth (mag_data->target_display,screen_num), + DisplayHeight(mag_data->target_display,screen_num), + GDK_RGB_DITHER_NORMAL,0,0); + return TRUE; +} + +void update_image(MagnifierData *mag_data) +{ + int x, y, total_width, total_height; + + if(mag_data->follow_mouse){ + Window root_return, child_return; + int win_x_return,win_y_return; + unsigned int mask_return; + XQueryPointer(mag_data->source_display,image_root_window, + &root_return,&child_return, + &mag_data->center.x,&mag_data->center.y, + &win_x_return,&win_y_return,&mask_return); + } + + total_width = DisplayWidth (mag_data->source_display,screen_num); + total_height = DisplayHeight(mag_data->source_display,screen_num); + + x = mag_data->center.x - mag_data->mag_width/mag_data->factor/2; + y = mag_data->center.y - mag_data->mag_height/mag_data->factor/2; + + if(mag_data->center.x < mag_data->mag_width/mag_data->factor/2) + x = 0; + if(mag_data->center.x > (total_width - mag_data->mag_width/mag_data->factor/2)) + x = total_width - mag_data->mag_width/mag_data->factor; + if(mag_data->center.y < mag_data->mag_height/mag_data->factor/2) + y = 0; + if(mag_data->center.y > (total_height - mag_data->mag_height/mag_data->factor/2)) + y = total_height - mag_data->mag_height/mag_data->factor; + if(x < 0) + x = 0; + if(y < 0) + y = 0; +/* + printf("p = (%d,%d), x,y = (%d,%d), h,w = (%d,%d), ht,wt = (%d,%d)\n", + mag_data->center.x, + mag_data->center.y, + x,y, + mag_data->mag_height,mag_data->mag_width, + total_height, + total_width); +*/ + if(mag_data->factor != old_factor){ + g_object_unref((GObject *)image); + image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8, + DisplayWidth (mag_data->target_display,screen_num)/mag_data->factor, + DisplayHeight(mag_data->target_display,screen_num)/mag_data->factor); + /* yes, use target display above, since the size of the area grabbed depends on the target */ + old_factor = mag_data->factor; + } + get_root_image(image_root_window, + image, + x, + y, + mag_data); +} +void expose_event(GtkWidget * w, GdkEventExpose *event, gpointer data){ + +} + + + + +/* Image grabbing and convertion routines from gdk-pixbuf-xlib */ +/* + convert 1 bits-pixel data + no alpha +*/ +static void +rgb1 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *s; + register guint8 data; + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + + /* convert upto 8 pixels/time */ + /* its probably not worth trying to make this run very fast, who uses + 1 bit displays anymore? */ + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + + for (xx = 0; xx < width; xx ++) { + data = srow[xx >> 3] >> (7 - (xx & 7)) & 1; + *o++ = colormap->colors[data].red; + *o++ = colormap->colors[data].green; + *o++ = colormap->colors[data].blue; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 1 bits/pixel data + with alpha +*/ +static void +rgb1a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *s; + register guint8 data; + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + guint32 remap[2]; + + /* convert upto 8 pixels/time */ + /* its probably not worth trying to make this run very fast, who uses + 1 bit displays anymore? */ + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (xx = 0; xx < 2; xx++) { +#ifdef LITTLE + remap[xx] = 0xff000000 + | colormap->colors[xx].blue << 16 + | colormap->colors[xx].green << 8 + | colormap->colors[xx].red; +#else + remap[xx] = 0xff + | colormap->colors[xx].red << 24 + | colormap->colors[xx].green << 16 + | colormap->colors[xx].blue << 8; +#endif + } + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + + for (xx = 0; xx < width; xx ++) { + data = srow[xx >> 3] >> (7 - (xx & 7)) & 1; + *o++ = remap[data]; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 8 bits/pixel data + no alpha +*/ +static void +rgb8 (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint32 mask; + register guint32 data; + guint8 *srow = image->data, *orow = pixels; + register guint8 *s; + register guint8 *o; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + mask = mask_table[image->depth]; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + data = *s++ & mask; + *o++ = colormap->colors[data].red; + *o++ = colormap->colors[data].green; + *o++ = colormap->colors[data].blue; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 8 bits/pixel data + with alpha +*/ +static void +rgb8a (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + guint32 mask; + register guint32 data; + guint32 remap[256]; + register guint8 *s; /* read 2 pixels at once */ + register guint32 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + mask = mask_table[image->depth]; + + for (xx = 0; xx < colormap->size; xx++) { +#ifdef LITTLE + remap[xx] = 0xff000000 + | colormap->colors[xx].blue << 16 + | colormap->colors[xx].green << 8 + | colormap->colors[xx].red; +#else + remap[xx] = 0xff + | colormap->colors[xx].red << 24 + | colormap->colors[xx].green << 16 + | colormap->colors[xx].blue << 8; +#endif + } + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + data = *s++ & mask; + *o++ = remap[data]; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + no alpha + data in lsb format +*/ +static void +rgb565lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint32 *s; /* read 2 pixels at once */ +#else + register guint8 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; +#else + s = srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + data = *s++; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21; + *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0xf800) | (data & 0xe000) >> 5 + | (data & 0x7e0) >> 3 | (data & 0x600) >> 9; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29; + *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); +#else + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#endif + ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7); + ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3); + ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7); + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + no alpha + data in msb format +*/ +static void +rgb565msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; /* need to swap data order */ +#else + register guint32 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = srow; +#else + s = (guint32 *) srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0xf8000000) >> 16 | (data & 0xe0000000) >> 21; + *o++ = (data & 0x7e00000) >> 19 | (data & 0x6000000) >> 25 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + data = *s++; + *o++ = (data & 0xf800) | (data & 0xe000) >> 5 + | (data & 0x7e0) >> 3 | (data & 0x600) >> 9; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0xf8000000) >> 24 | (data & 0xe0000000) >> 29; + *o++ = (data & 0x7e00000) >> 11 | (data & 0x6000000) >> 17 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#else + data = *((short *) s); +#endif + ((char *) o)[0] = ((data >> 8) & 0xf8) | ((data >> 13) & 0x7); + ((char *) o)[1] = ((data >> 3) & 0xfc) | ((data >> 9) & 0x3); + ((char *) o)[2] = ((data << 3) & 0xf8) | ((data >> 2) & 0x7); + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + with alpha + data in lsb format +*/ +static void +rgb565alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = (guint8 *) srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR ggggggGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB ggggggGG rrrrrRRR */ +#ifdef LITTLE + data = *s++; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11 + | (data & 0x7e0) << 13 | (data & 0x600) << 7 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 16 bits/pixel data + with alpha + data in msb format +*/ +static void +rgb565amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; +#else + register guint16 *s; /* read 1 pixels at once */ +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint32 *) orow; + for (xx = 0; xx < width; xx ++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggg00 bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggg00 rrrrrRRR */ +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0xf800) >> 8 | (data & 0xe000) >> 13 + | (data & 0x7e0) << 5 | (data & 0x600) >> 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + data = *s++; + *o++ = (data & 0xf800) << 16 | (data & 0xe000) << 11 + | (data & 0x7e0) << 13 | (data & 0x600) << 7 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + no alpha + data in lsb format +*/ +static void +rgb555lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint32 *s; /* read 2 pixels at once */ +#else + register guint8 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; +#else + s = srow; +#endif + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + data = *s++; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20; + *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4 + | (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28; + *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); +#else + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#endif + ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12; + ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + no alpha + data in msb format +*/ +static void +rgb555msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint8 *s; /* read 2 pixels at once */ +#else + register guint32 *s; /* read 2 pixels at once */ +#endif + register guint16 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = (guint16 *) orow; + for (xx = 1; xx < width; xx += 2) { + register guint32 data; +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; + s += 4; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1; + *o++ = (data & 0x1f) << 3 | (data & 0x1c) >> 2 + | (data & 0x7c000000) >> 15 | (data & 0x70000000) >> 20; + *o++ = (data & 0x3e00000) >> 18 | (data & 0x3800000) >> 23 + | (data & 0x1f0000) >> 5 | (data & 0x1c0000) >> 10; +#else + data = *s++; + *o++ = (data & 0x7c00) << 1 | (data & 0x7000) >> 4 + | (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + *o++ = (data & 0x1f) << 11 | (data & 0x1c) << 6 + | (data & 0x7c000000) >> 23 | (data & 0x70000000) >> 28; + *o++ = (data & 0x3e00000) >> 10 | (data & 0x3800000) >> 15 + | (data & 0x1f0000) >> 13 | (data & 0x1c0000) >> 18; +#endif + } + /* check for last remaining pixel */ + if (width & 1) { + register guint16 data; +#ifdef LITTLE + data = *((short *) s); + data = ((data >> 8) & 0xff) | ((data & 0xff) << 8); +#else + data = *((short *) s); +#endif + ((char *) o)[0] = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12; + ((char *) o)[1] = (data & 0x3e0) >> 2 | (data & 0x380) >> 7; + ((char *) o)[2] = (data & 0x1f) << 3 | (data & 0x1c) >> 2; + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + with alpha + data in lsb format +*/ +static void +rgb555alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */ +#ifdef LITTLE + data = *s++; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12 + | (data & 0x3e0) << 14 | (data & 0x380) << 9 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +/* + convert 15 bits/pixel data + with alpha + data in msb format +*/ +static void +rgb555amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + +#ifdef LITTLE + register guint16 *s; /* read 1 pixels at once */ +#else + register guint8 *s; +#endif + register guint32 *o; + + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint16 *) srow; +#else + s = srow; +#endif + o = (guint32 *) orow; + for (xx = 0; xx < width; xx++) { + register guint32 data; + /* rrrrrggg gggbbbbb -> rrrrrRRR gggggGGG bbbbbBBB aaaaaaaa */ + /* little endian: aaaaaaaa bbbbbBBB gggggGGG rrrrrRRR */ +#ifdef LITTLE + /* swap endianness first */ + data = s[0] | s[1] << 8; + s += 2; + *o++ = (data & 0x7c00) >> 7 | (data & 0x7000) >> 12 + | (data & 0x3e0) << 6 | (data & 0x380) << 1 + | (data & 0x1f) << 19 | (data & 0x1c) << 14 + | 0xff000000; +#else + data = *s++; + *o++ = (data & 0x7c00) << 17 | (data & 0x7000) << 12 + | (data & 0x3e0) << 14 | (data & 0x380) << 9 + | (data & 0x1f) << 11 | (data & 0x1c) << 6 + | 0xff; +#endif + } + srow += bpl; + orow += rowstride; + } +} + + +static void +rgb888alsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *s; /* for byte order swapping */ + guint8 *o; + guint8 *srow = image->data, *orow = pixels; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + /* lsb data */ + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[2]; + *o++ = s[1]; + *o++ = s[0]; + *o++ = 0xff; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888lsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; + guint8 *o, *s; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[2]; + *o++ = s[1]; + *o++ = s[0]; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888amsb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; +#ifdef LITTLE + guint32 *o; + guint32 *s; +#else + guint8 *s; /* for byte order swapping */ + guint8 *o; +#endif + + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + /* msb data */ + for (yy = 0; yy < height; yy++) { +#ifdef LITTLE + s = (guint32 *) srow; + o = (guint32 *) orow; +#else + s = srow; + o = orow; +#endif + for (xx = 0; xx < width; xx++) { +#ifdef LITTLE + *o++ = s[1]; + *o++ = s[2]; + *o++ = s[3]; + *o++ = 0xff; + s += 4; +#else + *o++ = (*s << 8) | 0xff; /* untested */ + s++; +#endif + } + srow += bpl; + orow += rowstride; + } +} + +static void +rgb888msb (XImage *image, guchar *pixels, int rowstride, xlib_colormap *colormap) +{ + int xx, yy; + int width, height; + int bpl; + + guint8 *srow = image->data, *orow = pixels; + guint8 *s; + guint8 *o; + + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + *o++ = s[1]; + *o++ = s[2]; + *o++ = s[3]; + s += 4; + } + srow += bpl; + orow += rowstride; + } +} +static void +visual_decompose_mask (gulong mask, + gint *shift, + gint *prec) +{ + *shift = 0; + *prec = 0; + + while (!(mask & 0x1)) { + (*shift)++; + mask >>= 1; + } + + while (mask & 0x1) { + (*prec)++; + mask >>= 1; + } +} + + +/* + This should work correctly with any display/any endianness, but will probably + run quite slow +*/ +static void +convert_real_slow (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap, int alpha) +{ + int xx, yy; + int width, height; + int bpl; + guint8 *srow = image->data, *orow = pixels; + guint8 *s; + guint8 *o; + guint32 pixel; + Visual *v; + guint8 component; + int i; + int red_shift, red_prec, green_shift, green_prec, blue_shift, blue_prec; + + width = image->width; + height = image->height; + bpl = image->bytes_per_line; + v = cmap->visual; + + visual_decompose_mask (v->red_mask, &red_shift, &red_prec); + visual_decompose_mask (v->green_mask, &green_shift, &green_prec); + visual_decompose_mask (v->blue_mask, &blue_shift, &blue_prec); + + for (yy = 0; yy < height; yy++) { + s = srow; + o = orow; + for (xx = 0; xx < width; xx++) { + pixel = XGetPixel (image, xx, yy); + switch (v->class) { + /* I assume this is right for static & greyscale's too? */ + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + *o++ = cmap->colors[pixel].red; + *o++ = cmap->colors[pixel].green; + *o++ = cmap->colors[pixel].blue; + break; + case TrueColor: + /* This is odd because it must sometimes shift left (otherwise + I'd just shift >> (*_shift - 8 + *_prec + <0-7>). This logic + should work for all bit sizes/shifts/etc. */ + component = 0; + for (i = 24; i < 32; i += red_prec) + component |= ((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> i; + *o++ = component; + component = 0; + for (i = 24; i < 32; i += green_prec) + component |= ((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> i; + *o++ = component; + component = 0; + for (i = 24; i < 32; i += blue_prec) + component |= ((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> i; + *o++ = component; + break; + case DirectColor: + *o++ = cmap->colors[((pixel & v->red_mask) << (32 - red_shift - red_prec)) >> 24].red; + *o++ = cmap->colors[((pixel & v->green_mask) << (32 - green_shift - green_prec)) >> 24].green; + *o++ = cmap->colors[((pixel & v->blue_mask) << (32 - blue_shift - blue_prec)) >> 24].blue; + break; + } + if (alpha) + *o++ = 0xff; + } + srow += bpl; + orow += rowstride; + } +} + +static xlib_colormap * +xlib_get_colormap (Colormap id, Visual *visual, MagnifierData *mag_data) +{ + int i; + xlib_colormap *xc = g_new (xlib_colormap, 1); + + xc->size = visual->map_entries; + xc->colors = g_new (XColor, xc->size); + xc->visual = visual; + xc->colormap = id; + + for (i = 0; i < xc->size; i++) { + xc->colors[i].pixel = i; + xc->colors[i].flags = DoRed | DoGreen | DoBlue; + } + + XQueryColors (mag_data->source_display, xc->colormap, xc->colors, xc->size); + + return xc; +} + +typedef void (* cfunc) (XImage *image, guchar *pixels, int rowstride, xlib_colormap *cmap); +static cfunc convert_map[] = { + rgb1,rgb1,rgb1a,rgb1a, + rgb8,rgb8,rgb8a,rgb8a, + rgb555lsb,rgb555msb,rgb555alsb,rgb555amsb, + rgb565lsb,rgb565msb,rgb565alsb,rgb565amsb, + rgb888lsb,rgb888msb,rgb888alsb,rgb888amsb +}; + +static void +rgbconvert (XImage *image, guchar *pixels, int rowstride, int alpha, xlib_colormap *cmap) +{ + int index = (image->byte_order == MSBFirst) | (alpha != 0) << 1; + int bank=5; /* default fallback converter */ + Visual *v = cmap->visual; + + switch (v->class) { + /* I assume this is right for static & greyscale's too? */ + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + switch (image->bits_per_pixel) { + case 1: + bank = 0; + break; + case 8: + bank = 1; + break; + } + break; + case TrueColor: + switch (image->depth) { + case 15: + if (v->red_mask == 0x7c00 && v->green_mask == 0x3e0 && v->blue_mask == 0x1f + && image->bits_per_pixel == 16) + bank = 2; + break; + case 16: + if (v->red_mask == 0xf800 && v->green_mask == 0x7e0 && v->blue_mask == 0x1f + && image->bits_per_pixel == 16) + bank = 3; + break; + case 24: + case 32: + if (v->red_mask == 0xff0000 && v->green_mask == 0xff00 && v->blue_mask == 0xff + && image->bits_per_pixel == 32) + bank = 4; + break; + } + break; + case DirectColor: + /* always use the slow version */ + break; + } + + if (bank==5) { + convert_real_slow(image, pixels, rowstride, cmap, alpha); + } else { + index |= bank << 2; + (* convert_map[index]) (image, pixels, rowstride, cmap); + } +} + + + +void get_root_image(Window src,GdkPixbuf *dest, int src_x, int src_y, MagnifierData *mag_data) { + XImage *image; + int width = mag_data->mag_width/mag_data->factor; + int height = mag_data->mag_height/mag_data->factor; + + /* Get Image in ZPixmap format (packed bits). */ + image = XGetImage (mag_data->source_display, src, src_x, src_y, + width, height, AllPlanes, ZPixmap); + g_assert(image != NULL); + + if(x_cmap == NULL){ + XWindowAttributes wa; + XGetWindowAttributes (mag_data->source_display, src, &wa); + x_cmap = xlib_get_colormap (wa.colormap, wa.visual, mag_data); + } + /* we offset into the image data based on the position we are retrieving from */ + rgbconvert (image, gdk_pixbuf_get_pixels(dest), + gdk_pixbuf_get_rowstride(dest), + gdk_pixbuf_get_has_alpha(dest), + x_cmap); + XDestroyImage (image); +} + + diff --git a/util/mag_image.h b/util/mag_image.h new file mode 100644 index 0000000..a816a8b --- /dev/null +++ b/util/mag_image.h @@ -0,0 +1,76 @@ +#ifndef __MAGNIFIER_IMAGE_H__ +#define __MAGNIFIER_IMAGE_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct _point { + int x; + int y; +} point; + +typedef struct xlib_colormap_struct xlib_colormap; + +struct xlib_colormap_struct { + int size; + XColor *colors; + Visual *visual; + Colormap colormap; +}; + +point center_position; +point curpos; /* Position of the magnified cursor */ +GdkPixbuf* image; +GdkPixbuf* scaled_image; +Window image_root_window; +int screen_num; +int old_factor; +xlib_colormap * x_cmap; + +typedef struct _MagnifierData { + int mag_width; + int mag_height; + int factor; + point center; + int follow_mouse; + int color_inverted; + int contrast; + GtkWidget *output_window; + void *source_display; + void *target_display; +} MagnifierData; + +#define FACTOR 1 +#define CONTRAST 2 +#define FOLLOW_MOUSE 3 +#define COLOR_INVERTED 4 +#define GOTO 5 +#define STOP 6 +#define SET_ROI 7 +#define SET_EXTENTS 8 + +struct sockaddr_un mag_server; +struct sockaddr_un client_sockaddr; +int size_client; +int desc; +GtkWidget *drawing_area; + +void parse_message(char *msg, MagnifierData *data); +void update_image(MagnifierData *data); +void expose_event(GtkWidget * w, GdkEventExpose *event, gpointer data); +void get_root_image(Window src,GdkPixbuf *dest,int src_x, int src_y, MagnifierData *data); +int display_image(gpointer data); + +#endif + diff --git a/util/magnifier.c b/util/magnifier.c new file mode 100644 index 0000000..c8e75c6 --- /dev/null +++ b/util/magnifier.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include "magnifier.h" +#include "mag_image.h" + +#define ENV_STRING_MAX_SIZE 128 + +/* + * Our parent GObject type + */ +#define PARENT_TYPE BONOBO_OBJECT_TYPE + +struct sockaddr_un mag_server = { AF_UNIX , "/tmp/magnifier_socket" }; + +typedef struct { + gchar *target_display; + gchar *source_display; + int vertical_split; + int horizontal_split; + int dual_head; + int fullscreen; + int mouse_follow; + int invert_image; + float zoom_factor; + int refresh_time; + int no_bonobo; +} MagnifierOptions; + +static MagnifierOptions global_options = { ":0.0", + ":0.0", + 0, + 0, + 0, + 0, + 0, + 0, + 2.0, + 200, + 0 + }; + +struct poptOption magnifier_options [] = { + {"target_display", 't', POPT_ARG_STRING, &global_options.target_display, 't', "specify display on which to show magnified view", NULL}, + {"source_display", 's', POPT_ARG_STRING, &global_options.source_display, 's', "specify display to magnify", NULL}, + {"vertical", 'v', POPT_ARG_NONE, &global_options.vertical_split, 'v', "split screen vertically (if target display = source display)", NULL}, + {"horizontal", 'h', POPT_ARG_NONE, &global_options.horizontal_split, 'h', "split screen horizontally (if target display = source display)", NULL}, + {"dual-head", 'd', POPT_ARG_NONE, &global_options.dual_head, 'd', "dual-head display mode (maps magnifier to second display)", NULL}, + {"mouse follow", 'm', POPT_ARG_NONE, &global_options.mouse_follow, 'm', "track mouse movements", NULL}, + {"refresh time", 'r', POPT_ARG_NONE, &global_options.refresh_time, 'r', "refresh time for mouse follow and idle, in ms", NULL}, + {"zoom (scale) factor", 'z', POPT_ARG_FLOAT, &global_options.zoom_factor, 'z', "zoom (scale) factor used to magnify source display", NULL}, +/* {"invert image", 'i', POPT_ARG_NONE, &global_options.invert_image, 'i', "invert the image colormap", NULL}, */ + {"no-bonobo", '\0', POPT_ARG_NONE, &global_options.no_bonobo, '\0', "don't use bonobo for controls, use sockets", NULL}, + {NULL, 0, 0, NULL, 0, 0} +}; + +#define MSG_LEN 80 + +static gboolean get_commands(GIOChannel* client, + GIOCondition condition, + gpointer data){ + char msg[MSG_LEN]; + int desc_client = 0; + + memset(msg,0,MSG_LEN); + + if((desc_client = accept(desc,(struct sockaddr*)&client_sockaddr,&size_client)) == -1){ + perror("Could connect to client");exit(1); + } + + read(desc_client,msg,sizeof(msg)); + parse_message(msg, data); + return TRUE; + +} + +int main (int argc, char** argv){ + GtkWidget *window; + GIOChannel *mag_channel; + char *dpyname; + char env_string[ENV_STRING_MAX_SIZE]; + + /* TODO: finish replacing socket connection IPC with bonobo service. */ + Magnifier *magnifier; + char * obj_id; + + x_cmap = NULL; + + size_client = sizeof(client_sockaddr); + + image = NULL; + + if (!bonobo_init (&argc, argv)) + { + g_error ("Could not initialize Bonobo"); + } + + magnifier = magnifier_new (argc, argv); + + magnifier->mag_data->follow_mouse = + global_options.mouse_follow; + magnifier->mag_data->color_inverted = + global_options.invert_image; + magnifier->mag_data->factor = + (int) global_options.zoom_factor; + + /* TODO: enable fractional magnifications ? */ + + if (global_options.target_display) { + snprintf (env_string, (size_t) (ENV_STRING_MAX_SIZE-1), "DISPLAY=%s", global_options.target_display); + putenv (env_string); + } + gtk_init (&argc, &argv); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + drawing_area = gtk_drawing_area_new(); + gtk_container_add (GTK_CONTAINER (window),drawing_area); + gtk_widget_add_events(GTK_WIDGET(drawing_area),GDK_BUTTON_PRESS_MASK); + gtk_signal_connect (GTK_OBJECT (drawing_area),"expose_event", + GTK_SIGNAL_FUNC(expose_event),NULL); + + /* Init socket */ + if (global_options.no_bonobo) { + if((desc = socket(AF_UNIX,SOCK_STREAM,0)) == -1){ + perror("Socket");exit(1); + } + unlink("/tmp/magnifier_socket"); + + if(bind(desc,(struct sockaddr*)&mag_server,sizeof(mag_server)) == -1){ + perror("Bind");exit(1); + } + + if(listen(desc,100) == -1){ + perror("Listen");exit(1); + } + mag_channel = g_io_channel_unix_new(desc); + g_io_add_watch(mag_channel, + G_IO_IN | G_IO_ERR, + get_commands, + magnifier->mag_data); + + } + + /* init image information */ + if (!global_options.source_display) global_options.source_display = gdk_get_display(); + dpyname = global_options.source_display + (strlen(global_options.source_display) - 1); + screen_num = atoi(dpyname); + if (!global_options.target_display) { + if((screen_num == 0) && global_options.dual_head) + screen_num++; + else if (global_options.dual_head) + screen_num--; + global_options.target_display = + (char *) malloc (strlen (global_options.source_display)); + strncpy (global_options.target_display, + global_options.source_display, + strlen(global_options.source_display)-2); + global_options.target_display[strlen(global_options.source_display)-2] = 0; + sprintf(global_options.target_display, "%s.%d", + global_options.target_display, screen_num); + } + + printf("displays: source=%s; target=%s\n", + global_options.source_display, + global_options.target_display); + + magnifier->mag_data->source_display = XOpenDisplay (global_options.source_display); + magnifier->mag_data->target_display = GDK_DISPLAY(); + + image_root_window = RootWindow(magnifier->mag_data->source_display, screen_num); + gdk_pixbuf_xlib_init (magnifier->mag_data->source_display, screen_num); + image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8, + DisplayWidth (magnifier->mag_data->source_display,screen_num)/2, + DisplayHeight(magnifier->mag_data->source_display,screen_num)/2); + scaled_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,FALSE, 8, + DisplayWidth (magnifier->mag_data->target_display,screen_num), + DisplayHeight(magnifier->mag_data->target_display,screen_num)); + if (global_options.vertical_split) + magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display,screen_num)/2; + else + magnifier->mag_data->mag_width = DisplayWidth (magnifier->mag_data->target_display, screen_num); + if (global_options.horizontal_split) + magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display,screen_num)/2; + else magnifier->mag_data->mag_height = DisplayHeight (magnifier->mag_data->target_display, screen_num); + gtk_widget_show_all (window); + + gdk_window_move(window->window, + gdk_screen_width() - magnifier->mag_data->mag_width, + gdk_screen_height() - magnifier->mag_data->mag_height); + gdk_window_resize (window->window, magnifier->mag_data->mag_width, magnifier->mag_data->mag_height); + magnifier->mag_data->output_window = window; + if (global_options.fullscreen) gdk_window_stick (window->window); + gdk_window_set_decorations(window->window, 0); + gdk_window_set_functions(window->window, 0); + gdk_window_raise(window->window); + + gtk_timeout_add(global_options.refresh_time, display_image, magnifier->mag_data); + + obj_id = "OAFIID:Accessibility_Util_Magnifier:proto0.1"; + + if (! global_options.no_bonobo) + { + bonobo_activation_active_server_register ( + obj_id, + bonobo_object_corba_objref (bonobo_object (magnifier))); + + bonobo_main (); + } + else + { + gtk_main (); + } + + unlink("magnifier_socket"); + return 0; +} + +static void +impl_magnifier_fullscreen (PortableServer_Servant servant, + CORBA_Environment *ev) +{ +} + +static void +impl_magnifier_set_extents (PortableServer_Servant servant, + CORBA_long x1, + CORBA_long y1, + CORBA_long x2, + CORBA_long y2, + CORBA_Environment *ev) +{ +} + +static void +impl_magnifier_set_follow_mouse (PortableServer_Servant servant, + const CORBA_boolean follow_mouse, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->follow_mouse = (int) follow_mouse; +} + +static void +impl_magnifier_set_contrast (PortableServer_Servant servant, + const CORBA_short contrast, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->contrast = (int) contrast; +} + +static void +impl_magnifier_set_source_display (PortableServer_Servant servant, + const CORBA_char *display, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->source_display = + XOpenDisplay (global_options.source_display); +} + +static void +impl_magnifier_set_target_display (PortableServer_Servant servant, + const CORBA_char *display, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->target_display = GDK_DISPLAY(); +} + +static void +impl_magnifier_goto (PortableServer_Servant servant, + const CORBA_long x, + const CORBA_long y, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->center.x = (int) x; + magnifier->mag_data->center.y = (int) y; +} + +static void +impl_magnifier_set_roi (PortableServer_Servant servant, + const CORBA_long x1, + const CORBA_long y1, + const CORBA_long x2, + const CORBA_long y2, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->center.x = (int) ((x1 + x2)/2); + magnifier->mag_data->center.y = (int) ((y1 + y2)/2); +} + +static void +impl_magnifier_set_mag_factor (PortableServer_Servant servant, + const CORBA_float mag_factor, + CORBA_Environment *ev) +{ + Magnifier *magnifier = MAGNIFIER (bonobo_object_from_servant (servant)); + magnifier->mag_data->factor = (float) mag_factor; +} + +static void +impl_magnifier_exit (PortableServer_Servant servant, CORBA_Environment *ev) +{ + ; +} + +static void +magnifier_class_init (MagnifierClass *klass) +{ + GObjectClass * object_class = (GObjectClass *) klass; + POA_Accessibility_Magnifier__epv *epv = &klass->epv; +/* + object_class->finalize = magnifier_finalize; +*/ + epv->_set_SourceDisplay = impl_magnifier_set_source_display; + epv->_set_TargetDisplay = impl_magnifier_set_target_display; + epv->setROI = impl_magnifier_set_roi; + epv->_set_MagFactor = impl_magnifier_set_mag_factor; + epv->exit = impl_magnifier_exit; +} + +static void +magnifier_init (Magnifier *magnifier) +{ + magnifier->mag_data = (MagnifierData *) g_new0 (MagnifierData, 1); + magnifier->mag_data->factor = 2; + magnifier->mag_data->contrast = 0; + magnifier->mag_data->color_inverted = FALSE; + magnifier->mag_data->center.x = 0; + magnifier->mag_data->center.y = 0; +} + +GType +magnifier_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = { + sizeof (MagnifierClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) magnifier_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class data */ + sizeof (Magnifier), + 0, /* n preallocs */ + (GInstanceInitFunc) magnifier_init, + NULL /* value table */ + }; + /* + * Here we use bonobo_type_unique instead of + * gtk_type_unique, this auto-generates a load of + * CORBA structures for us. All derived types must + * use bonobo_type_unique. + */ + type = bonobo_type_unique ( + PARENT_TYPE, + POA_Accessibility_Magnifier__init, + NULL, + G_STRUCT_OFFSET (MagnifierClass, epv), + &tinfo, + "Magnifier"); + } + + return type; +} + +Magnifier * +magnifier_new(int argc, char **argv) +{ + poptContext ctx; + Magnifier *magnifier = + MAGNIFIER (g_object_new (magnifier_get_type(), NULL)); + ctx = poptGetContext ("magnifier", + argc, + (const char **)argv, + magnifier_options, + 0); + + while (poptGetNextOpt (ctx) >= 0) + /**/; + + return magnifier; +} + + + + + + + + + + + + + + + + + diff --git a/util/magnifier.h b/util/magnifier.h new file mode 100644 index 0000000..082f966 --- /dev/null +++ b/util/magnifier.h @@ -0,0 +1,55 @@ +/* AT-SPI : Assistive Technology Service Provider Interface + * Copyright 2001 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef MAGNIFIER_H_ +#define MAGNIFIER_H_ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include "Magnifier.h" +#include "mag_image.h" /* TODO: remove this include */ + +#define MAGNIFIER_TYPE (magnifier_get_type ()) +#define MAGNIFIER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MAGNIFIER_TYPE, Magnifier)) +#define MAGNIFIER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MAGNIFIER_TYPE, MagnifierClass)) +#define IS_MAGNIFIER(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), MAGNIFIER_TYPE)) +#define IS_MAGNIFIER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), MAGNIFIER_TYPE)) + +typedef struct { + BonoboObject parent; + MagnifierData *mag_data; +} Magnifier; + +typedef struct { + BonoboObjectClass parent_class; + POA_Accessibility_Magnifier__epv epv; +} MagnifierClass; + +GType magnifier_get_type (void); +Magnifier *magnifier_new (int argc, char **argv); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MAGNIFIER_H_ */ -- 2.7.4