From 8b6d7a2723c7c5562f23e761b47b226ba45ac642 Mon Sep 17 00:00:00 2001 From: Packit Date: Sep 17 2020 15:19:13 +0000 Subject: at-spi2-core-2.28.0 base --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6f89ab4 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,17 @@ + +Authors of AT-SPI D-Bus implementation +-------------------------------------- + +Mike Gorse +Mark Doffman + + +Authors of AT-SPI spec & implementation in CORBA +------------------------------------------------ + +Bill Haneman +Marc Mulcahy +Michael Meeks + +with contributions from: +Mark McLoughlin diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b8f9ad6 --- /dev/null +++ b/COPYING @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..54c3246 --- /dev/null +++ b/INSTALL @@ -0,0 +1,26 @@ +Install procedure +----------------- + + % gzip -cd at-spi-core-2.0.0.tar.gz | tar xvf - # unpack the sources + % cd at-spi-core-2.0.0 # change to the toplevel directory + % ./configure # run the `configure' script + % make # build at-spi-core + + [ Become root if necessary ] + % make install # install at-spi-core + +Requirements +------------ + + GNU make + GNU autotools + + pkg-config + + glib + + dbus + dbus-glib + + X + XEVIE (Reccomended) diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..34024c3 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1 @@ +Mike Gorse diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3092770 --- /dev/null +++ b/NEWS @@ -0,0 +1,891 @@ +What's new in at-spi2-core 2.27.92: + +* Support building a static library (bgo#793652). +\ +* Fix build on FreeBSD (bgo#791608). + +What's new in at-spi2-core 2.27.1: + +* Dropped autotools support. + +* documentation: Remove list association from + ATSPI_ROLE_DESCRIPTION_{TERM,VALUE} (bgo#791021). + +* Fix a potential buffer overflow in at-spi-bus-launcher (bgo#791124). + +* Make the build reproducible (bgo#791167). + +What's new in at-spi2-core 2.26.1: + +* Remove unused dependency on libxkbcommon. + +* Various meson build fixes. + +* Updated Dutch and Catalan translations. + +What's new in at-spi2-core 2.25.92: + +* configure.ac: make xkb optional, as intended. + +* Optionally read the bus address from the ATSPI_BUS_ADDRESS environment + variable (bgo#787126). + +What's new in at-spi2-core 2.25.91: + +* Meson builds should now be usable. + +What's new in at-spi2-core 2.25.90: + +* Fix a couple of introspection issues (bgo#784481). + +* atspi_get_a11_bus: don't leak the DBusConnection. + +* Meson fixes. + +What's new in at-spi2-core 2.25.4: + +* Fix gir generation with autotools (bgo#783994). + +What's new in at-spi2-core 2.25.3: + +* Fix -Wmisleading-indentation warnings. + +* Fix memory leak of at-spi-bus-launcher. + +* Add error-message, error-for, details, and details-for relation types. + +* Poll direct dbus connections in the main loop--fixes processes + being marked hung and the hung flag never being removed. + +* Add Meson build system (thanks to Emmanuele Bassi). + +* Various build fixes (thanks to Emmanuele Bassi). + +What's new in at-spi2-core 2.25.2: + +* attempt to fix an occasional crash when an application disappears + (bgo#767074). + +* Add some missing roles to correspond with atk (description list, + description term, description value, and footnote). + +What's new in at-spi2-core 2.25.1: + +* atspi_table_cell_get_position: don't crash on error. + +What's new in at-spi2-core 2.23.92: + +* Table cell API fixes (bgo#779835). + +What's new in at-spi2-core 2.23.90: + +* Fix an occasional crash when an application is closed (bgo#767074). + +What's new in at-spi2-core 2.23.4: + +* Don't pull in X headers if x11 is disabled (bgo#773710). + +* at-spi-bus-launcher: session management fixes (bgo#774441). + + +* events: add recently added page changed event (bgo#719898). + +* roles: EXTENDED roles are deprecated (bgo#W720123). + + +What's new in at-spi2-core 2.2.0: + +* at-spi-bus-launcher: fix uninitialized variable. + +* Fix return value error in session_manager_connect (bgo#768881). + +* Updated translations. + +What's new in at-spi2-core 2.21.4: + +* Fixed a crash in atspi_accessible_clear_cache. + +* Fixed a crash caused by at-spi2-registryd dying. + +* Fixed some session management issues in at-spi-bus-launcher. + +What's new in at-spi2-core 2.21.2: + +* Allow building without Xtst, Xi with --disable-x11 + +* ref_accessible_desktop: don't unref reply until we're finished with it + +* Updated translations. + +What's new in at-spi2-core 2.21.1: + +* registryd: avoid crashing with a NULL keystring (bgo#764688). + +* Plug a memory leak in AtspiEventListener (bgo#764688). + +* Fix parsing of at-spi-bus-launcher command line arguments (bgo#765220). + +* Build clean-ups. + +What's new in at-spi2-core 2.19.92: + +* Support a stateless configuration by default (bgo#763540). + +What's new in at-spi2-core 2.19.91: + +* Don't display warnings when connecting to an app that no longer exists. + +What's new in at-spi2-core 2.19.90: + +* Don't display warning if unable to connect when logged in via ssh + (bgo#761600). + +* at-spi-bus-launcher: register with session manager (bgo#753931). + +What's new in at-spi2-core 2.19.2: + +* Disable xevie by default--it probably doesn't do anything anyhow. + +* get_index_in_parent: Don't crash if parent is defunct. + +* Don't crash when trying to set an invalid state (bgo#757915). + +What's new in at-spi2-core 2.19.1: + +* Don't crash if we get a children-changed event with a non-existent + child (bgo#755951). + +* atspi_hyperlink_get_index_range: don't return random values if the + call fails (bgo#755727). + +* Fixed some atspi_text_ functions (bgo#755731). + +* Fixed crash during removal of last application in registryd (bgo#756513). + +What's new in at-spi2-core 2.17.90: + +* Modified the cache API to specify an object's index and child count + rather than its children. This eliminates the need for the application + to enumerate its children, improving performance in some places with + large lists (bgo#650090). + +What's new in at-spi2-core 2.17.1: + +* Functions shouldn't try to return values (bgo#749330). + +* Fix atspi_table_cell_get_position. + +What's new in at-spi2-core 2.16.0: + +* Fix a couple of gtk-doc warnings (fdo#89678). + +What's new in at-spi2-core 2.15.90: + +* Deprecate atspi_text_get_text_{before,at,after}_offset() (bgo#697969) + +* Add roles for fractions, roots, subscripts, and superscripts (bgo#743403). + +What's new in at-spi2-core 2.15.4: + +* Add names to every timeout (bgo#710644). + +* Remove accessibility.conf from EXTRA_DIST (bgo#742987). + +* Add ATSPI_STATE_READONLY (bgo#690004). + +What's new in at-spi2-core 2.15.3: + +* Replace deprecated "Rename to" gtk-doc tag. + +* Fix atspi_table_cell_get_column_span prototype. + +What's new in at-spi2-core 2.15.2: + +* Make the documentation of ATSPI's STATE_ACTIVE consistent with that of + ATK's (bgo#740274). + +* Add ATSPI_ROLE_STATIC and update documentation for ATSPI_ROLE_TEXT + (bgo#740340). + +* gi-annotations: get_relation_set returns a array of AtspiRelation + +What's new in at-spi2-core 2.15.1: + +* Fix some issues with the accessibility bus configuration (bgo#722738). + +* Documentation for AtspiTableCell is now built. + +What's new in at-spi2-core 2.13.92: + +* Fix alignment checks when cross-compiling (bgo#736653). + +What's new in at-spi2-core 2.13.90: + +* Fix crash when testing interfaces with collections (bgo#734805). + +What's new in at-spi2-core 2.13.4: + +* Ensure that we register with the session manager only once (bgo#728934). + +* Fix ucs2keysym prototype (bgo#730897). + +* introspection: add some missing Returns: (nullable) annotations + +* Fix various memory leaks. + +What's new in at-spi2-core 2.13.1: + +* Add GError setter in atspi_accessible_get_process_id function + +* registryd: Wait for gnome-session before registering if it is not + running yet (bgo#728934). + +What's new in at-spi2-core 2.11.92: + +* Fix a crash with MediaElch and Onboard (bgo#726243). + +* Various i18n updates. + +What's new in at-spi2-core 2.11.91: + +* Improve compatibility with at-spi2-registryd <= 3.10. + +What's new in at-spi2-core 2.11.90: + +* bus-launcher: Do not use g_setenv when initializing the bus (bgo#724070). + +* Fix a critical when processing deferred messages (bgo#724292). + +* Add AtspitableCell, tracking the new atk interface + +What's new in at-spi2-core 2.11.5: + +* Add atspi_event_listener_register_full, and cache data requested by it + for the duration of the event callback (BGO#708695). + +* Fix a crash when atspi_accessible_get_process_id is called for an + application that is no longer present. + +What's new in at-spi2-core 2.11.3: + + * Fix atspi_text_get_bounded_ranges + +* document: add support to current page and page count (BGO#719508). + +What's new in at-spi2-core 2.11.2: + +* Add new roles and states to track atk (BGO#710464, BGO#712608, BGO#712609). + +What's new in at-spi2-core 2.11.1: + +* Fix a gsource leak that adversely impacted performance (BGO#709625). + +* Hopefully fix a rare crash when starting at-spi2-registryd (BGO#710689). + +* Fix atspi_component_contains (BGO#710730). + +* Fix some compiler warnings and build issues. + +What's new in at-spi2-core 2.9.92: + +* Fix multiple deadlocks with keystroke listeners (BGO#707218). + + +What's new in at-spi2-core 2.9.91: + +* Fix a performance issue when running for a long time without a main + loop, such as with a dogtail script (BGO#701145). + +* Remove an unneeded unref that was causing a warning (BGO#706893). + +* Skip some functions that were not introspectable (BGO#707010). + +What's new in at-spi2-core 2.9.90: + +* Separate out X-dependent functionality, allow building without X11 (albeit + with various things not working), and don't query/use X if DISPLAY is not + set (BGO#682199, BGO#701378). + +* Add atspi_text_get_string_at_offset, and deprecate + atspi_text_get_text_at_offset. + +What's new in at-spi2-core 2.9.5: + +* Fix possible memory leak when D-Bus calls time out. + +* Fix a memory leak in atspi_accessible_get_role_name that was introduced + earlier in the 2.9 cycle with the enum refactor. + +* A couple of functions not intended for introspection are now marked + as skip. + +What's new in at-spi2-core 2.9.4: + +* Add atspi_set_main_context (mainly for use by at-spi2-atk). + +What's new in at-spi2-core 2.9.3: + +* Add atspi_is_initialized (BGO#681276). + +What's new in at-spi2-core 2.9.2: + +* Fix D-Bus introspection for GetActions. + +* Use glib-mkenums to generate enum types, and use these generated types + for role and state names, rather than static tables. + +* Annotate filter in atspi_register_device_event_listener with allow-none + (BGO#700237). + +* Rename various functions to avoid name collisions (BGO#700243). The old + functions are deprecated in favor of the renamed functions and renamed + for introspection. + +What's new in at-spi2-core 2.7.91: + +* Add atspi_accessible_get_object_locale (BGO#694368). + +* Start the bus launcher in the initialization phase (BGO#694984). + +What's new in at-spi2-core 2.7.90: + +* Removed a debug print that was accidentally included in 2.7.5. + +What's new in at-spi2-core 2.7.5: + +* Add ATSPI_ROLE_LEVEL_BAR to correspond to the new atk role. + +* Fix various compiler warnings. + +What's new in at-spi2-core 2.7.4: + +* Fix some ref count leaks. + +* Some functions that return accessibles now propagate errors. + +What's new in at-spi2-core 2.7.3: + +* Atspi_accessible_get_index_in_parent no longer returns -1 if the object's + parent is not cached (BGO#688057). + +* re-register keystroke listeners if the registry goes away and then returns. + +* Fix atspi_device_listener_new_simple. + +* Fix some compiler warnings. + +* Build: use gobject-introspection's Makefile instead of rolling our own. + +* Fix a crash when parsing events without detail when there is a listener for the event that names a specific detail value. + +* Fix crash when removing hung processes. + +* Fix deregistering of applications. + +* A few documentation fixes. + +What's new in at-spi2-core 2.7.2: + +* Only call an event listener once per event, even if the listener registered + for both the event and a superset of the event. + +* Don't distribute dbind-config.h (BGO#688083). + +* Fix gtk-doc for Atspi-Registry (BGO#688224). + +* Some introspection fixes to make vapigen happy (BGO#688223). + +* [registry] Fixed a crash handling DeregisterKeystrokeListener. + +What's new in at-spi2-core 2.7.1: + +* Update the cache in response to role change notifications (BGO#685469). + +* Don't output a warning when a p2p connection isn't available. + +What's new in at-spi2-core 2.5.92: + +* Fix some annotations. + +* Exit, rather than crash, when unable to open an X display (BGO#660407). + +* Fix various memory leaks (BGO#684033). + +What's new in at-spi2-core 2.5.91: + +* Fix build with -fno-common. + +* Add glib-2.0 to requires in at-spi2.pc (BGO#682595) + +What's new in at-spi2-core 2.5.5: + +* Add atspi_action_get_localized_name (BGO#680598). + +* Allow building from out of source directory (BGO#680281) + +What's new in at-spi2-core 2.5.4: + +* Fix a missing return value. + +* Fix a crash when unable to remove a match rule. + +What's new in at-spi2-core 2.5.3: + +* Fix a memory leak (BGO#678738) + +What's new in at-spi2-core 2.5.2: + +* Fix a crash when a call to fetch a hyperlink times out. + +* Fix C++ compilation. + +* Remove a warning that was sometimes logged when a method call timed out. + +* Fix crash in atspi_deregister_keystroke_listener (FDO#50578) + +What's new in at-spi2-core 2.5.1: + +* Add atspi_set_timeout. + +* By default, disable method call timeouts until an application has been on +the bus for 15 seconds (work-around for applications with potentially long +start-up times). This behavior can be changed with a call to atspi_set_timeout. + +* Fix GError sent when receiving a reply of the wrong type + +* Fix typo in atspi_document_get_attribute_value + +* Fix for bug 675004 - object:state-changed:defunct events are emitted as object:state-change:defunct + +What's new in at-spi2-core 2.4.0: + +* Fix typo in at-spi-dbus-bus.desktop.in (BGO#605662). + +What's new in at-spi2-core 2.3.92: + +* Some changes to try to prevent at-spi2-registryd from incorrectly + thinking that an AT is hung and passing keys meant for it to the application. + +* Fix crash fetching an error from a reply when retrieving a property. + +What's new in at-spi2-core 2.3.91: + +* Invalidate states when receiving a focus event (BGO#663992). + +* Fix atspi_table_get_row_column_extents_at_index. + +* Expect a signed int for GetIndexInParent, per the spec. + +* Send key events to listeners assumed to be hung, but don't block. + +* Reduce the method call timeout slightly, so that it will be lower than + the keystroke listener timeout. + +* Don't cache data for transient objects. + +* Enable caching on a call to atspi_accessible_set_cache_mask, even if + atspi-event_main() hasn't been called. + +What's new in at-spi2-core 2.3.90: + +* At-spi-bus-launcher now emits PropertiesChanged signals from the correct + interface. + +* If a keystroke listener does not respond, disable it until it responds. + This prevents the desktop from locking up if an AT hangs or is suspended + and has a keyboard listener registered. + +* Fix a warning when a NULL object is returned as the detail of an event. + +What's new in at-spi2-core 2.3.5: + +* Fix for BGO#668334: Set correct end offset in atspi_text_get_attributes. + +* Add some type checking on method replies; this should prevent crashes if + an application-side AT-SPI implementor returns something unexpected. + +* Call g_settings_sync after updating toolkit-accessibility. + +* Add ScreenReaderEnabled D-Bus property as a proxy for the GSettings key. + +* Fix for BGO#669344: Don't use "restrict" as a variable name, since it can + be a keyword. + +What's new in at-spi2-core 2.3.4: + +* Add some dbus message signature checks. + +* Fix a crash if a device listener incorrectly returns a non-bool. + +* Fix for BGO#666870: Keystroke listeners do not work unless an event listener + is also registered [also needs updated at-spi2-atk] + +* Fix for BGO#667254: Some atspi-selection_* functions were broken. + +* When a call times out, ping the connection and avoid making subsequent calls + until the ping is answered. + +What's new in at-spi2-core 2.3.3: + +* Handle event detail suffixes (such as :system). + +What's new in at-spi2-core 2.3.2: + +* Some documentation improvements. + +What's new in at-spi2-core 2.3.1: + +* Fix return type of org.a11y.Bus.IsEnabled property + +* Declare void functions as such + +What's new in at-spi2-core 2.2.1: + +* Fix org.a11y.Bus.Enabled property to set its initial state from the + GSettings key, if available and an initial property is not given on the + command line. + +* Fix for BGO#660947: Gracefully exit when already running, rather than + triggering a SIGABRT. + +What's new in at-spi2-core 2.1.92: + +* Fixed a crash when handling event listeners. + +* Fix for BGO#659088: Correctly define ATSPI_MODIFIER_NUMLOCK. + +* Add some defensive checks to prevent problems with defunct objects. + +* BGO#657051: Fix a build error on Solaris. + +* Fix some missing return statements. + +* Some fixes related to deregistering event listeners. + +What's new in at-spi2-core 2.1.91: + +* Fixed a crash when deregistering event listeners. + +* Made DBus IsEnabled property readwrite. + +What's new in at-spi2-core 2.1.90: + +* Fixed a memory leak on DBus errors. + +* Added org.a11y.Status.IsEnabled (currently a read-only property) to the bus + launcher. + +* Fix for BGO#656004: atspi_accessible_get_relation_set returns a GArray again. + +* Numerous documentation fixes from Aline Bessa. + +* CLean up device listeners from disconnected applications. + +* Fix for BGO#657585: Do not crash when the bus launcher is unable to open the + X display. + +What's new in at-spi2-core 2.1.5: + +* Propertly free DBus error in atspi_accessible_get_process_id. + +* Clean up names of some private functions. + +* Move DBus interface name constants into atspi-constants.h and make public. + +* Remove support for relocated CORBA. + +* Fix for BGO#655127: Avoid Python crash for atspi_accessible_get_relation_set. + +What's new in at-spi2-core 2.1.4: + +* Some API changes to device and event listeners for compatibility with + Javascript. + +* Fix for BGO#654314: make role names consistent with atk. +* FIx for BGO#654921: Run within Unity. + +* Added some new roles. + +What's new in at-spi2-core 2.1.3: + +* use stored values for AT-SPI role names where possible. + +* Fix for BGO#652596: Use DBus property to set value. + + +* Fix gtk-doc build cflags/libraries. + +* Set error for some DBus errors where this was not being done. + + +* Add atspi_accessible_get_process_id (as a short-cut to help debugging). + +* Fix failure to update cache in response to children-changed events in some + cases. + +What's new in at-spi2-core 2.1.2: + +* Fix atspi_table_get_caption|summary. + +* Fix introspection for atspi_table_get_row_column_at_index. + +* Copy match rule attributes, rather than just ref counting the hash, for + compatibility with pygi. + +* Rework atspi_accessible_set_cache_mask to make it usable. + +* Fix a crash that might happen if a method call times out. + +* Disable caching if atspi_event_main has not been called to run the main loop. + +* Fix atspi_accessible_get_toolkit_version. + +* Add atspi_accessible_get_atspi_version to fetch the version of the AT-SPI + specification provided by an application. + +* Cache application-wide toolkit name and version. + +* Allow caching of attributes, but not enabling by default, as there is no + event yet (BGO#649771). + +* Make deferred_messages a GQueue rather than a GList for performance reasons. + +* Fix accessibility bus breakage when a user runs an administrative app. + +What's new in at-spi2-core 2.1.1: + +* Fixed a seg fault in at-spi-bus-launcher when ending a session (BGO#648942). + +* Fixed a possible crash when an application is short-lived. + +* FIxed memory leaks in atspi_accessible_get_toolkit_(name|version). + +* AT-SPI will now call g_error if it is unable to find the accessibility bus. + This results in aborting but with a somewhat less cryptic error than before. + +What's new in at-spi2-core 2.0.1: + +* Fix a memory leak when sending events. + +* Fix for BGO#648059: get_application should return something w/ROLE_APPLICATION + +* Fix for BGO#648013: Honor aclocal flags + +* FIx for BGO#648014: Add intltoolize to autogen.sh + +* Fix for BGO#648130: event host_application should return NULL for the desktop + +* Added atspi_accessible_get_id to retrieve the id of an application. + +* Remove doc about non-existent ATSPI_KEYSET_ALL_KEYS. + +What's new in at-spi2-core 2.0.0: + +* Fix for BGO#646403: Use correct signature in at-spi2-registryd for + EndSessionResponse. + +* Remove a Makefile reference to dbus-glib. + +What's new in at-spi2-core 1.91.93: + +* Removed dbus-glib-related includes, as they are no longer required. + +What's new in at-spi2-core 1.91.92: + +* Fixed atspi_table_get_column_header and atspi_value_set_current_value. + +* Removed dbus-glib dependency; libatspi now includes a copy of dbus-gmain.c + modified to fix a crash (FDO#35115). Session management code has been + ported to gdbus. + +* Fixed a crash when deregistering a keystroke listener. + +* Reworked accessibility bus management (BGO#644851). + +* Fixed a possible sign issue with state sets. + +What's new in at-spi2-core 1.91.91: + +* Changed device event IPC to use uint32 for hw_code and modifiers, to be + more consistent with the rest of the API. + +* GetNSelections has an out parameter, not an in. + +* Fix for BGO#643384: - atspi_register_keystroke_listener() should take a + bitmask, not AtspiKeyListenerSyncType. + +* Avoid setting enum values to 0x80000000, to prevent a pygi exception. + +* Fix for BGO#643454: Kill the accessibility bus daemon with the GNOME session + +* Fix for BGO#643110: Do not allow all users to connect to the accessibility bus. + +What's new in at-spi2-core 1.91.90: + +* BGO#641164: Fixed several build errors. + +* Fixed some memory leaks and possible crashes. + +* Fixed atspi_selection_get_selected_child and + atspi_selection_get_n_selected_children. + +* Fixed wrong introspection information in some places. + +* BGO#641869: Removed the --enable-relocate option. + +* Avoid returning uninitialized data on error for some methods. + +* Use the GSettings rather than GConf key to test that accessibility is + enabled. + +* Change some enums from 16-bit to 32-bit to match spec. + +What's new in at-spi2-core 1.91.6.1: + +* Fixed a crash introduced in 1.91.6. + +* atspi_accessible_get_interfaces will now explicitly return the Accessible + interface. + +What's new in at-spi2-core 1.91.6: + +* Some build fixes. + + * Several updated translations. + +* Added a method to check whether an object implements the Hyperlink interface. + +* Fixed a crash in atspi_image_get_image_description. + +* Fixed atspi_editable_text_set_text_contents. + +* More error-handling fixes. + +* Fixed a crash in atspi_event_listener_register_from-callback. + +* Method calls now time out after 1 second. + +* Added setters for component extents/size/position. + +* Added atspi-accessible_set_cache_mask. + +What's new in at-spi2-core 1.91.5: + +* Fixed several memory leaks. + +* Fixed some text methods, methods that return points or rectangles, + image locale and description, atspi-accessible_get_description, and some + table methods. + +* Added a trailing colon for focus events. + +* Set the error parameter for dbus errors rather than displaying a warning. + +* Fixed the keystroke listener deregister method. + +* The cache is now updated before raising an event, not after, so that event + handlers that query for cached values will see the updated data. + +* The registry daemon now returns an error when a caller requests a property + that the desktop does not support. + +* Added disposal of objects, and fixed several associated bugs. + +* Added i18n. + +* Fixed mouse events. + +* Libatspi's documentation is now compiled with gtk-doc. + +* Fixed building from a separate build directory. + + +What's new in at-spi2-core 1.91.4: + +* use peer-to-peer connections when available. + +* Fix uninitialized variable in get_index_in_parent. + +* Add timeout, and support inspecting our own app. + +* Add get_interfaces, and fetch interface and state set over the wire if needed. + +* Avoid adding data for an accessible twice if it is referenced prior to an + AddAccessible signal being received. + +* Fix copying of any_data for an event. + +* at-spi-registryd returns ChildCount as a variant, per the DBus spec. + +* Hypertext, hyperlink, and table fixes. + +* Several cache-related fixes. + +* Change some error return values to match AT-SPI-CORBA behavior. + +* Some attribute-related fixes. + +* Renamed 'text' to 'content' in AtspiTextRange to match original IDL. + +What's new in at-spi2-core 1.91.3: + +* Added a C-based AT-side binding (libatspi) which can be used in + conjunction with GObject introspection to generate bindings for other + languages. However, this release has many bugs and is more of a development + snapshot than a usable release. + +What's new in at-spi2-core 1.91.2: + +* The desktop object now returns ROLE_DESKTOP_FRAME rather than ROLE_UNKNOWN. + + +What's new in at-spi2-core 1.91.0: + +* --disable-relocate is the default again. + +What's new in at-spi2-core 0.3.92: + +* Do not start accessibility bus if at-spi-corba is enabled. + +What's new in at-spi2-core 0.3.91: + +* Enabled the accessibility bus, so apps should be accessible, for instance, +if an application becomes setuid root. + +* Several build fixes. + +* Default to --enable-relocate for now. + +What's new in at-spi2-core 0.3.90: + +* FDO#29427: Registering for mouse:abs now works. + +* Add methods/signals to allow an application to track the events that are +being listened to to avoid unnecessarily emitting signals. + +What's new in at-spi2-core 0.3.4: + +* Added GetChildren to the spec. + +What's new in at-spi2-core 0.3.3: + +* Add return values to some functions that were missing them. + +* Make DeviceEventListener notifiers reentrant so that an application can +query the desktop object while processing a device event. + +* Fix for FDO#28300: fails to link with pedantic linkers. + +* Fix crash if GetChildAtIndex is called with an invalid index. + +What's new in at-spi2-core 0.3.2: + +* Make sure that disconnecting applications send their root path in the +remove applications signal. This was causing applications to not be +removed from the desktop properly. + +What's new in at-spi2-core 0.3.1: + +* Set an application's Id when registering it. + +* Disabled relocation by default. diff --git a/README b/README new file mode 100644 index 0000000..e41a5c6 --- /dev/null +++ b/README @@ -0,0 +1,116 @@ +D-Bus AT-SPI +------------ + +This version of at-spi is a major break from version 1.x. +It has been completely rewritten to use D-Bus rather than +ORBIT / CORBA for its transport protocol. + +A page including instructions for testing, project status and +TODO items is kept up to date at: + + http://www.linuxfoundation.org/en/AT-SPI_on_D-Bus + +The mailing list used for general questions is: + + accessibility-atspi@lists.linux-foundation.org + +For bug reports, feature requests, patches or enhancements please use +the AT-SPI project on bugzilla.gnome.org. Use the at-spi2-core component for +bugs specific to this module. + + http://bugzilla.gnome.org + +A git repository with the latest development code is available at: + + git://git.gnome.org/at-spi2-core + +More information +---------------- + +The project was started with a D-Bus performance review +the results of which are available on the GNOME wiki. Keep in +mind that the D-Bus AT-SPI design documents on this page +have not been kept up to date. + + http://live.gnome.org/GAP/AtSpiDbusInvestigation/ + +Other sources of relevant information about AT-SPI and Accessibility +include: + + http://live.gnome.org/Accessibility + http://www.sun.com/software/star/gnome/accessibility/architecture.xml + http://accessibility.kde.org/developer/atk.php + http://www.gnome.org/~billh/at-spi-idl/html/ + + +Contents of this package +------------------------ + +This package includes the protocol definitions for the new D-Bus +at-spi. + +Also included is the daemon necessary for forwarding device events +and registering accessible applicaitions. + + +Directory structure +------------------- + +The directories within this package are arranged as follows: + + xml + + This directory contains XML documents describing + the D-Bus protocol in the format used for D-Bus introspection. + + idl + + The D-Bus specification in an idl-like format. This is likely not + parseable by any existing tools, is not entirely up-to-date, and may + by removed in a future release. + + registryd + + The registry daemon code. The registry daemon + keeps a register of accessible applications and presents + this to clients (ATs). + It is also responsible for delivering device events. + + dbind + + Library to ease making D-Bus method calls, contains + marshalling code to convert function arguments + and a provided D-Bus signature into a D-Bus message. + + Used by libatspi. + + atspi + + C library for use by ATs. Wraps the various D-Bus calls, provides + an interface for listening to events, and caches some information about + accessible objects. Also contains some functions used by at-spi2-atk. + + bus + + A server that sits on the session bus and provides an interface + allowing applications to find the accessibility bus daemon, launching + it as needed. The accessibility bus is separate from the session bus + because it may in fact span user sessions if a user, for instance, + runs an application that escalates to run as root. The accessibility + bus is thus tied to the X session rather than the D-Bus session. + + doc + + Contains infrastructure for creating libatspi documentation. + + test + + Contains files that may be useful for testing AT-SPI. + + m4 + + Some macros used for building the module. + + po + + Infrastructure used for translation. diff --git a/at-spi2-core.doap b/at-spi2-core.doap new file mode 100644 index 0000000..1ac8f84 --- /dev/null +++ b/at-spi2-core.doap @@ -0,0 +1,35 @@ + + + at-spi2-core + D-Bus accessibility specifications and registration daemon + + + + C + + + + Mark Doffman + + markdoffman + + + + + Mike Gorse + + mgorse + + + + + Li Yuan + + liyuan + + + diff --git a/atspi-2.pc.in b/atspi-2.pc.in new file mode 100644 index 0000000..71d028a --- /dev/null +++ b/atspi-2.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: atspi +Description: Accessibility Technology software library +Requires: dbus-1 glib-2.0 +Version: @VERSION@ +Libs: -L${libdir} -latspi +Cflags: -I${includedir}/at-spi-2.0 diff --git a/atspi/atspi-accessible-private.h b/atspi/atspi-accessible-private.h new file mode 100644 index 0000000..496f7d7 --- /dev/null +++ b/atspi/atspi-accessible-private.h @@ -0,0 +1,46 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_ACCESSIBLE_PRIVATE_H_ +#define _ATSPI_ACCESSIBLE_PRIVATE_H_ + +G_BEGIN_DECLS + +#include "atspi-accessible.h" + +struct _AtspiAccessiblePrivate +{ + GHashTable *cache; + guint cache_ref_count; +}; + +GHashTable * +_atspi_accessible_ref_cache (AtspiAccessible *accessible); + +void +_atspi_accessible_unref_cache (AtspiAccessible *accessible); +G_END_DECLS + +#endif /* _ATSPI_ACCESSIBLE_H_ */ diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c new file mode 100644 index 0000000..e7f1446 --- /dev/null +++ b/atspi/atspi-accessible.c @@ -0,0 +1,1803 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" +#include "atspi-accessible-private.h" +#include + +static gboolean enable_caching = FALSE; +static guint quark_locale; + +static void +atspi_action_interface_init (AtspiAction *action) +{ +} + +static void +atspi_collection_interface_init (AtspiCollection *component) +{ +} + +static void +atspi_component_interface_init (AtspiComponent *component) +{ +} + +static void +atspi_document_interface_init (AtspiDocument *document) +{ +} + +static void +atspi_editable_text_interface_init (AtspiEditableText *editable_text) +{ +} + +static void +atspi_hypertext_interface_init (AtspiHypertext *hypertext) +{ +} + +static void +atspi_image_interface_init (AtspiImage *image) +{ +} + +static void +atspi_selection_interface_init (AtspiSelection *selection) +{ +} + +static void +atspi_table_interface_init (AtspiTable *table) +{ +} + +static void +atspi_table_cell_interface_init (AtspiTableCell *cell) +{ +} + +static void +atspi_text_interface_init (AtspiText *text) +{ +} + +static void +atspi_value_interface_init (AtspiValue *value) +{ +} + +G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT, + G_ADD_PRIVATE (AtspiAccessible) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_DOCUMENT, atspi_document_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_EDITABLE_TEXT, atspi_editable_text_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_HYPERTEXT, atspi_hypertext_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_IMAGE, atspi_image_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_SELECTION, atspi_selection_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE, atspi_table_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TABLE_CELL, atspi_table_cell_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_TEXT, atspi_text_interface_init) + G_IMPLEMENT_INTERFACE (ATSPI_TYPE_VALUE, atspi_value_interface_init)) + +#ifdef DEBUG_REF_COUNTS +static gint accessible_count = 0; +#endif + +static void +atspi_accessible_init (AtspiAccessible *accessible) +{ +#ifdef DEBUG_REF_COUNTS + accessible_count++; + g_hash_table_insert (_atspi_get_live_refs (), accessible, NULL); + g_print("at-spi: init: %d objects\n", accessible_count); +#endif + + accessible->priv = atspi_accessible_get_instance_private (accessible); + + accessible->children = g_ptr_array_new_with_free_func (g_object_unref); +} + +static void +atspi_accessible_dispose (GObject *object) +{ + AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object); + AtspiEvent e; + AtspiAccessible *parent; + gint i; + + /* TODO: Only fire if object not already marked defunct */ + memset (&e, 0, sizeof (e)); + e.type = "object:state-changed:defunct"; + e.source = accessible; + e.detail1 = 1; + e.detail2 = 0; + _atspi_send_event (&e); + + g_clear_object (&accessible->states); + + parent = accessible->accessible_parent; + if (parent) + { + accessible->accessible_parent = NULL; + if (parent->children) + g_ptr_array_remove (parent->children, accessible); + g_object_unref (parent); + } + + if (accessible->children) for (i = accessible->children->len - 1; i >= 0; i--) + { + AtspiAccessible *child = g_ptr_array_index (accessible->children, i); + if (child && child->accessible_parent == accessible) + { + child->accessible_parent = NULL; + g_object_unref (accessible); + } + } + + if (accessible->children) + { + g_ptr_array_free (accessible->children, TRUE); + accessible->children = NULL; + } + + G_OBJECT_CLASS (atspi_accessible_parent_class) ->dispose (object); +} + +static void +atspi_accessible_finalize (GObject *object) +{ + AtspiAccessible *accessible = ATSPI_ACCESSIBLE (object); + + g_free (accessible->description); + g_free (accessible->name); + + if (accessible->attributes) + g_hash_table_unref (accessible->attributes); + + if (accessible->priv->cache) + g_hash_table_destroy (accessible->priv->cache); + +#ifdef DEBUG_REF_COUNTS + accessible_count--; + g_hash_table_remove (_atspi_get_live_refs (), accessible); + g_print ("at-spi: finalize: %d objects\n", accessible_count); +#endif + + G_OBJECT_CLASS (atspi_accessible_parent_class)->finalize (object); +} + +static void +atspi_accessible_class_init (AtspiAccessibleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = atspi_accessible_dispose; + object_class->finalize = atspi_accessible_finalize; + + quark_locale = g_quark_from_string ("accessible-locale"); +} + +/** + * atspi_accessible_get_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the name of an #AtspiAccessible object. + * + * Returns: a UTF-8 string indicating the name of the #AtspiAccessible object + * or NULL on exception. + **/ +gchar * +atspi_accessible_get_name (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, g_strdup ("")); + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_NAME)) + { + if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", error, + "s", &obj->name)) + return g_strdup (""); + _atspi_accessible_add_cache (obj, ATSPI_CACHE_NAME); + } + return g_strdup (obj->name); +} + +/** + * atspi_accessible_get_description: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the description of an #AtspiAccessible object. + * + * Returns: a UTF-8 string describing the #AtspiAccessible object + * or NULL on exception. + **/ +gchar * +atspi_accessible_get_description (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, g_strdup ("")); + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_DESCRIPTION)) + { + if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, + "Description", error, "s", + &obj->description)) + return g_strdup (""); + _atspi_accessible_add_cache (obj, ATSPI_CACHE_DESCRIPTION); + } + return g_strdup (obj->description); +} + +const char *str_parent = "Parent"; + +/** + * atspi_accessible_get_parent: + * @obj: a pointer to the #AtspiAccessible object to query. + * + * Gets an #AtspiAccessible object's parent container. + * + * Returns: (nullable) (transfer full): a pointer to the + * #AtspiAccessible object which contains the given + * #AtspiAccessible instance, or NULL if the @obj has no + * parent container. + * + **/ +AtspiAccessible * +atspi_accessible_get_parent (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT)) + { + DBusMessage *message, *reply; + DBusMessageIter iter, iter_variant; + if (!obj->parent.app) + return NULL; + message = dbus_message_new_method_call (obj->parent.app->bus_name, + obj->parent.path, + DBUS_INTERFACE_PROPERTIES, "Get"); + if (!message) + return NULL; + dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible, + DBUS_TYPE_STRING, &str_parent, + DBUS_TYPE_INVALID); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + if (!reply) + return NULL; + if (strcmp (dbus_message_get_signature (reply), "v") != 0) + { + dbus_message_unref (reply); + return NULL; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_variant); + obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant); + dbus_message_unref (reply); + _atspi_accessible_add_cache (obj, ATSPI_CACHE_PARENT); + } + if (!obj->accessible_parent) + return NULL; + return g_object_ref (obj->accessible_parent); +} + +/** + * atspi_accessible_get_child_count: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the number of children contained by an #AtspiAccessible object. + * + * Returns: a #long indicating the number of #AtspiAccessible children + * contained by an #AtspiAccessible object or -1 on exception. + * + **/ +gint +atspi_accessible_get_child_count (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, -1); + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN)) + { + dbus_int32_t ret; + if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, + "ChildCount", error, "i", &ret)) + return -1; + return ret; + } + + if (!obj->children) + return 0; /* assume it's disposed */ + + return obj->children->len; +} + +/** + * atspi_accessible_get_child_at_index: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * @child_index: a #long indicating which child is specified. + * + * Gets the #AtspiAccessible child of an #AtspiAccessible object at a given index. + * + * Returns: (transfer full): a pointer to the #AtspiAccessible child object at + * index @child_index or NULL on exception. + **/ +AtspiAccessible * +atspi_accessible_get_child_at_index (AtspiAccessible *obj, + gint child_index, + GError **error) +{ + AtspiAccessible *child; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN)) + { + if (!obj->children) + return NULL; /* assume disposed */ + + child = g_ptr_array_index (obj->children, child_index); + if (child) + return g_object_ref (child); + } + + reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, + "GetChildAtIndex", error, "i", child_index); + child = _atspi_dbus_return_accessible_from_message (reply); + + if (!child) + return NULL; + + if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_CHILDREN)) + { + if (child_index >= obj->children->len) + g_ptr_array_set_size (obj->children, child_index + 1); + g_ptr_array_index (obj->children, child_index) = g_object_ref (child); + } + return child; +} + +/** + * atspi_accessible_get_index_in_parent: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the index of an #AtspiAccessible object within its parent's + * #AtspiAccessible children list. + * + * Returns: a #glong indicating the index of the #AtspiAccessible object + * in its parent, + * or -1 if @obj has no containing parent or on exception. + **/ +gint +atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error) +{ + gint i = 0; + dbus_int32_t ret = -1; + + g_return_val_if_fail (obj != NULL, -1); + if (_atspi_accessible_test_cache (obj, ATSPI_CACHE_PARENT)) + { + if (!obj->accessible_parent) + return -1; + + if (!_atspi_accessible_test_cache (obj->accessible_parent, ATSPI_CACHE_CHILDREN) || !obj->accessible_parent->children) + goto dbus; + + for (i = 0; i < obj->accessible_parent->children->len; i++) + if (g_ptr_array_index (obj->accessible_parent->children, i) == obj) + return i; + } + +dbus: + _atspi_dbus_call (obj, atspi_interface_accessible, + "GetIndexInParent", NULL, "=>i", &ret); + return ret; +} + +typedef struct +{ + dbus_uint32_t type; + GArray *targets; +} Accessibility_Relation; + +/** + * atspi_accessible_get_relation_set: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the set of #AtspiRelation objects which describes this #AtspiAccessible object's + * relationships with other #AtspiAccessible objects. + * + * Returns: (element-type AtspiRelation*) (transfer full): a #GArray of + * #AtspiRelation pointers or NULL on exception. + **/ +GArray * +atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + GArray *ret; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetRelationSet", error, ""); + if (!reply) + return NULL; + _ATSPI_DBUS_CHECK_SIG (reply, "a(ua(so))", error, NULL); + + ret = g_array_new (TRUE, TRUE, sizeof (AtspiRelation *)); + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiRelation *relation; + relation = _atspi_relation_new_from_iter (&iter_array); + ret = g_array_append_val (ret, relation); + dbus_message_iter_next (&iter_array); + } + dbus_message_unref (reply); + return ret; +} + +/** + * atspi_accessible_get_role: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the UI role played by an #AtspiAccessible object. + * This role's name can be obtained via atspi_accessible_get_role_name (). + * + * Returns: the #AtspiRole of an #AtspiAccessible object. + * + **/ +AtspiRole +atspi_accessible_get_role (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID); + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ROLE)) + { + dbus_uint32_t role; + /* TODO: Make this a property */ + if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", error, "=>u", &role)) + { + obj->role = role; + _atspi_accessible_add_cache (obj, ATSPI_CACHE_ROLE); + } + } + return obj->role; +} + +/** + * atspi_accessible_get_role_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets a UTF-8 string corresponding to the name of the role played by an object. + * This method will return useful values for roles that fall outside the + * enumeration used in atspi_accessible_get_role (). + * + * Returns: a UTF-8 string specifying the type of UI role played by an + * #AtspiAccessible object. + * + **/ +gchar * +atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error) +{ + gchar *retval = NULL; + AtspiRole role; + + g_return_val_if_fail (obj != NULL, NULL); + + role = atspi_accessible_get_role (obj, error); + if (role >= 0 && role < ATSPI_ROLE_COUNT && role != ATSPI_ROLE_EXTENDED) + return atspi_role_get_name (role); + + _atspi_dbus_call (obj, atspi_interface_accessible, "GetRoleName", error, "=>s", &retval); + + if (!retval) + retval = g_strdup (""); + + return retval; +} + +/** + * atspi_accessible_get_localized_role_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets a UTF-8 string corresponding to the name of the role played by an + * object, translated to the current locale. + * This method will return useful values for roles that fall outside the + * enumeration used in atspi_accessible_getRole (). + * + * Returns: a localized, UTF-8 string specifying the type of UI role played + * by an #AtspiAccessible object. + * + **/ +gchar * +atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error) +{ + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_accessible, "GetLocalizedRoleName", error, "=>s", &retval); + + if (!retval) + return g_strdup (""); + + return retval; +} + +static AtspiStateSet * +defunct_set () +{ + AtspiStateSet *set = atspi_state_set_new (NULL); + atspi_state_set_add (set, ATSPI_STATE_DEFUNCT); + return set; +} + +/** + * atspi_accessible_get_state_set: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the states currently held by an object. + * + * Returns: (transfer full): a pointer to an #AtspiStateSet representing an + * object's current state set. + **/ +AtspiStateSet * +atspi_accessible_get_state_set (AtspiAccessible *obj) +{ + /* TODO: Should take a GError **, but would be an API break */ + if (!obj->parent.app || !obj->parent.app->bus) + return defunct_set (); + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_STATES)) + { + DBusMessage *reply; + DBusMessageIter iter; + reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, + "GetState", NULL, ""); + _ATSPI_DBUS_CHECK_SIG (reply, "au", NULL, defunct_set ()); + dbus_message_iter_init (reply, &iter); + _atspi_dbus_set_state (obj, &iter); + dbus_message_unref (reply); + _atspi_accessible_add_cache (obj, ATSPI_CACHE_STATES); + } + + return g_object_ref (obj->states); +} + +/** + * atspi_accessible_get_attributes: + * @obj: The #AtspiAccessible being queried. + * + * Gets the #AttributeSet representing any assigned + * name-value pair attributes or annotations for this object. + * For typographic, textual, or textually-semantic attributes, see + * atspi_text_get_attributes instead. + * + * Returns: (element-type gchar* gchar*) (transfer full): The name-value-pair + * attributes assigned to this object. + */ +GHashTable * +atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error) +{ + DBusMessage *message; + + g_return_val_if_fail (obj != NULL, NULL); + + if (obj->priv->cache) + { + GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes"); + if (val) + return g_value_dup_boxed (val); + } + + if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ATTRIBUTES)) + { + message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, + "GetAttributes", error, ""); + obj->attributes = _atspi_dbus_return_hash_from_message (message); + _atspi_accessible_add_cache (obj, ATSPI_CACHE_ATTRIBUTES); + } + + if (!obj->attributes) + return NULL; + return g_hash_table_ref (obj->attributes); +} + +static void +add_to_attribute_array (gpointer key, gpointer value, gpointer data) +{ + GArray **array = (GArray **)data; + gchar *str = g_strconcat (key, ":", value, NULL); + *array = g_array_append_val (*array, str); +} + +/** + * atspi_accessible_get_attributes_as_array: + * @obj: The #AtspiAccessible being queried. + * + * Gets a #GArray representing any assigned + * name-value pair attributes or annotations for this object. + * For typographic, textual, or textually-semantic attributes, see + * atspi_text_get_attributes_as_array instead. + * + * Returns: (element-type gchar*) (transfer full): The name-value-pair + * attributes assigned to this object. + */ +GArray * +atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error) +{ + DBusMessage *message; + + g_return_val_if_fail (obj != NULL, NULL); + + if (obj->priv->cache) + { + GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes"); + if (val) + { + GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *)); + GHashTable *attributes = g_value_get_boxed (val); + g_hash_table_foreach (attributes, add_to_attribute_array, &array); + return array; + } + } + + message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, ""); + return _atspi_dbus_return_attribute_array_from_message (message); +} + +/** + * atspi_accessible_get_application: + * @obj: The #AtspiAccessible being queried. + * + * Gets the containing #AtspiApplication for an object. + * + * Returns: (transfer full): the containing #AtspiApplication instance for + * this object. + */ +AtspiAccessible * +atspi_accessible_get_application (AtspiAccessible *obj, GError **error) +{ + AtspiAccessible *parent; + + g_object_ref (obj); + for (;;) + { + parent = atspi_accessible_get_parent (obj, NULL); + if (!parent && obj->parent.app && + atspi_accessible_get_role (obj, NULL) != ATSPI_ROLE_APPLICATION) + { + AtspiAccessible *root = g_object_ref (obj->parent.app->root); + if (root) + { + g_object_unref (obj); + if (atspi_accessible_get_role (root, NULL) == ATSPI_ROLE_DESKTOP_FRAME) + { + g_object_unref (root); + return NULL; + } + return root; + } + } + if (!parent || parent == obj || + atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME) + { + if (parent) + g_object_unref (parent); + return obj; + } + g_object_unref (obj); + obj = parent; + } +} + +/* Application-specific methods */ + +/** + * atspi_accessible_get_toolkit_name: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the toolkit name for an #AtspiAccessible object. + * Only works on application root objects. + * + * Returns: a UTF-8 string indicating the toolkit name for the #AtspiAccessible object or NULL on exception. + **/ +gchar * +atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + if (!obj->parent.app) + return NULL; + + if (!obj->parent.app->toolkit_name) + _atspi_dbus_get_property (obj, atspi_interface_application, "ToolkitName", + error, "s", &obj->parent.app->toolkit_name); + + return g_strdup (obj->parent.app->toolkit_name); +} + +/** + * atspi_accessible_get_toolkit_version: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the toolkit version for an #AtspiAccessible object. + * Only works on application root objects. + * + * Returns: a UTF-8 string indicating the toolkit version for the #AtspiAccessible object or NULL on exception. + **/ +gchar * +atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + if (!obj->parent.app) + return NULL; + + if (!obj->parent.app->toolkit_version) + _atspi_dbus_get_property (obj, atspi_interface_application, "Version", + error, "s", &obj->parent.app->toolkit_version); + + return g_strdup (obj->parent.app->toolkit_version); +} + +/** + * atspi_accessible_get_atspi_version: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the AT-SPI IPC specification version supported by the application + * pointed to by the #AtspiAccessible object. + * Only works on application root objects. + * + * Returns: a UTF-8 string indicating the AT-SPI version for the #AtspiAccessible object or NULL on exception. + **/ +gchar * +atspi_accessible_get_atspi_version (AtspiAccessible *obj, GError **error) +{ + g_return_val_if_fail (obj != NULL, NULL); + + if (!obj->parent.app) + return NULL; + + if (!obj->parent.app->atspi_version) + _atspi_dbus_get_property (obj, atspi_interface_application, "AtspiVersion", + error, "s", &obj->parent.app->atspi_version); + + return g_strdup (obj->parent.app->atspi_version); +} + +/** + * atspi_accessible_get_id: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the application id for a #AtspiAccessible object. + * Only works on application root objects. + * + * Returns: a positive #gint indicating the id for the #AtspiAccessible object + * or -1 on exception. + **/ +gint +atspi_accessible_get_id (AtspiAccessible *obj, GError **error) +{ + gint ret = -1; + + g_return_val_if_fail (obj != NULL, -1); + + if (!_atspi_dbus_get_property (obj, atspi_interface_application, "Id", error, "i", &ret)) + return -1; + return ret; +} + + +/* Interface query methods */ + +static gboolean +_atspi_accessible_is_a (AtspiAccessible *accessible, + const char *interface_name) +{ + int n; + + if (accessible == NULL) + { + return FALSE; + } + + if (!_atspi_accessible_test_cache (accessible, ATSPI_CACHE_INTERFACES)) + { + DBusMessage *reply; + DBusMessageIter iter; + reply = _atspi_dbus_call_partial (accessible, atspi_interface_accessible, + "GetInterfaces", NULL, ""); + _ATSPI_DBUS_CHECK_SIG (reply, "as", NULL, FALSE); + dbus_message_iter_init (reply, &iter); + _atspi_dbus_set_interfaces (accessible, &iter); + dbus_message_unref (reply); + _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES); + } + + n = _atspi_get_iface_num (interface_name); + if (n == -1) return FALSE; + return (gboolean) ((accessible->interfaces & (1 << n))? TRUE: FALSE); +} + +/** + * atspi_accessible_is_action: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiAction interface. + * + * Returns: #TRUE if @obj implements the #AtspiAction interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_action (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_action); +} + +/** + * atspi_accessible_is_application: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiApplication interface. + * + * Returns: #TRUE if @obj implements the #AtspiApplication interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_application (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_application); +} + +/** + * atspi_accessible_is_collection: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiCollection interface. + * + * Returns: #TRUE if @obj implements the #AtspiCollection interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_collection (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_collection); +} + +/** + * atspi_accessible_is_component: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements #AtspiComponent. + * + * Returns: #TRUE if @obj implements the #AtspiComponent interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_component (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_component); +} + +/** + * atspi_accessible_is_document: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiDocument interface. + * + * Returns: #TRUE if @obj implements the #AtspiDocument interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_document (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_document); +} + +/** + * atspi_accessible_is_editable_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiEditableText interface. + * + * Returns: #TRUE if @obj implements the #AtspiEditableText interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_editable_text (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_editable_text); +} + +/** + * atspi_accessible_is_hypertext: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiHypertext interface. + * + * Returns: #TRUE if @obj implements the #AtspiHypertext interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_hypertext (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_hypertext); +} + +/** + * atspi_accessible_is_hyperlink: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiHyperlink interface. + * + * Returns: #TRUE if @obj implements the #AtspiHypertext interface, + * #FALSE otherwise. + **/ +gboolean +atspi_accessible_is_hyperlink (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_hyperlink); +} + +/** + * atspi_accessible_is_image: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiImage interface. + * + * Returns: #TRUE if @obj implements the #AtspiImage interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_image (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_image); +} + +/** + * atspi_accessible_is_selection: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiSelection interface. + * + * Returns: #TRUE if @obj implements the #AtspiSelection interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_selection (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_selection); +} + +/** + * atspi_accessible_is_table: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiTable interface. + * + * Returns: #TRUE if @obj implements the #AtspiTable interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_table (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_table); +} + +/** + * atspi_accessible_is_table_cell: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiTableCell interface. + * + * Returns: #TRUE if @obj implements the #AtspiTable interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_table_cell (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_table_cell); +} + +/** + * atspi_accessible_is_streamable_content: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiStreamableContent interface. + * + * Returns: #TRUE if @obj implements the #AtspiStreamableContent interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_streamable_content (AtspiAccessible *obj) +{ +#if 0 + return _atspi_accessible_is_a (obj, + atspi_interface_streamable_content); +#else + g_warning ("Streamable content not implemented"); + return FALSE; +#endif +} + +/** + * atspi_accessible_is_text: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiText interface. + * + * Returns: #TRUE if @obj implements the #AtspiText interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_text (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_text); +} + +/** + * atspi_accessible_is_value: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Query whether the specified #AtspiAccessible implements the + * #AtspiValue interface. + * + * Returns: #TRUE if @obj implements the #AtspiValue interface, + * #FALSE otherwise. +**/ +gboolean +atspi_accessible_is_value (AtspiAccessible *obj) +{ + return _atspi_accessible_is_a (obj, + atspi_interface_value); +} + +/** + * atspi_accessible_get_action: (rename-to atspi_accessible_get_action_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiAction interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiAction interface + * instance, or NULL if @obj does not implement #AtspiAction. + * + * Deprecated: 2.10: Use atspi_accessible_get_action_iface instead. + **/ +AtspiAction * +atspi_accessible_get_action (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_action) ? + g_object_ref (ATSPI_ACTION (accessible)) : NULL); +} + +/** + * atspi_accessible_get_action_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiAction interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiAction interface + * instance, or NULL if @obj does not implement #AtspiAction. + **/ +AtspiAction * +atspi_accessible_get_action_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_action) ? + g_object_ref (ATSPI_ACTION (accessible)) : NULL); +} + +/** + * atspi_accessible_get_collection: (rename-to atspi_accessible_get_collection_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiCollection interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiCollection interface + * instance, or NULL if @obj does not implement #AtspiCollection. + * + * Deprecated: 2.10: Use atspi_accessible_get_collection_iface instead. + **/ +AtspiCollection * +atspi_accessible_get_collection (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ? + g_object_ref (ATSPI_COLLECTION (accessible)) : NULL); +} + +/** + * atspi_accessible_get_collection_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiCollection interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiCollection interface + * instance, or NULL if @obj does not implement #AtspiCollection. + **/ +AtspiCollection * +atspi_accessible_get_collection_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_collection) ? + g_object_ref (ATSPI_COLLECTION (accessible)) : NULL); +} + +/** + * atspi_accessible_get_component: (rename-to atspi_accessible_get_component_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiComponent interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiComponent interface + * instance, or NULL if @obj does not implement #AtspiComponent. + * + * Deprecated: 2.10: Use atspi_accessible_get_component_iface instead. + **/ +AtspiComponent * +atspi_accessible_get_component (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_component) ? + g_object_ref (ATSPI_COMPONENT (obj)) : NULL); +} + +/** + * atspi_accessible_get_component_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiComponent interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiComponent interface + * instance, or NULL if @obj does not implement #AtspiComponent. + **/ +AtspiComponent * +atspi_accessible_get_component_iface (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_component) ? + g_object_ref (ATSPI_COMPONENT (obj)) : NULL); +} + +/** + * atspi_accessible_get_document: (rename-to atspi_accessible_get_document_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiDocument interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiDocument interface + * instance, or NULL if @obj does not implement #AtspiDocument. + * + * Deprecated: 2.10: Use atspi_accessible_get_document_iface instead. + **/ +AtspiDocument * +atspi_accessible_get_document (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_document) ? + g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_document_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiDocument interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiDocument interface + * instance, or NULL if @obj does not implement #AtspiDocument. + **/ +AtspiDocument * +atspi_accessible_get_document_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_document) ? + g_object_ref (ATSPI_DOCUMENT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_editable_text: (rename-to atspi_accessible_get_editable_text_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiEditableText interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiEditableText interface + * instance, or NULL if @obj does not implement #AtspiEditableText. + * + * Deprecated: 2.10: Use atspi_accessible_get_editable_text_iface instead. + **/ +AtspiEditableText * +atspi_accessible_get_editable_text (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ? + g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_editable_text_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiEditableText interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiEditableText interface + * instance, or NULL if @obj does not implement #AtspiEditableText. + **/ +AtspiEditableText * +atspi_accessible_get_editable_text_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_editable_text) ? + g_object_ref (ATSPI_EDITABLE_TEXT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_hyperlink: + * @obj: a pointer to the #AtspiAccessible object on which to operate. + * + * Gets the #AtspiHyperlink interface for an #AtspiAccessible. + * + * Returns: (transfer full): the #AtspiHyperlink object associated with + * the given #AtspiAccessible, or NULL if not supported. + **/ +AtspiHyperlink * +atspi_accessible_get_hyperlink (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_hyperlink) ? + _atspi_hyperlink_new (accessible->parent.app, accessible->parent.path) : NULL); +} + +/** + * atspi_accessible_get_hypertext: (rename-to atspi_accessible_get_hypertext_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiHypertext interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiHypertext interface + * instance, or NULL if @obj does not implement #AtspiHypertext. + * + * Deprecated: 2.10: Use atspi_accessible_get_hypertext_iface instead. + **/ +AtspiHypertext * +atspi_accessible_get_hypertext (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ? + g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_hypertext_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiHypertext interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiHypertext interface + * instance, or NULL if @obj does not implement #AtspiHypertext. + **/ +AtspiHypertext * +atspi_accessible_get_hypertext_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_hypertext) ? + g_object_ref (ATSPI_HYPERTEXT (accessible)) : NULL); +} + +/** + * atspi_accessible_get_image: (rename-to atspi_accessible_get_image_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiImage interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or + * NULL if @obj does not implement #AtspiImage. + * + * Deprecated: 2.10: Use atspi_accessible_get_image_iface instead. + **/ +AtspiImage * +atspi_accessible_get_image (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_image) ? + g_object_ref (ATSPI_IMAGE (accessible)) : NULL); +} + +/** + * atspi_accessible_get_image_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiImage interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiImage interface instance, or + * NULL if @obj does not implement #AtspiImage. + **/ +AtspiImage * +atspi_accessible_get_image_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_image) ? + g_object_ref (ATSPI_IMAGE (accessible)) : NULL); +} + +/** + * atspi_accessible_get_selection: (rename-to atspi_accessible_get_selection_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiSelection interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiSelection interface + * instance, or NULL if @obj does not implement #AtspiSelection. + * + * Deprecated: 2.10: Use atspi_accessible_get_selection_iface instead. + **/ +AtspiSelection * +atspi_accessible_get_selection (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ? + g_object_ref (ATSPI_SELECTION (accessible)) : NULL); +} + +/** + * atspi_accessible_get_selection_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiSelection interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiSelection interface + * instance, or NULL if @obj does not implement #AtspiSelection. + **/ +AtspiSelection * +atspi_accessible_get_selection_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_selection) ? + g_object_ref (ATSPI_SELECTION (accessible)) : NULL); +} + +#if 0 +/** + * atspi_accessible_get_streamable_content: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiStreamableContent interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiStreamableContent interface + * instance, or NULL if @obj does not implement #AtspiStreamableContent. + **/ +AtspiStreamableContent * +atspi_accessible_get_streamable_content (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_streamable_content) ? + accessible : NULL); +} +#endif + +/** + * atspi_accessible_get_table: (rename-to atspi_accessible_get_table_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or + * NULL if @obj does not implement #AtspiTable. + * + * Deprecated: 2.10: Use atspi_accessible_get_table_iface instead. + **/ +AtspiTable * +atspi_accessible_get_table (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_table) ? + g_object_ref (ATSPI_TABLE (obj)) : NULL); +} + +/** + * atspi_accessible_get_table_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiTable interface instance, or + * NULL if @obj does not implement #AtspiTable. + **/ +AtspiTable * +atspi_accessible_get_table_iface (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_table) ? + g_object_ref (ATSPI_TABLE (obj)) : NULL); +} + +/** + * atspi_accessible_get_table_cell: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTableCell interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiTableCell interface instance, + * or NULL if @obj does not implement #AtspiTable. + **/ +AtspiTableCell * +atspi_accessible_get_table_cell (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_table_cell) ? + g_object_ref (ATSPI_TABLE_CELL (obj)) : NULL); +} + +/** + * atspi_accessible_get_text: (rename-to atspi_accessible_get_text_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiText interface instance, or + * NULL if @obj does not implement #AtspiText. + * + * Deprecated: 2.10: Use atspi_accessible_get_text_iface instead. + **/ +AtspiText * +atspi_accessible_get_text (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_text) ? + g_object_ref (ATSPI_TEXT (obj)) : NULL); +} + +/** + * atspi_accessible_get_text_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiText interface instance, or + * NULL if @obj does not implement #AtspiText. + **/ +AtspiText * +atspi_accessible_get_text_iface (AtspiAccessible *obj) +{ + return (_atspi_accessible_is_a (obj, atspi_interface_text) ? + g_object_ref (ATSPI_TEXT (obj)) : NULL); +} + +/** + * atspi_accessible_get_value: (rename-to atspi_accessible_get_value_iface) + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or + * NULL if @obj does not implement #AtspiValue. + * + * Deprecated: 2.10: Use atspi_accessible_get_value_iface instead. + **/ +AtspiValue * +atspi_accessible_get_value (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_value) ? + g_object_ref (ATSPI_VALUE (accessible)) : NULL); +} + +/** + * atspi_accessible_get_value_iface: + * @obj: a pointer to the #AtspiAccessible instance to query. + * + * Gets the #AtspiTable interface for an #AtspiAccessible. + * + * Returns: (transfer full): a pointer to an #AtspiValue interface instance, or + * NULL if @obj does not implement #AtspiValue. + **/ +AtspiValue * +atspi_accessible_get_value_iface (AtspiAccessible *accessible) +{ + return (_atspi_accessible_is_a (accessible, atspi_interface_value) ? + g_object_ref (ATSPI_VALUE (accessible)) : NULL); +} + +static void +append_const_val (GArray *array, const gchar *val) +{ + gchar *dup = g_strdup (val); + + if (dup) + g_array_append_val (array, dup); +} + +/** + * atspi_accessible_get_interfaces: + * @obj: The #AtspiAccessible to query. + * + * A set of pointers to all interfaces supported by an #AtspiAccessible. + * + * Returns: (element-type gchar*) (transfer full): A #GArray of strings + * describing the interfaces supported by the object. Interfaces are + * denoted in short-hand (i.e. "Component", "Text" etc.). + **/ +GArray * +atspi_accessible_get_interfaces (AtspiAccessible *obj) +{ + GArray *ret = g_array_new (TRUE, TRUE, sizeof (gchar *)); + + g_return_val_if_fail (obj != NULL, NULL); + + append_const_val (ret, "Accessible"); + if (atspi_accessible_is_action (obj)) + append_const_val (ret, "Action"); + if (atspi_accessible_is_collection (obj)) + append_const_val (ret, "Collection"); + if (atspi_accessible_is_component (obj)) + append_const_val (ret, "Component"); + if (atspi_accessible_is_document (obj)) + append_const_val (ret, "Document"); + if (atspi_accessible_is_editable_text (obj)) + append_const_val (ret, "EditableText"); + if (atspi_accessible_is_hypertext (obj)) + append_const_val (ret, "Hypertext"); + if (atspi_accessible_is_hyperlink (obj)) + append_const_val (ret, "Hyperlink"); + if (atspi_accessible_is_image (obj)) + append_const_val (ret, "Image"); + if (atspi_accessible_is_selection (obj)) + append_const_val (ret, "Selection"); + if (atspi_accessible_is_table (obj)) + append_const_val (ret, "Table"); + if (atspi_accessible_is_table_cell (obj)) + append_const_val (ret, "TableCell"); + if (atspi_accessible_is_text (obj)) + append_const_val (ret, "Text"); + if (atspi_accessible_is_value (obj)) + append_const_val (ret, "Value"); + + return ret; +} + +AtspiAccessible * +_atspi_accessible_new (AtspiApplication *app, const gchar *path) +{ + AtspiAccessible *accessible; + + accessible = g_object_new (ATSPI_TYPE_ACCESSIBLE, NULL); + g_return_val_if_fail (accessible != NULL, NULL); + + accessible->parent.app = g_object_ref (app); + accessible->parent.path = g_strdup (path); + + return accessible; +} + +/** + * atspi_accessible_set_cache_mask: + * @accessible: The #AtspiAccessible to operate on. Must be the desktop or + * the root of an application. + * @mask: An #AtspiCache specifying a bit mask of the types of data to cache. + * + * Sets the type of data to cache for accessibles. + * If this is not set for an application or is reset to ATSPI_CACHE_UNDEFINED, + * then the desktop's cache flag will be used. + * If the desktop's cache flag is also undefined, then all possible data will + * be cached. + * This function is intended to work around bugs in toolkits where the proper + * events are not raised / to aid in testing for such bugs. + **/ +void +atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask) +{ + g_return_if_fail (accessible != NULL); + g_return_if_fail (accessible->parent.app != NULL); + g_return_if_fail (accessible == accessible->parent.app->root); + accessible->parent.app->cache = mask; + enable_caching = TRUE; +} + +/** + * atspi_accessible_clear_cache: + * @obj: The #AtspiAccessible whose cache to clear. + * + * Clears the cached information for the given accessible and all of its + * descendants. + */ +void +atspi_accessible_clear_cache (AtspiAccessible *obj) +{ + gint i; + + if (obj) + { + obj->cached_properties = ATSPI_CACHE_NONE; + if (obj->children) + for (i = 0; i < obj->children->len; i++) + atspi_accessible_clear_cache (g_ptr_array_index (obj->children, i)); + } +} + +/** + * atspi_accessible_get_process_id: + * @accessible: The #AtspiAccessible to query. + * @error: a pointer to a %NULL #GError pointer + * + * Returns the process id associated with the given accessible. Mainly + * added for debugging; it is a shortcut to explicitly querying the + * accessible's app->bus_name and then calling GetConnectionUnixProcessID. + * + * Returns: The process ID or undetermined value if @error is set. + **/ +guint +atspi_accessible_get_process_id (AtspiAccessible *accessible, GError **error) +{ + DBusMessage *message, *reply; + DBusConnection *bus = _atspi_bus (); + dbus_uint32_t pid = -1; + DBusError d_error; + + if (!accessible->parent.app || !accessible->parent.app->bus_name) + { + g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct"); + return -1; + } + + message = dbus_message_new_method_call ("org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID"); + dbus_message_append_args (message, DBUS_TYPE_STRING, + &accessible->parent.app->bus_name, + DBUS_TYPE_INVALID); + dbus_error_init (&d_error); + reply = dbus_connection_send_with_reply_and_block (bus, message, -1, &d_error); + dbus_message_unref (message); + if (reply) + { + if (!strcmp (dbus_message_get_signature (reply), "u")) + dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_INVALID); + dbus_message_unref (reply); + } + if (dbus_error_is_set (&d_error)) + { + g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "Process is defunct"); + dbus_error_free (&d_error); + } + return pid; +} + +AtspiCache +_atspi_accessible_get_cache_mask (AtspiAccessible *accessible) +{ + AtspiCache mask; + + if (!accessible->parent.app) + return ATSPI_CACHE_NONE; + + mask = accessible->parent.app->cache; + if (mask == ATSPI_CACHE_UNDEFINED && + accessible->parent.app->root && + accessible->parent.app->root->accessible_parent) + { + AtspiAccessible *desktop = atspi_get_desktop (0); + mask = desktop->parent.app->cache; + g_object_unref (desktop); + } + + if (mask == ATSPI_CACHE_UNDEFINED) + mask = ATSPI_CACHE_DEFAULT; + + return mask; +} + +gboolean +_atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag) +{ + AtspiCache mask = _atspi_accessible_get_cache_mask (accessible); + AtspiCache result = accessible->cached_properties & mask & flag; + if (accessible->states && atspi_state_set_contains (accessible->states, ATSPI_STATE_TRANSIENT)) + return FALSE; + return (result != 0 && (atspi_main_loop || enable_caching || + flag == ATSPI_CACHE_INTERFACES) && + !atspi_no_cache); +} + +void +_atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag) +{ + AtspiCache mask = _atspi_accessible_get_cache_mask (accessible); + + accessible->cached_properties |= flag & mask; +} + +/** + * atspi_accessible_get_locale: + * @accessible: an #AtspiAccessible + * + * Gets a UTF-8 string indicating the POSIX-style LC_MESSAGES locale + * of @accessible. + * + * Since: 2.7.91 + * + * Returns: a UTF-8 string indicating the POSIX-style LC_MESSAGES + * locale of @accessible. + **/ +const gchar* +atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error) +{ + gchar *locale; + + g_return_val_if_fail (accessible != NULL, NULL); + + locale = g_object_get_qdata (G_OBJECT (accessible), quark_locale); + if (!locale) + { + if (!_atspi_dbus_get_property (accessible, atspi_interface_accessible, + "Locale", error, "s", &locale)) + return NULL; + if (locale) + g_object_set_qdata_full (G_OBJECT (accessible), quark_locale, locale, + g_free); + } + return locale; +} + +void +free_value (gpointer data) +{ + GValue *value = data; + + g_value_unset (value); + g_free (value); +} + +GHashTable * +_atspi_accessible_ref_cache (AtspiAccessible *accessible) +{ + AtspiAccessiblePrivate *priv = accessible->priv; + + priv->cache_ref_count++; + if (priv->cache) + return g_hash_table_ref (priv->cache); + priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, + free_value); + return priv->cache; +} + +void +_atspi_accessible_unref_cache (AtspiAccessible *accessible) +{ + AtspiAccessiblePrivate *priv = accessible->priv; + + if (priv->cache) + { + g_hash_table_unref (priv->cache); + if (--priv->cache_ref_count == 0) + priv->cache = NULL; + } +} diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h new file mode 100644 index 0000000..443e395 --- /dev/null +++ b/atspi/atspi-accessible.h @@ -0,0 +1,177 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_ACCESSIBLE_H_ +#define _ATSPI_ACCESSIBLE_H_ + +G_BEGIN_DECLS + +#include "glib-object.h" + +#include "atspi-application.h" +#include "atspi-constants.h" +#include "atspi-object.h" +#include "atspi-stateset.h" +#include "atspi-types.h" + +#define ATSPI_TYPE_ACCESSIBLE (atspi_accessible_get_type ()) +#define ATSPI_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessible)) +#define ATSPI_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass)) +#define ATSPI_IS_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_ACCESSIBLE)) +#define ATSPI_IS_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_ACCESSIBLE)) +#define ATSPI_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass)) + +typedef struct _AtspiAccessiblePrivate AtspiAccessiblePrivate; + +struct _AtspiAccessible +{ + AtspiObject parent; + AtspiAccessible *accessible_parent; + GPtrArray *children; + AtspiRole role; + gint interfaces; + char *name; + char *description; + AtspiStateSet *states; + GHashTable *attributes; + guint cached_properties; + AtspiAccessiblePrivate *priv; +}; + +typedef struct _AtspiAccessibleClass AtspiAccessibleClass; +struct _AtspiAccessibleClass +{ + AtspiObjectClass parent_class; +}; + +GType atspi_accessible_get_type (void); + +AtspiAccessible * +_atspi_accessible_new (AtspiApplication *app, const gchar *path); + +gchar * atspi_accessible_get_name (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_description (AtspiAccessible *obj, GError **error); + +AtspiAccessible * atspi_accessible_get_parent (AtspiAccessible *obj, GError **error); + +gint atspi_accessible_get_child_count (AtspiAccessible *obj, GError **error); + +AtspiAccessible * atspi_accessible_get_child_at_index (AtspiAccessible *obj, gint child_index, GError **error); + +gint atspi_accessible_get_index_in_parent (AtspiAccessible *obj, GError **error); + +GArray * atspi_accessible_get_relation_set (AtspiAccessible *obj, GError **error); + +AtspiRole atspi_accessible_get_role (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_role_name (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_localized_role_name (AtspiAccessible *obj, GError **error); + +AtspiStateSet * atspi_accessible_get_state_set (AtspiAccessible *obj); + +GHashTable * atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error); + +GArray * atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_toolkit_name (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_toolkit_version (AtspiAccessible *obj, GError **error); + +gchar * atspi_accessible_get_atspi_version (AtspiAccessible *obj, GError **error); + +gint atspi_accessible_get_id (AtspiAccessible *obj, GError **error); + +AtspiAccessible * atspi_accessible_get_application (AtspiAccessible *obj, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +AtspiAction * atspi_accessible_get_action (AtspiAccessible *obj); + +AtspiCollection * atspi_accessible_get_collection (AtspiAccessible *obj); + +AtspiComponent * atspi_accessible_get_component (AtspiAccessible *obj); + +AtspiDocument * atspi_accessible_get_document (AtspiAccessible *obj); + +AtspiEditableText * atspi_accessible_get_editable_text (AtspiAccessible *obj); + +AtspiHyperlink * atspi_accessible_get_hyperlink (AtspiAccessible *obj); + +AtspiHypertext * atspi_accessible_get_hypertext (AtspiAccessible *obj); + +AtspiImage * atspi_accessible_get_image (AtspiAccessible *obj); + +AtspiSelection * atspi_accessible_get_selection (AtspiAccessible *obj); + +AtspiTable * atspi_accessible_get_table (AtspiAccessible *obj); + +AtspiTableCell * atspi_accessible_get_table_cell (AtspiAccessible *obj); + +AtspiText * atspi_accessible_get_text (AtspiAccessible *obj); + +AtspiValue * atspi_accessible_get_value (AtspiAccessible *obj); +#endif + +AtspiAction * atspi_accessible_get_action_iface (AtspiAccessible *obj); + +AtspiCollection * atspi_accessible_get_collection_iface (AtspiAccessible *obj); + +AtspiComponent * atspi_accessible_get_component_iface (AtspiAccessible *obj); + +AtspiDocument * atspi_accessible_get_document_iface (AtspiAccessible *obj); + +AtspiEditableText * atspi_accessible_get_editable_text_iface (AtspiAccessible *obj); + +AtspiHypertext * atspi_accessible_get_hypertext_iface (AtspiAccessible *obj); + +AtspiImage * atspi_accessible_get_image_iface (AtspiAccessible *obj); + +AtspiSelection * atspi_accessible_get_selection_iface (AtspiAccessible *obj); + +AtspiTable * atspi_accessible_get_table_iface (AtspiAccessible *obj); + +AtspiText * atspi_accessible_get_text_iface (AtspiAccessible *obj); + +AtspiValue * atspi_accessible_get_value_iface (AtspiAccessible *obj); + +GArray * atspi_accessible_get_interfaces (AtspiAccessible *obj); + +const gchar* atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error); + +void atspi_accessible_set_cache_mask (AtspiAccessible *accessible, AtspiCache mask); + +void atspi_accessible_clear_cache (AtspiAccessible *obj); + +guint atspi_accessible_get_process_id (AtspiAccessible *accessible, GError **error); + +/* private */ +void _atspi_accessible_add_cache (AtspiAccessible *accessible, AtspiCache flag); +AtspiCache _atspi_accessible_get_cache_mask (AtspiAccessible *accessible); +gboolean _atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag); + +G_END_DECLS + +#endif /* _ATSPI_ACCESSIBLE_H_ */ diff --git a/atspi/atspi-action.c b/atspi/atspi-action.c new file mode 100644 index 0000000..731773a --- /dev/null +++ b/atspi/atspi-action.c @@ -0,0 +1,239 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_action_get_n_actions: + * @obj: a pointer to the #AtspiAction to query. + * + * Get the number of actions invokable on an #AtspiAction implementor. + * + * Returns: an integer indicating the number of invocable actions. + **/ +gint +atspi_action_get_n_actions (AtspiAction *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_action, "NActions", error, "i", &retval); + + return retval; +} + +/** + * atspi_action_get_description: (rename-to atspi_action_get_action_description) + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the description of '@i-th' action invocable on an + * object implementing #AtspiAction. + * + * Returns: a UTF-8 string describing the '@i-th' invocable action. + * + * Deprecated: 2.10: Use atspi_action_get_action_description instead. + **/ +gchar * +atspi_action_get_description (AtspiAction *obj, int i, GError **error) +{ + return atspi_action_get_action_description (obj, i, error); +} + +/** + * atspi_action_get_action_description: + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the description of '@i-th' action invocable on an + * object implementing #AtspiAction. + * + * Returns: a UTF-8 string describing the '@i-th' invocable action. + **/ +gchar * +atspi_action_get_action_description (AtspiAction *obj, int i, GError **error) +{ + dbus_int32_t d_i = i; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_action, "GetDescription", error, "i=>s", d_i, &retval); + + return retval; +} + +/** + * atspi_action_get_key_binding: + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the keybindings for the @i-th action invocable on an + * object implementing #AtspiAction, if any are defined. + * The keybindings string format is as follows: + * there are multiple parts to a keybinding string (typically 3). + * They are delimited with ";". The first is the action's + * keybinding which is usable if the object implementing the action + * is currently posted to the screen, e.g. if a menu is posted + * then these keybindings for the corresponding menu-items are + * available. The second keybinding substring is the full key sequence + * necessary to post the action's widget and activate it, e.g. for + * a menu item such as "File->Open" it would both post the menu and + * activate the item. Thus the second keybinding string is available + * during the lifetime of the containing toplevel window as a whole, + * whereas the first keybinding string only works while the object + * implementing AtkAction is posted. The third (and optional) + * keybinding string is the "keyboard shortcut" which invokes the + * action without posting any menus. + * Meta-keys are indicated by the conventional strings + * "<Control>", "<Alt>", "<Shift>", "<Mod2>", + * etc. (we use the same string as gtk_accelerator_name() in + * gtk+-2.X. + * + * Returns: a UTF-8 string which can be parsed to determine the @i-th + * invocable action's keybindings. + **/ +gchar * +atspi_action_get_key_binding (AtspiAction *obj, gint i, GError **error) +{ + dbus_int32_t d_i = i; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_action, "GetKeyBinding", error, "i=>s", d_i, &retval); + + return retval; +} + +/** + * atspi_action_get_name: (rename-to atspi_action_get_action_name) + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the name of the '@i-th' action invocable on an + * object implementing #AtspiAction. + * + * Returns: the non-localized name of the action, as a UTF-8 string. + * + * Deprecated: 2.10: Use atspi_action_get_action_name instead. + **/ +gchar * +atspi_action_get_name (AtspiAction *obj, gint i, GError **error) +{ + return atspi_action_get_action_name (obj, i, error); +} + +/** + * atspi_action_get_action_name: + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the name of the '@i-th' action invocable on an + * object implementing #AtspiAction. + * + * Returns: the non-localized name of the action, as a UTF-8 string. + **/ +gchar * +atspi_action_get_action_name (AtspiAction *obj, gint i, GError **error) +{ + dbus_int32_t d_i = i; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_action, "GetName", error, "i=>s", d_i, &retval); + + return retval; +} + +/** + * atspi_action_get_localized_name: + * @obj: a pointer to the #AtspiAction implementor to query. + * @i: an integer indicating which action to query. + * + * Get the name of the '@i-th' action invocable on an + * object implementing #AtspiAction. + * + * Returns: the name of the action, as a UTF-8 string. + **/ +gchar * +atspi_action_get_localized_name (AtspiAction *obj, gint i, GError **error) +{ + dbus_int32_t d_i = i; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_action, "GetLocalizedName", error, + "i=>s", d_i, &retval); + + return retval; +} + +/** + * atspi_action_do_action: + * @obj: a pointer to the #AtspiAction to query. + * @i: an integer specifying which action to invoke. + * + * Invoke the action indicated by #index. + * + * Returns: #TRUE if the action is successfully invoked, otherwise #FALSE. + **/ +gboolean +atspi_action_do_action (AtspiAction *obj, gint i, GError **error) +{ + dbus_int32_t d_i = i; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_action, "DoAction", error, "i=>b", d_i, &retval); + + return retval; +} + +static void +atspi_action_base_init (AtspiAction *klass) +{ +} + +GType +atspi_action_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiAction), + (GBaseInitFunc) atspi_action_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiAction", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-action.h b/atspi/atspi-action.h new file mode 100644 index 0000000..99de8af --- /dev/null +++ b/atspi/atspi-action.h @@ -0,0 +1,67 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_ACTION_H_ +#define _ATSPI_ACTION_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_ACTION (atspi_action_get_type ()) +#define ATSPI_IS_ACTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_ACTION) +#define ATSPI_ACTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_ACTION, AtspiAction) +#define ATSPI_ACTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_ACTION, AtspiAction)) + +GType atspi_action_get_type (); + +struct _AtspiAction +{ + GTypeInterface parent; +}; + +gchar * atspi_action_get_action_description (AtspiAction *obj, int i, GError **error); + +gchar * atspi_action_get_action_name (AtspiAction *obj, gint i, GError **error); + +gint atspi_action_get_n_actions (AtspiAction *obj, GError **error); + +gchar * atspi_action_get_key_binding (AtspiAction *obj, gint i, GError **error); + + +gchar * atspi_action_get_localized_name (AtspiAction *obj, gint i, GError **error); + +gboolean atspi_action_do_action (AtspiAction *obj, gint i, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +gchar * atspi_action_get_description (AtspiAction *obj, gint i, GError **error); +gchar * atspi_action_get_name (AtspiAction *obj, gint i, GError **error); +#endif +G_END_DECLS + +#endif /* _ATSPI_ACTION_H_ */ diff --git a/atspi/atspi-application.c b/atspi/atspi-application.c new file mode 100644 index 0000000..f7dd225 --- /dev/null +++ b/atspi/atspi-application.c @@ -0,0 +1,100 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include "atspi-private.h" + +G_DEFINE_TYPE (AtspiApplication, atspi_application, G_TYPE_OBJECT) + +static void +atspi_application_init (AtspiApplication *application) +{ +} + +static void +dispose_accessible (gpointer key, gpointer obj_data, gpointer data) +{ + g_object_run_dispose (obj_data); +} + +static void +atspi_application_dispose (GObject *object) +{ + AtspiApplication *application = ATSPI_APPLICATION (object); + + if (application->bus) + { + if (application->bus != _atspi_bus ()) + dbus_connection_close (application->bus); + dbus_connection_unref (application->bus); + application->bus = NULL; + } + + if (application->hash) + { + g_hash_table_foreach (application->hash, dispose_accessible, NULL); + g_hash_table_unref (application->hash); + application->hash = NULL; + } + + if (application->root) + { + g_clear_object (&application->root->parent.app); + g_object_unref (application->root); + application->root = NULL; + } + + G_OBJECT_CLASS (atspi_application_parent_class)->dispose (object); +} + +static void +atspi_application_finalize (GObject *object) +{ + AtspiApplication *application = ATSPI_APPLICATION (object); + + g_free (application->bus_name); + g_free (application->toolkit_name); + g_free (application->toolkit_version); + g_free (application->atspi_version); + + G_OBJECT_CLASS (atspi_application_parent_class)->finalize (object); +} + +static void +atspi_application_class_init (AtspiApplicationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = atspi_application_dispose; + object_class->finalize = atspi_application_finalize; +} + +AtspiApplication * +_atspi_application_new (const gchar *bus_name) +{ + AtspiApplication *application; + + application = g_object_new (ATSPI_TYPE_APPLICATION, NULL); + application->bus_name = g_strdup (bus_name); + application->root = NULL; + return application; +} diff --git a/atspi/atspi-application.h b/atspi/atspi-application.h new file mode 100644 index 0000000..a3826d5 --- /dev/null +++ b/atspi/atspi-application.h @@ -0,0 +1,69 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_APPLICATION_H_ +#define _ATSPI_APPLICATION_H_ + +#include + +#include "atspi-types.h" +#include "atspi-accessible.h" +#include + +G_BEGIN_DECLS + +#define ATSPI_TYPE_APPLICATION (atspi_application_get_type ()) +#define ATSPI_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_APPLICATION, AtspiApplication)) +#define ATSPI_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_APPLICATION, AtspiAccessibleClass)) +#define ATSPI_IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_APPLICATION)) +#define ATSPI_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_APPLICATION)) +#define ATSPI_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_APPLICATION, AtspiAccessibleClass)) + +typedef struct _AtspiApplication AtspiApplication; +struct _AtspiApplication +{ + GObject parent; + GHashTable *hash; + char *bus_name; + DBusConnection *bus; + struct _AtspiAccessible *root; + AtspiCache cache; + gchar *toolkit_name; + gchar *toolkit_version; + gchar *atspi_version; + struct timeval time_added; +}; + +typedef struct _AtspiApplicationClass AtspiApplicationClass; +struct _AtspiApplicationClass +{ + GObjectClass parent_class; +}; + +AtspiApplication * +_atspi_application_new (const char *bus_name); + +G_END_DECLS + +#endif /* _ATSPI_APPLICATION_H_ */ diff --git a/atspi/atspi-collection.c b/atspi/atspi-collection.c new file mode 100644 index 0000000..f4e33ef --- /dev/null +++ b/atspi/atspi-collection.c @@ -0,0 +1,296 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2007 IBM Corp. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/* TODO: Improve documentation and implement some missing functions */ + +/** + * atspi_collection_is_ancestor_of: + * + * Not yet implemented. + * + **/ +gboolean +atspi_collection_is_ancestor_of (AtspiCollection *collection, + AtspiAccessible *test, + GError **error) +{ + g_warning ("Atspi: TODO: Implement is_ancestor_of"); + return FALSE; +} + +static DBusMessage * +new_message (AtspiCollection *collection, char *method) +{ + AtspiAccessible *accessible; + + if (!collection) + return NULL; + + accessible = ATSPI_ACCESSIBLE (collection); + if (!accessible->parent.app) + return NULL; + return dbus_message_new_method_call (accessible->parent.app->bus_name, + accessible->parent.path, + atspi_interface_collection, + method); +} + +static gboolean +append_match_rule (DBusMessage *message, AtspiMatchRule *rule) +{ + DBusMessageIter iter; + + dbus_message_iter_init_append (message, &iter); + return _atspi_match_rule_marshal (rule, &iter); +} + +static gboolean +append_accessible (DBusMessage *message, AtspiAccessible *accessible) +{ + DBusMessageIter iter; + + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, + &accessible->parent.path); + return TRUE; /* TODO: Check for out-of-memory */ +} + +static GArray * +return_accessibles (DBusMessage *message) +{ + DBusMessageIter iter, iter_array; + GArray *ret = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *)); + + _ATSPI_DBUS_CHECK_SIG (message, "a(so)", NULL, NULL); + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *accessible; + accessible = _atspi_dbus_return_accessible_from_iter (&iter_array); + ret = g_array_append_val (ret, accessible); + /* Iter was moved already, so no need to call dbus_message_iter_next */ + } + dbus_message_unref (message); + return ret; +} + +/** + * atspi_collection_get_matches: + * @collection: A pointer to the #AtspiCollection to query. + * @rule: An #AtspiMatchRule describing the match criteria. + * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to + * be sorted. + * @count: The maximum number of results to return, or 0 for no limit. + * @traverse: Not supported. + * + * Gets all #AtspiAccessible objects from the @collection matching a given + * @rule. + * + * Returns: (element-type AtspiAccessible*) (transfer full): All + * #AtspiAccessible objects matching the given match rule. + **/ +GArray * +atspi_collection_get_matches (AtspiCollection *collection, + AtspiMatchRule *rule, + AtspiCollectionSortOrder sortby, + gint count, + gboolean traverse, + GError **error) +{ + DBusMessage *message = new_message (collection, "GetMatches"); + DBusMessage *reply; + dbus_int32_t d_sortby = sortby; + dbus_int32_t d_count = count; + dbus_bool_t d_traverse = traverse; + + if (!message) + return NULL; + + if (!append_match_rule (message, rule)) + return NULL; + dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby, + DBUS_TYPE_INT32, &d_count, + DBUS_TYPE_BOOLEAN, &d_traverse, + DBUS_TYPE_INVALID); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + if (!reply) + return NULL; + return return_accessibles (reply); +} + +/** + * atspi_collection_get_matches_to: + * @collection: A pointer to the #AtspiCollection to query. + * @current_object: The object at which to start searching. + * @rule: An #AtspiMatchRule describing the match criteria. + * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to + * be sorted. + * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on + * the objects to be traversed. + * @limit_scope: If #TRUE, only descendants of @current_object's parent + * will be returned. Otherwise (if #FALSE), any accessible may be + * returned if it would preceed @current_object in a flattened + * hierarchy. + * @count: The maximum number of results to return, or 0 for no limit. + * @traverse: Not supported. + * + * Gets all #AtspiAccessible objects from the @collection, after + * @current_object, matching a given @rule. + * + * Returns: (element-type AtspiAccessible*) (transfer full): All + * #AtspiAccessible objects matching the given match rule after + * @current_object. + **/ +GArray * +atspi_collection_get_matches_to (AtspiCollection *collection, + AtspiAccessible *current_object, + AtspiMatchRule *rule, + AtspiCollectionSortOrder sortby, + AtspiCollectionTreeTraversalType tree, + gboolean limit_scope, + gint count, + gboolean traverse, + GError **error) +{ + DBusMessage *message = new_message (collection, "GetMatchesTo"); + DBusMessage *reply; + dbus_int32_t d_sortby = sortby; + dbus_int32_t d_tree = tree; + dbus_bool_t d_limit_scope = limit_scope; + dbus_int32_t d_count = count; + dbus_bool_t d_traverse = traverse; + + if (!message) + return NULL; + + if (!append_accessible (message, current_object)) + return NULL; + if (!append_match_rule (message, rule)) + return NULL; + dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby, + DBUS_TYPE_UINT32, &d_tree, + DBUS_TYPE_BOOLEAN, &d_limit_scope, + DBUS_TYPE_INT32, &d_count, + DBUS_TYPE_BOOLEAN, &d_traverse, + DBUS_TYPE_INVALID); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + if (!reply) + return NULL; + return return_accessibles (reply); +} + +/** + * atspi_collection_get_matches_from: + * @collection: A pointer to the #AtspiCollection to query. + * @current_object: Upon reaching this object, searching should stop. + * @rule: An #AtspiMatchRule describing the match criteria. + * @sortby: An #AtspiCollectionSortOrder specifying the way the results are to + * be sorted. + * @tree: An #AtspiCollectionTreeTraversalType specifying restrictions on + * the objects to be traversed. + * @count: The maximum number of results to return, or 0 for no limit. + * @traverse: Not supported. + * + * Gets all #AtspiAccessible objects from the @collection, before + * @current_object, matching a given @rule. + * + * Returns: (element-type AtspiAccessible*) (transfer full): All + * #AtspiAccessible objects matching the given match rule that preceed + * @current_object. + **/ +GArray * +atspi_collection_get_matches_from (AtspiCollection *collection, + AtspiAccessible *current_object, + AtspiMatchRule *rule, + AtspiCollectionSortOrder sortby, + AtspiCollectionTreeTraversalType tree, + gint count, + gboolean traverse, + GError **error) +{ + DBusMessage *message = new_message (collection, "GetMatchesFrom"); + DBusMessage *reply; + dbus_int32_t d_sortby = sortby; + dbus_int32_t d_tree = tree; + dbus_int32_t d_count = count; + dbus_bool_t d_traverse = traverse; + + if (!message) + return NULL; + + if (!append_accessible (message, current_object)) + return NULL; + if (!append_match_rule (message, rule)) + return NULL; + dbus_message_append_args (message, DBUS_TYPE_UINT32, &d_sortby, + DBUS_TYPE_UINT32, &d_tree, + DBUS_TYPE_INT32, &d_count, + DBUS_TYPE_BOOLEAN, &d_traverse, + DBUS_TYPE_INVALID); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + if (!reply) + return NULL; + return return_accessibles (reply); +} + +/** + * atspi_collection_get_active_descendant: + * +* Returns: (transfer full): The active descendant of the given object. + * Not yet implemented. + **/ +AtspiAccessible * +atspi_collection_get_active_descendant (AtspiCollection *collection, GError **error) +{ + g_warning ("atspi: TODO: Implement get_active_descendants"); + return NULL; +} + +static void +atspi_collection_base_init (AtspiCollection *klass) +{ +} + +GType +atspi_collection_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiCollection), + (GBaseInitFunc) atspi_collection_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiCollection", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-collection.h b/atspi/atspi-collection.h new file mode 100644 index 0000000..2ba9361 --- /dev/null +++ b/atspi/atspi-collection.h @@ -0,0 +1,62 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_COLLECTION_H_ +#define _ATSPI_COLLECTION_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" +#include "atspi-matchrule.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_COLLECTION (atspi_collection_get_type ()) +#define ATSPI_IS_COLLECTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_COLLECTION) +#define ATSPI_COLLECTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_COLLECTION, AtspiCollection) +#define ATSPI_COLLECTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_COLLECTION, AtspiCollection)) + +GType atspi_collection_get_type (); + +struct _AtspiCollection +{ + GTypeInterface parent; +}; + +gboolean atspi_collection_is_ancestor_of (AtspiCollection *collection, AtspiAccessible *test, GError **error); + +GArray * atspi_collection_get_matches (AtspiCollection *collection, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, gint count, gboolean traverse, GError **error); + +GArray * atspi_collection_get_matches_to (AtspiCollection *collection, AtspiAccessible *current_object, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, gboolean limit_scope, gint count, gboolean traverse, GError **error); + +GArray * atspi_collection_get_matches_from (AtspiCollection *collection, AtspiAccessible *current_object, AtspiMatchRule *rule, AtspiCollectionSortOrder sortby, AtspiCollectionTreeTraversalType tree, gint count, gboolean traverse, GError **error); + +AtspiAccessible * atspi_collection_get_active_descendant (AtspiCollection *collection, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_COLLECTION_H_ */ diff --git a/atspi/atspi-component.c b/atspi/atspi-component.c new file mode 100644 index 0000000..0ab552b --- /dev/null +++ b/atspi/atspi-component.c @@ -0,0 +1,437 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +/* + * + * AtspiComponent function implementations + * + */ + +#include "atspi-private.h" +#include "atspi-accessible-private.h" + +void +atspi_rect_free (AtspiRect *rect) +{ + g_free (rect); +} + +AtspiRect * +atspi_rect_copy (AtspiRect *src) +{ + AtspiRect *dst = g_new (AtspiRect, 1); + dst->x = src->x; + dst->y = src->y; + dst->height = src->height; + dst->width = src->width; + return dst; +} + +G_DEFINE_BOXED_TYPE (AtspiRect, atspi_rect, atspi_rect_copy, atspi_rect_free) + +AtspiPoint * +atspi_point_copy (AtspiPoint *src) +{ + AtspiPoint *dst = g_new (AtspiPoint, 1); + dst->x = src->x; + dst->y = src->y; + return dst; +} + +G_DEFINE_BOXED_TYPE (AtspiPoint, atspi_point, atspi_point_copy, g_free) + +/** + * atspi_component_contains: + * @obj: a pointer to the #AtspiComponent to query. + * @x: a #gint specifying the x coordinate in question. + * @y: a #gint specifying the y coordinate in question. + * @ctype: the desired coordinate system of the point (@x, @y) + * (e.g. CSPI_COORD_TYPE_WINDOW, CSPI_COORD_TYPE_SCREEN). + * + * Queries whether a given #AtspiComponent contains a particular point. + * + * Returns: #TRUE if the specified component contains the point (@x, @y), + * #FALSE otherwise. + **/ +gboolean +atspi_component_contains (AtspiComponent *obj, + gint x, + gint y, + AtspiCoordType ctype, GError **error) +{ + dbus_bool_t retval = FALSE; + dbus_int32_t d_x = x, d_y = y; + dbus_uint32_t d_ctype = ctype; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_component, "Contains", error, "iiu=>b", d_x, d_y, d_ctype, &retval); + + return retval; +} + +/** + * atspi_component_get_accessible_at_point: + * @obj: a pointer to the #AtspiComponent to query. + * @x: a #gint specifying the x coordinate of the point in question. + * @y: a #gint specifying the y coordinate of the point in question. + * @ctype: the coordinate system of the point (@x, @y) + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Gets the accessible child at a given coordinate within an #AtspiComponent. + * + * Returns: (nullable) (transfer full): a pointer to an + * #AtspiAccessible child of the specified component which + * contains the point (@x, @y), or NULL if no child contains + * the point. + **/ +AtspiAccessible * +atspi_component_get_accessible_at_point (AtspiComponent *obj, + gint x, + gint y, + AtspiCoordType ctype, GError **error) +{ + dbus_int32_t d_x = x, d_y = y; + dbus_uint32_t d_ctype = ctype; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, FALSE); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_component, "GetAccessibleAtPoint", error, "iiu", d_x, d_y, d_ctype); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_component_get_extents: + * @obj: a pointer to the #AtspiComponent to query. + * @ctype: the desired coordinate system into which to return the results, + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Gets the bounding box of the specified #AtspiComponent. + * + * Returns: An #AtspiRect giving the accessible's extents. + **/ +AtspiRect * +atspi_component_get_extents (AtspiComponent *obj, + AtspiCoordType ctype, GError **error) +{ + dbus_uint32_t d_ctype = ctype; + AtspiRect bbox; + AtspiAccessible *accessible; + + bbox.x = bbox.y = bbox.width = bbox.height = -1; + g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox)); + + accessible = ATSPI_ACCESSIBLE (obj); + if (accessible->priv->cache && ctype == ATSPI_COORD_TYPE_SCREEN) + { + GValue *val = g_hash_table_lookup (accessible->priv->cache, "Component.ScreenExtents"); + if (val) + { + return g_value_dup_boxed (val); + } + } + + _atspi_dbus_call (obj, atspi_interface_component, "GetExtents", error, "u=>(iiii)", d_ctype, &bbox); + return atspi_rect_copy (&bbox); +} + +/** + * atspi_component_get_position: + * @obj: a pointer to the #AtspiComponent to query. + * @ctype: the desired coordinate system into which to return the results, + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Gets the minimum x and y coordinates of the specified #AtspiComponent. + * + * returns: An #AtspiPoint giving the @obj's position. + **/ +AtspiPoint * +atspi_component_get_position (AtspiComponent *obj, + AtspiCoordType ctype, GError **error) +{ + dbus_int32_t d_x, d_y; + dbus_uint32_t d_ctype = ctype; + AtspiPoint ret; + + ret.x = ret.y = -1; + + if (!obj) + return atspi_point_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_component, "GetPosition", error, "u=>ii", d_ctype, &d_x, &d_y); + + ret.x = d_x; + ret.y = d_y; + return atspi_point_copy (&ret); +} + +/** + * atspi_component_get_size: + * @obj: a pointer to the #AtspiComponent to query. + * + * Gets the size of the specified #AtspiComponent. + * + * returns: An #AtspiPoint giving the @obj's size. + **/ +AtspiPoint * +atspi_component_get_size (AtspiComponent *obj, GError **error) +{ + dbus_int32_t d_w, d_h; + AtspiPoint ret; + + ret.x = ret.y = -1; + if (!obj) + return atspi_point_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_component, "GetSize", error, "=>ii", &d_w, &d_h); + ret.x = d_w; + ret.y = d_h; + return atspi_point_copy (&ret); +} + +/** + * atspi_component_get_layer: + * @obj: a pointer to the #AtspiComponent to query. + * + * Queries which layer the component is painted into, to help determine its + * visibility in terms of stacking order. + * + * Returns: the #AtspiComponentLayer into which this component is painted. + **/ +AtspiComponentLayer +atspi_component_get_layer (AtspiComponent *obj, GError **error) +{ + dbus_uint32_t zlayer = -1; + + _atspi_dbus_call (obj, atspi_interface_component, "GetLayer", error, "=>u", &zlayer); + + return zlayer; +} + +/** + * atspi_component_get_mdi_z_order: + * @obj: a pointer to the #AtspiComponent to query. + * + * Queries the z stacking order of a component which is in the MDI or window + * layer. (Bigger z-order numbers mean nearer the top) + * + * Returns: a #gshort indicating the stacking order of the component + * in the MDI layer, or -1 if the component is not in the MDI layer. + **/ +gshort +atspi_component_get_mdi_z_order (AtspiComponent *obj, GError **error) +{ + dbus_uint16_t retval = -1; + + _atspi_dbus_call (obj, atspi_interface_component, "GetMDIZOrder", error, "=>n", &retval); + + return retval; +} + +/** + * atspi_component_grab_focus: + * @obj: a pointer to the #AtspiComponent on which to operate. + * + * Attempts to set the keyboard input focus to the specified + * #AtspiComponent. + * + * Returns: #TRUE if successful, #FALSE otherwise. + * + **/ +gboolean +atspi_component_grab_focus (AtspiComponent *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + _atspi_dbus_call (obj, atspi_interface_component, "GrabFocus", error, "=>b", &retval); + + return retval; +} + +/** + * atspi_component_get_alpha: + * @obj: The #AtspiComponent to be queried. + * + * Gets the opacity/alpha value of a component, if alpha blending is in use. + * + * Returns: the opacity value of a component, as a #gdouble between 0.0 and 1.0. + **/ +gdouble +atspi_component_get_alpha (AtspiComponent *obj, GError **error) +{ + double retval = 1; + + _atspi_dbus_call (obj, atspi_interface_component, "GetAlpha", error, "=>d", &retval); + + return retval; +} + +/** + * atspi_component_set_extents: + * @obj: a pointer to the #AtspiComponent to move. + * @x: the new vertical position to which the component should be moved. + * @y: the new horizontal position to which the component should be moved. + * @width: the width to which the component should be resized. + * @height: the height to which the component should be resized. + * @ctype: the coordinate system in which the position is specified. + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Moves and resizes the specified component. + * + * Returns: #TRUE if successful; #FALSE otherwise. + **/ +gboolean +atspi_component_set_extents (AtspiComponent *obj, + gint x, + gint y, + gint width, + gint height, + AtspiCoordType ctype, + GError **error) +{ + dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height; + dbus_uint32_t d_ctype = ctype; + DBusMessageIter iter, iter_struct; + DBusMessage *message, *reply; + dbus_bool_t retval = FALSE; + AtspiAccessible *aobj = ATSPI_ACCESSIBLE (obj); + + g_return_val_if_fail (obj != NULL, FALSE); + + if (!aobj->parent.app || !aobj->parent.app->bus_name) + { + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE, + _("The application no longer exists")); + return FALSE; + } + + message = dbus_message_new_method_call (aobj->parent.app->bus_name, + aobj->parent.path, + atspi_interface_component, + "SetExtents"); + if (!message) + return FALSE; + + dbus_message_iter_init_append (message, &iter); + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &iter_struct)) + { + dbus_message_unref (message); + return FALSE; + } + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_x); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_y); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_width); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_height); + dbus_message_iter_close_container (&iter, &iter_struct); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &d_ctype); + + reply = _atspi_dbus_send_with_reply_and_block (message, error); + dbus_message_get_args (reply, NULL, DBUS_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + dbus_message_unref (reply); + return retval; +} + +/** + * atspi_component_set_position: + * @obj: a pointer to the #AtspiComponent to move. + * @x: the new vertical position to which the component should be moved. + * @y: the new horizontal position to which the component should be moved. + * @ctype: the coordinate system in which the position is specified. + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Moves the component to the specified position. + * + * Returns: #TRUE if successful; #FALSE otherwise. + **/ +gboolean +atspi_component_set_position (AtspiComponent *obj, + gint x, + gint y, + AtspiCoordType ctype, + GError **error) +{ + dbus_int32_t d_x = x, d_y = y; + dbus_uint32_t d_ctype = ctype; + dbus_bool_t ret = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_component, "SetPosition", error, + "iiu=>b", d_x, d_y, d_ctype, &ret); + + return ret; +} + +/** + * atspi_component_set_size: + * @obj: a pointer to the #AtspiComponent to query. + * @width: the width to which the component should be resized. + * @height: the height to which the component should be resized. + * + * Resizes the specified component to the given coordinates. + * + * Returns: #TRUE if successful; #FALSE otherwise. + **/ +gboolean +atspi_component_set_size (AtspiComponent *obj, + gint width, + gint height, + GError **error) +{ + dbus_int32_t d_width = width, d_height = height; + dbus_bool_t ret = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_component, "SetSize", error, "ii=>b", + d_width, d_height, &ret); + + return ret; +} + +static void +atspi_component_base_init (AtspiComponent *klass) +{ +} + +GType +atspi_component_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiComponent), + (GBaseInitFunc) atspi_component_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiComponent", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-component.h b/atspi/atspi-component.h new file mode 100644 index 0000000..dd3455a --- /dev/null +++ b/atspi/atspi-component.h @@ -0,0 +1,112 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_COMPONENT_H_ +#define _ATSPI_COMPONENT_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +typedef struct _AtspiRect AtspiRect; +struct _AtspiRect +{ + gint x; + gint y; + gint width; + gint height; +}; + +/** + * ATSPI_TYPE_RECT: + * + * The #GType for a boxed type holding a #AtspiRect. + */ +#define ATSPI_TYPE_RECT (atspi_rect_get_type ()) + +GType atspi_rect_get_type (); + +AtspiRect *atspi_rect_copy (AtspiRect *src); + +typedef struct _AtspiPoint AtspiPoint; +struct _AtspiPoint +{ + gint x; + gint y; +}; + +/** + * ATSPI_TYPE_POINT: + * + * The #GType for a boxed type holding a #AtspiPoint. + */ +#define ATSPI_TYPE_POINT (atspi_point_get_type ()) + +GType atspi_point_get_type (); + +AtspiPoint *atspi_point_copy (AtspiPoint *src); + +#define ATSPI_TYPE_COMPONENT (atspi_component_get_type ()) +#define ATSPI_IS_COMPONENT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_COMPONENT) +#define ATSPI_COMPONENT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_COMPONENT, AtspiComponent) +#define ATSPI_COMPONENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_COMPONENT, AtspiComponent)) + +GType atspi_component_get_type (); + +struct _AtspiComponent +{ + GTypeInterface parent; +}; + +gboolean atspi_component_contains (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error); + +AtspiAccessible *atspi_component_get_accessible_at_point (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error); + +AtspiRect *atspi_component_get_extents (AtspiComponent *obj, AtspiCoordType ctype, GError **error); + +AtspiPoint *atspi_component_get_position (AtspiComponent *obj, AtspiCoordType ctype, GError **error); + +AtspiPoint *atspi_component_get_size (AtspiComponent *obj, GError **error); + +AtspiComponentLayer atspi_component_get_layer (AtspiComponent *obj, GError **error); + +gshort atspi_component_get_mdi_z_order (AtspiComponent *obj, GError **error); + +gboolean atspi_component_grab_focus (AtspiComponent *obj, GError **error); + +gdouble atspi_component_get_alpha (AtspiComponent *obj, GError **error); + +gboolean atspi_component_set_extents (AtspiComponent *obj, gint x, gint y, gint width, gint height, AtspiCoordType ctype, GError **error); + +gboolean atspi_component_set_position (AtspiComponent *obj, gint x, gint y, AtspiCoordType ctype, GError **error); + +gboolean atspi_component_set_size (AtspiComponent *obj, gint width, gint height, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_COMPONENT_H_ */ diff --git a/atspi/atspi-constants.h b/atspi/atspi-constants.h new file mode 100644 index 0000000..1604f59 --- /dev/null +++ b/atspi/atspi-constants.h @@ -0,0 +1,1421 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2010, 2011 Novell, Inc. + * Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * 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. + */ + +/* TODO: Auto-generate this file again + + + + !\mainpage AT-SPI Interfaces and Subinterfaces + + This is the main documentation page for the + Assistive Technology Service Provider Interface (AT-SPI). + + \section apps Applications and Interface Components + Namespace Accessibility includes service APIs implemented by + participating applications and their user interface components:\n\n + Accessibility::Accessible\n + Accessibility::Application\n + Accessibility::Desktop\n + Accessibility::Collecgtion\n + Accessibility::Component\n + Accessibility::Hypertext\n + Accessibility::Image\n + Accessibility::Selection\n + Accessibility::Table\n + Accessibility::Text\n + Accessibility::EditableText\n + Accessibility::Value + + \section types Enumerated Types + Accessibility defines a number of key enumerated types, including:\n\n + Accessibility::RelationType\n + Accessibility::Role\n + Accessibility::StateType\n + Accessibility::Event\n + Accessibility::EventDetails \n + + \section Registry + Accessibility also includes Accessibility::Registry, + which is the service used by assistive technologies and related + AT-SPI clients to register interest in certain classes of events, + enumerate the currently available desktop and application list, + and to synthesize certain kinds of device events. + + \section listeners Event Listener Interfaces + Accessibility::EventListener\n + Accessibility::DeviceEventListener + + \section helpers Helper Interfaces + + The following interfaces may be implemented by assistive technologies + themselves, in order to export their services in a consistent manner or + in order to interoperate with other applications or desktop services.\n + + Accessibility::LoginHelper : Implemented by adaptive technologies which + need to participate in user-authentication or login activities, and which + therefore may need negotiation with authentication agents or processes.\n + + Accessibility::Selector [NEW]: Implemented by user agents or assistive + technologies which export lists of choices from which the end-user is + expected to make selections. Useful for various types of remote + activation or intercommunication between multiple ATs. + + */ + +#ifndef _ATSPI_CONSTANTS_H_ +#define _ATSPI_CONSTANTS_H_ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * AtspiLocaleType: + * @ATSPI_LOCALE_TYPE_MESSAGES: For localizable natural-language messages. + * @ATSPI_LOCALE_TYPE_COLLATE: For regular expression matching and string + * collation. + * @ATSPI_LOCALE_TYPE_CTYPE: For regular expression matching, character + * classification, conversion, case-sensitive comparison, and wide character + * functions. + * @ATSPI_LOCALE_TYPE_MONETARY: For monetary formatting. + * @ATSPI_LOCALE_TYPE_NUMERIC: For number formatting (such as the decimal + * point and the thousands separator). + * @ATSPI_LOCALE_TYPE_TIME: For time and date formatting. + * + * Used by interfaces #AtspiText and #AtspiDocument, this + * enumeration corresponds to the POSIX 'setlocale' enum values. + * + **/ +typedef enum { + ATSPI_LOCALE_TYPE_MESSAGES, + ATSPI_LOCALE_TYPE_COLLATE, + ATSPI_LOCALE_TYPE_CTYPE, + ATSPI_LOCALE_TYPE_MONETARY, + ATSPI_LOCALE_TYPE_NUMERIC, + ATSPI_LOCALE_TYPE_TIME, +} AtspiLocaleType; + +/** + * ATSPI_LOCALE_TYPE_COUNT: + * + * One higher than the highest valid value of #AtspiLocaleType. + **/ +#define ATSPI_LOCALE_TYPE _COUNT(5+1) + +/** + * AtspiCoordType: + * @ATSPI_COORD_TYPE_SCREEN: Specifies xy coordinates relative to the screen. + * @ATSPI_COORD_TYPE_WINDOW: Specifies xy coordinates relative to the widget's + * top-level window. + * + * Enumeration used by #AtspiComponent, #AtspiImage, and #AtspiText interfaces + * to specify whether coordinates are relative to the window or the screen. + * + **/ +typedef enum { + ATSPI_COORD_TYPE_SCREEN, + ATSPI_COORD_TYPE_WINDOW, +} AtspiCoordType; + +/** + * ATSPI_COORD_TYPE_COUNT: + * + * One higher than the highest valid value of #AtspiCoordType. + **/ +#define ATSPI_COORD_TYPE_COUNT (1+1) + +/** + * AtspiCollectionSortOrder: + * @ATSPI_Collection_SORT_ORDER_INVALID: + * @ATSPI_Collection_SORT_ORDER_CANONICAL: + * @ATSPI_Collection_SORT_ORDER_FLOW: + * @ATSPI_Collection_SORT_ORDER_TAB: + * @ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL: + * @ATSPI_Collection_SORT_ORDER_REVERSE_FLOW: + * @ATSPI_Collection_SORT_ORDER_REVERSE_TAB: + * @ATSPI_Collection_SORT_ORDER_LAST_DEFINED: + * + * Enumeration used by interface #AtspiCollection to specify + * the way #AtspiAccesible objects should be sorted. + * + **/ +typedef enum { + ATSPI_Collection_SORT_ORDER_INVALID, + ATSPI_Collection_SORT_ORDER_CANONICAL, + ATSPI_Collection_SORT_ORDER_FLOW, + ATSPI_Collection_SORT_ORDER_TAB, + ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL, + ATSPI_Collection_SORT_ORDER_REVERSE_FLOW, + ATSPI_Collection_SORT_ORDER_REVERSE_TAB, + ATSPI_Collection_SORT_ORDER_LAST_DEFINED, +} AtspiCollectionSortOrder; + +/** + * ATSPI_SORTORDER_COUNT: + * + * One higher than the highest valid value of #AtspiCollectionSortOrder. + */ +#define ATSPI_SORTORDER_COUNT (7+1) + +/** + * AtspiCollectionMatchType: + * @ATSPI_Collection_MATCH_INVALID: Indicates an error condition or + * uninitialized value. + * @ATSPI_Collection_MATCH_ALL: #TRUE if all of the criteria are met. + * @ATSPI_Collection_MATCH_ANY: #TRUE if any of the criteria are met. + * @ATSPI_Collection_MATCH_NONE: #TRUE if none of the criteria are met. + * @ATSPI_Collection_MATCH_EMPTY: Same as @ATSPI_Collection_MATCH_ALL if + * the criteria is non-empty; for empty criteria this rule requires returned + * value to also have empty set. + * @ATSPI_Collection_MATCH_LAST_DEFINED: Used only to determine the end of the + * enumeration. + * + * Enumeration used by #AtspiMatchRule to specify + * how to interpret #AtspiAccessible objects. + * + **/ +typedef enum { + ATSPI_Collection_MATCH_INVALID, + ATSPI_Collection_MATCH_ALL, + ATSPI_Collection_MATCH_ANY, + ATSPI_Collection_MATCH_NONE, + ATSPI_Collection_MATCH_EMPTY, + ATSPI_Collection_MATCH_LAST_DEFINED, +} AtspiCollectionMatchType; + +/** + * ATSPI_MATCHTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiCollectionMatchType. + **/ +#define ATSPI_MATCHTYPES_COUNT (5+1) + +/** + * AtspiCollectionTreeTraversalType: + * @ATSPI_Collection_TREE_RESTRICT_CHILDREN: + * @ATSPI_Collection_TREE_RESTRICT_SIBLING: + * @ATSPI_Collection_TREE_INORDER: + * @ATSPI_Collection_TREE_LAST_DEFINED: + * + * Enumeration used by interface #AtspiCollection to specify + * restrictions on #AtspiAccesible objects to be traversed. + * + **/ +typedef enum { + ATSPI_Collection_TREE_RESTRICT_CHILDREN, + ATSPI_Collection_TREE_RESTRICT_SIBLING, + ATSPI_Collection_TREE_INORDER, + ATSPI_Collection_TREE_LAST_DEFINED, +} AtspiCollectionTreeTraversalType; + +/** + * ATSPI_TREETRAVERSALTYPE_COUNT: + * + * One higher than the highest valid value of + * #AtspiCollection_TreeTraversalType. + */ +#define ATSPI_TREETRAVERSALTYPE _COUNT(3+1) + +/** + * AtspiComponentLayer: + * @ATSPI_LAYER_INVALID: Indicates an error condition or uninitialized value. + * @ATSPI_LAYER_BACKGROUND: The bottom-most layer, over which everything else + * is painted. The 'desktop background' is generally in this layer. + * @ATSPI_LAYER_CANVAS: The 'background' layer for most content renderers and + * UI #AtspiComponent containers. + * @ATSPI_LAYER_WIDGET: The layer in which the majority of ordinary + * 'foreground' widgets reside. + * @ATSPI_LAYER_MDI: A special layer between @ATSPI_LAYER_CANVAS and + * @ATSPI_LAYER_WIDGET, in which the 'pseudo windows' (e.g. the MDI frames) + * reside. See #atspi_component_get_mdi_z_order. + * @ATSPI_LAYER_POPUP: A layer for popup window content, above + * @ATSPI_LAYER_WIDGET. + * @ATSPI_LAYER_OVERLAY: The topmost layer. + * @ATSPI_LAYER_WINDOW: The layer in which a toplevel window background usually + * resides. + * @ATSPI_LAYER_LAST_DEFINED: Used only to determine the end of the + * enumeration. + * + * The #AtspiComponentLayer of an #AtspiComponent instance indicates its + * relative stacking order with respect to the onscreen visual representation + * of the UI. #AtspiComponentLayer, in combination with #AtspiComponent bounds + * information, can be used to compute the visibility of all or part of a + * component. This is important in programmatic determination of + * region-of-interest for magnification, and in + * flat screen review models of the screen, as well as + * for other uses. Objects residing in two of the #AtspiComponentLayer + * categories support further z-ordering information, with respect to their + * peers in the same layer: namely, @ATSPI_LAYER_WINDOW and + * @ATSPI_LAYER_MDI. Relative stacking order for other objects within the + * same layer is not available; the recommended heuristic is + * first child paints first. In other words, assume that the + * first siblings in the child list are subject to being overpainted by later + * siblings if their bounds intersect. The order of layers, from bottom to top, + * is: @ATSPI_LAYER_BACKGROUND, @ATSPI_LAYER_WINDOW, @ATSPI_LAYER_MDI, + * @ATSPI_LAYER_CANVAS, @ATSPI_LAYER_WIDGET, @ATSPI_LAYER_POPUP, and + * @ATSPI_LAYER_OVERLAY. + * + */ +typedef enum { + ATSPI_LAYER_INVALID, + ATSPI_LAYER_BACKGROUND, + ATSPI_LAYER_CANVAS, + ATSPI_LAYER_WIDGET, + ATSPI_LAYER_MDI, + ATSPI_LAYER_POPUP, + ATSPI_LAYER_OVERLAY, + ATSPI_LAYER_WINDOW, + ATSPI_LAYER_LAST_DEFINED, +} AtspiComponentLayer; + +/** + * ATSPI_COMPONENTLAYER_COUNT: + * + * One higher than the highest valid value of #AtspiComponentLayer. + **/ +#define ATSPI_COMPONENTLAYER_COUNT (8+1) + +/** + * AtspiTextBoundaryType: + * @ATSPI_TEXT_BOUNDARY_CHAR: An #AtspiText instance is bounded by this + * character only. Start and end offsets differ by one, by definition, + * for this value. + * @ATSPI_TEXT_BOUNDARY_WORD_START: Boundary condition is start of a word; i.e. + * range is from start of one word to the start of another word. + * @ATSPI_TEXT_BOUNDARY_WORD_END: Boundary condition is the end of a word; i.e. + * range is from the end of one word to the end of another. Some locales + * may not distinguish between words and characters or glyphs. In particular, + * those locales which use wholly or partially ideographic character sets. + * In these cases, characters may be returned in lieu of multi-character + * substrings. + * @ATSPI_TEXT_BOUNDARY_SENTENCE_START: Boundary condition is start of a + * sentence, as determined by the application. Some locales or + * character sets may not include explicit sentence delimiters, so this + * boundary type can not always be honored. Some locales will return lines + * of text instead of grammatical sentences. + * @ATSPI_TEXT_BOUNDARY_SENTENCE_END: Boundary condition is end of a sentence, + * as determined by the application, including the sentence-delimiting + * character, for instance '.' Some locales or character sets may not + * include explicit sentence delimiters, so this boundary type can not + * always be honored. Some locales will return lines of text instead of + * grammatical sentences. + * @ATSPI_TEXT_BOUNDARY_LINE_START: Boundary condition is the start of a line; + * i.e. range is from start of one line to the start of another. This + * generally means that an end-of-line character will appear at the end of + * the range. + * @ATSPI_TEXT_BOUNDARY_LINE_END: Boundary condition is the end of a line; i.e. + * range is from start of one line to the start of another. This generally + * means that an end-of-line character will be the first character of the + * range. + * + * Specifies the boundary conditions determining a run of text as returned from + * #atspi_text_get_text_at_offset, #atspi_text_get_text_after_offset, and + * #atspi_text_get_text_before_offset. + * + * This enumerationis deprecated since 2.9.90 and should not be used. Use + * AtspiTextGranularity with #atspi_text_get_string_at_offset instead. + **/ +typedef enum { + ATSPI_TEXT_BOUNDARY_CHAR, + ATSPI_TEXT_BOUNDARY_WORD_START, + ATSPI_TEXT_BOUNDARY_WORD_END, + ATSPI_TEXT_BOUNDARY_SENTENCE_START, + ATSPI_TEXT_BOUNDARY_SENTENCE_END, + ATSPI_TEXT_BOUNDARY_LINE_START, + ATSPI_TEXT_BOUNDARY_LINE_END, +} AtspiTextBoundaryType; + +/** + *AtspiTextGranularity: + *@ATSPI_TEXT_GRANULARITY_CHAR: Granularity is defined by the boundaries between characters + * (including non-printing characters) + *@ATSPI_TEXT_GRANULARITY_WORD: Granularity is defined by the boundaries of a word, + * starting at the beginning of the current word and finishing at the beginning of + * the following one, if present. + *@ATSPI_TEXT_GRANULARITY_SENTENCE: Granularity is defined by the boundaries of a sentence, + * starting at the beginning of the current sentence and finishing at the beginning of + * the following one, if present. + *@ATSPI_TEXT_GRANULARITY_LINE: Granularity is defined by the boundaries of a line, + * starting at the beginning of the current line and finishing at the beginning of + * the following one, if present. + *@ATSPI_TEXT_GRANULARITY_PARAGRAPH: Granularity is defined by the boundaries of a paragraph, + * starting at the beginning of the current paragraph and finishing at the beginning of + * the following one, if present. + * + * Text granularity types used for specifying the granularity of the region of + * text we are interested in. + **/ +typedef enum { + ATSPI_TEXT_GRANULARITY_CHAR, + ATSPI_TEXT_GRANULARITY_WORD, + ATSPI_TEXT_GRANULARITY_SENTENCE, + ATSPI_TEXT_GRANULARITY_LINE, + ATSPI_TEXT_GRANULARITY_PARAGRAPH +} AtspiTextGranularity; + +/** + * ATSPI_TEXT_BOUNDARY_TYPE_COUNT: + * + * One higher than the highest valid value of #AtspiTextBoundaryType. + */ +#define ATSPI_TEXT_BOUNDARY_TYPE_COUNT (6+1) + +/** + * AtspiTextClipType: + * @ATSPI_TEXT_CLIP_NONE: No characters/glyphs are omitted. + * @ATSPI_TEXT_CLIP_MIN: Characters/glyphs clipped by the minimum coordinate + * are omitted. + * @ATSPI_TEXT_CLIP_MAX: Characters/glyphs which intersect the maximum + * coordinate are omitted. + * @ATSPI_TEXT_CLIP_BOTH: Only glyphs falling entirely within the region + * bounded by min and max are retained. + * + * Enumeration used by interface #AtspiText to indicate + * how to treat characters intersecting bounding boxes. + * + **/ +typedef enum { + ATSPI_TEXT_CLIP_NONE, + ATSPI_TEXT_CLIP_MIN, + ATSPI_TEXT_CLIP_MAX, + ATSPI_TEXT_CLIP_BOTH, +} AtspiTextClipType; + +/** + * ATSPI_TEXT_CLIP_TYPE_COUNT: + * + * One higher than the highest valid value of #AtspiTextClipType. + */ +#define ATSPI_TEXT_CLIP_TYPE_COUNT (3+1) + +/** + * AtspiStateType: + * @ATSPI_STATE_INVALID: Indicates an invalid state - probably an error + * condition. + * @ATSPI_STATE_ACTIVE: Indicates a window is currently the active window, or + * an object is the active subelement within a container or table. + * @ATSPI_STATE_ACTIVE should not be used for objects which have + * @ATSPI_STATE_FOCUSABLE or @ATSPI_STATE_SELECTABLE: Those objects should use + * @ATSPI_STATE_FOCUSED and @ATSPI_STATE_SELECTED respectively. + * @ATSPI_STATE_ACTIVE is a means to indicate that an object which is not + * focusable and not selectable is the currently-active item within its + * parent container. + * @ATSPI_STATE_ARMED: Indicates that the object is armed. + * @ATSPI_STATE_BUSY: Indicates the current object is busy, i.e. onscreen + * representation is in the process of changing, or the object is + * temporarily unavailable for interaction due to activity already in progress. + * @ATSPI_STATE_CHECKED: Indicates this object is currently checked. + * @ATSPI_STATE_COLLAPSED: Indicates this object is collapsed. + * @ATSPI_STATE_DEFUNCT: Indicates that this object no longer has a valid + * backing widget (for instance, if its peer object has been destroyed). + * @ATSPI_STATE_EDITABLE: Indicates the user can change the contents of this + * object. + * @ATSPI_STATE_ENABLED: Indicates that this object is enabled, i.e. that it + * currently reflects some application state. Objects that are "greyed out" + * may lack this state, and may lack the @ATSPI_STATE_SENSITIVE if direct + * user interaction cannot cause them to acquire @ATSPI_STATE_ENABLED. + * See @ATSPI_STATE_SENSITIVE. + * @ATSPI_STATE_EXPANDABLE: Indicates this object allows progressive + * disclosure of its children. + * @ATSPI_STATE_EXPANDED: Indicates this object is expanded. + * @ATSPI_STATE_FOCUSABLE: Indicates this object can accept keyboard focus, + * which means all events resulting from typing on the keyboard will + * normally be passed to it when it has focus. + * @ATSPI_STATE_FOCUSED: Indicates this object currently has the keyboard + * focus. + * @ATSPI_STATE_HAS_TOOLTIP: Indicates that the object has an associated + * tooltip. + * @ATSPI_STATE_HORIZONTAL: Indicates the orientation of this object is + * horizontal. + * @ATSPI_STATE_ICONIFIED: Indicates this object is minimized and is + * represented only by an icon. + * @ATSPI_STATE_MODAL: Indicates something must be done with this object + * before the user can interact with an object in a different window. + * @ATSPI_STATE_MULTI_LINE: Indicates this (text) object can contain multiple + * lines of text. + * @ATSPI_STATE_MULTISELECTABLE: Indicates this object allows more than one of + * its children to be selected at the same time, or in the case of text + * objects, that the object supports non-contiguous text selections. + * @ATSPI_STATE_OPAQUE: Indicates this object paints every pixel within its + * rectangular region. It also indicates an alpha value of unity, if it + * supports alpha blending. + * @ATSPI_STATE_PRESSED: Indicates this object is currently pressed. + * @ATSPI_STATE_RESIZABLE: Indicates the size of this object's size is not + * fixed. + * @ATSPI_STATE_SELECTABLE: Indicates this object is the child of an object + * that allows its children to be selected and that this child is one of + * those children that can be selected. + * @ATSPI_STATE_SELECTED: Indicates this object is the child of an object that + * allows its children to be selected and that this child is one of those + * children that has been selected. + * @ATSPI_STATE_SENSITIVE: Indicates this object is sensitive, e.g. to user + * interaction. @ATSPI_STATE_SENSITIVE usually accompanies. + * @ATSPI_STATE_ENABLED for user-actionable controls, but may be found in the + * absence of @ATSPI_STATE_ENABLED if the current visible state of the control + * is "disconnected" from the application state. In such cases, direct user + * interaction can often result in the object gaining @ATSPI_STATE_SENSITIVE, + * for instance if a user makes an explicit selection using an object whose + * current state is ambiguous or undefined. See @ATSPI_STATE_ENABLED, + * @ATSPI_STATE_INDETERMINATE. + * @ATSPI_STATE_SHOWING: Indicates this object, the object's parent, the + * object's parent's parent, and so on, are all 'shown' to the end-user, + * i.e. subject to "exposure" if blocking or obscuring objects do not + * interpose between this object and the top of the window stack. + * @ATSPI_STATE_SINGLE_LINE: Indicates this (text) object can contain only a + * single line of text. + * @ATSPI_STATE_STALE: Indicates that the information returned for this object + * may no longer be synchronized with the application state. This can occur + * if the object has @ATSPI_STATE_TRANSIENT, and can also occur towards the + * end of the object peer's lifecycle. + * @ATSPI_STATE_TRANSIENT: Indicates this object is transient. + * @ATSPI_STATE_VERTICAL: Indicates the orientation of this object is vertical; + * for example this state may appear on such objects as scrollbars, text + * objects (with vertical text flow), separators, etc. + * @ATSPI_STATE_VISIBLE: Indicates this object is visible, e.g. has been + * explicitly marked for exposure to the user. @ATSPI_STATE_VISIBLE is no + * guarantee that the object is actually unobscured on the screen, only that + * it is 'potentially' visible, barring obstruction, being scrolled or clipped + * out of the field of view, or having an ancestor container that has not yet + * made visible. A widget is potentially onscreen if it has both + * @ATSPI_STATE_VISIBLE and @ATSPI_STATE_SHOWING. The absence of + * @ATSPI_STATE_VISIBLE and @ATSPI_STATE_SHOWING is + * semantically equivalent to saying that an object is 'hidden'. + * @ATSPI_STATE_MANAGES_DESCENDANTS: Indicates that "active-descendant-changed" + * event is sent when children become 'active' (i.e. are selected or + * navigated to onscreen). Used to prevent need to enumerate all children + * in very large containers, like tables. The presence of + * @ATSPI_STATE_MANAGES_DESCENDANTS is an indication to the client that the + * children should not, and need not, be enumerated by the client. + * Objects implementing this state are expected to provide relevant state + * notifications to listening clients, for instance notifications of + * visibility changes and activation of their contained child objects, without + * the client having previously requested references to those children. + * @ATSPI_STATE_INDETERMINATE: Indicates that a check box or other boolean + * indicator is in a state other than checked or not checked. This + * usually means that the boolean value reflected or controlled by the + * object does not apply consistently to the entire current context. + * For example, a checkbox for the "Bold" attribute of text may have + * @ATSPI_STATE_INDETERMINATE if the currently selected text contains a mixture + * of weight attributes. In many cases interacting with a + * @ATSPI_STATE_INDETERMINATE object will cause the context's corresponding + * boolean attribute to be homogenized, whereupon the object will lose + * @ATSPI_STATE_INDETERMINATE and a corresponding state-changed event will be + * fired. + * @ATSPI_STATE_REQUIRED: Indicates that user interaction with this object is + * 'required' from the user, for instance before completing the + * processing of a form. + * @ATSPI_STATE_TRUNCATED: Indicates that an object's onscreen content + * is truncated, e.g. a text value in a spreadsheet cell. + * @ATSPI_STATE_ANIMATED: Indicates this object's visual representation is + * dynamic, not static. This state may be applied to an object during an + * animated 'effect' and be removed from the object once its visual + * representation becomes static. Some applications, notably content viewers, + * may not be able to detect all kinds of animated content. Therefore the + * absence of this state should not be taken as + * definitive evidence that the object's visual representation is + * static; this state is advisory. + * @ATSPI_STATE_INVALID_ENTRY: This object has indicated an error condition + * due to failure of input validation. For instance, a form control may + * acquire this state in response to invalid or malformed user input. + * @ATSPI_STATE_SUPPORTS_AUTOCOMPLETION: This state indicates that the object + * in question implements some form of typeahead or + * pre-selection behavior whereby entering the first character of one or more + * sub-elements causes those elements to scroll into view or become + * selected. Subsequent character input may narrow the selection further as + * long as one or more sub-elements match the string. This state is normally + * only useful and encountered on objects that implement #AtspiSelection. + * In some cases the typeahead behavior may result in full or partial + * completion of the data in the input field, in which case + * these input events may trigger text-changed events from the source. + * @ATSPI_STATE_SELECTABLE_TEXT: This state indicates that the object in + * question supports text selection. It should only be exposed on objects + * which implement the #AtspiText interface, in order to distinguish this state + * from @ATSPI_STATE_SELECTABLE, which infers that the object in question is a + * selectable child of an object which implements #AtspiSelection. While + * similar, text selection and subelement selection are distinct operations. + * @ATSPI_STATE_IS_DEFAULT: This state indicates that the object in question is + * the 'default' interaction object in a dialog, i.e. the one that gets + * activated if the user presses "Enter" when the dialog is initially + * posted. + * @ATSPI_STATE_VISITED: This state indicates that the object (typically a + * hyperlink) has already been activated or invoked, with the result that + * some backing data has been downloaded or rendered. + *@ATSPI_STATE_CHECKABLE: Indicates this object has the potential to + * be checked, such as a checkbox or toggle-able table cell. @Since: + * 2.12 + *@ATSPI_STATE_HAS_POPUP: Indicates that the object has a popup + * context menu or sub-level menu which may or may not be + * showing. This means that activation renders conditional content. + * Note that ordinary tooltips are not considered popups in this + * context. @Since: 2.12 + * @ATSPI_STATE_READ_ONLY: Indicates that an object which is ENABLED and + * SENSITIVE has a value which can be read, but not modified, by the + * user. @Since: 2.16 + * @ATSPI_STATE_LAST_DEFINED: This value of the enumeration should not be used + * as a parameter, it indicates the number of items in the #AtspiStateType + * enumeration. + * + * + * Enumeration used by various interfaces indicating every possible state + * an #AtspiAccesible object can assume. + * + **/ +typedef enum { + ATSPI_STATE_INVALID, + ATSPI_STATE_ACTIVE, + ATSPI_STATE_ARMED, + ATSPI_STATE_BUSY, + ATSPI_STATE_CHECKED, + ATSPI_STATE_COLLAPSED, + ATSPI_STATE_DEFUNCT, + ATSPI_STATE_EDITABLE, + ATSPI_STATE_ENABLED, + ATSPI_STATE_EXPANDABLE, + ATSPI_STATE_EXPANDED, + ATSPI_STATE_FOCUSABLE, + ATSPI_STATE_FOCUSED, + ATSPI_STATE_HAS_TOOLTIP, + ATSPI_STATE_HORIZONTAL, + ATSPI_STATE_ICONIFIED, + ATSPI_STATE_MODAL, + ATSPI_STATE_MULTI_LINE, + ATSPI_STATE_MULTISELECTABLE, + ATSPI_STATE_OPAQUE, + ATSPI_STATE_PRESSED, + ATSPI_STATE_RESIZABLE, + ATSPI_STATE_SELECTABLE, + ATSPI_STATE_SELECTED, + ATSPI_STATE_SENSITIVE, + ATSPI_STATE_SHOWING, + ATSPI_STATE_SINGLE_LINE, + ATSPI_STATE_STALE, + ATSPI_STATE_TRANSIENT, + ATSPI_STATE_VERTICAL, + ATSPI_STATE_VISIBLE, + ATSPI_STATE_MANAGES_DESCENDANTS, + ATSPI_STATE_INDETERMINATE, + ATSPI_STATE_REQUIRED, + ATSPI_STATE_TRUNCATED, + ATSPI_STATE_ANIMATED, + ATSPI_STATE_INVALID_ENTRY, + ATSPI_STATE_SUPPORTS_AUTOCOMPLETION, + ATSPI_STATE_SELECTABLE_TEXT, + ATSPI_STATE_IS_DEFAULT, + ATSPI_STATE_VISITED, + ATSPI_STATE_CHECKABLE, + ATSPI_STATE_HAS_POPUP, + ATSPI_STATE_READ_ONLY, + ATSPI_STATE_LAST_DEFINED, +} AtspiStateType; + +/** + * ATSPI_STATETYPE_COUNT: + * + * One higher than the highest valid value of #AtspiStateType. + **/ +#define ATSPI_STATETYPE_COUNT (41+1) + +/** + * AtspiKeyEventType: + * @ATSPI_KEY_PRESSED: + * @ATSPI_KEY_RELEASED: + * + * Deprecated. Should not be used. + * + **/ +typedef enum { + ATSPI_KEY_PRESSED, + ATSPI_KEY_RELEASED, +} AtspiKeyEventType; + +/** + * ATSPI_KEYEVENTTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiKeyEventType. + **/ +#define ATSPI_KEYEVENTTYPE_COUNT (1+1) + +/** + * AtspiEventType: + * @ATSPI_KEY_PRESSED_EVENT: Indicates that a key on a keyboard device was + * pressed. + * @ATSPI_KEY_RELEASED_EVENT: Indicates that a key on a keyboard device was + * released. + * @ATSPI_BUTTON_PRESSED_EVENT: Indicates that a button on a non-keyboard + * human interface device (HID) was pressed. + * @ATSPI_BUTTON_RELEASED_EVENT: Indicates that a button on a non-keyboard + * human interface device (HID) was released. + * + * Enumeration used to specify the event types of interest to an + * #AtspiEventListener, or + * to identify the type of an event for which notification has been sent. + * + **/ +typedef enum { + ATSPI_KEY_PRESSED_EVENT, + ATSPI_KEY_RELEASED_EVENT, + ATSPI_BUTTON_PRESSED_EVENT, + ATSPI_BUTTON_RELEASED_EVENT, +} AtspiEventType; + +/** + * ATSPI_EVENTTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiEventType. + */ +#define ATSPI_EVENTTYPE_COUNT (3+1) + +/** + * AtspiKeySynthType: + * @ATSPI_KEY_PRESS: Emulates the pressing of a hardware keyboard key. + * @ATSPI_KEY_RELEASE: Emulates the release of a hardware keyboard key. + * @ATSPI_KEY_PRESSRELEASE: Emulates the pressing and immediate releasing + * of a hardware keyboard key. + * @ATSPI_KEY_SYM: A symbolic key event is generated, without specifying a + * hardware key. Note: if the keysym is not present in the current keyboard + * map, the #AtspiDeviceEventController instance has a limited ability to + * generate such keysyms on-the-fly. Reliability of GenerateKeyboardEvent + * calls using out-of-keymap keysyms will vary from system to system, and on + * the number of different out-of-keymap keysyms being generated in quick + * succession. + * In practice this is rarely significant, since the keysyms of interest to + * AT clients and keyboard emulators are usually part of the current keymap, + * i.e., present on the system keyboard for the current locale (even if a + * physical hardware keyboard is not connected). + * @ATSPI_KEY_STRING: A string is converted to its equivalent keyboard events + * and emitted. If the string consists of complex characters or composed + * characters which are not in the current keymap, string emission is + * subject to the out-of-keymap limitations described for + * @ATSPI_KEY_SYM. In practice this limitation primarily effects + * Chinese and Japanese locales. + * + * Enumeration used when synthesizing keyboard input via + * #atspi_generate_keyboard_event. + * + **/ +typedef enum { + ATSPI_KEY_PRESS, + ATSPI_KEY_RELEASE, + ATSPI_KEY_PRESSRELEASE, + ATSPI_KEY_SYM, + ATSPI_KEY_STRING, +} AtspiKeySynthType; + +/** + * ATSPI_KEYSYNTHTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiKeySynthType. + **/ +#define ATSPI_KEYSYNTHTYPE_COUNT (4+1) + +/** + * AtspiModifierType: + * @ATSPI_MODIFIER_SHIFT: The left or right 'Shift' key. + * @ATSPI_MODIFIER_SHIFTLOCK: The ShiftLock or CapsLock key. + * @ATSPI_MODIFIER_CONTROL: 'Control'/'Ctrl'. + * @ATSPI_MODIFIER_ALT: The Alt key (as opposed to AltGr). + * @ATSPI_MODIFIER_META: Depending on the platform, this may map to 'Window', + * 'Function', 'Meta', 'Menu', or 'NumLock'. Such 'Meta keys' will + * map to one of META, META2, META3. On X Windows platforms these META + * values map to the modifier masks Mod1Mask, Mod2Mask, Mod3Mask, e.g. an + * event having @ATSPI_MODIFIER_META2 means that the 'Mod2Mask' bit + * is set in the corresponding XEvent. + * @ATSPI_MODIFIER_META2: See @ATSPI_MODIFIER_META. + * @ATSPI_MODIFIER_META3: See @ATSPI_MODIFIER_META. + * @ATSPI_MODIFIER_NUMLOCK: A symbolic meta key name that is mapped by AT-SPI + * to the appropriate META value, for the convenience of the client. + * + * + * + **/ +typedef enum { + ATSPI_MODIFIER_SHIFT, + ATSPI_MODIFIER_SHIFTLOCK, + ATSPI_MODIFIER_CONTROL, + ATSPI_MODIFIER_ALT, + ATSPI_MODIFIER_META, + ATSPI_MODIFIER_META2, + ATSPI_MODIFIER_META3, + ATSPI_MODIFIER_NUMLOCK = 14, +} AtspiModifierType; + +/** + * ATSPI_MODIFIERTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiModifierType. + **/ +#define ATSPI_MODIFIERTYPE_COUNT (7+1) + +/** + * AtspiRelationType: + * @ATSPI_RELATION_NULL: Not a meaningful relationship; clients should not + * normally encounter this #AtspiRelationType value. + * @ATSPI_RELATION_LABEL_FOR: Object is a label for one or more other objects. + * @ATSPI_RELATION_LABELLED_BY: Object is labelled by one or more other + * objects. + * @ATSPI_RELATION_CONTROLLER_FOR: Object is an interactive object which + * modifies the state, onscreen location, or other attributes of one or more + * target objects. + * @ATSPI_RELATION_CONTROLLED_BY: Object state, position, etc. is + * modified/controlled by user interaction with one or more other objects. + * For instance a viewport or scroll pane may be @ATSPI_RELATION_CONTROLLED_BY + * scrollbars. + * @ATSPI_RELATION_MEMBER_OF: Object has a grouping relationship (e.g. 'same + * group as') to one or more other objects. + * @ATSPI_RELATION_TOOLTIP_FOR: Object is a tooltip associated with another + * object. + * @ATSPI_RELATION_NODE_CHILD_OF: Object is a child of the target. + * @ATSPI_RELATION_NODE_PARENT_OF: Object is a parent of the target. + * @ATSPI_RELATION_EXTENDED: Used to indicate that a relationship exists, but + * its type is not specified in the enumeration. + * @ATSPI_RELATION_FLOWS_TO: Object renders content which flows logically to + * another object. For instance, text in a paragraph may flow to another + * object which is not the 'next sibling' in the accessibility hierarchy. + * @ATSPI_RELATION_FLOWS_FROM: Reciprocal of @ATSPI_RELATION_FLOWS_TO. + * @ATSPI_RELATION_SUBWINDOW_OF: Object is visually and semantically considered + * a subwindow of another object, even though it is not the object's child. + * Useful when dealing with embedded applications and other cases where the + * widget hierarchy does not map cleanly to the onscreen presentation. + * @ATSPI_RELATION_EMBEDS: Similar to @ATSPI_RELATION_SUBWINDOW_OF, but + * specifically used for cross-process embedding. + * @ATSPI_RELATION_EMBEDDED_BY: Reciprocal of @ATSPI_RELATION_EMBEDS. Used to + * denote content rendered by embedded renderers that live in a separate process + * space from the embedding context. + * @ATSPI_RELATION_POPUP_FOR: Denotes that the object is a transient window or + * frame associated with another onscreen object. Similar to @ATSPI_TOOLTIP_FOR, + * but more general. Useful for windows which are technically toplevels + * but which, for one or more reasons, do not explicitly cause their + * associated window to lose 'window focus'. Creation of an @ATSPI_ROLE_WINDOW + * object with the @ATSPI_RELATION_POPUP_FOR relation usually requires + * some presentation action on the part + * of assistive technology clients, even though the previous toplevel + * @ATSPI_ROLE_FRAME object may still be the active window. + * @ATSPI_RELATION_PARENT_WINDOW_OF: This is the reciprocal relation to + * @ATSPI_RELATION_POPUP_FOR. + * @ATSPI_RELATION_DESCRIBED_BY: Reciprocal of %ATSPI_RELATION_DESCRIPTION_FOR. + * Indicates that one or more target objects provide descriptive information + * about this object. This relation type is most appropriate for information + * that is not essential as its presentation may be user-configurable and/or + * limited to an on-demand mechanism such as an assistive technology command. + * For brief, essential information such as can be found in a widget's on-screen + * label, use %ATSPI_RELATION_LABELLED_BY. For an on-screen error message, use + * %ATSPI_RELATION_ERROR_MESSAGE. For lengthy extended descriptive information + * contained in an on-screen object, consider using %ATSPI_RELATION_DETAILS as + * assistive technologies may provide a means for the user to navigate to + * objects containing detailed descriptions so that their content can be more + * closely reviewed. + * @ATSPI_RELATION_DESCRIPTION_FOR: Reciprocal of %ATSPI_RELATION_DESCRIBED_BY. + * Indicates that this object provides descriptive information about the target + * object(s). See also %ATSPI_RELATION_DETAILS_FOR and %ATSPI_RELATION_ERROR_FOR. + * @ATSPI_RELATION_DETAILS: Reciprocal of %ATSPI_RELATION_DETAILS_FOR. Indicates + * that this object has a detailed or extended description, the contents of + * which can be found in the target object(s). This relation type is most + * appropriate for information that is sufficiently lengthy as to make + * navigation to the container of that information desirable. For less verbose + * information suitable for announcement only, see %ATSPI_RELATION_DESCRIBED_BY. + * If the detailed information describes an error condition, + * %ATSPI_RELATION_ERROR_FOR should be used instead. @Since: 2.26. + * @ATSPI_RELATION_DETAILS_FOR: Reciprocal of %ATSPI_RELATION_DETAILS. Indicates + * that this object provides a detailed or extended description about the target + * object(s). See also %ATSPI_RELATION_DESCRIPTION_FOR and + * %ATSPI_RELATION_ERROR_FOR. @Since: 2.26. + * @ATSPI_RELATION_ERROR_MESSAGE: Reciprocal of %ATSPI_RELATION_ERROR_FOR. + * Indicates that this object has one or more errors, the nature of which is + * described in the contents of the target object(s). Objects that have this + * relation type should also contain %ATSPI_STATE_INVALID_ENTRY in their + * #AtspiStateSet. @Since: 2.26. + * @ATSPI_RELATION_ERROR_FOR: Reciprocal of %ATSPI_RELATION_ERROR_MESSAGE. + * Indicates that this object contains an error message describing an invalid + * condition in the target object(s). @Since: 2.26. + * @ATSPI_RELATION_LAST_DEFINED: Do not use as a parameter value, used to + * determine the size of the enumeration. + * + * #AtspiRelationType specifies a relationship between objects + * (possibly one-to-many + * or many-to-one) outside of the normal parent/child hierarchical + * relationship. It allows better semantic identification of how objects + * are associated with one another. For instance the + * @ATSPI_RELATION_LABELLED_BY + * relationship may be used to identify labelling information that should + * accompany the accessible name property when presenting an object's content or + * identity to the end user. Similarly, + * @ATSPI_RELATION_CONTROLLER_FOR can be used + * to further specify the context in which a valuator is useful, and/or the + * other UI components which are directly effected by user interactions with + * the valuator. Common examples include association of scrollbars with the + * viewport or panel which they control. + * + * + * Enumeration used to specify + * the type of relation encapsulated in an #AtspiRelation object. + * + **/ +typedef enum { + ATSPI_RELATION_NULL, + ATSPI_RELATION_LABEL_FOR, + ATSPI_RELATION_LABELLED_BY, + ATSPI_RELATION_CONTROLLER_FOR, + ATSPI_RELATION_CONTROLLED_BY, + ATSPI_RELATION_MEMBER_OF, + ATSPI_RELATION_TOOLTIP_FOR, + ATSPI_RELATION_NODE_CHILD_OF, + ATSPI_RELATION_NODE_PARENT_OF, + ATSPI_RELATION_EXTENDED, + ATSPI_RELATION_FLOWS_TO, + ATSPI_RELATION_FLOWS_FROM, + ATSPI_RELATION_SUBWINDOW_OF, + ATSPI_RELATION_EMBEDS, + ATSPI_RELATION_EMBEDDED_BY, + ATSPI_RELATION_POPUP_FOR, + ATSPI_RELATION_PARENT_WINDOW_OF, + ATSPI_RELATION_DESCRIPTION_FOR, + ATSPI_RELATION_DESCRIBED_BY, + ATSPI_RELATION_DETAILS, + ATSPI_RELATION_DETAILS_FOR, + ATSPI_RELATION_ERROR_MESSAGE, + ATSPI_RELATION_ERROR_FOR, + ATSPI_RELATION_LAST_DEFINED, +} AtspiRelationType; + +/** + * ATSPI_RELATIONTYPE_COUNT: + * + * One higher than the highest valid value of #AtspiRelationType. + **/ +#define ATSPI_RELATIONTYPE_COUNT (23+1) + +/** + * AtspiRole: + * @ATSPI_ROLE_INVALID: A role indicating an error condition, such as + * uninitialized Role data. + * @ATSPI_ROLE_ACCELERATOR_LABEL: Object is a label indicating the keyboard + * accelerators for the parent. + * @ATSPI_ROLE_ALERT: Object is used to alert the user about something. + * @ATSPI_ROLE_ANIMATION: Object contains a dynamic or moving image of some + * kind. + * @ATSPI_ROLE_ARROW: Object is a 2d directional indicator. + * @ATSPI_ROLE_CALENDAR: Object contains one or more dates, usually arranged + * into a 2d list. + * @ATSPI_ROLE_CANVAS: Object that can be drawn into and is used to trap + * events. + * @ATSPI_ROLE_CHECK_BOX: A choice that can be checked or unchecked and + * provides a separate indicator for the current state. + * @ATSPI_ROLE_CHECK_MENU_ITEM: A menu item that behaves like a check box. See + * @ATSPI_ROLE_CHECK_BOX. + * @ATSPI_ROLE_COLOR_CHOOSER: A specialized dialog that lets the user choose a + * color. + * @ATSPI_ROLE_COLUMN_HEADER: The header for a column of data. + * @ATSPI_ROLE_COMBO_BOX: A list of choices the user can select from. + * @ATSPI_ROLE_DATE_EDITOR: An object which allows entry of a date. + * @ATSPI_ROLE_DESKTOP_ICON: An inconifed internal frame within a DESKTOP_PANE. + * @ATSPI_ROLE_DESKTOP_FRAME: A pane that supports internal frames and + * iconified versions of those internal frames. + * @ATSPI_ROLE_DIAL: An object that allows a value to be changed via rotating a + * visual element, or which displays a value via such a rotating element. + * @ATSPI_ROLE_DIALOG: A top level window with title bar and a border. + * @ATSPI_ROLE_DIRECTORY_PANE: A pane that allows the user to navigate through + * and select the contents of a directory. + * @ATSPI_ROLE_DRAWING_AREA: A specialized dialog that displays the files in + * the directory and lets the user select a file, browse a different + * directory, or specify a filename. + * @ATSPI_ROLE_FILE_CHOOSER: An object used for drawing custom user interface + * elements. + * @ATSPI_ROLE_FILLER: A object that fills up space in a user interface. + * @ATSPI_ROLE_FOCUS_TRAVERSABLE: Don't use, reserved for future use. + * @ATSPI_ROLE_FONT_CHOOSER: Allows selection of a display font. + * @ATSPI_ROLE_FRAME: A top level window with a title bar, border, menubar, + * etc. + * @ATSPI_ROLE_GLASS_PANE: A pane that is guaranteed to be painted on top of + * all panes beneath it. + * @ATSPI_ROLE_HTML_CONTAINER: A document container for HTML, whose children + * represent the document content. + * @ATSPI_ROLE_ICON: A small fixed size picture, typically used to decorate + * components. + * @ATSPI_ROLE_IMAGE: An image, typically static. + * @ATSPI_ROLE_INTERNAL_FRAME: A frame-like object that is clipped by a desktop + * pane. + * @ATSPI_ROLE_LABEL: An object used to present an icon or short string in an + * interface. + * @ATSPI_ROLE_LAYERED_PANE: A specialized pane that allows its children to be + * drawn in layers, providing a form of stacking order. + * @ATSPI_ROLE_LIST: An object that presents a list of objects to the user and + * allows the user to select one or more of them. + * @ATSPI_ROLE_LIST_ITEM: An object that represents an element of a list. + * @ATSPI_ROLE_MENU: An object usually found inside a menu bar that contains a + * list of actions the user can choose from. + * @ATSPI_ROLE_MENU_BAR: An object usually drawn at the top of the primary + * dialog box of an application that contains a list of menus the user can + * choose from. + * @ATSPI_ROLE_MENU_ITEM: An object usually contained in a menu that presents + * an action the user can choose. + * @ATSPI_ROLE_OPTION_PANE: A specialized pane whose primary use is inside a + * dialog. + * @ATSPI_ROLE_PAGE_TAB: An object that is a child of a page tab list. + * @ATSPI_ROLE_PAGE_TAB_LIST: An object that presents a series of panels (or + * page tabs), one at a time,through some mechanism provided by the + * object. + * @ATSPI_ROLE_PANEL: A generic container that is often used to group objects. + * @ATSPI_ROLE_PASSWORD_TEXT: A text object uses for passwords, or other places + * where the text content is not shown visibly to the user. + * @ATSPI_ROLE_POPUP_MENU: A temporary window that is usually used to offer the + * user a list of choices, and then hides when the user selects one of those + * choices. + * @ATSPI_ROLE_PROGRESS_BAR: An object used to indicate how much of a task has + * been completed. + * @ATSPI_ROLE_PUSH_BUTTON: An object the user can manipulate to tell the + * application to do something. + * @ATSPI_ROLE_RADIO_BUTTON: A specialized check box that will cause other + * radio buttons in the same group to become unchecked when this one is + * checked. + * @ATSPI_ROLE_RADIO_MENU_ITEM: Object is both a menu item and a "radio button" + * . See @ATSPI_ROLE_RADIO_BUTTON. + * @ATSPI_ROLE_ROOT_PANE: A specialized pane that has a glass pane and a + * layered pane as its children. + * @ATSPI_ROLE_ROW_HEADER: The header for a row of data. + * @ATSPI_ROLE_SCROLL_BAR: An object usually used to allow a user to + * incrementally view a large amount of data by moving the bounds of a + * viewport along a one-dimensional axis. + * @ATSPI_ROLE_SCROLL_PANE: An object that allows a user to incrementally view + * a large amount of information. @ATSPI_ROLE_SCROLL_PANE objects are usually + * accompanied by @ATSPI_ROLE_SCROLL_BAR controllers, on which the + * @ATSPI_RELATION_CONTROLLER_FOR and @ATSPI_RELATION_CONTROLLED_BY + * reciprocal relations are set. See #atspi_get_relation_set. + * @ATSPI_ROLE_SEPARATOR: An object usually contained in a menu to provide a + * visible and logical separation of the contents in a menu. + * @ATSPI_ROLE_SLIDER: An object that allows the user to select from a bounded + * range. + * @ATSPI_ROLE_SPIN_BUTTON: An object which allows one of a set of choices to + * be selected, and which displays the current choice. Unlike + * @ATSPI_ROLE_SCROLL_BAR, @ATSPI_ROLE_SLIDER objects need not control + * 'viewport'-like objects. + * @ATSPI_ROLE_SPLIT_PANE: A specialized panel that presents two other panels + * at the same time. + * @ATSPI_ROLE_STATUS_BAR: Object displays non-quantitative status information + * (c.f. @ATSPI_ROLE_PROGRESS_BAR) + * @ATSPI_ROLE_TABLE: An object used to repesent information in terms of rows + * and columns. + * @ATSPI_ROLE_TABLE_CELL: A 'cell' or discrete child within a Table. Note: + * Table cells need not have @ATSPI_ROLE_TABLE_CELL, other + * #AtspiRoleType values are valid as well. + * @ATSPI_ROLE_TABLE_COLUMN_HEADER: An object which labels a particular column + * in an #AtspiTable. + * @ATSPI_ROLE_TABLE_ROW_HEADER: An object which labels a particular row in a + * #AtspiTable. #AtspiTable rows and columns may also be labelled via the + * @ATSPI_RELATION_LABEL_FOR/@ATSPI_RELATION_LABELLED_BY relationships. + * See #atspi_get_relation_set. + * @ATSPI_ROLE_TEAROFF_MENU_ITEM: Object allows menu to be removed from menubar + * and shown in its own window. + * @ATSPI_ROLE_TERMINAL: An object that emulates a terminal. + * @ATSPI_ROLE_TEXT: An interactive widget that supports multiple lines of text + * and optionally accepts user input, but whose purpose is not to solicit user + * input. Thus @ATSPI_ROLE_TEXT is appropriate for the text view in a plain text + * editor but inappropriate for an input field in a dialog box or web form. For + * widgets whose purpose is to solicit input from the user, see @ATSPI_ROLE_ENTRY + * and @ATSPI_ROLE_PASSWORD_TEXT. For generic objects which display a brief amount + * of textual information, see @ATSPI_ROLE_STATIC. + * @ATSPI_ROLE_TOGGLE_BUTTON: A specialized push button that can be checked or + * unchecked, but does not procide a separate indicator for the current + * state. + * @ATSPI_ROLE_TOOL_BAR: A bar or palette usually composed of push buttons or + * toggle buttons. + * @ATSPI_ROLE_TOOL_TIP: An object that provides information about another + * object. + * @ATSPI_ROLE_TREE: An object used to repsent hierarchical information to the + * user. + * @ATSPI_ROLE_TREE_TABLE: An object that presents both tabular and + * hierarchical info to the user. + * @ATSPI_ROLE_UNKNOWN: The object contains some #AtspiAccessible information, + * but its role is not known. + * @ATSPI_ROLE_VIEWPORT: An object usually used in a scroll pane, or to + * otherwise clip a larger object or content renderer to a specific + * onscreen viewport. + * @ATSPI_ROLE_WINDOW: A top level window with no title or border. + * @ATSPI_ROLE_EXTENDED: means that the role for this item is known, but not + * included in the core enumeration. Deprecated since 2.24. + * @ATSPI_ROLE_HEADER: An object that serves as a document header. + * @ATSPI_ROLE_FOOTER: An object that serves as a document footer. + * @ATSPI_ROLE_PARAGRAPH: An object which is contains a single paragraph of + * text content. See also @ATSPI_ROLE_TEXT. + * @ATSPI_ROLE_RULER: An object which describes margins and tab stops, etc. + * for text objects which it controls (should have + * @ATSPI_RELATION_CONTROLLER_FOR relation to such). + * @ATSPI_ROLE_APPLICATION: An object corresponding to the toplevel accessible + * of an application, which may contain @ATSPI_ROLE_FRAME objects or other + * accessible objects. Children of #AccessibleDesktop objects are generally + * @ATSPI_ROLE_APPLICATION objects. + * @ATSPI_ROLE_AUTOCOMPLETE: The object is a dialog or list containing items + * for insertion into an entry widget, for instance a list of words for + * completion of a text entry. + * @ATSPI_ROLE_EDITBAR: The object is an editable text object in a toolbar. + * @ATSPI_ROLE_EMBEDDED: The object is an embedded component container. This + * role is a "grouping" hint that the contained objects share a context + * which is different from the container in which this accessible is + * embedded. In particular, it is used for some kinds of document embedding, + * and for embedding of out-of-process component, "panel applets", etc. + * @ATSPI_ROLE_ENTRY: The object is a component whose textual content may be + * entered or modified by the user, provided @ATSPI_STATE_EDITABLE is present. + * A readonly @ATSPI_ROLE_ENTRY object (i.e. where @ATSPI_STATE_EDITABLE is + * not present) implies a read-only 'text field' in a form, as opposed to a + * title, label, or caption. + * @ATSPI_ROLE_CHART: The object is a graphical depiction of quantitative data. + * It may contain multiple subelements whose attributes and/or description + * may be queried to obtain both the quantitative data and information about + * how the data is being presented. The @ATSPI_LABELLED_BY relation is + * particularly important in interpreting objects of this type, as is the + * accessible description property. See @ATSPI_ROLE_CAPTION. + * @ATSPI_ROLE_CAPTION: The object contains descriptive information, usually + * textual, about another user interface element such as a table, chart, or + * image. + * @ATSPI_ROLE_DOCUMENT_FRAME: The object is a visual frame or container which + * contains a view of document content. #AtspiDocument frames may occur within + * another #AtspiDocument instance, in which case the second document may be + * said to be embedded in the containing instance. HTML frames are often + * ATSPI_ROLE_DOCUMENT_FRAME: Either this object, or a singleton descendant, + * should implement the #AtspiDocument interface. + * @ATSPI_ROLE_HEADING: The object serves as a heading for content which + * follows it in a document. The 'heading level' of the heading, if + * availabe, may be obtained by querying the object's attributes. + * @ATSPI_ROLE_PAGE: The object is a containing instance which encapsulates a + * page of information. @ATSPI_ROLE_PAGE is used in documents and content which + * support a paginated navigation model. + * @ATSPI_ROLE_SECTION: The object is a containing instance of document content + * which constitutes a particular 'logical' section of the document. The + * type of content within a section, and the nature of the section division + * itself, may be obtained by querying the object's attributes. Sections + * may be nested. + * @ATSPI_ROLE_REDUNDANT_OBJECT: The object is redundant with another object in + * the hierarchy, and is exposed for purely technical reasons. Objects of + * this role should be ignored by clients, if they are encountered at all. + * @ATSPI_ROLE_FORM: The object is a containing instance of document content + * which has within it components with which the user can interact in order + * to input information; i.e. the object is a container for pushbuttons, + * comboboxes, text input fields, and other 'GUI' components. @ATSPI_ROLE_FORM + * should not, in general, be used for toplevel GUI containers or dialogs, + * but should be reserved for 'GUI' containers which occur within document + * content, for instance within Web documents, presentations, or text + * documents. Unlike other GUI containers and dialogs which occur inside + * application instances, @ATSPI_ROLE_FORM containers' components are + * associated with the current document, rather than the current foreground + * application or viewer instance. + * @ATSPI_ROLE_LINK: The object is a hypertext anchor, i.e. a "link" in a + * hypertext document. Such objects are distinct from 'inline' content + * which may also use the #AtspiHypertext/#AtspiHyperlink interfacesto indicate + * the range/location within a text object where an inline or embedded object + * lies. + * @ATSPI_ROLE_INPUT_METHOD_WINDOW: The object is a window or similar viewport + * which is used to allow composition or input of a 'complex character', + * in other words it is an "input method window". + * @ATSPI_ROLE_TABLE_ROW: A row in a table. + * @ATSPI_ROLE_TREE_ITEM: An object that represents an element of a tree. + * @ATSPI_ROLE_DOCUMENT_SPREADSHEET: A document frame which contains a + * spreadsheet. + * @ATSPI_ROLE_DOCUMENT_PRESENTATION: A document frame which contains a + * presentation or slide content. + * @ATSPI_ROLE_DOCUMENT_TEXT: A document frame which contains textual content, + * such as found in a word processing + * application. + * @ATSPI_ROLE_DOCUMENT_WEB: A document frame which contains HTML or other + * markup suitable for display in a web browser. + * @ATSPI_ROLE_DOCUMENT_EMAIL: A document frame which contains email content + * to be displayed or composed either in plain text or + * HTML. + * @ATSPI_ROLE_COMMENT: An object found within a document and designed to + * present a comment, note, or other annotation. In some cases, this object + * might not be visible until activated. + * @ATSPI_ROLE_LIST_BOX: A non-collapsible list of choices the user can + * select from. + * @ATSPI_ROLE_GROUPING: A group of related widgets. This group typically has + * a label. + * @ATSPI_ROLE_IMAGE_MAP: An image map object. Usually a graphic with multiple + * hotspots, where each hotspot can be activated resulting in the loading of + * another document or section of a document. + * @ATSPI_ROLE_NOTIFICATION: A transitory object designed to present a + * message to the user, typically at the desktop level rather than inside a + * particular application. + * @ATSPI_ROLE_INFO_BAR: An object designed to present a message to the user + * within an existing window. + * @ATSPI_ROLE_LEVEL_BAR: A bar that serves as a level indicator to, for + * instance, show the strength of a password or the state of a battery. + * Since: 2.8 + *@ATSPI_ROLE_TITLE_BAR: A bar that serves as the title of a window or a + * dialog. @Since: 2.12 + *@ATSPI_ROLE_BLOCK_QUOTE: An object which contains a text section + * that is quoted from another source. @Since: 2.12 + *@ATSPI_ROLE_AUDIO: An object which represents an audio + * element. @Since: 2.12 + *@ATSPI_ROLE_VIDEO: An object which represents a video + * element. @Since: 2.12 + *@ATSPI_ROLE_DEFINITION: A definition of a term or concept. @Since: 2.12 + *@ATSPI_ROLE_ARTICLE: A section of a page that consists of a + * composition that forms an independent part of a document, page, or + * site. Examples: A blog entry, a news story, a forum post. @Since: + * 2.12 + *@ATSPI_ROLE_LANDMARK: A region of a web page intended as a + * navigational landmark. This is designed to allow Assistive + * Technologies to provide quick navigation among key regions within a + * document. @Since: 2.12 + *@ATSPI_ROLE_LOG: A text widget or container holding log content, such + * as chat history and error logs. In this role there is a + * relationship between the arrival of new items in the log and the + * reading order. The log contains a meaningful sequence and new + * information is added only to the end of the log, not at arbitrary + * points. @Since: 2.12 + *@ATSPI_ROLE_MARQUEE: A container where non-essential information + * changes frequently. Common usages of marquee include stock tickers + * and ad banners. The primary difference between a marquee and a log + * is that logs usually have a meaningful order or sequence of + * important content changes. @Since: 2.12 + *@ATSPI_ROLE_MATH: A text widget or container that holds a mathematical + * expression. @Since: 2.12 + *@ATSPI_ROLE_RATING: A widget whose purpose is to display a rating, + * such as the number of stars associated with a song in a media + * player. Objects of this role should also implement + * AtspiValue. @Since: 2.12 + *@ATSPI_ROLE_TIMER: An object containing a numerical counter which + * indicates an amount of elapsed time from a start point, or the time + * remaining until an end point. @Since: 2.12 + *@ATSPI_ROLE_STATIC: A generic non-container object whose purpose is to display + * a brief amount of information to the user and whose role is known by the + * implementor but lacks semantic value for the user. Examples in which + * @ATSPI_ROLE_STATIC is appropriate include the message displayed in a message + * box and an image used as an alternative means to display text. + * @ATSPI_ROLE_STATIC should not be applied to widgets which are traditionally + * interactive, objects which display a significant amount of content, or any + * object which has an accessible relation pointing to another object. The + * displayed information, as a general rule, should be exposed through the + * accessible name of the object. For labels which describe another widget, see + * @ATSPI_ROLE_LABEL. For text views, see @ATSPI_ROLE_TEXT. For generic + * containers, see @ATSPI_ROLE_PANEL. For objects whose role is not known by the + * implementor, see @ATSPI_ROLE_UNKNOWN. @Since: 2.16. + *@ATSPI_ROLE_MATH_FRACTION: An object that represents a mathematical fraction. + * @Since: 2.16. + *@ATSPI_ROLE_MATH_ROOT: An object that represents a mathematical expression + * displayed with a radical. @Since: 2.16. + *@ATSPI_ROLE_SUBSCRIPT: An object that contains text that is displayed as a + * subscript. @Since: 2.16. + *@ATSPI_ROLE_SUPERSCRIPT: An object that contains text that is displayed as a + * superscript. @Since: 2.16. + *@ATSPI_ROLE_DESCRIPTION_LIST: An object that represents a list of term-value + * groups. A term-value group represents an individual description and consist + * of one or more names (@ATSPI_ROLE_DESCRIPTION_TERM) followed by one or more + * values (@ATSPI_ROLE_DESCRIPTION_VALUE). For each list, there should not be + * more than one group with the same term name. @Since: 2.26. + *@ATSPI_ROLE_DESCRIPTION_TERM: An object that represents a term or phrase + * with a corresponding definition. @Since: 2.26. + *@ATSPI_ROLE_DESCRIPTION_VALUE: An object that represents the description, + * definition, or value of a term. @Since: 2.26. + *@ATSPI_ROLE_FOOTNOTE: An object that contains the text of a footnote. @Since: 2.26. + * @ATSPI_ROLE_LAST_DEFINED: Not a valid role, used for finding end of + * enumeration. + * + * Enumeration used by interface #AtspiAccessible to specify the role + * of an #AtspiAccessible object. + * + */ +typedef enum { + ATSPI_ROLE_INVALID, + ATSPI_ROLE_ACCELERATOR_LABEL, + ATSPI_ROLE_ALERT, + ATSPI_ROLE_ANIMATION, + ATSPI_ROLE_ARROW, + ATSPI_ROLE_CALENDAR, + ATSPI_ROLE_CANVAS, + ATSPI_ROLE_CHECK_BOX, + ATSPI_ROLE_CHECK_MENU_ITEM, + ATSPI_ROLE_COLOR_CHOOSER, + ATSPI_ROLE_COLUMN_HEADER, + ATSPI_ROLE_COMBO_BOX, + ATSPI_ROLE_DATE_EDITOR, + ATSPI_ROLE_DESKTOP_ICON, + ATSPI_ROLE_DESKTOP_FRAME, + ATSPI_ROLE_DIAL, + ATSPI_ROLE_DIALOG, + ATSPI_ROLE_DIRECTORY_PANE, + ATSPI_ROLE_DRAWING_AREA, + ATSPI_ROLE_FILE_CHOOSER, + ATSPI_ROLE_FILLER, + ATSPI_ROLE_FOCUS_TRAVERSABLE, + ATSPI_ROLE_FONT_CHOOSER, + ATSPI_ROLE_FRAME, + ATSPI_ROLE_GLASS_PANE, + ATSPI_ROLE_HTML_CONTAINER, + ATSPI_ROLE_ICON, + ATSPI_ROLE_IMAGE, + ATSPI_ROLE_INTERNAL_FRAME, + ATSPI_ROLE_LABEL, + ATSPI_ROLE_LAYERED_PANE, + ATSPI_ROLE_LIST, + ATSPI_ROLE_LIST_ITEM, + ATSPI_ROLE_MENU, + ATSPI_ROLE_MENU_BAR, + ATSPI_ROLE_MENU_ITEM, + ATSPI_ROLE_OPTION_PANE, + ATSPI_ROLE_PAGE_TAB, + ATSPI_ROLE_PAGE_TAB_LIST, + ATSPI_ROLE_PANEL, + ATSPI_ROLE_PASSWORD_TEXT, + ATSPI_ROLE_POPUP_MENU, + ATSPI_ROLE_PROGRESS_BAR, + ATSPI_ROLE_PUSH_BUTTON, + ATSPI_ROLE_RADIO_BUTTON, + ATSPI_ROLE_RADIO_MENU_ITEM, + ATSPI_ROLE_ROOT_PANE, + ATSPI_ROLE_ROW_HEADER, + ATSPI_ROLE_SCROLL_BAR, + ATSPI_ROLE_SCROLL_PANE, + ATSPI_ROLE_SEPARATOR, + ATSPI_ROLE_SLIDER, + ATSPI_ROLE_SPIN_BUTTON, + ATSPI_ROLE_SPLIT_PANE, + ATSPI_ROLE_STATUS_BAR, + ATSPI_ROLE_TABLE, + ATSPI_ROLE_TABLE_CELL, + ATSPI_ROLE_TABLE_COLUMN_HEADER, + ATSPI_ROLE_TABLE_ROW_HEADER, + ATSPI_ROLE_TEAROFF_MENU_ITEM, + ATSPI_ROLE_TERMINAL, + ATSPI_ROLE_TEXT, + ATSPI_ROLE_TOGGLE_BUTTON, + ATSPI_ROLE_TOOL_BAR, + ATSPI_ROLE_TOOL_TIP, + ATSPI_ROLE_TREE, + ATSPI_ROLE_TREE_TABLE, + ATSPI_ROLE_UNKNOWN, + ATSPI_ROLE_VIEWPORT, + ATSPI_ROLE_WINDOW, + ATSPI_ROLE_EXTENDED, + ATSPI_ROLE_HEADER, + ATSPI_ROLE_FOOTER, + ATSPI_ROLE_PARAGRAPH, + ATSPI_ROLE_RULER, + ATSPI_ROLE_APPLICATION, + ATSPI_ROLE_AUTOCOMPLETE, + ATSPI_ROLE_EDITBAR, + ATSPI_ROLE_EMBEDDED, + ATSPI_ROLE_ENTRY, + ATSPI_ROLE_CHART, + ATSPI_ROLE_CAPTION, + ATSPI_ROLE_DOCUMENT_FRAME, + ATSPI_ROLE_HEADING, + ATSPI_ROLE_PAGE, + ATSPI_ROLE_SECTION, + ATSPI_ROLE_REDUNDANT_OBJECT, + ATSPI_ROLE_FORM, + ATSPI_ROLE_LINK, + ATSPI_ROLE_INPUT_METHOD_WINDOW, + ATSPI_ROLE_TABLE_ROW, + ATSPI_ROLE_TREE_ITEM, + ATSPI_ROLE_DOCUMENT_SPREADSHEET, + ATSPI_ROLE_DOCUMENT_PRESENTATION, + ATSPI_ROLE_DOCUMENT_TEXT, + ATSPI_ROLE_DOCUMENT_WEB, + ATSPI_ROLE_DOCUMENT_EMAIL, + ATSPI_ROLE_COMMENT, + ATSPI_ROLE_LIST_BOX, + ATSPI_ROLE_GROUPING, + ATSPI_ROLE_IMAGE_MAP, + ATSPI_ROLE_NOTIFICATION, + ATSPI_ROLE_INFO_BAR, + ATSPI_ROLE_LEVEL_BAR, + ATSPI_ROLE_TITLE_BAR, + ATSPI_ROLE_BLOCK_QUOTE, + ATSPI_ROLE_AUDIO, + ATSPI_ROLE_VIDEO, + ATSPI_ROLE_DEFINITION, + ATSPI_ROLE_ARTICLE, + ATSPI_ROLE_LANDMARK, + ATSPI_ROLE_LOG, + ATSPI_ROLE_MARQUEE, + ATSPI_ROLE_MATH, + ATSPI_ROLE_RATING, + ATSPI_ROLE_TIMER, + ATSPI_ROLE_STATIC, + ATSPI_ROLE_MATH_FRACTION, + ATSPI_ROLE_MATH_ROOT, + ATSPI_ROLE_SUBSCRIPT, + ATSPI_ROLE_SUPERSCRIPT, + ATSPI_ROLE_DESCRIPTION_LIST, + ATSPI_ROLE_DESCRIPTION_TERM, + ATSPI_ROLE_DESCRIPTION_VALUE, + ATSPI_ROLE_FOOTNOTE, + ATSPI_ROLE_LAST_DEFINED, +} AtspiRole; + +/** + * ATSPI_ROLE_COUNT: + * + * One higher than the highest valid value of #AtspiRole. + */ +#define ATSPI_ROLE_COUNT (125+1) + +typedef enum +{ + ATSPI_CACHE_NONE = 0, + ATSPI_CACHE_PARENT = 1 << 0, + ATSPI_CACHE_CHILDREN = 1 << 1, + ATSPI_CACHE_NAME = 1 << 2, + ATSPI_CACHE_DESCRIPTION = 1 << 3, + ATSPI_CACHE_STATES = 1 << 4, + ATSPI_CACHE_ROLE = 1 << 5, + ATSPI_CACHE_INTERFACES = 1 << 6, + ATSPI_CACHE_ATTRIBUTES = 1 << 7, + ATSPI_CACHE_ALL = 0x3fffffff, + ATSPI_CACHE_DEFAULT = ATSPI_CACHE_PARENT | ATSPI_CACHE_CHILDREN | ATSPI_CACHE_NAME | ATSPI_CACHE_DESCRIPTION | ATSPI_CACHE_STATES | ATSPI_CACHE_ROLE | ATSPI_CACHE_INTERFACES, + ATSPI_CACHE_UNDEFINED = 0x40000000, +} AtspiCache; + +#define ATSPI_DBUS_NAME_REGISTRY "org.a11y.atspi.Registry" +#define ATSPI_DBUS_PATH_REGISTRY "/org/a11y/atspi/registry" +#define ATSPI_DBUS_INTERFACE_REGISTRY "org.a11y.atspi.Registry" + +#define ATSPI_DBUS_PATH_NULL "/org/a11y/atspi/null" +#define ATSPI_DBUS_PATH_ROOT "/org/a11y/atspi/accessible/root" + +#define ATSPI_DBUS_PATH_DEC "/org/a11y/atspi/registry/deviceeventcontroller" +#define ATSPI_DBUS_INTERFACE_DEC "org.a11y.atspi.DeviceEventController" +#define ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.a11y.atspi.DeviceEventListener" + +#define ATSPI_DBUS_INTERFACE_CACHE "org.a11y.atspi.Cache" +#define ATSPI_DBUS_INTERFACE_ACCESSIBLE "org.a11y.atspi.Accessible" +#define ATSPI_DBUS_INTERFACE_ACTION "org.a11y.atspi.Action" +#define ATSPI_DBUS_INTERFACE_APPLICATION "org.a11y.atspi.Application" +#define ATSPI_DBUS_INTERFACE_COLLECTION "org.a11y.atspi.Collection" +#define ATSPI_DBUS_INTERFACE_COMPONENT "org.a11y.atspi.Component" +#define ATSPI_DBUS_INTERFACE_DOCUMENT "org.a11y.atspi.Document" +#define ATSPI_DBUS_INTERFACE_EDITABLE_TEXT "org.a11y.atspi.EditableText" +#define ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD "org.a11y.atspi.Event.Keyboard" +#define ATSPI_DBUS_INTERFACE_EVENT_MOUSE "org.a11y.atspi.Event.Mouse" +#define ATSPI_DBUS_INTERFACE_EVENT_OBJECT "org.a11y.atspi.Event.Object" +#define ATSPI_DBUS_INTERFACE_HYPERLINK "org.a11y.atspi.Hyperlink" +#define ATSPI_DBUS_INTERFACE_HYPERTEXT "org.a11y.atspi.Hypertext" +#define ATSPI_DBUS_INTERFACE_IMAGE "org.a11y.atspi.Image" +#define ATSPI_DBUS_INTERFACE_SELECTION "org.a11y.atspi.Selection" +#define ATSPI_DBUS_INTERFACE_TABLE "org.a11y.atspi.Table" +#define ATSPI_DBUS_INTERFACE_TABLE_CELL "org.a11y.atspi.TableCell" +#define ATSPI_DBUS_INTERFACE_TEXT "org.a11y.atspi.Text" +#define ATSPI_DBUS_INTERFACE_VALUE "org.a11y.atspi.Value" +#define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket" + +#ifdef __cplusplus +} +#endif +#endif /* _ATSPI_CONSTANTS_H_ */ diff --git a/atspi/atspi-device-listener-private.h b/atspi/atspi-device-listener-private.h new file mode 100644 index 0000000..1089e45 --- /dev/null +++ b/atspi/atspi-device-listener-private.h @@ -0,0 +1,40 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_DEVICE_LISTENER_PRIVATE_H_ +#define _ATSPI_DEVICE_LISTENER_PRIVATE_H_ + +#include "atspi-device-listener.h" + +#include "dbus/dbus.h" + +G_BEGIN_DECLS + +DBusHandlerResult _atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data); + +gchar *_atspi_device_listener_get_path (AtspiDeviceListener *listener); + +G_END_DECLS + +#endif /* _ATSPI_DEVICE_LISTENER_H_ */ diff --git a/atspi/atspi-device-listener.c b/atspi/atspi-device-listener.c new file mode 100644 index 0000000..5aac60a --- /dev/null +++ b/atspi/atspi-device-listener.c @@ -0,0 +1,405 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian Inc. + * Copyright 2002 Sun Microsystems, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" +#include + +typedef struct +{ + AtspiDeviceListenerCB callback; + gpointer user_data; + GDestroyNotify callback_destroyed; +} DeviceEventHandler; + +GObjectClass *device_parent_class; + +/* + * Misc. helpers. + */ + +static DeviceEventHandler * +device_event_handler_new (AtspiDeviceListenerCB callback, + GDestroyNotify callback_destroyed, + gpointer user_data) +{ + DeviceEventHandler *eh = g_new0 (DeviceEventHandler, 1); + + eh->callback = callback; + eh->callback_destroyed = callback_destroyed; + eh->user_data = user_data; + + return eh; +} + +static gboolean +device_remove_datum (const AtspiDeviceEvent *event, void *user_data) +{ + AtspiDeviceListenerSimpleCB cb = user_data; + return cb (event); +} + +static void +device_event_handler_free (DeviceEventHandler *eh) +{ +#if 0 + /* TODO; Test this; it will probably crash with pyatspi for unknown reasons */ + if (eh->callback_destroyed) + { + gpointer rea_callback = (eh->callback == device_remove_datum ? + eh->user_data : eh->callback); + (*eh->callback_destroyed) (real_callback); + } +#endif + g_free (eh); +} + +static GList * +event_list_remove_by_cb (GList *list, AtspiDeviceListenerCB callback) +{ + GList *l, *next; + + for (l = list; l; l = next) + { + DeviceEventHandler *eh = l->data; + next = l->next; + + if (eh->callback == callback) + { + list = g_list_delete_link (list, l); + device_event_handler_free (eh); + } + } + + return list; +} + +/* + * Standard event dispatcher + */ + +static guint listener_id = 0; +static GList *device_listeners = NULL; + +static gboolean +id_is_free (guint id) +{ + GList *l; + + for (l = device_listeners; l; l = g_list_next (l)) + { + AtspiDeviceListener *listener = l->data; + if (listener->id == id) return FALSE; + } + return TRUE; +} + +static AtspiDeviceEvent * +atspi_device_event_copy (const AtspiDeviceEvent *src) +{ + AtspiDeviceEvent *dst = g_new0 (AtspiDeviceEvent, 1); + dst->type = src->type; + dst->id = src->id; + dst->hw_code = src->hw_code; + dst->modifiers = src->modifiers; + dst->timestamp = src->timestamp; + if (src->event_string) + dst->event_string = g_strdup (src->event_string); + dst->is_text = src->is_text; + return dst; +} + +void +atspi_device_event_free (AtspiDeviceEvent *event) +{ + if (event->event_string) + g_free (event->event_string); + g_free (event); +} + +/* + * Device event handler + */ +static gboolean +atspi_device_event_dispatch (AtspiDeviceListener *listener, + const AtspiDeviceEvent *event) +{ + GList *l; + gboolean handled = FALSE; + + /* FIXME: re-enterancy hazard on this list */ + for (l = listener->callbacks; l; l = l->next) + { + DeviceEventHandler *eh = l->data; + + if ((handled = eh->callback (atspi_device_event_copy (event), eh->user_data))) + { + break; + } + } + + return handled; +} + +static void +atspi_device_listener_init (AtspiDeviceListener *listener) +{ + + do + { + listener->id = listener_id++; + } while (!id_is_free (listener->id)); + device_listeners = g_list_append (device_listeners, listener); +} + +static void +atspi_device_listener_finalize (GObject *object) +{ + AtspiDeviceListener *listener = (AtspiDeviceListener *) object; + GList *l; + + for (l = listener->callbacks; l; l = l->next) + { + device_event_handler_free (l->data); + } + + g_list_free (listener->callbacks); + + device_parent_class->finalize (object); +} + +static void +atspi_device_listener_class_init (AtspiDeviceListenerClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + device_parent_class = g_type_class_peek_parent (klass); + object_class->finalize = atspi_device_listener_finalize; + + klass->device_event = atspi_device_event_dispatch; +} + +G_DEFINE_TYPE (AtspiDeviceListener, atspi_device_listener, + G_TYPE_OBJECT) + +/** + * atspi_device_listener_new: + * @callback: (scope notified): an #AtspiDeviceListenerCB callback function, + * or NULL. + * @user_data: (closure): a pointer to data which will be passed to the + * callback when invoked. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It can be NULL. + * + * Creates a new #AtspiDeviceListener with a specified callback function. + * + * Returns: (transfer full): a pointer to a newly-created #AtspiDeviceListener. + * + **/ +AtspiDeviceListener * +atspi_device_listener_new (AtspiDeviceListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed) +{ + AtspiDeviceListener *listener = g_object_new (atspi_device_listener_get_type (), NULL); + + if (callback) + atspi_device_listener_add_callback (listener, callback, callback_destroyed, + user_data); + return listener; +} + +/** + * atspi_device_listener_new_simple: (skip) + * @callback: (scope notified): an #AtspiDeviceListenerCB callback function, + * or NULL. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It an be NULL. + * + * Creates a new #AtspiDeviceListener with a specified callback function. + * This method is similar to #atspi_device_listener_new, but callback + * takes no user data. + * + * Returns: a pointer to a newly-created #AtspiDeviceListener. + * + **/ +AtspiDeviceListener * +atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback, + GDestroyNotify callback_destroyed) +{ + return atspi_device_listener_new (device_remove_datum, callback, callback_destroyed); +} + +/** + * atspi_device_listener_add_callback: + * @listener: the #AtspiDeviceListener instance to modify. + * @callback: (scope notified): an #AtspiDeviceListenerCB function pointer. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. It can be NULL. + * @user_data: (closure): a pointer to data which will be passed to the + * callback when invoked. + * + * Adds an in-process callback function to an existing #AtspiDeviceListener. + * + **/ +void +atspi_device_listener_add_callback (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback, + GDestroyNotify callback_destroyed, + void *user_data) +{ + g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener)); + DeviceEventHandler *new_handler; + + new_handler = device_event_handler_new (callback, + callback_destroyed, user_data); + + listener->callbacks = g_list_prepend (listener->callbacks, new_handler); +} + +/** + * atspi_device_listener_remove_callback: + * @listener: the #AtspiDeviceListener instance to modify. + * @callback: (scope call): an #AtspiDeviceListenerCB function pointer. + * + * Removes an in-process callback function from an existing + * #AtspiDeviceListener. + * + **/ +void +atspi_device_listener_remove_callback (AtspiDeviceListener *listener, + AtspiDeviceListenerCB callback) +{ + g_return_if_fail (ATSPI_IS_DEVICE_LISTENER (listener)); + + listener->callbacks = event_list_remove_by_cb (listener->callbacks, (void *) callback); +} + +static void +read_device_event_from_iter (DBusMessageIter *iter, AtspiDeviceEvent *event) +{ + dbus_uint32_t type; + dbus_int32_t id; + dbus_int32_t hw_code; + dbus_int32_t modifiers; + dbus_int32_t timestamp; + dbus_bool_t is_text; + DBusMessageIter iter_struct; + + dbus_message_iter_recurse (iter, &iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &type); + event->type = type; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &id); + event->id = id; + dbus_message_iter_next (&iter_struct); + + /* TODO: Remove cast from next two on ABI break */ + dbus_message_iter_get_basic (&iter_struct, &hw_code); + event->hw_code = (gushort) hw_code; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &modifiers); + event->modifiers = (gushort) modifiers; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, ×tamp); + event->timestamp = timestamp; + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &event->event_string); + dbus_message_iter_next (&iter_struct); + + dbus_message_iter_get_basic (&iter_struct, &is_text); + event->is_text = is_text; +} + +DBusHandlerResult +_atspi_dbus_handle_DeviceEvent (DBusConnection *bus, DBusMessage *message, void *data) +{ + const char *path = dbus_message_get_path (message); + int id; + AtspiDeviceEvent event; + AtspiDeviceListener *listener; + DBusMessageIter iter; + AtspiDeviceListenerClass *klass; + dbus_bool_t retval = FALSE; + GList *l; + DBusMessage *reply; + + if (strcmp (dbus_message_get_signature (message), "(uiuuisb)") != 0) + { + g_warning ("Atspi: Unknown signature for an event"); + goto done; + } + + if (sscanf (path, "/org/a11y/atspi/listeners/%d", &id) != 1) + { + g_warning ("Atspi: Bad listener path: %s\n", path); + goto done; + } + + for (l = device_listeners; l; l = g_list_next (l)) + { + listener = l->data; + if (listener->id == id) break; + } + + if (!l) + { + goto done; + } + dbus_message_iter_init (message, &iter); + read_device_event_from_iter (&iter, &event); + klass = ATSPI_DEVICE_LISTENER_GET_CLASS (listener); + if (klass->device_event) + { + retval = (*klass->device_event) (listener, &event); + if (retval != 0 && retval != 1) + { + g_warning ("at-spi: device event handler returned %d; should be 0 or 1", retval); + retval = 0; + } + } +done: + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, DBUS_TYPE_INVALID); + dbus_connection_send (_atspi_bus(), reply, NULL); + dbus_message_unref (reply); + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +gchar * +_atspi_device_listener_get_path (AtspiDeviceListener *listener) +{ return g_strdup_printf ("/org/a11y/atspi/listeners/%d", listener->id); +} + +G_DEFINE_BOXED_TYPE (AtspiDeviceEvent, + atspi_device_event, + atspi_device_event_copy, + atspi_device_event_free) diff --git a/atspi/atspi-device-listener.h b/atspi/atspi-device-listener.h new file mode 100644 index 0000000..3b1b96d --- /dev/null +++ b/atspi/atspi-device-listener.h @@ -0,0 +1,97 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_DEVICE_LISTENER_H_ +#define _ATSPI_DEVICE_LISTENER_H_ + +#include "glib-object.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +GType atspi_device_event_get_type (void); + +/** + * AtspiDeviceListenerCB: + * @stroke: (transfer full): The #AtspiDeviceEvent for which notification is + * being received. + * @user_data: Data which is passed to the client each time this callback is notified. + * + * A callback function prototype via which clients receive device event notifications. + * + * Returns: #TRUE if the client wishes to consume/preempt the event, preventing it from being + * relayed to the currently focussed application, #FALSE if the event delivery should proceed as normal. + **/ +typedef gboolean (*AtspiDeviceListenerCB) (const AtspiDeviceEvent *stroke, + void *user_data); + +/** + * AtspiDeviceListenerSimpleCB: + * @stroke: (transfer full): The #AtspiDeviceEvent for which notification is + * being received. + * + * Similar to #AtspiDeviceListenerCB, but with no user data. + * + * Returns: #TRUE if the client wishes to consume/preempt the event, preventing it from being + * relayed to the currently focussed application, #FALSE if the event delivery should proceed as normal. + **/ +typedef gboolean (*AtspiDeviceListenerSimpleCB) (const AtspiDeviceEvent *stroke); + +#define ATSPI_TYPE_DEVICE_LISTENER (atspi_device_listener_get_type ()) +#define ATSPI_DEVICE_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListener)) +#define ATSPI_DEVICE_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass)) +#define ATSPI_IS_DEVICE_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DEVICE_LISTENER)) +#define ATSPI_IS_DEVICE_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_DEVICE_LISTENER)) +#define ATSPI_DEVICE_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_DEVICE_LISTENER, AtspiDeviceListenerClass)) + +typedef struct _AtspiDeviceListener AtspiDeviceListener; +struct _AtspiDeviceListener +{ + GObject parent; + guint id; + GList *callbacks; +}; + +typedef struct _AtspiDeviceListenerClass AtspiDeviceListenerClass; +struct _AtspiDeviceListenerClass +{ + GObjectClass parent_class; + gboolean (*device_event) (AtspiDeviceListener *listener, const AtspiDeviceEvent *event); +}; + +GType atspi_device_listener_get_type (void); + +AtspiDeviceListener *atspi_device_listener_new (AtspiDeviceListenerCB callback, void *user_data, GDestroyNotify callback_destroyed); + +AtspiDeviceListener *atspi_device_listener_new_simple (AtspiDeviceListenerSimpleCB callback, GDestroyNotify callback_destroyed); + +void atspi_device_listener_add_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback, GDestroyNotify callback_destroyed, void *user_data); + +void atspi_device_listener_remove_callback (AtspiDeviceListener *listener, AtspiDeviceListenerCB callback); + +G_END_DECLS + +#endif /* _ATSPI_DEVICE_LISTENER_H_ */ diff --git a/atspi/atspi-document.c b/atspi/atspi-document.c new file mode 100644 index 0000000..98dfc4f --- /dev/null +++ b/atspi/atspi-document.c @@ -0,0 +1,198 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_document_get_locale: + * @obj: a pointer to the #AtspiDocument object on which to operate. + * + * Gets the locale associated with the document's content, + * e.g. the locale for LOCALE_TYPE_MESSAGES. + * + * Returns: a string compliant with the POSIX standard for locale description. + **/ +gchar * +atspi_document_get_locale (AtspiDocument *obj, GError **error) +{ + gchar *retval = NULL; + + g_return_val_if_fail (obj != NULL, g_strdup ("C")); + + _atspi_dbus_call (obj, atspi_interface_document, "GetLocale", error, "=>s", &retval); + + return retval; +} + +/** + * atspi_document_get_attribute_value: (rename-to atspi_document_get_document_attribute_value) + * @obj: a pointer to the #AtspiDocument object on which to operate. + * @attribute: a string indicating the name of a specific attribute. + * + * Gets the value of a single attribute, if specified for the document as a whole. + * + * Returns: a string corresponding to the value of the specified attribute, or + * an empty string if the attribute is unspecified for the object. + * + * Deprecated: 2.10: Use atspi_document_get_document_attribute_value instead. + **/ +gchar * +atspi_document_get_attribute_value (AtspiDocument *obj, + gchar *attribute, + GError **error) +{ + return atspi_document_get_document_attribute_value (obj, attribute, error); +} + +/** + * atspi_document_get_document_attribute_value: + * @obj: a pointer to the #AtspiDocument object on which to operate. + * @attribute: a string indicating the name of a specific attribute. + * + * Gets the value of a single attribute, if specified for the document as a whole. + * + * Returns: a string corresponding to the value of the specified attribute, or + * an empty string if the attribute is unspecified for the object. + **/ +gchar * +atspi_document_get_document_attribute_value (AtspiDocument *obj, + gchar *attribute, + GError **error) +{ + gchar *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_document, "GetAttributeValue", error, "s=>s", attribute, &retval); + + if (!retval) + retval = g_strdup (""); + + return retval; +} + + +/** + * atspi_document_get_attributes: (rename-to atspi_document_get_document_attributes) + * @obj: a pointer to the #AtspiDocument object on which to operate. + * + * Gets all constant attributes for the document as a whole. For attributes + * that change within the document content, see @atspi_text_get_attribute_run instead. + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable + * containing the constant attributes of the document, as name-value pairs. + * + * Deprecated: 2.10: Use atspi_document_get_document_attributes instead. + **/ +GHashTable * +atspi_document_get_attributes (AtspiDocument *obj, GError **error) +{ + return atspi_document_get_document_attributes (obj, error); +} + +/** + * atspi_document_get_document_attributes: + * @obj: a pointer to the #AtspiDocument object on which to operate. + * + * Gets all constant attributes for the document as a whole. For attributes + * that change within the document content, see @atspi_text_get_attribute_run instead. + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable + * containing the constant attributes of the document, as name-value pairs. + **/ +GHashTable * +atspi_document_get_document_attributes (AtspiDocument *obj, GError **error) +{ + DBusMessage *message; + + g_return_val_if_fail (obj != NULL, NULL); + + message = _atspi_dbus_call_partial (obj, atspi_interface_document, "GetAttributes", error, ""); + return _atspi_dbus_return_hash_from_message (message); +} + +/** + * atspi_document_get_page_count: + * @obj: a pointer to the #AtspiDocument object to query. + * + * Gets the page count of an #AccessibleDocument object. + * + * Returns: a #gint indicating the page count of an + * #AccessibleDocument object. + **/ +gint +atspi_document_get_page_count (AtspiDocument *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_document, "PageCount", error, "i", &retval); + + return retval; +} + +/** + * atspi_document_get_current_page_number: + * @obj: a pointer to the #AtspiDocument object to query. + * + * Gets the current page number of an #AccessibleDocument object. + * + * Returns: a #gint indicating the current page number in the + * #AccessibleDocument object. + **/ +gint +atspi_document_get_current_page_number (AtspiDocument *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_document, "CurrentPageNumber", error, "i", &retval); + + return retval; +} + +static void +atspi_document_base_init (AtspiDocument *klass) +{ +} + +GType +atspi_document_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiDocument), + (GBaseInitFunc) atspi_document_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiDocument", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-document.h b/atspi/atspi-document.h new file mode 100644 index 0000000..f326d89 --- /dev/null +++ b/atspi/atspi-document.h @@ -0,0 +1,68 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_DOCUMENT_H_ +#define _ATSPI_DOCUMENT_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_DOCUMENT (atspi_document_get_type ()) +#define ATSPI_IS_DOCUMENT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_DOCUMENT) +#define ATSPI_DOCUMENT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_DOCUMENT, AtspiDocument) +#define ATSPI_DOCUMENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_DOCUMENT, AtspiDocument)) + +GType atspi_document_get_type (); + +struct _AtspiDocument +{ + GTypeInterface parent; +}; + +gchar * atspi_document_get_locale (AtspiDocument *obj, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +gchar * atspi_document_get_attribute_value (AtspiDocument *obj, gchar *attribute, GError **error); +#endif + +gchar * atspi_document_get_document_attribute_value (AtspiDocument *obj, gchar *attribute, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +GHashTable * atspi_document_get_attributes (AtspiDocument *obj, GError **error); +#endif + +GHashTable * atspi_document_get_document_attributes (AtspiDocument *obj, GError **error); + +gint atspi_document_get_page_count (AtspiDocument *obj, GError **error); +gint atspi_document_get_current_page_number (AtspiDocument *obj, GError **error); + + +G_END_DECLS + +#endif /* _ATSPI_DOCUMENT_H_ */ diff --git a/atspi/atspi-editabletext.c b/atspi/atspi-editabletext.c new file mode 100644 index 0000000..58ac715 --- /dev/null +++ b/atspi/atspi-editabletext.c @@ -0,0 +1,258 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include "atspi-private.h" + +#if 0 +/* TODO: implement */ +/** + * atspi_editable_text_set_attributes: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @attributes: a string indicating the attributes to apply to the range, + * delimited by ':'. + * @startOffset: a #gint indicating the start of the desired text range. + * @endOffset: a #gint indicating the first character past the desired range. + * + * Sets the attributes applied to a range of text from an #AtspiEditableText + * object, and the bounds of the range. + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_set_attributes (AtspiEditableText *obj, + const char *attributes, + gint start_pos, + gint end_pos, + GError **error +{ + dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos; + dbus_bool_t retval = FALSE; + + cspi_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "SetAttributes", error, "sii=>b", attributes, d_start_pos, d_end_pos, &retval); + + return retval; +} +#endif + +/** + * atspi_editable_text_set_text_contents: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @new_contents: a character string, encoded in UTF-8, which is to + * become the new text contents of the #AtspiEditableText object. + * + * Replace the entire text contents of an #AtspiEditableText object. + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_set_text_contents (AtspiEditableText *obj, + const gchar *new_contents, + GError **error) +{ + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "SetTextContents", error, "s=>b", new_contents, &retval); + + return retval; +} + +/** + * atspi_editable_text_insert_text: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @position: a #gint indicating the character offset at which to insert + * the new text. + * @text: a string representing the text to insert, in UTF-8 encoding. + * @length: the number of characters of text to insert. If the character + * count of text is less than or equal to length, the entire contents + * of text will be inserted. + * + * Inserts text into an #AtspiEditableText object. + * As with all character offsets, the specified @position may not be the + * same as the resulting byte offset, since the text is in a + * variable-width encoding. + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_insert_text (AtspiEditableText *obj, + gint position, + const gchar *text, + gint length, + GError **error) +{ + dbus_int32_t d_position = position, d_length = length; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "InsertText", error, "isi=>b", d_position, text, d_length, &retval); + + return retval; +} + +/** + * atspi_editable_text_copy_text: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @start_pos: a #gint indicating the starting character offset + * of the text to copy. + * @end_pos: a #gint indicating the offset of the first character + * past the end of the text section to be copied. + * + * Copies text from an #AtspiEditableText object into the system clipboard. + * + * see: #atspi_editable_text_paste_text + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_copy_text (AtspiEditableText *obj, + gint start_pos, + gint end_pos, + GError **error) +{ + dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "CopyText", error, "ii", d_start_pos, d_end_pos); + + return TRUE; +} + +/** + * atspi_editable_text_cut_text: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @start_pos: a #gint indicating the starting character offset + * of the text to cut. + * @end_pos: a #gint indicating the offset of the first character + * past the end of the text section to be cut. + * + * Deletes text from an #AtspiEditableText object, copying the + * excised portion into the system clipboard. + * + * see: #atspi_editable_text_paste_text + * + * Returns: #TRUE if operation was successful, #FALSE otherwise. + **/ +gboolean +atspi_editable_text_cut_text (AtspiEditableText *obj, + gint start_pos, + gint end_pos, + GError **error) +{ + dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "CutText", error, "ii=>b", d_start_pos, d_end_pos, &retval); + + return retval; +} + +/** + * atspi_editable_text_delete_text: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @start_pos: a #gint indicating the starting character offset + * of the text to delete. + * @end_pos: a #gint indicating the offset of the first character + * past the end of the text section to be deleted. + * + * Deletes text from an #AtspiEditableText object, without copying the + * excised portion into the system clipboard. + * + * see: #atspi_editable_text_cut_text + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_delete_text (AtspiEditableText *obj, + gint start_pos, + gint end_pos, + GError **error) +{ + dbus_int32_t d_start_pos = start_pos, d_end_pos = end_pos; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "DeleteText", error, "ii=>b", d_start_pos, d_end_pos, &retval); + + return retval; +} + +/** + * atspi_editable_text_paste_text: + * @obj: a pointer to the #AtspiEditableText object to modify. + * @position: a #gint indicating the character offset at which to insert + * the new text. + * + * Inserts text from the system clipboard into an #AtspiEditableText object. + * As with all character offsets, the specified @position may not be the + * same as the resulting byte offset, since the text is in a + * variable-width encoding. + * + * Returns: #TRUE if the operation was successful, otherwise #FALSE. + **/ +gboolean +atspi_editable_text_paste_text (AtspiEditableText *obj, + gint position, + GError **error) +{ + dbus_int32_t d_position = position; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_editable_text, "PasteText", error, "i=>b", d_position, &retval); + + return retval; +} + +static void +atspi_editable_text_base_init (AtspiEditableText *klass) +{ +} + +GType +atspi_editable_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiEditableText), + (GBaseInitFunc) atspi_editable_text_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiEditableText", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-editabletext.h b/atspi/atspi-editabletext.h new file mode 100644 index 0000000..59b2331 --- /dev/null +++ b/atspi/atspi-editabletext.h @@ -0,0 +1,66 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_EDITABLE_TEXT_H_ +#define _ATSPI_EDITABLE_TEXT_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_EDITABLE_TEXT (atspi_editable_text_get_type ()) +#define ATSPI_IS_EDITABLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_EDITABLE_TEXT) +#define ATSPI_EDITABLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_EDITABLE_TEXT, AtspiEditableText) +#define ATSPI_EDITABLE_TEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_EDITABLE_TEXT, AtspiEditableText)) + +GType atspi_editable_text_get_type (); + +struct _AtspiEditableText +{ + GTypeInterface parent; +}; + +#if 0 +gboolean atspi_editable_text_set_attributes (AtspiEditableText *obj, const char *attributes, gint start_pos, gint end_pos, GError **error) +#endif + +gboolean atspi_editable_text_set_text_contents (AtspiEditableText *obj, const gchar *new_contents, GError **error); + +gboolean atspi_editable_text_insert_text (AtspiEditableText *obj, gint position, const gchar *text, gint length, GError **error); + +gboolean atspi_editable_text_copy_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error); + +gboolean atspi_editable_text_cut_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error); + +gboolean atspi_editable_text_delete_text (AtspiEditableText *obj, gint start_pos, gint end_pos, GError **error); + +gboolean atspi_editable_text_paste_text (AtspiEditableText *obj, gint position, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_EDITABLE_TEXT_H_ */ diff --git a/atspi/atspi-enum-types.c.template b/atspi/atspi-enum-types.c.template new file mode 100644 index 0000000..385d0ee --- /dev/null +++ b/atspi/atspi-enum-types.c.template @@ -0,0 +1,39 @@ +/*** BEGIN file-header ***/ +#include "atspi-enum-types.h" + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +#include "@filename@" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static GType the_type = 0; + + if (the_type == 0) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, + "@VALUENAME@", + "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + the_type = g_@type@_register_static ( + g_intern_static_string ("@EnumName@"), + values); + } + return the_type; +} + +/*** END value-tail ***/ diff --git a/atspi/atspi-enum-types.h.template b/atspi/atspi-enum-types.h.template new file mode 100644 index 0000000..789ad2e --- /dev/null +++ b/atspi/atspi-enum-types.h.template @@ -0,0 +1,27 @@ +/*** BEGIN file-header ***/ +#ifndef __ATSPI_ENUM_TYPES_H__ +#define __ATSPI_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* Enumerations from "@basename@" */ + +/*** END file-production ***/ + +/*** BEGIN enumeration-production ***/ +#define ATSPI_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +GType @enum_name@_get_type (void) G_GNUC_CONST; + +/*** END enumeration-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __ATSPI_ENUM_TYPES_H__ */ +/*** END file-tail ***/ + diff --git a/atspi/atspi-event-listener-private.h b/atspi/atspi-event-listener-private.h new file mode 100644 index 0000000..260db74 --- /dev/null +++ b/atspi/atspi-event-listener-private.h @@ -0,0 +1,46 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_EVENT_LISTENER_PRIVATE_H_ +#define _ATSPI_EVENT_LISTENER_PRIVATE_H_ + +#include "atspi-event-listener.h" + +#include "dbus/dbus.h" + +G_BEGIN_DECLS + +DBusHandlerResult _atspi_dbus_handle_Event (DBusConnection *bus, DBusMessage *message, void *data); + +void _atspi_send_event (AtspiEvent *e); + +DBusHandlerResult _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data); + +void +_atspi_reregister_event_listeners (); + +G_END_DECLS + +#endif /* _ATSPI_EVENT_LISTENER_H_ */ diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c new file mode 100644 index 0000000..752547d --- /dev/null +++ b/atspi/atspi-event-listener.c @@ -0,0 +1,1098 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian Inc. + * Copyright 2002 Sun Microsystems, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" +#include "atspi-accessible-private.h" +#include +#include + +typedef struct +{ + AtspiEventListenerCB callback; + void *user_data; + GDestroyNotify callback_destroyed; + char *event_type; + char *category; + char *name; + char *detail; + GArray *properties; +} EventListenerEntry; + +G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener, G_TYPE_OBJECT) + +void +atspi_event_listener_init (AtspiEventListener *listener) +{ +} + +void +atspi_event_listener_class_init (AtspiEventListenerClass *klass) +{ +} + +static void +remove_datum (AtspiEvent *event, void *user_data) +{ + AtspiEventListenerSimpleCB cb = user_data; + cb (event); +} + +typedef struct +{ + gpointer callback; + GDestroyNotify callback_destroyed; + gint ref_count; +} CallbackInfo; +static GHashTable *callbacks; + +void +callback_ref (void *callback, GDestroyNotify callback_destroyed) +{ + CallbackInfo *info; + + if (!callbacks) + { + callbacks = g_hash_table_new (g_direct_hash, g_direct_equal); + if (!callbacks) + return; + } + + info = g_hash_table_lookup (callbacks, callback); + if (!info) + { + info = g_new (CallbackInfo, 1); + info->callback = callback; + info->callback_destroyed = callback_destroyed; + info->ref_count = 1; + g_hash_table_insert (callbacks, callback, info); + } + else + info->ref_count++; +} + +void +callback_unref (gpointer callback) +{ + CallbackInfo *info; + + if (!callbacks) + return; + info = g_hash_table_lookup (callbacks, callback); + if (!info) + { + g_warning ("Atspi: Dereferencing invalid callback %p\n", callback); + return; + } + info->ref_count--; + if (info->ref_count == 0) + { +#if 0 + /* TODO: Figure out why this seg faults from Python */ + if (info->callback_destroyed) + (*info->callback_destroyed) (info->callback); +#endif + g_free (info); + g_hash_table_remove (callbacks, callback); + } +} + +/** + * atspi_event_listener_new: + * @callback: (scope notified): An #AtspiEventListenerCB to be called + * when an event is fired. + * @user_data: (closure): data to pass to the callback. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. Can be NULL. + * + * Creates a new #AtspiEventListener associated with a specified @callback. + * + * Returns: (transfer full): A new #AtspiEventListener. + */ +AtspiEventListener * +atspi_event_listener_new (AtspiEventListenerCB callback, + gpointer user_data, + GDestroyNotify callback_destroyed) +{ + AtspiEventListener *listener = g_object_new (ATSPI_TYPE_EVENT_LISTENER, NULL); + listener->callback = callback; + callback_ref (callback, callback_destroyed); + listener->user_data = user_data; + listener->cb_destroyed = callback_destroyed; + return listener; +} + +/** + * atspi_event_listener_new_simple: (skip) + * @callback: (scope notified): An #AtspiEventListenerSimpleCB to be called + * when an event is fired. + * @callback_destroyed: A #GDestroyNotify called when the listener is freed + * and data associated with the callback should be freed. Can be NULL. + * + * Creates a new #AtspiEventListener associated with a specified @callback. + * Returns: (transfer full): A new #AtspiEventListener. + **/ +AtspiEventListener * +atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback, + GDestroyNotify callback_destroyed) +{ + AtspiEventListener *listener = g_object_new (ATSPI_TYPE_EVENT_LISTENER, NULL); + listener->callback = remove_datum; + callback_ref (remove_datum, callback_destroyed); + listener->user_data = callback; + listener->cb_destroyed = callback_destroyed; + return listener; +} + +static GList *event_listeners = NULL; + +static gchar * +convert_name_from_dbus (const char *name, gboolean path_hack) +{ + gchar *ret = g_malloc (g_utf8_strlen (name, -1) * 2 + 1); + const char *p = name; + gchar *q = ret; + + if (!ret) + return NULL; + + while (*p) + { + if (isupper (*p)) + { + if (q > ret) + *q++ = '-'; + *q++ = tolower (*p++); + } + else if (path_hack && *p == '/') + { + *q++ = ':'; + p++; + } + else + *q++ = *p++; + } + *q = '\0'; + return ret; +} + +static void +cache_process_children_changed (AtspiEvent *event) +{ + AtspiAccessible *child; + + if (!G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE) || + !(event->source->cached_properties & ATSPI_CACHE_CHILDREN) || + atspi_state_set_contains (event->source->states, ATSPI_STATE_MANAGES_DESCENDANTS)) + return; + + child = g_value_get_object (&event->any_data); + if (child == NULL) + return; + + if (!strncmp (event->type, "object:children-changed:add", 27)) + { + g_ptr_array_remove (event->source->children, child); /* just to be safe */ + if (event->detail1 < 0 || event->detail1 > event->source->children->len) + { + event->source->cached_properties &= ~ATSPI_CACHE_CHILDREN; + return; + } + /* Unfortunately, there's no g_ptr_array_insert or similar */ + g_ptr_array_add (event->source->children, NULL); + memmove (event->source->children->pdata + event->detail1 + 1, + event->source->children->pdata + event->detail1, + (event->source->children->len - event->detail1 - 1) * sizeof (gpointer)); + g_ptr_array_index (event->source->children, event->detail1) = g_object_ref (child); + } + else + { + g_ptr_array_remove (event->source->children, child); + if (child == child->parent.app->root) + g_object_run_dispose (G_OBJECT (child->parent.app)); + } +} + +static void +cache_process_property_change (AtspiEvent *event) +{ + if (!strcmp (event->type, "object:property-change:accessible-parent")) + { + if (event->source->accessible_parent) + g_object_unref (event->source->accessible_parent); + if (G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE)) + { + event->source->accessible_parent = g_value_dup_object (&event->any_data); + _atspi_accessible_add_cache (event->source, ATSPI_CACHE_PARENT); + } + else + { + event->source->accessible_parent = NULL; + event->source->cached_properties &= ~ATSPI_CACHE_PARENT; + } + } + else if (!strcmp (event->type, "object:property-change:accessible-name")) + { + if (event->source->name) + g_free (event->source->name); + if (G_VALUE_HOLDS_STRING (&event->any_data)) + { + event->source->name = g_value_dup_string (&event->any_data); + _atspi_accessible_add_cache (event->source, ATSPI_CACHE_NAME); + } + else + { + event->source->name = NULL; + event->source->cached_properties &= ~ATSPI_CACHE_NAME; + } + } + else if (!strcmp (event->type, "object:property-change:accessible-description")) + { + if (event->source->description) + g_free (event->source->description); + if (G_VALUE_HOLDS_STRING (&event->any_data)) + { + event->source->description = g_value_dup_string (&event->any_data); + _atspi_accessible_add_cache (event->source, ATSPI_CACHE_DESCRIPTION); + } + else + { + event->source->description = NULL; + event->source->cached_properties &= ~ATSPI_CACHE_DESCRIPTION; + } + } + else if (!strcmp (event->type, "object:property-change:accessible-role")) + { + if (G_VALUE_HOLDS_INT (&event->any_data)) + { + event->source->role = g_value_get_int (&event->any_data); + _atspi_accessible_add_cache (event->source, ATSPI_CACHE_ROLE); + } + else + { + event->source->cached_properties &= ~ATSPI_CACHE_ROLE; + } + } +} + +static void +cache_process_state_changed (AtspiEvent *event) +{ + if (event->source->states) + atspi_state_set_set_by_name (event->source->states, event->type + 21, + event->detail1); +} + +static dbus_bool_t +demarshal_rect (DBusMessageIter *iter, AtspiRect *rect) +{ + dbus_int32_t x, y, width, height; + DBusMessageIter iter_struct; + + dbus_message_iter_recurse (iter, &iter_struct); + if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE; + dbus_message_iter_get_basic (&iter_struct, &x); + dbus_message_iter_next (&iter_struct); + if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE; + dbus_message_iter_get_basic (&iter_struct, &y); + dbus_message_iter_next (&iter_struct); + if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE; + dbus_message_iter_get_basic (&iter_struct, &width); + dbus_message_iter_next (&iter_struct); + if (dbus_message_iter_get_arg_type (&iter_struct) != DBUS_TYPE_INT32) return FALSE; + dbus_message_iter_get_basic (&iter_struct, &height); + rect->x = x; + rect->y = y; + rect->width = width; + rect->height = height; + return TRUE; +} + +static gchar * +strdup_and_adjust_for_dbus (const char *s) +{ + gchar *d = g_strdup (s); + gchar *p; + int parts = 0; + + if (!d) + return NULL; + + for (p = d; *p; p++) + { + if (*p == '-') + { + memmove (p, p + 1, g_utf8_strlen (p, -1)); + *p = toupper (*p); + } + else if (*p == ':') + { + parts++; + if (parts == 2) + break; + p [1] = toupper (p [1]); + } + } + + d [0] = toupper (d [0]); + return d; +} + +static gboolean +convert_event_type_to_dbus (const char *eventType, char **categoryp, char **namep, char **detailp, GPtrArray **matchrule_array) +{ + gchar *tmp = strdup_and_adjust_for_dbus (eventType); + char *category = NULL, *name = NULL, *detail = NULL; + char *saveptr = NULL; + + if (tmp == NULL) return FALSE; + category = strtok_r (tmp, ":", &saveptr); + if (category) category = g_strdup (category); + name = strtok_r (NULL, ":", &saveptr); + if (name) + { + name = g_strdup (name); + detail = strtok_r (NULL, ":", &saveptr); + if (detail) detail = g_strdup (detail); + } + if (matchrule_array) + { + gchar *matchrule; + matchrule = g_strdup_printf ("type='signal',interface='org.a11y.atspi.Event.%s'", category); + if (name && name [0]) + { + gchar *new_str = g_strconcat (matchrule, ",member='", name, "'", NULL); + g_free (matchrule); + matchrule = new_str; + } + (*matchrule_array) = g_ptr_array_new (); + if (detail && detail [0]) + { + gchar *new_str = g_strconcat (matchrule, ",arg0='", detail, "'", NULL); + g_ptr_array_add (*matchrule_array, new_str); + new_str = g_strconcat (matchrule, ",arg0path='", detail, "/'", NULL); + g_ptr_array_add (*matchrule_array, new_str); + g_free (matchrule); + } + else + g_ptr_array_add (*matchrule_array, matchrule); + } + if (categoryp) *categoryp = category; + else g_free (category); + if (namep) *namep = name; + else if (name) g_free (name); + if (detailp) *detailp = detail; + else if (detail) g_free (detail); + g_free (tmp); + return TRUE; +} + +static void +listener_entry_free (EventListenerEntry *e) +{ + gpointer callback = (e->callback == remove_datum ? (gpointer)e->user_data : (gpointer)e->callback); + g_free (e->event_type); + g_free (e->category); + g_free (e->name); + if (e->detail) g_free (e->detail); + callback_unref (callback); + g_free (e); +} + +/** + * atspi_event_listener_register: + * @listener: The #AtspiEventListener to register against an event type. + * @event_type: a character string indicating the type of events for which + * notification is requested. Format is + * EventClass:major_type:minor_type:detail + * where all subfields other than EventClass are optional. + * EventClasses include "object", "window", "mouse", + * and toolkit events (e.g. "Gtk", "AWT"). + * Examples: "focus:", "Gtk:GtkWidget:button_press_event". + * + * Adds an in-process callback function to an existing #AtspiEventListener. + * + * Legal object event types: + * + * (property change events) + * + * object:property-change + * object:property-change:accessible-name + * object:property-change:accessible-description + * object:property-change:accessible-parent + * object:property-change:accessible-value + * object:property-change:accessible-role + * object:property-change:accessible-table-caption + * object:property-change:accessible-table-column-description + * object:property-change:accessible-table-column-header + * object:property-change:accessible-table-row-description + * object:property-change:accessible-table-row-header + * object:property-change:accessible-table-summary + * + * (other object events) + * + * object:state-changed + * object:children-changed + * object:visible-data-changed + * object:selection-changed + * object:text-selection-changed + * object:text-changed + * object:text-caret-moved + * object:row-inserted + * object:row-reordered + * object:row-deleted + * object:column-inserted + * object:column-reordered + * object:column-deleted + * object:model-changed + * object:active-descendant-changed + * + * (window events) + * + * window:minimize + * window:maximize + * window:restore + * window:close + * window:create + * window:reparent + * window:desktop-create + * window:desktop-destroy + * window:activate + * window:deactivate + * window:raise + * window:lower + * window:move + * window:resize + * window:shade + * window:unshade + * window:restyle + * + * (other events) + * + * focus: + * mouse:abs + * mouse:rel + * mouse:b1p + * mouse:b1r + * mouse:b2p + * mouse:b2r + * mouse:b3p + * mouse:b3r + * + * NOTE: this character string may be UTF-8, but should not contain byte + * value 56 + * (ascii ':'), except as a delimiter, since non-UTF-8 string + * delimiting functions are used internally. + * In general, listening to + * toolkit-specific events is not recommended. + * + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_register (AtspiEventListener *listener, + const gchar *event_type, + GError **error) +{ + /* TODO: Keep track of which events have been registered, so that we + * deregister all of them when the event listener is destroyed */ + + return atspi_event_listener_register_from_callback (listener->callback, + listener->user_data, + listener->cb_destroyed, + event_type, error); +} + +/** + * atspi_event_listener_register_full: + * @listener: The #AtspiEventListener to register against an event type. + * @event_type: a character string indicating the type of events for which + * notification is requested. See #atspi_event_listener_register + * for a description of the format and legal event types. +* @properties: (element-type gchar*) (transfer none) (allow-none): a list of + * properties that should be sent along with the event. The + * properties are valued for the duration of the event callback.k + * TODO: Document. + * + * Adds an in-process callback function to an existing #AtspiEventListener. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_register_full (AtspiEventListener *listener, + const gchar *event_type, + GArray *properties, + GError **error) +{ + /* TODO: Keep track of which events have been registered, so that we + * deregister all of them when the event listener is destroyed */ + + return atspi_event_listener_register_from_callback_full (listener->callback, + listener->user_data, + listener->cb_destroyed, + event_type, + properties, + error); +} + +static gboolean +notify_event_registered (EventListenerEntry *e) +{ + + if (e->properties) + dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry, + atspi_path_registry, + atspi_interface_registry, + "RegisterEvent", + NULL, "sas", e->event_type, + e->properties); + else + dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry, + atspi_path_registry, + atspi_interface_registry, + "RegisterEvent", + NULL, "s", e->event_type); + + return TRUE; +} + +/** + * atspi_event_listener_register_from_callback: + * @callback: (scope notified): the #AtspiEventListenerCB to be registered + * against an event type. + * @user_data: (closure): User data to be passed to the callback. + * @callback_destroyed: A #GDestroyNotify called when the callback is destroyed. + * @event_type: a character string indicating the type of events for which + * notification is requested. See #atspi_event_listener_register + * for a description of the format. + * + * Registers an #AtspiEventListenerCB against an @event_type. + * + * Returns: #TRUE if successfull, otherwise #FALSE. + * + **/ +gboolean +atspi_event_listener_register_from_callback (AtspiEventListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GError **error) +{ + return atspi_event_listener_register_from_callback_full (callback, + user_data, + callback_destroyed, + event_type, NULL, + error); +} + +static GArray * +copy_event_properties (GArray *src) +{ + gint i; + + GArray *dst = g_array_new (FALSE, FALSE, sizeof (char *)); + + if (!src) + return dst; + for (i = 0; i < src->len; i++) + { + gchar *dup = g_strdup (g_array_index (src, char *, i)); + g_array_append_val (dst, dup); + } + return dst; +} + +/** + * atspi_event_listener_register_from_callback_full: + * @callback: (scope async): an #AtspiEventListenerCB function pointer. + * @user_data: (closure callback) + * @callback_destroyed: (destroy callback) + * @event_type: + * @properties: (element-type utf8) + * @error: + * + * Returns: #TRUE if successful, otherwise #FALSE. + * + **/ +gboolean +atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GArray *properties, + GError **error) +{ + EventListenerEntry *e; + DBusError d_error; + GPtrArray *matchrule_array; + gint i; + + if (!callback) + { + return FALSE; + } + + if (!event_type) + { + g_warning ("called atspi_event_listener_register_from_callback with a NULL event_type"); + return FALSE; + } + + e = g_new (EventListenerEntry, 1); + e->event_type = g_strdup (event_type); + e->callback = callback; + e->user_data = user_data; + e->callback_destroyed = callback_destroyed; + callback_ref (callback == remove_datum ? (gpointer)user_data : (gpointer)callback, + callback_destroyed); + if (!convert_event_type_to_dbus (event_type, &e->category, &e->name, &e->detail, &matchrule_array)) + { + g_free (e); + return FALSE; + } + e->properties = copy_event_properties (properties); + event_listeners = g_list_prepend (event_listeners, e); + for (i = 0; i < matchrule_array->len; i++) + { + char *matchrule = g_ptr_array_index (matchrule_array, i); + dbus_error_init (&d_error); + dbus_bus_add_match (_atspi_bus(), matchrule, &d_error); + if (dbus_error_is_set (&d_error)) + { + g_warning ("Atspi: Adding match: %s", d_error.message); + dbus_error_free (&d_error); + /* TODO: Set error */ + } + + g_free (matchrule); + } + g_ptr_array_free (matchrule_array, TRUE); + + notify_event_registered (e); + return TRUE; +} + +void +_atspi_reregister_event_listeners () +{ + GList *l; + EventListenerEntry *e; + + for (l = event_listeners; l; l = l->next) + { + e = l->data; + notify_event_registered (e); + } +} + +/** + * atspi_event_listener_register_no_data: (skip) + * @callback: (scope notified): the #AtspiEventListenerSimpleCB to be + * registered against an event type. + * @callback_destroyed: A #GDestroyNotify called when the callback is destroyed. + * @event_type: a character string indicating the type of events for which + * notification is requested. Format is + * EventClass:major_type:minor_type:detail + * where all subfields other than EventClass are optional. + * EventClasses include "object", "window", "mouse", + * and toolkit events (e.g. "Gtk", "AWT"). + * Examples: "focus:", "Gtk:GtkWidget:button_press_event". + * + * Registers an #AtspiEventListenetSimpleCB. The method is similar to + * #atspi_event_listener_register, but @callback takes no user_data. + * + * Returns: #TRUE if successfull, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GError **error) +{ + return atspi_event_listener_register_from_callback (remove_datum, callback, + callback_destroyed, + event_type, error); +} + +static gboolean +is_superset (const gchar *super, const gchar *sub) +{ + if (!super || !super [0]) + return TRUE; + return (strcmp (super, sub) == 0); +} + +/** + * atspi_event_listener_deregister: + * @listener: The #AtspiEventListener to deregister. + * @event_type: a string specifying the event type for which this + * listener is to be deregistered. + * + * Deregisters an #AtspiEventListener from the registry, for a specific + * event type. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_deregister (AtspiEventListener *listener, + const gchar *event_type, + GError **error) +{ + return atspi_event_listener_deregister_from_callback (listener->callback, + listener->user_data, + event_type, error); +} + +/** + * atspi_event_listener_deregister_from_callback: + * @callback: (scope call): the #AtspiEventListenerCB registered against an + * event type. + * @user_data: (closure): User data that was passed in for this callback. + * @event_type: a string specifying the event type for which this + * listener is to be deregistered. + * + * Deregisters an #AtspiEventListenerCB from the registry, for a specific + * event type. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback, + void *user_data, + const gchar *event_type, + GError **error) +{ + char *category, *name, *detail; + GPtrArray *matchrule_array; + gint i; + GList *l; + + if (!convert_event_type_to_dbus (event_type, &category, &name, &detail, &matchrule_array)) + { + return FALSE; + } + if (!callback) + { + return FALSE; + } + + for (l = event_listeners; l;) + { + EventListenerEntry *e = l->data; + if (e->callback == callback && + e->user_data == user_data && + is_superset (category, e->category) && + is_superset (name, e->name) && + is_superset (detail, e->detail)) + { + gboolean need_replace; + DBusMessage *message, *reply; + need_replace = (l == event_listeners); + l = g_list_remove (l, e); + if (need_replace) + event_listeners = l; + for (i = 0; i < matchrule_array->len; i++) + { + char *matchrule = g_ptr_array_index (matchrule_array, i); + dbus_bus_remove_match (_atspi_bus(), matchrule, NULL); + } + message = dbus_message_new_method_call (atspi_bus_registry, + atspi_path_registry, + atspi_interface_registry, + "DeregisterEvent"); + if (!message) + return FALSE; + dbus_message_append_args (message, DBUS_TYPE_STRING, &event_type, DBUS_TYPE_INVALID); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + if (reply) + dbus_message_unref (reply); + + listener_entry_free (e); + } + else l = g_list_next (l); + } + g_free (category); + g_free (name); + if (detail) g_free (detail); + for (i = 0; i < matchrule_array->len; i++) + g_free (g_ptr_array_index (matchrule_array, i)); + g_ptr_array_free (matchrule_array, TRUE); + return TRUE; +} + +/** + * atspi_event_listener_deregister_no_data: (skip) + * @callback: (scope call): the #AtspiEventListenerSimpleCB registered against + * an event type. + * @event_type: a string specifying the event type for which this + * listener is to be deregistered. + * + * deregisters an #AtspiEventListenerSimpleCB from the registry, for a specific + * event type. + * + * Returns: #TRUE if successful, otherwise #FALSE. + **/ +gboolean +atspi_event_listener_deregister_no_data (AtspiEventListenerSimpleCB callback, + const gchar *event_type, + GError **error) +{ + return atspi_event_listener_deregister_from_callback (remove_datum, callback, + event_type, + error); +} + +static AtspiEvent * +atspi_event_copy (AtspiEvent *src) +{ + AtspiEvent *dst = g_new0 (AtspiEvent, 1); + dst->type = g_strdup (src->type); + dst->source = g_object_ref (src->source); + dst->detail1 = src->detail1; + dst->detail2 = src->detail2; + g_value_init (&dst->any_data, G_VALUE_TYPE (&src->any_data)); + g_value_copy (&src->any_data, &dst->any_data); + return dst; +} + +static void +atspi_event_free (AtspiEvent *event) +{ + g_object_unref (event->source); + g_free (event->type); + g_value_unset (&event->any_data); + g_free (event); +} + +static gboolean +detail_matches_listener (const char *event_detail, const char *listener_detail) +{ + if (!listener_detail) + return TRUE; + + if (!event_detail) + return (listener_detail ? FALSE : TRUE); + + return !(listener_detail [strcspn (listener_detail, ":")] == '\0' + ? strncmp (listener_detail, event_detail, + strcspn (event_detail, ":")) + : strcmp (listener_detail, event_detail)); +} + +void +_atspi_send_event (AtspiEvent *e) +{ + char *category, *name, *detail; + GList *l; + GList *called_listeners = NULL; + + /* Ensure that the value is set to avoid a Python exception */ + /* TODO: Figure out how to do this without using a private field */ + if (e->any_data.g_type == 0) + { + g_value_init (&e->any_data, G_TYPE_INT); + g_value_set_int (&e->any_data, 0); + } + + if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL)) + { + g_warning ("Atspi: Couldn't parse event: %s\n", e->type); + return; + } + for (l = event_listeners; l; l = g_list_next (l)) + { + EventListenerEntry *entry = l->data; + if (!strcmp (category, entry->category) && + (entry->name == NULL || !strcmp (name, entry->name)) && + detail_matches_listener (detail, entry->detail)) + { + GList *l2; + for (l2 = called_listeners; l2; l2 = l2->next) + { + EventListenerEntry *e2 = l2->data; + if (entry->callback == e2->callback && entry->user_data == e2->user_data) + break; + } + if (!l2) + { + entry->callback (atspi_event_copy (e), entry->user_data); + called_listeners = g_list_prepend (called_listeners, entry); + } + } + } + if (detail) g_free (detail); + g_free (name); + g_free (category); + g_list_free (called_listeners); +} + +DBusHandlerResult +_atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data) +{ + char *detail = NULL; + const char *category = dbus_message_get_interface (message); + const char *member = dbus_message_get_member (message); + const char *signature = dbus_message_get_signature (message); + gchar *name; + gchar *converted_type; + DBusMessageIter iter, iter_variant; + dbus_message_iter_init (message, &iter); + AtspiEvent e; + dbus_int32_t detail1, detail2; + char *p; + GHashTable *cache = NULL; + + if (strcmp (signature, "siiv(so)") != 0 && + strcmp (signature, "siiva{sv}") != 0) + { + g_warning ("Got invalid signature %s for signal %s from interface %s\n", signature, member, category); + return DBUS_HANDLER_RESULT_HANDLED; + } + + memset (&e, 0, sizeof (e)); + + if (category) + { + category = g_utf8_strrchr (category, -1, '.'); + if (category == NULL) + { + // TODO: Error + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + category++; + } + dbus_message_iter_get_basic (&iter, &detail); + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &detail1); + e.detail1 = detail1; + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &detail2); + e.detail2 = detail2; + dbus_message_iter_next (&iter); + + converted_type = convert_name_from_dbus (category, FALSE); + name = convert_name_from_dbus (member, FALSE); + detail = convert_name_from_dbus (detail, TRUE); + + if (strcasecmp (category, name) != 0) + { + p = g_strconcat (converted_type, ":", name, NULL); + g_free (converted_type); + converted_type = p; + } + else if (detail [0] == '\0') + { + p = g_strconcat (converted_type, ":", NULL); + g_free (converted_type); + converted_type = p; + } + + if (detail[0] != '\0') + { + p = g_strconcat (converted_type, ":", detail, NULL); + g_free (converted_type); + converted_type = p; + } + e.type = converted_type; + e.source = _atspi_ref_accessible (dbus_message_get_sender(message), dbus_message_get_path(message)); + if (e.source == NULL) + { + g_warning ("Got no valid source accessible for signal for signal %s from interface %s\n", member, category); + g_free (converted_type); + g_free (name); + g_free (detail); + return DBUS_HANDLER_RESULT_HANDLED; + } + + dbus_message_iter_recurse (&iter, &iter_variant); + switch (dbus_message_iter_get_arg_type (&iter_variant)) + { + case DBUS_TYPE_STRUCT: + { + AtspiRect rect; + if (demarshal_rect (&iter_variant, &rect)) + { + g_value_init (&e.any_data, ATSPI_TYPE_RECT); + g_value_set_boxed (&e.any_data, &rect); + } + else + { + AtspiAccessible *accessible; + accessible = _atspi_dbus_return_accessible_from_iter (&iter_variant); + g_value_init (&e.any_data, ATSPI_TYPE_ACCESSIBLE); + g_value_set_instance (&e.any_data, accessible); + if (accessible) + g_object_unref (accessible); /* value now owns it */ + } + break; + } + case DBUS_TYPE_STRING: + { + dbus_message_iter_get_basic (&iter_variant, &p); + g_value_init (&e.any_data, G_TYPE_STRING); + g_value_set_string (&e.any_data, p); + break; + } + default: + break; + } + + dbus_message_iter_next (&iter); + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY) + { + /* new form -- parse properties sent with event */ + cache = _atspi_dbus_update_cache_from_dict (e.source, &iter); + } + + if (!strncmp (e.type, "object:children-changed", 23)) + { + cache_process_children_changed (&e); + } + else if (!strncmp (e.type, "object:property-change", 22)) + { + cache_process_property_change (&e); + } + else if (!strncmp (e.type, "object:state-changed", 20)) + { + cache_process_state_changed (&e); + } + else if (!strncmp (e.type, "focus", 5)) + { + /* BGO#663992 - TODO: figure out the real problem */ + e.source->cached_properties &= ~(ATSPI_CACHE_STATES); + } + + _atspi_send_event (&e); + + if (cache) + _atspi_accessible_unref_cache (e.source); + + g_free (converted_type); + g_free (name); + g_free (detail); + g_object_unref (e.source); + g_value_unset (&e.any_data); + return DBUS_HANDLER_RESULT_HANDLED; +} + +G_DEFINE_BOXED_TYPE (AtspiEvent, atspi_event, atspi_event_copy, atspi_event_free) diff --git a/atspi/atspi-event-listener.h b/atspi/atspi-event-listener.h new file mode 100644 index 0000000..ee52fac --- /dev/null +++ b/atspi/atspi-event-listener.h @@ -0,0 +1,140 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_EVENT_LISTENER_H_ +#define _ATSPI_EVENT_LISTENER_H_ + +#include "glib-object.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +GType atspi_event_get_type (void); + +/** + * AtspiEventListenerCB: + * @event: (transfer full): The event for which notification is sent. + * @user_data: User data which is passed to the callback each time a notification takes place. + * + * A function prototype for callbacks via which clients are notified of AT-SPI events. + * + **/ +typedef void (*AtspiEventListenerCB) (AtspiEvent *event, + void *user_data); + +/** + * AtspiEventListenerSimpleCB: + * @event: (transfer full): The event for which notification is sent. + * + * Like #AtspiEventlistenerCB, but with no user_data. + * + **/ +typedef void (*AtspiEventListenerSimpleCB) (const AtspiEvent *event); + +#define ATSPI_TYPE_EVENT_LISTENER (atspi_event_listener_get_type ()) +#define ATSPI_EVENT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListener)) +#define ATSPI_EVENT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass)) +#define ATSPI_IS_EVENT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_EVENT_LISTENER)) +#define ATSPI_IS_EVENT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_EVENT_LISTENER)) +#define ATSPI_EVENT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_EVENT_LISTENER, AtspiEventListenerClass)) + +typedef struct _AtspiEventListener AtspiEventListener; +struct _AtspiEventListener +{ + GObject parent; + AtspiEventListenerCB callback; + void *user_data; + GDestroyNotify cb_destroyed; +}; + +typedef struct _AtspiEventListenerClass AtspiEventListenerClass; +struct _AtspiEventListenerClass +{ + GObjectClass parent_class; +}; + +GType atspi_event_listener_get_type (void); + +AtspiEventListener * +atspi_event_listener_new (AtspiEventListenerCB callback, + gpointer user_data, + GDestroyNotify callback_destroyed); + +AtspiEventListener * +atspi_event_listener_new_simple (AtspiEventListenerSimpleCB callback, + GDestroyNotify callback_destroyed); + +gboolean +atspi_event_listener_register (AtspiEventListener *listener, + const gchar *event_type, + GError **error); + +gboolean +atspi_event_listener_register_full (AtspiEventListener *listener, + const gchar *event_type, + GArray *properties, + GError **error); + +gboolean +atspi_event_listener_register_from_callback (AtspiEventListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GError **error); + +gboolean +atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback, + void *user_data, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GArray *properties, + GError **error); + +gboolean +atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback, + GDestroyNotify callback_destroyed, + const gchar *event_type, + GError **error); + +gboolean +atspi_event_listener_deregister (AtspiEventListener *listener, + const gchar *event_type, + GError **error); + +gboolean +atspi_event_listener_deregister_from_callback (AtspiEventListenerCB callback, + void *user_data, + const gchar *event_type, + GError **error); + +gboolean +atspi_event_listener_deregister_no_data (AtspiEventListenerSimpleCB callback, + const gchar *event_type, + GError **error); + +G_END_DECLS + +#endif /* _ATSPI_EVENT_LISTENER_H_ */ diff --git a/atspi/atspi-gmain.c b/atspi/atspi-gmain.c new file mode 100644 index 0000000..3ab985b --- /dev/null +++ b/atspi/atspi-gmain.c @@ -0,0 +1,665 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gmain.c GLib main loop integration + * + * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * This file is based on dbus-gmain.c from dbus-glib with functions renamed + * and unnecessary code removed. + */ + +#include +#include +#include "glib.h" +#include + +#include +#define _(x) dgettext (GETTEXT_PACKAGE, x) +#define N_(x) x + +/** + * DBusGMessageQueue: + * A GSource subclass for dispatching DBusConnection messages. + * We need this on top of the IO handlers, because sometimes + * there are messages to dispatch queued up but no IO pending. + */ +typedef struct +{ + GSource source; /**< the parent GSource */ + DBusConnection *connection; /**< the connection to dispatch */ +} DBusGMessageQueue; + +static gboolean message_queue_prepare (GSource *source, + gint *timeout); +static gboolean message_queue_check (GSource *source); +static gboolean message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static const GSourceFuncs message_queue_funcs = { + message_queue_prepare, + message_queue_check, + message_queue_dispatch, + NULL +}; + +static gboolean +message_queue_prepare (GSource *source, + gint *timeout) +{ + DBusConnection *connection = ((DBusGMessageQueue *)source)->connection; + + *timeout = -1; + + return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS); +} + +static gboolean +message_queue_check (GSource *source) +{ + return FALSE; +} + +static gboolean +message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + DBusConnection *connection = ((DBusGMessageQueue *)source)->connection; + + dbus_connection_ref (connection); + + /* Only dispatch once - we don't want to starve other GSource */ + dbus_connection_dispatch (connection); + + dbus_connection_unref (connection); + + return TRUE; +} + +typedef struct +{ + GMainContext *context; /**< the main context */ + GSList *ios; /**< all IOHandler */ + GSList *timeouts; /**< all TimeoutHandler */ + DBusConnection *connection; /**< NULL if this is really for a server not a connection */ + GSource *message_queue_source; /**< DBusGMessageQueue */ +} ConnectionSetup; + + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusWatch *watch; +} IOHandler; + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusTimeout *timeout; +} TimeoutHandler; + +dbus_int32_t _dbus_gmain_connection_slot = -1; +static dbus_int32_t server_slot = -1; + +static ConnectionSetup* +connection_setup_new (GMainContext *context, + DBusConnection *connection) +{ + ConnectionSetup *cs; + + cs = g_new0 (ConnectionSetup, 1); + + g_assert (context != NULL); + + cs->context = context; + g_main_context_ref (cs->context); + + if (connection) + { + cs->connection = connection; + + cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs, + sizeof (DBusGMessageQueue)); + ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection; + g_source_attach (cs->message_queue_source, cs->context); + } + + return cs; +} + +static void +io_handler_source_finalized (gpointer data) +{ + IOHandler *handler; + + handler = data; + + if (handler->watch) + dbus_watch_set_data (handler->watch, NULL, NULL); + + g_free (handler); +} + +static void +io_handler_destroy_source (void *data) +{ + IOHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->ios = g_slist_remove (handler->cs->ios, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +io_handler_watch_freed (void *data) +{ + IOHandler *handler; + + handler = data; + + handler->watch = NULL; + + io_handler_destroy_source (handler); +} + +static gboolean +io_handler_dispatch (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + IOHandler *handler; + guint dbus_condition = 0; + DBusConnection *connection; + + handler = data; + + connection = handler->cs->connection; + + if (connection) + dbus_connection_ref (connection); + + if (condition & G_IO_IN) + dbus_condition |= DBUS_WATCH_READABLE; + if (condition & G_IO_OUT) + dbus_condition |= DBUS_WATCH_WRITABLE; + if (condition & G_IO_ERR) + dbus_condition |= DBUS_WATCH_ERROR; + if (condition & G_IO_HUP) + dbus_condition |= DBUS_WATCH_HANGUP; + + /* Note that we don't touch the handler after this, because + * dbus may have disabled the watch and thus killed the + * handler. + */ + dbus_watch_handle (handler->watch, dbus_condition); + handler = NULL; + + if (connection) + dbus_connection_unref (connection); + + return TRUE; +} + +/* Attach the connection setup to the given watch, removing any + * previously-attached connection setup. + */ +static void +connection_setup_add_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + guint flags; + GIOCondition condition; + GIOChannel *channel; + IOHandler *handler; + + if (!dbus_watch_get_enabled (watch)) + return; + + flags = dbus_watch_get_flags (watch); + + condition = G_IO_ERR | G_IO_HUP; + if (flags & DBUS_WATCH_READABLE) + condition |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) + condition |= G_IO_OUT; + + handler = g_new0 (IOHandler, 1); + handler->cs = cs; + handler->watch = watch; + + channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch)); + + handler->source = g_io_create_watch (channel, condition); + g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler, + io_handler_source_finalized); + g_source_attach (handler->source, cs->context); + + cs->ios = g_slist_prepend (cs->ios, handler); + + dbus_watch_set_data (watch, handler, io_handler_watch_freed); + g_io_channel_unref (channel); +} + +static void +connection_setup_remove_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + IOHandler *handler; + + handler = dbus_watch_get_data (watch); + + if (handler == NULL || handler->cs != cs) + return; + + io_handler_destroy_source (handler); +} + +static void +timeout_handler_source_finalized (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->timeout) + dbus_timeout_set_data (handler->timeout, NULL, NULL); + + g_free (handler); +} + +static void +timeout_handler_destroy_source (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +timeout_handler_timeout_freed (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + handler->timeout = NULL; + + timeout_handler_destroy_source (handler); +} + +static gboolean +timeout_handler_dispatch (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + dbus_timeout_handle (handler->timeout); + + return TRUE; +} + +static void +connection_setup_add_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + if (!dbus_timeout_get_enabled (timeout)) + return; + + handler = g_new0 (TimeoutHandler, 1); + handler->cs = cs; + handler->timeout = timeout; + + handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout)); + g_source_set_callback (handler->source, timeout_handler_dispatch, handler, + timeout_handler_source_finalized); + g_source_attach (handler->source, handler->cs->context); + + cs->timeouts = g_slist_prepend (cs->timeouts, handler); + + dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed); +} + +static void +connection_setup_remove_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + handler = dbus_timeout_get_data (timeout); + + if (handler == NULL) + return; + + timeout_handler_destroy_source (handler); +} + +static void +connection_setup_free (ConnectionSetup *cs) +{ + while (cs->ios) + io_handler_destroy_source (cs->ios->data); + + while (cs->timeouts) + timeout_handler_destroy_source (cs->timeouts->data); + + if (cs->message_queue_source) + { + GSource *source; + + source = cs->message_queue_source; + cs->message_queue_source = NULL; + + g_source_destroy (source); + g_source_unref (source); + } + + g_main_context_unref (cs->context); + g_free (cs); +} + +static dbus_bool_t +add_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_add_watch (cs, watch); + + return TRUE; +} + +static void +remove_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_watch (cs, watch); +} + +static void +watch_toggled (DBusWatch *watch, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_watch_get_enabled (watch)) + add_watch (watch, data); + else + remove_watch (watch, data); +} + +static dbus_bool_t +add_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + + connection_setup_add_timeout (cs, timeout); + + return TRUE; +} + +static void +remove_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_timeout (cs, timeout); +} + +static void +timeout_toggled (DBusTimeout *timeout, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_timeout_get_enabled (timeout)) + add_timeout (timeout, data); + else + remove_timeout (timeout, data); +} + +static void +wakeup_main (void *data) +{ + ConnectionSetup *cs = data; + + g_main_context_wakeup (cs->context); +} + + +/* Move to a new context */ +static ConnectionSetup* +connection_setup_new_from_old (GMainContext *context, + ConnectionSetup *old) +{ + ConnectionSetup *cs; + + g_assert (old->context != context); + + cs = connection_setup_new (context, old->connection); + + while (old->ios != NULL) + { + IOHandler *handler = old->ios->data; + + connection_setup_add_watch (cs, handler->watch); + /* The old handler will be removed from old->ios as a side-effect */ + } + + while (old->timeouts != NULL) + { + TimeoutHandler *handler = old->timeouts->data; + + connection_setup_add_timeout (cs, handler->timeout); + } + + return cs; +} + +/** @} */ /* End of GLib bindings internals */ + +/** + * atspi_dbus_connection_setup_with_g_main: (skip) + * @connection: the connection + * @context: the #GMainContext or #NULL for default context + * + * Sets the watch and timeout functions of a #DBusConnection + * to integrate the connection with the GLib main loop. + * Pass in #NULL for the #GMainContext unless you're + * doing something specialized. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +atspi_dbus_connection_setup_with_g_main (DBusConnection *connection, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot); + if (_dbus_gmain_connection_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL); + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, connection); + + if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_connection_set_watch_functions (connection, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_connection_set_timeout_functions (connection, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + dbus_connection_set_wakeup_main_function (connection, + wakeup_main, + cs, NULL); + + return; + + nomem: + g_error ("Not enough memory to set up DBusConnection for use with GLib"); +} + +/** + * atspi_dbus_server_setup_with_g_main: (skip) + * @server: the server + * @context: the #GMainContext or #NULL for default + * + * Sets the watch and timeout functions of a #DBusServer + * to integrate the server with the GLib main loop. + * In most cases the context argument should be #NULL. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +atspi_dbus_server_setup_with_g_main (DBusServer *server, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_server_allocate_data_slot (&server_slot); + if (server_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_server_get_data (server, server_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + if (!dbus_server_set_data (server, server_slot, NULL, NULL)) + goto nomem; + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, NULL); + + if (!dbus_server_set_data (server, server_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_server_set_watch_functions (server, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_server_set_timeout_functions (server, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + return; + + nomem: + g_error ("Not enough memory to set up DBusServer for use with GLib"); +} diff --git a/atspi/atspi-gmain.h b/atspi/atspi-gmain.h new file mode 100644 index 0000000..8e2396c --- /dev/null +++ b/atspi/atspi-gmain.h @@ -0,0 +1,39 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* atspi-gmain.h atspi dbus gmain prototypes + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * This file is based on dbus-gmain.c from dbus-glib with functions renamed + * and unnecessary code removed. + */ + +#ifndef _ATSPI_GMAIN_H +#define _ATSPI_GMAIN_H + +G_BEGIN_DECLS + +void +atspi_dbus_connection_setup_with_g_main (DBusConnection *connection, + GMainContext *context); + +void +atspi_dbus_server_setup_with_g_main (DBusServer *server, + GMainContext *context); + +G_END_DECLS + +#endif diff --git a/atspi/atspi-hyperlink.c b/atspi/atspi-hyperlink.c new file mode 100644 index 0000000..80f8a54 --- /dev/null +++ b/atspi/atspi-hyperlink.c @@ -0,0 +1,216 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +G_DEFINE_TYPE (AtspiHyperlink, atspi_hyperlink, ATSPI_TYPE_OBJECT) + +static void +atspi_hyperlink_init (AtspiHyperlink *hyperlink) +{ +} + +static void +atspi_hyperlink_class_init (AtspiHyperlinkClass *klass) +{ +} + +AtspiHyperlink * +_atspi_hyperlink_new (AtspiApplication *app, const gchar *path) +{ + AtspiHyperlink *hyperlink; + + hyperlink = g_object_new (ATSPI_TYPE_HYPERLINK, NULL); + hyperlink->parent.app = g_object_ref (app); + hyperlink->parent.path = g_strdup (path); + + return hyperlink; +} + +/** + * atspi_hyperlink_get_n_anchors: + * @obj: a pointer to the #AtspiHyperlink object on which to operate. + * + * Gets the total number of anchors which an #AtspiHyperlink implementor has. + * Though typical hyperlinks have only one anchor, client-side image maps and + * other hypertext objects may potentially activate or refer to multiple + * URIs. For each anchor there is a corresponding URI and object. + * + * see: #atspi_hyperlink_get_uri and #atspi_hyperlink_get_object. + * + * Returns: a #gint indicating the number of anchors in this hyperlink. + **/ +gint +atspi_hyperlink_get_n_anchors (AtspiHyperlink *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "NAnchors", error, "i", &retval); + + return retval; +} + +/** + * atspi_hyperlink_get_uri: + * @obj: a pointer to the #AtspiHyperlink implementor on which to operate. + * @i: a (zero-index) integer indicating which hyperlink anchor to query. + * + * Gets the URI associated with a particular hyperlink anchor. + * + * Returns: a UTF-8 string giving the URI of the @ith hyperlink anchor. + **/ +gchar * +atspi_hyperlink_get_uri (AtspiHyperlink *obj, int i, GError **error) +{ + dbus_int32_t d_i = i; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_hyperlink, "GetURI", error, "i=>s", d_i, &retval); + + if (!retval) + retval = g_strdup (""); + + return retval; +} + +/** + * atspi_hyperlink_get_object: + * @obj: a pointer to the #AtspiHyperlink implementor on which to operate. + * @i: a (zero-index) #gint indicating which hyperlink anchor to query. + * + * Gets the object associated with a particular hyperlink anchor, as an + * #AtspiAccessible. + * + * Returns: (transfer full): an #AtspiAccessible that represents the object + * associated with the @ith anchor of the specified #AtspiHyperlink. + **/ +AtspiAccessible* +atspi_hyperlink_get_object (AtspiHyperlink *obj, gint i, GError **error) +{ + dbus_int32_t d_i = i; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_hyperlink, "GetObject", error, "i", d_i); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_hyperlink_get_index_range: + * @obj: a pointer to the #AtspiHyperlink implementor on which to operate. + * + * + * Gets the starting and ending character offsets of the text range + * associated with an #AtspiHyperlink, in its originating #AtspiHypertext. + **/ +AtspiRange * +atspi_hyperlink_get_index_range (AtspiHyperlink *obj, GError **error) +{ + dbus_int32_t d_start_offset = -1; + dbus_int32_t d_end_offset = -1; + AtspiRange *ret = g_new (AtspiRange, 1); + + ret->start_offset = ret->end_offset = -1; + + if (!obj) + return ret; + + _atspi_dbus_call (obj, atspi_interface_hyperlink, "GetIndexRange", error, "=>ii", &d_start_offset, &d_end_offset); + + ret->start_offset = d_start_offset; + ret->end_offset = d_end_offset; + return ret; +} + +/** + * atspi_hyperlink_get_start_index: + * @obj: a pointer to the #AtspiHyperlink implementor on which to operate. + * + * + * Gets the starting character offset of the text range associated with + * an #AtspiHyperlink, in its originating #AtspiHypertext. + **/ +gint +atspi_hyperlink_get_start_index (AtspiHyperlink *obj, GError **error) +{ + dbus_int32_t d_start_offset = -1; + + if (!obj) + return -1; + + _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "StartIndex", + error, "i", &d_start_offset); + + return d_start_offset; +} +/** + * atspi_hyperlink_get_end_index: + * @obj: a pointer to the #AtspiHyperlink implementor on which to operate. + * + * + * Gets the ending character offset of the text range associated with + * an #AtspiHyperlink, in its originating #AtspiHypertext. + **/ +gint +atspi_hyperlink_get_end_index (AtspiHyperlink *obj, GError **error) +{ + dbus_int32_t d_end_offset = -1; + + if (!obj) + return -1; + + _atspi_dbus_get_property (obj, atspi_interface_hyperlink, "EndIndex", error, + "i", &d_end_offset); + + return d_end_offset; +} + + +/** + * atspi_hyperlink_is_valid: + * @obj: a pointer to the #AtspiHyperlink on which to operate. + * + * Tells whether an #AtspiHyperlink object is still valid with respect to its + * originating hypertext object. + * + * Returns: #TRUE if the specified #AtspiHyperlink is still valid with respect + * to its originating #AtspiHypertext object, #FALSE otherwise. + **/ +gboolean +atspi_hyperlink_is_valid (AtspiHyperlink *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_hyperlink, "IsValid", error, "=>b", &retval); + + return retval; +} diff --git a/atspi/atspi-hyperlink.h b/atspi/atspi-hyperlink.h new file mode 100644 index 0000000..86efa7b --- /dev/null +++ b/atspi/atspi-hyperlink.h @@ -0,0 +1,77 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_HYPERLINK_H_ +#define _ATSPI_HYPERLINK_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-text.h" /* for AtspiRange */ +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_HYPERLINK (atspi_hyperlink_get_type ()) +#define ATSPI_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_HYPERLINK, AtspiHyperlink)) +#define ATSPI_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_HYPERLINK, AtspiHyperlinkClass)) +#define ATSPI_IS_HYPERLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_HYPERLINK)) +#define ATSPI_IS_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_HYPERLINK)) +#define ATSPI_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_HYPERLINK, AtspiHyperlinkClass)) + +struct _AtspiHyperlink +{ + AtspiObject parent; +}; + +typedef struct _AtspiHyperlinkClass AtspiHyperlinkClass; +struct _AtspiHyperlinkClass +{ + AtspiObjectClass parent_class; +}; + +GType atspi_hyperlink_get_type (void); + +AtspiHyperlink * +_atspi_hyperlink_new (AtspiApplication *app, const gchar *path); + +gint atspi_hyperlink_get_n_anchors (AtspiHyperlink *obj, GError **error); + +gchar * atspi_hyperlink_get_uri (AtspiHyperlink *obj, int i, GError **error); + +AtspiAccessible* atspi_hyperlink_get_object (AtspiHyperlink *obj, gint i, GError **error); + +AtspiRange * atspi_hyperlink_get_index_range (AtspiHyperlink *obj, GError **error); + +gint atspi_hyperlink_get_start_index (AtspiHyperlink *obj, GError **error); + +gint atspi_hyperlink_get_end_index (AtspiHyperlink *obj, GError **error); + +gboolean atspi_hyperlink_is_valid (AtspiHyperlink *obj, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_HYPERLINK_H_ */ diff --git a/atspi/atspi-hypertext.c b/atspi/atspi-hypertext.c new file mode 100644 index 0000000..ca186ea --- /dev/null +++ b/atspi/atspi-hypertext.c @@ -0,0 +1,124 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_hypertext_get_n_links: + * @obj: a pointer to the #AtspiHypertext implementor on which to operate. + * + * Gets the total number of #AtspiHyperlink objects that an + * #AtspiHypertext implementor has. + * + * Returns: a #gint indicating the number of #AtspiHyperlink objects + * of the #AtspiHypertext implementor, or -1 if + * the number cannot be determined (for example, if the + * #AtspiHypertext object is so large that it is not + * all currently in the memory cache). + **/ +gint +atspi_hypertext_get_n_links (AtspiHypertext *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_hypertext, "GetNLinks", error, "=>i", &retval); + + return retval; +} + +/** + * atspi_hypertext_get_link: + * @obj: a pointer to the #AtspiHypertext implementor on which to operate. + * @link_index: a (zero-index) #gint indicating which hyperlink to query. + * + * Gets the #AtspiHyperlink object at a specified index. + * + * Returns: (nullable) (transfer full): the #AtspiHyperlink object + * specified by @link_index. + **/ +AtspiHyperlink * +atspi_hypertext_get_link (AtspiHypertext *obj, gint link_index, GError **error) +{ + dbus_int32_t d_link_index = link_index; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_hypertext, "GetLink", error, "i", d_link_index); + + return _atspi_dbus_return_hyperlink_from_message (reply); +} + +/** + * atspi_hypertext_get_link_index: + * @obj: a pointer to the #AtspiHypertext implementor on which to operate. + * @character_offset: a #gint specifying the character offset to query. + * + * Gets the index of the #AtspiHyperlink object at a specified + * character offset. + * + * Returns: the linkIndex of the #AtspiHyperlink active at + * character offset @character_offset, or -1 if there is + * no hyperlink at the specified character offset. + **/ +int +atspi_hypertext_get_link_index (AtspiHypertext *obj, + gint character_offset, + GError **error) +{ + dbus_int32_t d_character_offset = character_offset; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_hypertext, "GetLinkIndex", error, "i=>i", d_character_offset, &retval); + + return retval; +} + +static void +atspi_hypertext_base_init (AtspiHypertext *klass) +{ +} + +GType +atspi_hypertext_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiHypertext), + (GBaseInitFunc) atspi_hypertext_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiHypertext", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-hypertext.h b/atspi/atspi-hypertext.h new file mode 100644 index 0000000..bebcf51 --- /dev/null +++ b/atspi/atspi-hypertext.h @@ -0,0 +1,57 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_HYPERTEXT_H_ +#define _ATSPI_HYPERTEXT_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_HYPERTEXT (atspi_hypertext_get_type ()) +#define ATSPI_IS_HYPERTEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_HYPERTEXT) +#define ATSPI_HYPERTEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_HYPERTEXT, AtspiHypertext) +#define ATSPI_HYPERTEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_HYPERTEXT, AtspiHypertext)) + +GType atspi_hypertext_get_type (); + +struct _AtspiHypertext +{ + GTypeInterface parent; +}; + +gint atspi_hypertext_get_n_links (AtspiHypertext *obj, GError **error); + +AtspiHyperlink * atspi_hypertext_get_link (AtspiHypertext *obj, gint link_index, GError **error); + +gint atspi_hypertext_get_link_index (AtspiHypertext *obj, gint character_offset, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_HYPERTEXT_H_ */ diff --git a/atspi/atspi-image.c b/atspi/atspi-image.c new file mode 100644 index 0000000..4f17326 --- /dev/null +++ b/atspi/atspi-image.c @@ -0,0 +1,177 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_image_get_image_description: + * @obj: a pointer to the #AtspiImage implementor on which to operate. + * + * Gets the description of the image displayed in an #AtspiImage object. + * + * Returns: a UTF-8 string describing the image. + **/ +gchar * +atspi_image_get_image_description (AtspiImage *obj, GError **error) +{ + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_get_property (obj, atspi_interface_image, "ImageDescription", error, "s", &retval); + + return retval; +} + +/** + * atspi_image_get_image_size: + * @obj: a pointer to the #AtspiImage to query. + * + * Gets the size of the image displayed in a specified #AtspiImage object. + * + * Returns: a pointer to an #AtspiPoint where x corresponds to + * the image's width and y corresponds to the image's height. + * + **/ +AtspiPoint * +atspi_image_get_image_size (AtspiImage *obj, GError **error) +{ + dbus_int32_t d_w, d_h; + AtspiPoint ret; + + ret.x = ret.y = -1; + if (!obj) + return atspi_point_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_image, "GetImageSize", error, "=>ii", &d_w, &d_h); + ret.x = d_w; + ret.y = d_h; + return atspi_point_copy (&ret); +} + +/** + * atspi_image_get_image_position: + * @obj: a pointer to the #AtspiImage implementor to query. + * @ctype: the desired coordinate system into which to return the results, + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Gets the minimum x and y coordinates of the image displayed in a + * specified #AtspiImage implementor. + * + * Returns: a pointer to an #AtspiPoint where x and y correspond to the + * minimum coordinates of the displayed image. + * + **/ +AtspiPoint * +atspi_image_get_image_position (AtspiImage *obj, + AtspiCoordType ctype, + GError **error) +{ + dbus_int32_t d_x, d_y; + dbus_uint32_t d_ctype = ctype; + AtspiPoint ret; + + ret.x = ret.y = 0; + + if (!obj) + return atspi_point_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_image, "GetImagePosition", error, "u=>ii", d_ctype, &d_x, &d_y); + + ret.x = d_x; + ret.y = d_y; + return atspi_point_copy (&ret); +} + +/** + * atspi_image_get_image_extents: + * @obj: a pointer to the #AtspiImage implementor to query. + * @ctype: the desired coordinate system into which to return the results, + * (e.g. ATSPI_COORD_TYPE_WINDOW, ATSPI_COORD_TYPE_SCREEN). + * + * Gets the bounding box of the image displayed in a + * specified #AtspiImage implementor. + * + * Returns: a pointer to an #AtspiRect corresponding to the image's bounding box. The minimum x and y coordinates, + * width, and height are specified. + **/ +AtspiRect * +atspi_image_get_image_extents (AtspiImage *obj, + AtspiCoordType ctype, + GError **error) +{ + dbus_uint32_t d_ctype = ctype; + AtspiRect bbox; + + bbox.x = bbox.y = bbox.width = bbox.height = -1; + g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox)); + + _atspi_dbus_call (obj, atspi_interface_image, "GetImageExtents", error, "u=>(iiii)", d_ctype, &bbox); + + return atspi_rect_copy (&bbox); +} + +/** + * atspi_image_get_image_locale: + * @obj: a pointer to the #AtspiImage to query. + * + * Gets the locale associated with an image and its textual representation. + * + * Returns: A POSIX LC_MESSAGES-style locale value for image description and text. + **/ +gchar * +atspi_image_get_image_locale (AtspiImage *obj, GError **error) +{ + gchar *retval = NULL; + + g_return_val_if_fail (obj != NULL, g_strdup ("C")); + + _atspi_dbus_get_property (obj, atspi_interface_image, "ImageLocale", error, "s", &retval); + + return retval; +} + +static void +atspi_image_base_init (AtspiImage *klass) +{ +} + +GType +atspi_image_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiImage), + (GBaseInitFunc) atspi_image_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiImage", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-image.h b/atspi/atspi-image.h new file mode 100644 index 0000000..3fa40ef --- /dev/null +++ b/atspi/atspi-image.h @@ -0,0 +1,61 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_IMAGE_H_ +#define _ATSPI_IMAGE_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_IMAGE (atspi_image_get_type ()) +#define ATSPI_IS_IMAGE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_IMAGE) +#define ATSPI_IMAGE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_IMAGE, AtspiImage) +#define ATSPI_IMAGE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_IMAGE, AtspiImage)) + +GType atspi_image_get_type (); + +struct _AtspiImage +{ + GTypeInterface parent; +}; + +gchar * atspi_image_get_image_description (AtspiImage *obj, GError **error); + +AtspiPoint * atspi_image_get_image_size (AtspiImage *obj, GError **error); + +AtspiPoint * atspi_image_get_image_position (AtspiImage *obj, AtspiCoordType ctype, GError **error); + +AtspiRect * atspi_image_get_image_extents (AtspiImage *obj, AtspiCoordType ctype, GError **error); + +gchar * atspi_image_get_image_locale (AtspiImage *obj, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_IMAGE_H_ */ diff --git a/atspi/atspi-matchrule-private.h b/atspi/atspi-matchrule-private.h new file mode 100644 index 0000000..e55c2fa --- /dev/null +++ b/atspi/atspi-matchrule-private.h @@ -0,0 +1,41 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_MATCH_RULE_PRIVATE_H_ +#define _ATSPI_MATCH_RULE_PRIVATE_H_ + +#include "glib-object.h" + +#include "atspi-matchrule.h" +#include "dbus/dbus.h" + +G_BEGIN_DECLS + +gboolean +_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter); + +G_END_DECLS + +#endif /* _ATSPI_MATCH_RULE_PRIVATE_H_ */ diff --git a/atspi/atspi-matchrule.c b/atspi/atspi-matchrule.c new file mode 100644 index 0000000..e995459 --- /dev/null +++ b/atspi/atspi-matchrule.c @@ -0,0 +1,269 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +G_DEFINE_TYPE (AtspiMatchRule, atspi_match_rule, G_TYPE_OBJECT) + +static void +atspi_match_rule_init (AtspiMatchRule *match_rule) +{ +} + +static void +atspi_match_rule_dispose (GObject *object) +{ + AtspiMatchRule *rule = ATSPI_MATCH_RULE (object); + + if (rule->states) + { + g_object_unref (rule->states); + rule->states = NULL; + } + + if (rule->attributes) + { + g_hash_table_unref (rule->attributes); + rule->attributes = NULL; + } + + G_OBJECT_CLASS (atspi_match_rule_parent_class)->dispose (object); +} + +static void +atspi_match_rule_finalize (GObject *object) +{ + AtspiMatchRule *rule = ATSPI_MATCH_RULE (object); + gint i; + + if (rule->interfaces) + { + for (i = 0; i < rule->interfaces->len; i++) + g_free (g_array_index (rule->interfaces, gchar *, i)); + g_array_free (rule->interfaces, TRUE); + } + + if (rule->attributes) + g_hash_table_unref (rule->attributes); + + G_OBJECT_CLASS (atspi_match_rule_parent_class)->finalize (object); +} + +static void +atspi_match_rule_class_init (AtspiMatchRuleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = atspi_match_rule_dispose; + object_class->finalize = atspi_match_rule_finalize; +} + +/** + * atspi_match_rule_new: + * @states: An #AtspiStateSet specifying the states to match or NULL if none. + * @statematchtype: An #AtspiCollectionMatchType specifying how to interpret + * @states. + * @attributes: (element-type gchar* gchar*): A #GHashTable specifying + * attributes to match. To specify multiple attribute values, + * separate each value with a :: If an attribute value contains a :, + * then it can be escaped by preceding it with a \. A backslash can + * likewise be escaped by inserting a double backslash. + * @attributematchtype: An #AtspiCollectionMatchType specifying how to + * interpret @attributes. + * @interfaces: (element-type gchar*): An array of interfaces to match, or + * NULL if not applicable. Interface names should be specified + * by their DBus names (org.a11y.Atspi.Accessible, + * org.a11y.Atspi.Component, etc). + * @interfacematchtype: An #AtspiCollectionMatchType specifying how to + * interpret @interfaces. + * @roles: (element-type AtspiRole): A #GArray of roles to match, or NULL if + * not applicable. + * @rolematchtype: An #AtspiCollectionMatchType specifying how to + * interpret @roles. + * @invert: if #TRUE, the match rule should be denied (inverted); if #FALSE, + * it should not. For example, if the match rule defines that a match is + * an object of ROLE_HEADING which has STATE_FOCUSABLE and a click action, + * inverting it would match all objects that are not of ROLE_HEADING, + * focusable and clickable at the same time. + * + * Creates a new #AtspiMatchRule with specified @states, @attributes, + * @interfaces, and @roles. + * + * Returns: (transfer full): A new #AtspiMatchRule. + **/ +AtspiMatchRule * +atspi_match_rule_new (AtspiStateSet *states, + AtspiCollectionMatchType statematchtype, + GHashTable *attributes, + AtspiCollectionMatchType attributematchtype, + GArray *roles, + AtspiCollectionMatchType rolematchtype, + GArray *interfaces, + AtspiCollectionMatchType interfacematchtype, + gboolean invert) +{ + AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL); + int i; + + if (states) + rule->states = g_object_ref (states); + rule->statematchtype = statematchtype; + + if (attributes) + { + GHashTableIter hash_table_iter; + gchar *key, *value; + rule->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + g_hash_table_iter_init (&hash_table_iter, attributes); + while (g_hash_table_iter_next (&hash_table_iter, (gpointer *)&key, + (gpointer *)&value)) + g_hash_table_insert (rule->attributes, g_strdup (key), g_strdup (value)); + } else + rule->attributes = NULL; + rule->attributematchtype = attributematchtype; + + if (interfaces) + { + rule->interfaces = g_array_new (TRUE, TRUE, sizeof (gchar *)); + for (i = 0; i < interfaces->len; i++) + { + gchar *val = g_strdup (g_array_index (interfaces, gchar *, i)); + rule->interfaces = g_array_append_val (rule->interfaces, val); + } + } + rule->interfacematchtype = interfacematchtype; + + if (roles) + { + for (i = 0; i < roles->len; i++) + { + AtspiRole role = g_array_index (roles, AtspiRole, i); + if (role < 128) + rule->roles [role / 32] |= (1 << (role % 32)); + else + g_warning ("Atspi: unexpected role %d\n", role); + } + } + else + rule->roles [0] = rule->roles [1] = 0; + rule->rolematchtype = rolematchtype; + + rule->invert = invert; + + return rule; +} + +static void +append_entry (gpointer key, gpointer val, gpointer data) +{ + DBusMessageIter *iter = data; + DBusMessageIter iter_entry; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, + &iter_entry)) + return; + dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &key); + dbus_message_iter_append_basic (&iter_entry, DBUS_TYPE_STRING, &val); + dbus_message_iter_close_container (iter, &iter_entry); +} + +gboolean +_atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter) +{ + DBusMessageIter iter_struct, iter_array, iter_dict; + dbus_int32_t states [2]; + dbus_int32_t d_statematchtype = rule->statematchtype; + dbus_int32_t d_attributematchtype = rule->attributematchtype; + dbus_int32_t d_interfacematchtype = rule->interfacematchtype; + dbus_uint32_t d_rolematchtype = rule->rolematchtype; + dbus_bool_t d_invert = rule->invert; + gint i; + dbus_int32_t d_role; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct)) + return FALSE; + + /* states */ + if (rule->states) + { + states [0] = rule->states->states & 0xffffffff; + states [1] = rule->states->states >> 32; + } + else + { + states [0] = states [1] = 0; + } + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", &iter_array); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [0]); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &states [1]); + dbus_message_iter_close_container (&iter_struct, &iter_array); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_statematchtype); + + /* attributes */ + if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}", + &iter_dict)) + return FALSE; + if (rule->attributes) + g_hash_table_foreach (rule->attributes, append_entry, &iter_dict); + dbus_message_iter_close_container (&iter_struct, &iter_dict); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype); + + if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "i", + &iter_array)) + return FALSE; + d_role = rule->roles [0]; + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role); + d_role = rule->roles [1]; + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role); + d_role = rule->roles [2]; + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role); + d_role = rule->roles [3]; + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_INT32, &d_role); + dbus_message_iter_close_container (&iter_struct, &iter_array); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, + &d_rolematchtype); + + /* interfaces */ + if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", + &iter_array)) + return FALSE; + if (rule->interfaces) + { + for (i = 0; i < rule->interfaces->len; i++) + { + char *val = g_array_index (rule->interfaces, gchar *, i); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &val); + } + } + dbus_message_iter_close_container (&iter_struct, &iter_array); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_interfacematchtype); + + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &d_invert); + + dbus_message_iter_close_container (iter, &iter_struct); + return TRUE; +} diff --git a/atspi/atspi-matchrule.h b/atspi/atspi-matchrule.h new file mode 100644 index 0000000..0a006d0 --- /dev/null +++ b/atspi/atspi-matchrule.h @@ -0,0 +1,80 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_MATCH_RULE_H_ +#define _ATSPI_MATCH_RULE_H_ + +#include "glib-object.h" + +#include "atspi-stateset.h" +#include "atspi-constants.h" +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_MATCH_RULE (atspi_match_rule_get_type ()) +#define ATSPI_MATCH_RULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_MATCH_RULE, AtspiMatchRule)) +#define ATSPI_MATCH_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_MATCH_RULE, AtspiMatchRuleClass)) +#define ATSPI_IS_MATCH_RULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_MATCH_RULE)) +#define ATSPI_IS_MATCH_RULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_MATCH_RULE)) +#define ATSPI_MATCH_RULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_MATCH_RULE, AtspiMatchRuleClass)) + +typedef struct _AtspiMatchRule AtspiMatchRule; +struct _AtspiMatchRule +{ + GObject parent; + AtspiStateSet *states; + AtspiCollectionMatchType statematchtype; + GHashTable *attributes; + AtspiCollectionMatchType attributematchtype; + GArray *interfaces; + AtspiCollectionMatchType interfacematchtype; + gint roles [4]; + AtspiCollectionMatchType rolematchtype; + gboolean invert; +}; + +typedef struct _AtspiMatchRuleClass AtspiMatchRuleClass; +struct _AtspiMatchRuleClass +{ + GObjectClass parent_class; +}; + +GType atspi_match_rule_get_type (); + +AtspiMatchRule * +atspi_match_rule_new (AtspiStateSet *states, + AtspiCollectionMatchType statematchtype, + GHashTable *attributes, + AtspiCollectionMatchType attributematchtype, + GArray *roles, + AtspiCollectionMatchType rolematchtype, + GArray *interfaces, + AtspiCollectionMatchType interfacematchtype, + gboolean invert); + +G_END_DECLS + +#endif /* _ATSPI_MATCH_RULE_H_ */ diff --git a/atspi/atspi-misc-private.h b/atspi/atspi-misc-private.h new file mode 100644 index 0000000..fe5ca56 --- /dev/null +++ b/atspi/atspi-misc-private.h @@ -0,0 +1,171 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_MISC_PRIVATE_H_ +#define _ATSPI_MISC_PRIVATE_H_ + +/* Private internal implementation details of at-spi. */ + +#include + +#include "atspi.h" + +#include "dbus/dbus.h" + +#include "dbind/dbind.h" + +G_BEGIN_DECLS + +typedef struct _AtspiReference AtspiReference; +struct _AtspiReference +{ + char *name; + char *path; +}; + +/* externs */ +extern const char *atspi_path_dec; +extern const char *atspi_path_registry; +extern const char *atspi_path_root; +extern const char *atspi_bus_registry; +extern const char *atspi_interface_accessible; +extern const char *atspi_interface_action; +extern const char *atspi_interface_application; +extern const char *atspi_interface_collection; +extern const char *atspi_interface_component; +extern const char *atspi_interface_dec; +extern const char *atspi_interface_device_event_listener; +extern const char *atspi_interface_document; +extern const char *atspi_interface_editable_text; +extern const char *atspi_interface_hyperlink; +extern const char *atspi_interface_hypertext; +extern const char *atspi_interface_image; +extern const char *atspi_interface_registry; +extern const char *atspi_interface_selection; +extern const char *atspi_interface_table; +extern const char *atspi_interface_table_cell; +extern const char *atspi_interface_text; +extern const char *atspi_interface_cache; +extern const char *atspi_interface_value; + +/* function prototypes */ +gint _atspi_get_iface_num (const char *iface); + +DBusConnection * _atspi_bus (); + +AtspiAccessible * _atspi_ref_accessible (const char *app, const char *path); + +AtspiAccessible * +_atspi_dbus_return_accessible_from_message (DBusMessage *message); + +AtspiAccessible * +_atspi_dbus_return_accessible_from_iter (DBusMessageIter *iter); + +AtspiHyperlink * +_atspi_dbus_return_hyperlink_from_message (DBusMessage *message); + +AtspiHyperlink * +_atspi_dbus_return_hyperlink_from_iter (DBusMessageIter *iter); + +dbus_bool_t _atspi_dbus_call (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...); + +DBusMessage *_atspi_dbus_call_partial (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...); + +DBusMessage *_atspi_dbus_call_partial_va (gpointer obj, const char *interface, const char *method, GError **error, const char *type, va_list args); + +dbus_bool_t _atspi_dbus_get_property (gpointer obj, const char *interface, const char *name, GError **error, const char *type, void *data); + +DBusMessage * _atspi_dbus_send_with_reply_and_block (DBusMessage *message, GError **error); + +GHashTable *_atspi_dbus_return_hash_from_message (DBusMessage *message); + +GHashTable *_atspi_dbus_hash_from_iter (DBusMessageIter *iter); + +GArray *_atspi_dbus_return_attribute_array_from_message (DBusMessage *message); + +GArray *_atspi_dbus_attribute_array_from_iter (DBusMessageIter *iter); + +void _atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter); + +void _atspi_dbus_set_state (AtspiAccessible *accessible, DBusMessageIter *iter); + +#define _ATSPI_DBUS_CHECK_SIG(message, type, error, ret) \ + if (!message) \ + return (ret); \ + if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) \ + { \ + const char *err; \ + dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &err, DBUS_TYPE_INVALID); \ + if (err) \ + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err); \ + dbus_message_unref (message); \ + return ret; \ + } \ + if (strcmp (dbus_message_get_signature (message), type) != 0) \ + { \ + g_warning ("at-spi: Expected message signature %s but got %s at %s line %d", type, dbus_message_get_signature (message), __FILE__, __LINE__); \ + dbus_message_unref (message); \ + return (ret); \ + } + + +/** + * ATSPI_ERROR: + * + * Error domain for AT-SPI IPC failures. Errors in this domain will + * be from the #ATSPIAtspiError enumeration. See #GError for information on + * error domains. + */ +#define ATSPI_ERROR _atspi_error_quark() +GQuark _atspi_error_quark (void); + +/** + * AtspiError: + * @ATSPI_APPLICATION_NO_LONGER_EXISTS: The application has quit. + */ +typedef enum +{ + ATSPI_ERROR_APPLICATION_GONE, + ATSPI_ERROR_IPC, + ATSPI_ERROR_SYNC_NOT_ALLOWED, +} AtspiError; + +extern GMainLoop *atspi_main_loop; +extern gboolean atspi_no_cache; + +GHashTable *_atspi_get_live_refs (); + +gchar *_atspi_name_compat (gchar *in); + +GHashTable *_atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter); + +gboolean _atspi_get_allow_sync (); + +gboolean _atspi_set_allow_sync (gboolean val); + +void _atspi_set_error_no_sync (GError **error); +G_END_DECLS + +#endif /* _ATSPI_MISC_PRIVATE_H_ */ diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c new file mode 100644 index 0000000..eebbed4 --- /dev/null +++ b/atspi/atspi-misc.c @@ -0,0 +1,1851 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +/* + * + * Basic SPI initialization and event loop function prototypes + * + */ + +#include "atspi-private.h" +#ifdef HAVE_X11 +#include "X11/Xlib.h" +#endif +#include "atspi-gmain.h" +#include +#include + +static void handle_get_items (DBusPendingCall *pending, void *user_data); + +static DBusConnection *bus = NULL; +static GHashTable *live_refs = NULL; +static gint method_call_timeout = 800; +static gint app_startup_time = 15000; +static gboolean allow_sync = TRUE; + +GMainLoop *atspi_main_loop; +GMainContext *atspi_main_context; +gboolean atspi_no_cache; + +const char *atspi_path_dec = ATSPI_DBUS_PATH_DEC; +const char *atspi_path_registry = ATSPI_DBUS_PATH_REGISTRY; +const char *atspi_path_root = ATSPI_DBUS_PATH_ROOT; +const char *atspi_bus_registry = ATSPI_DBUS_NAME_REGISTRY; +const char *atspi_interface_accessible = ATSPI_DBUS_INTERFACE_ACCESSIBLE; +const char *atspi_interface_action = ATSPI_DBUS_INTERFACE_ACTION; +const char *atspi_interface_application = ATSPI_DBUS_INTERFACE_APPLICATION; +const char *atspi_interface_collection = ATSPI_DBUS_INTERFACE_COLLECTION; +const char *atspi_interface_component = ATSPI_DBUS_INTERFACE_COMPONENT; +const char *atspi_interface_dec = ATSPI_DBUS_INTERFACE_DEC; +const char *atspi_interface_device_event_listener = ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER; +const char *atspi_interface_document = ATSPI_DBUS_INTERFACE_DOCUMENT; +const char *atspi_interface_editable_text = ATSPI_DBUS_INTERFACE_EDITABLE_TEXT; +const char *atspi_interface_event_object = ATSPI_DBUS_INTERFACE_EVENT_OBJECT; +const char *atspi_interface_hyperlink = ATSPI_DBUS_INTERFACE_HYPERLINK; +const char *atspi_interface_hypertext = ATSPI_DBUS_INTERFACE_HYPERTEXT; +const char *atspi_interface_image = ATSPI_DBUS_INTERFACE_IMAGE; +const char *atspi_interface_registry = ATSPI_DBUS_INTERFACE_REGISTRY; +const char *atspi_interface_selection = ATSPI_DBUS_INTERFACE_SELECTION; +const char *atspi_interface_table = ATSPI_DBUS_INTERFACE_TABLE; +const char *atspi_interface_table_cell = ATSPI_DBUS_INTERFACE_TABLE_CELL; +const char *atspi_interface_text = ATSPI_DBUS_INTERFACE_TEXT; +const char *atspi_interface_cache = ATSPI_DBUS_INTERFACE_CACHE; +const char *atspi_interface_value = ATSPI_DBUS_INTERFACE_VALUE; + +static const char *interfaces[] = +{ + ATSPI_DBUS_INTERFACE_ACCESSIBLE, + ATSPI_DBUS_INTERFACE_ACTION, + ATSPI_DBUS_INTERFACE_APPLICATION, + ATSPI_DBUS_INTERFACE_COLLECTION, + ATSPI_DBUS_INTERFACE_COMPONENT, + ATSPI_DBUS_INTERFACE_DOCUMENT, + ATSPI_DBUS_INTERFACE_EDITABLE_TEXT, + ATSPI_DBUS_INTERFACE_HYPERLINK, + ATSPI_DBUS_INTERFACE_HYPERTEXT, + ATSPI_DBUS_INTERFACE_IMAGE, + "org.a11y.atspi.LoginHelper", + ATSPI_DBUS_INTERFACE_SELECTION, + ATSPI_DBUS_INTERFACE_TABLE, + ATSPI_DBUS_INTERFACE_TABLE_CELL, + ATSPI_DBUS_INTERFACE_TEXT, + ATSPI_DBUS_INTERFACE_VALUE, + NULL +}; + +gint +_atspi_get_iface_num (const char *iface) +{ + /* TODO: Use a binary search or hash to improve performance */ + int i; + + for (i = 0; interfaces[i]; i++) + { + if (!strcmp(iface, interfaces[i])) return i; + } + return -1; +} + +GHashTable * +_atspi_get_live_refs (void) +{ + if (!live_refs) + { + live_refs = g_hash_table_new (g_direct_hash, g_direct_equal); + } + return live_refs; +} + +/* TODO: Add an application parameter */ +DBusConnection * +_atspi_bus () +{ + if (!bus) + atspi_init (); + if (!bus) + g_error ("AT-SPI: Couldn't connect to accessibility bus. Is at-spi-bus-launcher running?"); + return bus; +} + +#define APP_IS_REGISTRY(app) (!strcmp (app->bus_name, atspi_bus_registry)) + +static AtspiAccessible *desktop; + +static void +cleanup () +{ + GHashTable *refs; + gint i; + + refs = live_refs; + live_refs = NULL; + if (refs) + { + g_hash_table_destroy (refs); + } + + if (bus) + { + dbus_connection_close (bus); + dbus_connection_unref (bus); + bus = NULL; + } + + if (!desktop) + return; + + /* TODO: Do we need this code, or should we just dispose the desktop? */ + for (i = desktop->children->len - 1; i >= 0; i--) + { + AtspiAccessible *child = g_ptr_array_index (desktop->children, i); + g_object_run_dispose (G_OBJECT (child->parent.app)); + g_object_run_dispose (G_OBJECT (child)); + } + + g_object_run_dispose (G_OBJECT (desktop->parent.app)); + g_object_unref (desktop); + desktop = NULL; +} + +static gboolean atspi_inited = FALSE; + +static GHashTable *app_hash = NULL; + +static void +handle_get_bus_address (DBusPendingCall *pending, void *user_data) +{ + AtspiApplication *app = user_data; + DBusMessage *reply = dbus_pending_call_steal_reply (pending); + DBusMessage *message; + const char *address; + DBusPendingCall *new_pending; + + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) + { + if (dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &address, + DBUS_TYPE_INVALID) && address [0]) + { + DBusError error; + DBusConnection *bus; + + dbus_error_init (&error); + bus = dbus_connection_open_private (address, &error); + if (bus) + { + if (app->bus) + { + dbus_connection_unref (app->bus); + } + app->bus = bus; + atspi_dbus_connection_setup_with_g_main(bus, g_main_context_default()); + } + else + { + if (!strcmp (error.name, DBUS_ERROR_FILE_NOT_FOUND)) + g_warning ("Unable to open bus connection: %s", error.message); + dbus_error_free (&error); + } + } + } + dbus_message_unref (reply); + dbus_pending_call_unref (pending); + + if (!app->bus) + return; /* application has gone away / been disposed */ + + message = dbus_message_new_method_call (app->bus_name, + "/org/a11y/atspi/cache", + atspi_interface_cache, "GetItems"); + + dbus_connection_send_with_reply (app->bus, message, &new_pending, 2000); + dbus_message_unref (message); + if (!new_pending) + return; + dbus_pending_call_set_notify (new_pending, handle_get_items, app, NULL); +} + +static AtspiApplication * +get_application (const char *bus_name) +{ + AtspiApplication *app = NULL; + char *bus_name_dup; + DBusMessage *message; + DBusPendingCall *pending = NULL; + + if (!app_hash) + { + app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_object_unref); + if (!app_hash) return NULL; + } + app = g_hash_table_lookup (app_hash, bus_name); + if (app) return app; + bus_name_dup = g_strdup (bus_name); + if (!bus_name_dup) return NULL; + // TODO: change below to something that will send state-change:defunct notification if necessary */ + app = _atspi_application_new (bus_name); + app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + app->bus = dbus_connection_ref (_atspi_bus ()); + gettimeofday (&app->time_added, NULL); + app->cache = ATSPI_CACHE_UNDEFINED; + g_hash_table_insert (app_hash, bus_name_dup, app); + message = dbus_message_new_method_call (bus_name, atspi_path_root, + atspi_interface_application, "GetApplicationBusAddress"); + + dbus_connection_send_with_reply (app->bus, message, &pending, 2000); + dbus_message_unref (message); + if (!pending) + { + g_hash_table_remove (app_hash, bus_name_dup); + return NULL; + } + dbus_pending_call_set_notify (pending, handle_get_bus_address, app, NULL); + return app; +} + +static AtspiAccessible * +ref_accessible (const char *app_name, const char *path) +{ + AtspiApplication *app; + AtspiAccessible *a; + + if (!strcmp (path, ATSPI_DBUS_PATH_NULL)) + return NULL; + + app = get_application (app_name); + + if (!strcmp (path, "/org/a11y/atspi/accessible/root")) + { + if (!app->root) + { + app->root = _atspi_accessible_new (app, atspi_path_root); + app->root->accessible_parent = atspi_get_desktop (0); + g_ptr_array_add (app->root->accessible_parent->children, g_object_ref (app->root)); + } + return g_object_ref (app->root); + } + + a = g_hash_table_lookup (app->hash, path); + if (a) + { + return g_object_ref (a); + } + a = _atspi_accessible_new (app, path); + if (!a) + return NULL; + g_hash_table_insert (app->hash, g_strdup (a->parent.path), g_object_ref (a)); + return a; +} + +static AtspiHyperlink * +ref_hyperlink (const char *app_name, const char *path) +{ + AtspiApplication *app = get_application (app_name); + AtspiHyperlink *hyperlink; + + if (!strcmp (path, ATSPI_DBUS_PATH_NULL)) + return NULL; + + hyperlink = g_hash_table_lookup (app->hash, path); + if (hyperlink) + { + return g_object_ref (hyperlink); + } + hyperlink = _atspi_hyperlink_new (app, path); + g_hash_table_insert (app->hash, g_strdup (hyperlink->parent.path), hyperlink); + /* TODO: This should be a weak ref */ + g_object_ref (hyperlink); /* for the hash */ + return hyperlink; +} + +typedef struct +{ + char *path; + char *parent; + GArray *children; + GArray *interfaces; + char *name; + dbus_uint32_t role; + char *description; + GArray *state_bitflags; +} CACHE_ADDITION; + +static DBusHandlerResult +handle_remove_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const char *sender = dbus_message_get_sender (message); + AtspiApplication *app; + const char *path; + DBusMessageIter iter, iter_struct; + const char *signature = dbus_message_get_signature (message); + AtspiAccessible *a; + + if (strcmp (signature, "(so)") != 0) + { + g_warning ("AT-SPI: Unknown signature %s for RemoveAccessible", signature); + return DBUS_HANDLER_RESULT_HANDLED; + } + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &sender); + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &path); + app = get_application (sender); + a = ref_accessible (sender, path); + if (!a) + return DBUS_HANDLER_RESULT_HANDLED; + g_object_run_dispose (G_OBJECT (a)); + g_hash_table_remove (app->hash, a->parent.path); + g_object_unref (a); /* unref our own ref */ + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const char *name, *new, *old; + static gboolean registry_lost = FALSE; + + if (!dbus_message_get_args (message, NULL, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID)) + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (name, "org.a11y.atspi.Registry")) + { + if (registry_lost && !old[0]) + { + _atspi_reregister_event_listeners (); + _atspi_reregister_device_listeners (); + registry_lost = FALSE; + } + else if (!new[0]) + registry_lost = TRUE; + } + else if (app_hash) + { + AtspiApplication *app = g_hash_table_lookup (app_hash, old); + if (app && !strcmp (app->bus_name, old)) + g_object_run_dispose (G_OBJECT (app)); + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +static gboolean +add_app_to_desktop (AtspiAccessible *a, const char *bus_name) +{ + AtspiAccessible *obj = ref_accessible (bus_name, atspi_path_root); + /* The app will be added to the desktop as a side-effect of calling + * ref_accessible */ + g_object_unref (obj); + return (obj != NULL); +} + +void +get_reference_from_iter (DBusMessageIter *iter, const char **app_name, const char **path) +{ + DBusMessageIter iter_struct; + + dbus_message_iter_recurse (iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, app_name); + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, path); + dbus_message_iter_next (iter); +} + +static void +add_accessible_from_iter (DBusMessageIter *iter) +{ + DBusMessageIter iter_struct, iter_array; + const char *app_name, *path; + AtspiAccessible *accessible; + const char *name, *description; + dbus_uint32_t role; + gboolean children_cached = FALSE; + dbus_int32_t count, index; + + dbus_message_iter_recurse (iter, &iter_struct); + + /* get accessible */ + get_reference_from_iter (&iter_struct, &app_name, &path); + accessible = ref_accessible (app_name, path); + if (!accessible) + return; + + /* Get application: TODO */ + dbus_message_iter_next (&iter_struct); + + /* get parent */ + get_reference_from_iter (&iter_struct, &app_name, &path); + if (accessible->accessible_parent) + g_object_unref (accessible->accessible_parent); + accessible->accessible_parent = ref_accessible (app_name, path); + + if (dbus_message_iter_get_arg_type (&iter_struct) == 'i') + { + /* Get index in parent */ + dbus_message_iter_get_basic (&iter_struct, &index); + if (index >= 0 && accessible->accessible_parent) + { + if (index >= accessible->accessible_parent->children->len) + g_ptr_array_set_size (accessible->accessible_parent->children, index + 1); + g_ptr_array_index (accessible->accessible_parent->children, index) = g_object_ref (accessible); + } + + /* get child count */ + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &count); + if (count >= 0) + { + g_ptr_array_set_size (accessible->children, count); + children_cached = TRUE; + } + } + else if (dbus_message_iter_get_arg_type (&iter_struct) == 'a') + { + /* It's the old API with a list of children */ + /* TODO: Perhaps remove this code eventually */ + dbus_message_iter_recurse (&iter_struct, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *child; + get_reference_from_iter (&iter_array, &app_name, &path); + child = ref_accessible (app_name, path); + g_ptr_array_remove (accessible->children, child); + g_ptr_array_add (accessible->children, child); + } + children_cached = TRUE; + } + + /* interfaces */ + dbus_message_iter_next (&iter_struct); + _atspi_dbus_set_interfaces (accessible, &iter_struct); + dbus_message_iter_next (&iter_struct); + + /* name */ + if (accessible->name) + g_free (accessible->name); + dbus_message_iter_get_basic (&iter_struct, &name); + accessible->name = g_strdup (name); + dbus_message_iter_next (&iter_struct); + + /* role */ + dbus_message_iter_get_basic (&iter_struct, &role); + accessible->role = role; + dbus_message_iter_next (&iter_struct); + + /* description */ + if (accessible->description) + g_free (accessible->description); + dbus_message_iter_get_basic (&iter_struct, &description); + accessible->description = g_strdup (description); + dbus_message_iter_next (&iter_struct); + + _atspi_dbus_set_state (accessible, &iter_struct); + dbus_message_iter_next (&iter_struct); + + _atspi_accessible_add_cache (accessible, ATSPI_CACHE_NAME | ATSPI_CACHE_ROLE | + ATSPI_CACHE_PARENT | ATSPI_CACHE_DESCRIPTION); + if (!atspi_state_set_contains (accessible->states, + ATSPI_STATE_MANAGES_DESCENDANTS) && + children_cached) + _atspi_accessible_add_cache (accessible, ATSPI_CACHE_CHILDREN); + + /* This is a bit of a hack since the cache holds a ref, so we don't need + * the one provided for us anymore */ + g_object_unref (accessible); +} + +static void +handle_get_items (DBusPendingCall *pending, void *user_data) +{ + DBusMessage *reply = dbus_pending_call_steal_reply (pending); + DBusMessageIter iter, iter_array; + + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + { + const char *sender = dbus_message_get_sender (reply); + const char *error = NULL; + if (!strcmp (dbus_message_get_error_name (reply), + DBUS_ERROR_SERVICE_UNKNOWN)) + { + } + else + { + dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &error, + DBUS_TYPE_INVALID); + g_warning ("AT-SPI: Error in GetItems, sender=%s, error=%s", sender, error); + } + dbus_message_unref (reply); + dbus_pending_call_unref (pending); + return; + } + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + add_accessible_from_iter (&iter_array); + dbus_message_iter_next (&iter_array); + } + dbus_message_unref (reply); + dbus_pending_call_unref (pending); +} + +/* TODO: Do we stil need this function? */ +static AtspiAccessible * +ref_accessible_desktop (AtspiApplication *app) +{ + GError *error; + DBusMessage *message, *reply; + DBusMessageIter iter, iter_array; + gchar *bus_name_dup; + + if (desktop) + { + g_object_ref (desktop); + return desktop; + } + desktop = _atspi_accessible_new (app, atspi_path_root); + if (!desktop) + { + return NULL; + } + g_hash_table_insert (app->hash, g_strdup (desktop->parent.path), + g_object_ref (desktop)); + app->root = g_object_ref (desktop); + desktop->name = g_strdup ("main"); + message = dbus_message_new_method_call (atspi_bus_registry, + atspi_path_root, + atspi_interface_accessible, + "GetChildren"); + if (!message) + return NULL; + error = NULL; + reply = _atspi_dbus_send_with_reply_and_block (message, &error); + if (!reply || strcmp (dbus_message_get_signature (reply), "a(so)") != 0) + { + if (error != NULL) + { + g_warning ("Couldn't get application list: %s", error->message); + g_clear_error (&error); + } + if (reply) + dbus_message_unref (reply); + return NULL; + } + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *app_name, *path; + get_reference_from_iter (&iter_array, &app_name, &path); + add_app_to_desktop (desktop, app_name); + } + + /* Record the alternate name as an alias for org.a11y.atspi.Registry */ + bus_name_dup = g_strdup (dbus_message_get_sender (reply)); + if (bus_name_dup) + g_hash_table_insert (app_hash, bus_name_dup, app); + + dbus_message_unref (reply); + + return g_object_ref (desktop); +} + +AtspiAccessible * +_atspi_ref_accessible (const char *app, const char *path) +{ + AtspiApplication *a = get_application (app); + if (!a) + return NULL; + if ( APP_IS_REGISTRY(a)) + { + if (!a->root) + g_object_unref (ref_accessible_desktop (a)); /* sets a->root */ + return g_object_ref (a->root); + } + return ref_accessible (app, path); +} + +AtspiAccessible * +_atspi_dbus_return_accessible_from_message (DBusMessage *message) +{ + DBusMessageIter iter; + AtspiAccessible *retval = NULL; + const char *signature; + + if (!message) + return NULL; + + signature = dbus_message_get_signature (message); + if (!strcmp (signature, "(so)")) + { + dbus_message_iter_init (message, &iter); + retval = _atspi_dbus_return_accessible_from_iter (&iter); + } + else + { + g_warning ("AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange signature %s", signature); + } + dbus_message_unref (message); + return retval; +} + +AtspiAccessible * +_atspi_dbus_return_accessible_from_iter (DBusMessageIter *iter) +{ + const char *app_name, *path; + + get_reference_from_iter (iter, &app_name, &path); + return ref_accessible (app_name, path); +} + +AtspiHyperlink * +_atspi_dbus_return_hyperlink_from_message (DBusMessage *message) +{ + DBusMessageIter iter; + AtspiHyperlink *retval = NULL; + const char *signature; + + if (!message) + return NULL; + + signature = dbus_message_get_signature (message); + if (!strcmp (signature, "(so)")) + { + dbus_message_iter_init (message, &iter); + retval = _atspi_dbus_return_hyperlink_from_iter (&iter); + } + else + { + g_warning ("AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange signature %s", signature); + } + dbus_message_unref (message); + return retval; +} + +AtspiHyperlink * +_atspi_dbus_return_hyperlink_from_iter (DBusMessageIter *iter) +{ + const char *app_name, *path; + + get_reference_from_iter (iter, &app_name, &path); + return ref_hyperlink (app_name, path); +} + +const char *cache_signal_type = "((so)(so)(so)iiassusau)"; +const char *old_cache_signal_type = "((so)(so)(so)a(so)assusau)"; + +static DBusHandlerResult +handle_add_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *signature = dbus_message_get_signature (message); + + if (strcmp (signature, cache_signal_type) != 0 && + strcmp (signature, old_cache_signal_type) != 0) + { + g_warning ("AT-SPI: AddAccessible with unknown signature %s\n", signature); + return DBUS_HANDLER_RESULT_HANDLED; + } + + dbus_message_iter_init (message, &iter); + add_accessible_from_iter (&iter); + return DBUS_HANDLER_RESULT_HANDLED; +} + +typedef struct +{ + DBusConnection *bus; + DBusMessage *message; + void *data; +} BusDataClosure; + +static GSource *process_deferred_messages_source = NULL; + +static void +process_deferred_message (BusDataClosure *closure) +{ + int type = dbus_message_get_type (closure->message); + const char *interface = dbus_message_get_interface (closure->message); + + if (type == DBUS_MESSAGE_TYPE_SIGNAL && + !strncmp (interface, "org.a11y.atspi.Event.", 21)) + { + _atspi_dbus_handle_event (closure->bus, closure->message, closure->data); + } + if (dbus_message_is_method_call (closure->message, atspi_interface_device_event_listener, "NotifyEvent")) + { + _atspi_dbus_handle_DeviceEvent (closure->bus, + closure->message, closure->data); + } + if (dbus_message_is_signal (closure->message, atspi_interface_cache, "AddAccessible")) + { + handle_add_accessible (closure->bus, closure->message, closure->data); + } + if (dbus_message_is_signal (closure->message, atspi_interface_cache, "RemoveAccessible")) + { + handle_remove_accessible (closure->bus, closure->message, closure->data); + } + if (dbus_message_is_signal (closure->message, "org.freedesktop.DBus", "NameOwnerChanged")) + { + handle_name_owner_changed (closure->bus, closure->message, closure->data); + } +} + +static GQueue *deferred_messages = NULL; + +static gboolean +process_deferred_messages (void) +{ + static int in_process_deferred_messages = 0; + BusDataClosure *closure; + + if (in_process_deferred_messages) + return TRUE; + in_process_deferred_messages = 1; + while ((closure = g_queue_pop_head (deferred_messages))) + { + process_deferred_message (closure); + dbus_message_unref (closure->message); + dbus_connection_unref (closure->bus); + g_free (closure); + } + in_process_deferred_messages = 0; + return FALSE; +} + +static gboolean +process_deferred_messages_callback (gpointer data) +{ + if (process_deferred_messages ()) + return G_SOURCE_CONTINUE; + + process_deferred_messages_source = NULL; + return G_SOURCE_REMOVE; +} + +static DBusHandlerResult +defer_message (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + BusDataClosure *closure = g_new (BusDataClosure, 1); + + closure->bus = dbus_connection_ref (bus); + closure->message = dbus_message_ref (message); + closure->data = user_data; + + g_queue_push_tail (deferred_messages, closure); + + if (process_deferred_messages_source == NULL) + { + process_deferred_messages_source = g_idle_source_new (); + g_source_set_callback (process_deferred_messages_source, + process_deferred_messages_callback, NULL, NULL); + g_source_attach (process_deferred_messages_source, atspi_main_context); + g_source_unref (process_deferred_messages_source); + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusHandlerResult +atspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data) +{ + int type = dbus_message_get_type (message); + const char *interface = dbus_message_get_interface (message); + + if (type == DBUS_MESSAGE_TYPE_SIGNAL && + !strncmp (interface, "org.a11y.atspi.Event.", 21)) + { + return defer_message (bus, message, data); + } + if (dbus_message_is_method_call (message, atspi_interface_device_event_listener, "NotifyEvent")) + { + return defer_message (bus, message, data); + } + if (dbus_message_is_signal (message, atspi_interface_cache, "AddAccessible")) + { + return defer_message (bus, message, data); + } + if (dbus_message_is_signal (message, atspi_interface_cache, "RemoveAccessible")) + { + return defer_message (bus, message, data); + } + if (dbus_message_is_signal (message, "org.freedesktop.DBus", "NameOwnerChanged")) + { + defer_message (bus, message, data); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +/* + * Returns a 'canonicalized' value for DISPLAY, + * with the screen number stripped off if present. + * + * TODO: Avoid having duplicate functions for this here and in at-spi2-atk + */ +static gchar * +spi_display_name (void) +{ + char *canonical_display_name = NULL; + const gchar *display_env = g_getenv ("AT_SPI_DISPLAY"); + + if (!display_env) + { + display_env = g_getenv ("DISPLAY"); + if (!display_env || !display_env[0]) + return NULL; + else + { + gchar *display_p, *screen_p; + canonical_display_name = g_strdup (display_env); + display_p = g_utf8_strrchr (canonical_display_name, -1, ':'); + screen_p = g_utf8_strrchr (canonical_display_name, -1, '.'); + if (screen_p && display_p && (screen_p > display_p)) + { + *screen_p = '\0'; + } + } + } + else + { + canonical_display_name = g_strdup (display_env); + } + + return canonical_display_name; +} + +/** + * atspi_init: + * + * Connects to the accessibility registry and initializes the SPI. + * + * Returns: 0 on success, 1 if already initialized, or an integer error code. + **/ +int +atspi_init (void) +{ + char *match; + const gchar *no_cache; + + if (atspi_inited) + { + return 1; + } + + atspi_inited = TRUE; + + _atspi_get_live_refs(); + + bus = atspi_get_a11y_bus (); + if (!bus) + return 2; + dbus_bus_register (bus, NULL); + atspi_dbus_connection_setup_with_g_main(bus, g_main_context_default()); + dbus_connection_add_filter (bus, atspi_dbus_filter, NULL, NULL); + match = g_strdup_printf ("type='signal',interface='%s',member='AddAccessible'", atspi_interface_cache); + dbus_bus_add_match (bus, match, NULL); + g_free (match); + match = g_strdup_printf ("type='signal',interface='%s',member='RemoveAccessible'", atspi_interface_cache); + dbus_bus_add_match (bus, match, NULL); + g_free (match); + match = g_strdup_printf ("type='signal',interface='%s',member='ChildrenChanged'", atspi_interface_event_object); + dbus_bus_add_match (bus, match, NULL); + g_free (match); + match = g_strdup_printf ("type='signal',interface='%s',member='PropertyChange'", atspi_interface_event_object); + dbus_bus_add_match (bus, match, NULL); + g_free (match); + match = g_strdup_printf ("type='signal',interface='%s',member='StateChanged'", atspi_interface_event_object); + dbus_bus_add_match (bus, match, NULL); + g_free (match); + + dbus_bus_add_match (bus, + "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'", + NULL); + + no_cache = g_getenv ("ATSPI_NO_CACHE"); + if (no_cache && g_strcmp0 (no_cache, "0") != 0) + atspi_no_cache = TRUE; + + deferred_messages = g_queue_new (); + + return 0; +} + +/** + * atspi_is_initialized: + * + * Indicates whether AT-SPI has been initialized. + * + * Returns: %True if initialized; %False otherwise. + */ +gboolean +atspi_is_initialized () +{ + return atspi_inited; +} + +/** + * atspi_event_main: + * + * Starts/enters the main event loop for the AT-SPI services. + * + * NOTE: This method does not return control; it is exited via a call to + * #atspi_event_quit from within an event handler. + * + **/ +void +atspi_event_main (void) +{ + atspi_main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (atspi_main_loop); + atspi_main_loop = NULL; +} + +/** + * atspi_event_quit: + * + * Quits the last main event loop for the AT-SPI services, + * See: #atspi_event_main + **/ +void +atspi_event_quit (void) +{ + g_main_loop_quit (atspi_main_loop); +} + +/** + * atspi_exit: + * + * Disconnects from #AtspiRegistry instances and releases + * any floating resources. Call only once at exit. + * + * Returns: 0 if there were no leaks, otherwise other integer values. + **/ +int +atspi_exit (void) +{ + int leaked; + + if (!atspi_inited) + { + return 0; + } + + atspi_inited = FALSE; + + if (live_refs) + { + leaked = g_hash_table_size (live_refs); + } + else + { + leaked = 0; + } + + cleanup (); + + return leaked; +} + +static GSList *hung_processes; + +static void +remove_hung_process (DBusPendingCall *pending, void *data) +{ + hung_processes = g_slist_remove (hung_processes, data); + g_free (data); + dbus_pending_call_unref (pending); +} + +static void +check_for_hang (DBusMessage *message, DBusError *error, DBusConnection *bus, const char *bus_name) +{ + if (!message && error->name && + !strcmp (error->name, "org.freedesktop.DBus.Error.NoReply")) + { + GSList *l; + DBusMessage *message; + gchar *bus_name_dup; + DBusPendingCall *pending = NULL; + for (l = hung_processes; l; l = l->next) + if (!strcmp (l->data, bus_name)) + return; + message = dbus_message_new_method_call (bus_name, "/", + "org.freedesktop.DBus.Peer", + "Ping"); + if (!message) + return; + dbus_connection_send_with_reply (bus, message, &pending, -1); + dbus_message_unref (message); + if (!pending) + return; + bus_name_dup = g_strdup (bus_name); + hung_processes = g_slist_append (hung_processes, bus_name_dup); + dbus_pending_call_set_notify (pending, remove_hung_process, bus_name_dup, NULL); + } +} + +static gboolean +connection_is_hung (const char *bus_name) +{ + GSList *l; + + for (l = hung_processes; l; l = l->next) + if (!strcmp (l->data, bus_name)) + return TRUE; + return FALSE; +} + +static gboolean +check_app (AtspiApplication *app, GError **error) +{ + if (!app || !app->bus) + { + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE, + _("The application no longer exists")); + return FALSE; + } + + if (atspi_main_loop && connection_is_hung (app->bus_name)) + { + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, + "The process appears to be hung."); + return FALSE; + } + + return TRUE; +} + +static void +set_timeout (AtspiApplication *app) +{ + struct timeval tv; + int diff; + + if (app && app_startup_time > 0) + { + gettimeofday (&tv, NULL); + diff = (tv.tv_sec - app->time_added.tv_sec) * 1000 + (tv.tv_usec - app->time_added.tv_usec) / 1000; + dbind_set_timeout (MAX(method_call_timeout, app_startup_time - diff)); + } + else + dbind_set_timeout (method_call_timeout); +} + +dbus_bool_t +_atspi_dbus_call (gpointer obj, const char *interface, const char *method, GError **error, const char *type, ...) +{ + va_list args; + dbus_bool_t retval; + DBusError err; + AtspiObject *aobj = ATSPI_OBJECT (obj); + + if (!check_app (aobj->app, error)) + return FALSE; + + if (!allow_sync) + { + _atspi_set_error_no_sync (error); + return FALSE; + } + + va_start (args, type); + dbus_error_init (&err); + set_timeout (aobj->app); + retval = dbind_method_call_reentrant_va (aobj->app->bus, aobj->app->bus_name, + aobj->path, interface, method, &err, + type, args); + va_end (args); + check_for_hang (NULL, &err, aobj->app->bus, aobj->app->bus_name); + process_deferred_messages (); + if (dbus_error_is_set (&err)) + { + g_set_error(error, ATSPI_ERROR, ATSPI_ERROR_IPC, "%s", err.message); + dbus_error_free (&err); + } + return retval; +} + +DBusMessage * +_atspi_dbus_call_partial (gpointer obj, + const char *interface, + const char *method, + GError **error, + const char *type, ...) +{ + va_list args; + + va_start (args, type); + return _atspi_dbus_call_partial_va (obj, interface, method, error, type, args); +} + + +DBusMessage * +_atspi_dbus_call_partial_va (gpointer obj, + const char *interface, + const char *method, + GError **error, + const char *type, + va_list args) +{ + AtspiObject *aobj = ATSPI_OBJECT (obj); + DBusError err; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter; + const char *p; + + dbus_error_init (&err); + + if (!check_app (aobj->app, error)) + goto out; + + msg = dbus_message_new_method_call (aobj->app->bus_name, aobj->path, interface, method); + if (!msg) + goto out; + + p = type; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + set_timeout (aobj->app); + reply = dbind_send_and_allow_reentry (aobj->app->bus, msg, &err); + check_for_hang (reply, &err, aobj->app->bus, aobj->app->bus_name); +out: + va_end (args); + if (msg) + dbus_message_unref (msg); + process_deferred_messages (); + if (dbus_error_is_set (&err)) + { + /* TODO: Set gerror */ + dbus_error_free (&err); + } + + if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + { + const char *err_str = NULL; + dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID); + if (err_str) + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err_str); + dbus_message_unref (reply); + return NULL; + } + + return reply; +} + +dbus_bool_t +_atspi_dbus_get_property (gpointer obj, const char *interface, const char *name, GError **error, const char *type, void *data) +{ + DBusMessage *message, *reply; + DBusMessageIter iter, iter_variant; + DBusError err; + dbus_bool_t retval = FALSE; + AtspiObject *aobj = ATSPI_OBJECT (obj); + char expected_type = (type [0] == '(' ? 'r' : type [0]); + + if (!aobj) + return FALSE; + + if (!check_app (aobj->app, error)) + return FALSE; + + if (!allow_sync) + { + _atspi_set_error_no_sync (error); + return FALSE; + } + + message = dbus_message_new_method_call (aobj->app->bus_name, + aobj->path, + "org.freedesktop.DBus.Properties", + "Get"); + if (!message) + { + // TODO: throw exception + return FALSE; + } + dbus_message_append_args (message, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); + dbus_error_init (&err); + set_timeout (aobj->app); + reply = dbind_send_and_allow_reentry (aobj->app->bus, message, &err); + check_for_hang (reply, &err, aobj->app->bus, aobj->app->bus_name); + dbus_message_unref (message); + process_deferred_messages (); + if (!reply) + { + // TODO: throw exception + goto done; + } + + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + { + const char *err_str = NULL; + dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID); + if (err_str) + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err_str); + goto done; + } + + dbus_message_iter_init (reply, &iter); + if (dbus_message_iter_get_arg_type (&iter) != 'v') + { + g_warning ("AT-SPI: expected a variant when fetching %s from interface %s; got %s\n", name, interface, dbus_message_get_signature (reply)); + goto done; + } + dbus_message_iter_recurse (&iter, &iter_variant); + if (dbus_message_iter_get_arg_type (&iter_variant) != expected_type) + { + g_warning ("atspi_dbus_get_property: Wrong type: expected %s, got %c\n", type, dbus_message_iter_get_arg_type (&iter_variant)); + goto done; + } + if (!strcmp (type, "(so)")) + { + *((AtspiAccessible **)data) = _atspi_dbus_return_accessible_from_iter (&iter_variant); + } + else + { + dbus_message_iter_get_basic (&iter_variant, data); + if (type [0] == 's') + *(char **)data = g_strdup (*(char **)data); + } + retval = TRUE; +done: + dbus_error_free (&err); + if (reply) + dbus_message_unref (reply); + return retval; +} + +DBusMessage * +_atspi_dbus_send_with_reply_and_block (DBusMessage *message, GError **error) +{ + DBusMessage *reply; + DBusError err; + AtspiApplication *app; + DBusConnection *bus; + + app = get_application (dbus_message_get_destination (message)); + + if (app && !app->bus) + return NULL; /* will fail anyway; app has been disposed */ + + bus = (app ? app->bus : _atspi_bus()); + dbus_error_init (&err); + set_timeout (app); + reply = dbind_send_and_allow_reentry (bus, message, &err); + process_deferred_messages (); + dbus_message_unref (message); + if (dbus_error_is_set (&err)) + { + if (error) + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_IPC, err.message); + dbus_error_free (&err); + } + return reply; +} + +GHashTable * +_atspi_dbus_return_hash_from_message (DBusMessage *message) +{ + DBusMessageIter iter; + GHashTable *ret; + + if (!message) + return NULL; + + _ATSPI_DBUS_CHECK_SIG (message, "a{ss}", NULL, NULL); + + dbus_message_iter_init (message, &iter); + ret = _atspi_dbus_hash_from_iter (&iter); + dbus_message_unref (message); + return ret; +} + +GHashTable * +_atspi_dbus_hash_from_iter (DBusMessageIter *iter) +{ + GHashTable *hash = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + DBusMessageIter iter_array, iter_dict; + + dbus_message_iter_recurse (iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *name, *value; + dbus_message_iter_recurse (&iter_array, &iter_dict); + dbus_message_iter_get_basic (&iter_dict, &name); + dbus_message_iter_next (&iter_dict); + dbus_message_iter_get_basic (&iter_dict, &value); + g_hash_table_insert (hash, g_strdup (name), g_strdup (value)); + dbus_message_iter_next (&iter_array); + } + return hash; +} + +GArray * +_atspi_dbus_return_attribute_array_from_message (DBusMessage *message) +{ + DBusMessageIter iter; + GArray *ret; + + if (!message) + return NULL; + + _ATSPI_DBUS_CHECK_SIG (message, "a{ss}", NULL, NULL); + + dbus_message_iter_init (message, &iter); + + ret = _atspi_dbus_attribute_array_from_iter (&iter); + dbus_message_unref (message); + return ret; +} + +GArray * +_atspi_dbus_attribute_array_from_iter (DBusMessageIter *iter) +{ + DBusMessageIter iter_array, iter_dict; + GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *)); + + dbus_message_iter_recurse (iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *name, *value; + gchar *str; + dbus_message_iter_recurse (&iter_array, &iter_dict); + dbus_message_iter_get_basic (&iter_dict, &name); + dbus_message_iter_next (&iter_dict); + dbus_message_iter_get_basic (&iter_dict, &value); + str = g_strdup_printf ("%s:%s", name, value); + array = g_array_append_val (array, str); + dbus_message_iter_next (&iter_array);; + } + return array; +} + +void +_atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter) +{ + DBusMessageIter iter_array; + char *iter_sig = dbus_message_iter_get_signature (iter); + + accessible->interfaces = 0; + if (strcmp (iter_sig, "as") != 0) + { + g_warning ("_atspi_dbus_set_interfaces: Passed iterator with invalid signature %s", dbus_message_iter_get_signature (iter)); + dbus_free (iter_sig); + return; + } + dbus_free (iter_sig); + dbus_message_iter_recurse (iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *iface; + gint n; + dbus_message_iter_get_basic (&iter_array, &iface); + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue; + n = _atspi_get_iface_num (iface); + if (n == -1) + { + g_warning ("AT-SPI: Unknown interface %s", iface); + } + else + accessible->interfaces |= (1 << n); + dbus_message_iter_next (&iter_array); + } + _atspi_accessible_add_cache (accessible, ATSPI_CACHE_INTERFACES); +} + +void +_atspi_dbus_set_state (AtspiAccessible *accessible, DBusMessageIter *iter) +{ + DBusMessageIter iter_array; + gint count; + dbus_uint32_t *states; + + dbus_message_iter_recurse (iter, &iter_array); + dbus_message_iter_get_fixed_array (&iter_array, &states, &count); + if (count != 2) + { + g_warning ("AT-SPI: expected 2 values in states array; got %d\n", count); + if (!accessible->states) + accessible->states = _atspi_state_set_new_internal (accessible, 0); + } + else + { + guint64 val = ((guint64)states [1]) << 32; + val += states [0]; + if (!accessible->states) + accessible->states = _atspi_state_set_new_internal (accessible, val); + else + accessible->states->states = val; + } + _atspi_accessible_add_cache (accessible, ATSPI_CACHE_STATES); +} + +GQuark +_atspi_error_quark (void) +{ + return g_quark_from_static_string ("atspi_error"); +} + +/* + * Gets the IOR from the XDisplay. + */ +#ifdef HAVE_X11 +static char * +get_accessibility_bus_address_x11 (void) +{ + Atom AT_SPI_BUS; + Atom actual_type; + Display *bridge_display = NULL; + int actual_format; + char *data; + unsigned char *data_x11 = NULL; + unsigned long nitems; + unsigned long leftover; + char *display_name; + + display_name = spi_display_name (); + if (!display_name) + return NULL; + + bridge_display = XOpenDisplay (display_name); + g_free (display_name); + + if (!bridge_display) + { + g_warning ("Could not open X display"); + return NULL; + } + + AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", False); + XGetWindowProperty (bridge_display, + XDefaultRootWindow (bridge_display), + AT_SPI_BUS, 0L, + (long) BUFSIZ, False, + (Atom) 31, &actual_type, &actual_format, + &nitems, &leftover, &data_x11); + XCloseDisplay (bridge_display); + + data = g_strdup ((gchar *)data_x11); + XFree (data_x11); + return data; +} +#endif + +static char * +get_accessibility_bus_address_dbus (void) +{ + DBusConnection *session_bus = NULL; + DBusMessage *message; + DBusMessage *reply; + DBusError error; + char *address = NULL; + + session_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL); + if (!session_bus) + return NULL; + + message = dbus_message_new_method_call ("org.a11y.Bus", + "/org/a11y/bus", + "org.a11y.Bus", + "GetAddress"); + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (session_bus, + message, + -1, + &error); + dbus_message_unref (message); + + if (!reply) + { + g_warning ("Error retrieving accessibility bus address: %s: %s", + error.name, error.message); + dbus_error_free (&error); + goto out; + } + + { + const char *tmp_address; + if (!dbus_message_get_args (reply, + NULL, + DBUS_TYPE_STRING, + &tmp_address, + DBUS_TYPE_INVALID)) + { + dbus_message_unref (reply); + goto out; + } + address = g_strdup (tmp_address); + dbus_message_unref (reply); + } + +out: + dbus_connection_unref (session_bus); + return address; +} + +static DBusConnection *a11y_bus; +static dbus_int32_t a11y_dbus_slot = -1; + +static void +a11y_bus_free (void *data) +{ + if (data == a11y_bus) + { + a11y_bus = NULL; + dbus_connection_free_data_slot (&a11y_dbus_slot); + } +} + +/** + * atspi_get_a11y_bus: (skip) + */ +DBusConnection * +atspi_get_a11y_bus (void) +{ + DBusError error; + char *address = NULL; + const char *address_env = NULL; + + if (a11y_bus && dbus_connection_get_is_connected (a11y_bus)) + return a11y_bus; + + if (a11y_dbus_slot == -1) + if (!dbus_connection_allocate_data_slot (&a11y_dbus_slot)) + g_warning ("at-spi: Unable to allocate D-Bus slot"); + + address_env = g_getenv ("AT_SPI_BUS_ADDRESS"); + if (address_env != NULL && *address_env != 0) + address = g_strdup (address_env); +#ifdef HAVE_X11 + if (!address) + address = get_accessibility_bus_address_x11 (); +#endif + if (!address) + address = get_accessibility_bus_address_dbus (); + if (!address) + return NULL; + + dbus_error_init (&error); + a11y_bus = dbus_connection_open_private (address, &error); + g_free (address); + + if (!a11y_bus) + { + if (!g_getenv("SSH_CONNECTION")) + g_warning ("Couldn't connect to accessibility bus: %s", error.message); + dbus_error_free (&error); + return NULL; + } + else + { + if (!dbus_bus_register (a11y_bus, &error)) + { + g_warning ("Couldn't register with accessibility bus: %s", error.message); + dbus_error_free (&error); + dbus_connection_close (a11y_bus); + dbus_connection_unref (a11y_bus); + a11y_bus = NULL; + return NULL; + } + } + + /* Simulate a weak ref on the bus */ + dbus_connection_set_data (a11y_bus, a11y_dbus_slot, a11y_bus, a11y_bus_free); + + return a11y_bus; +} + +/** + * atspi_set_timeout: + * @val: The timeout value, in milliseconds, or -1 to disable the timeout. + * @startup_time: The amount of time, in milliseconds, to allow to pass + * before enforcing timeouts on an application. Can be used to prevent + * timeout exceptions if an application is likely to block for an extended + * period of time on initialization. -1 can be passed to disable this + * behavior. + * + * Set the timeout used for method calls. If this is not set explicitly, + * a default of 0.8 ms is used. + * Note that at-spi2-registryd currently uses a timeout of 3 seconds when + * sending a keyboard event notification. This means that, if an AT makes + * a call in response to the keyboard notification and the application + * being called does not respond before the timeout is reached, + * at-spi2-registryd will time out on the keyboard event notification and + * pass the key onto the application (ie, reply to indicate that the key + * was not consumed), so this may make it undesirable to set a timeout + * larger than 3 seconds. + * + * By default, the normal timeout is set to 800 ms, and the application startup + * timeout is set to 15 seconds. + */ +void +atspi_set_timeout (gint val, gint startup_time) +{ + method_call_timeout = val; + app_startup_time = startup_time; +} + +/** + * atspi_set_main_context: + * @cnx: The #GMainContext to use. + * + * Sets the main loop context that AT-SPI should assume is in use when + * setting an idle callback. + * This function should be called by application-side implementors (ie, + * at-spi2-atk) when it is desirable to re-enter the main loop. + */ +void +atspi_set_main_context (GMainContext *cnx) +{ + if (atspi_main_context == cnx) + return; + if (process_deferred_messages_source != NULL) + { + g_source_destroy (process_deferred_messages_source); + process_deferred_messages_source = g_idle_source_new (); + g_source_set_callback (process_deferred_messages_source, + process_deferred_messages_callback, NULL, NULL); + g_source_attach (process_deferred_messages_source, cnx); + g_source_unref (process_deferred_messages_source); + } + atspi_main_context = cnx; + atspi_dbus_connection_setup_with_g_main (atspi_get_a11y_bus (), cnx); + + if (desktop) + { + gint i; + for (i = desktop->children->len - 1; i >= 0; i--) + { + AtspiAccessible *child = g_ptr_array_index (desktop->children, i); + if (child->parent.app && child->parent.app->bus) + atspi_dbus_connection_setup_with_g_main (child->parent.app->bus, cnx); + } + } +} + +#ifdef DEBUG_REF_COUNTS +static void +print_disposed (gpointer key, gpointer value, gpointer data) +{ + AtspiAccessible *accessible = key; + if (accessible->parent.app) + return; + g_print ("disposed: %s %d\n", accessible->name, accessible->role); +} + +void +debug_disposed () +{ + g_hash_table_foreach (live_refs, print_disposed, NULL); +} +#endif + +gchar * +_atspi_name_compat (gchar *name) +{ + gchar *p = name; + + while (*p) + { + if (*p == '-') + *p = ' '; + p++; + } + return name; +} + +/** + * atspi_role_get_name: + * @role: an #AtspiRole object to query. + * + * Gets a localizable string that indicates the name of an #AtspiRole. + * DEPRECATED. + * + * Returns: a localizable string name for an #AtspiRole enumerated type. + **/ +gchar * +atspi_role_get_name (AtspiRole role) +{ + gchar *retval = NULL; + GTypeClass *type_class; + GEnumValue *value; + + type_class = g_type_class_ref (ATSPI_TYPE_ROLE); + g_return_val_if_fail (G_IS_ENUM_CLASS (type_class), NULL); + + value = g_enum_get_value (G_ENUM_CLASS (type_class), role); + + if (value) + { + retval = g_strdup (value->value_nick); + } + + g_type_class_unref (type_class); + + if (retval) + return _atspi_name_compat (retval); + + return NULL; +} + +GHashTable * +_atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter) +{ + GHashTable *cache = _atspi_accessible_ref_cache (accessible); + DBusMessageIter iter_dict, iter_dict_entry, iter_struct, iter_variant; + + dbus_message_iter_recurse (iter, &iter_dict); + while (dbus_message_iter_get_arg_type (&iter_dict) != DBUS_TYPE_INVALID) + { + const char *key; + GValue *val = NULL; + dbus_message_iter_recurse (&iter_dict, &iter_dict_entry); + dbus_message_iter_get_basic (&iter_dict_entry, &key); + dbus_message_iter_next (&iter_dict_entry); + dbus_message_iter_recurse (&iter_dict_entry, &iter_variant); + if (!strcmp (key, "interfaces")) + { + _atspi_dbus_set_interfaces (accessible, &iter_variant); + } + else if (!strcmp (key, "Attributes")) + { + char *iter_sig = dbus_message_iter_get_signature (&iter_variant); + val = g_new0 (GValue, 1);; + g_value_init (val, G_TYPE_HASH_TABLE); + if (strcmp (iter_sig, "a{ss}") != 0) + { + dbus_free (iter_sig); + break; + } + dbus_free (iter_sig); + g_value_take_boxed (val, _atspi_dbus_hash_from_iter (&iter_variant)); + } + else if (!strcmp (key, "Component.ScreenExtents")) + { + dbus_int32_t d_int; + AtspiRect extents; + char *iter_sig = dbus_message_iter_get_signature (&iter_variant); + val = g_new0 (GValue, 1);; + g_value_init (val, ATSPI_TYPE_RECT); + if (strcmp (iter_sig, "(iiii)") != 0) + { + dbus_free (iter_sig); + break; + } + dbus_free (iter_sig); + dbus_message_iter_recurse (&iter_variant, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_int); + extents.x = d_int; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_int); + extents.y = d_int; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_int); + extents.width = d_int; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_int); + extents.height = d_int; + g_value_set_boxed (val, &extents); + } + if (val) + g_hash_table_insert (cache, g_strdup (key), val); + dbus_message_iter_next (&iter_dict); + } + + return cache; +} + +gboolean +_atspi_get_allow_sync () +{ + return allow_sync; +} + +gboolean +_atspi_set_allow_sync (gboolean val) +{ + gboolean ret = allow_sync; + + allow_sync = val; + return ret; +} + +void +_atspi_set_error_no_sync (GError **error) +{ + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_SYNC_NOT_ALLOWED, + _("Attempted synchronous call where prohibited")); +} diff --git a/atspi/atspi-misc.h b/atspi/atspi-misc.h new file mode 100644 index 0000000..f13596f --- /dev/null +++ b/atspi/atspi-misc.h @@ -0,0 +1,52 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_MISC_H_ +#define _ATSPI_MISC_H_ + +G_BEGIN_DECLS + +int atspi_init (void); +gboolean atspi_is_initialized (void); + +void atspi_event_main (); + +void atspi_event_quit (); + +int atspi_exit (); + +DBusConnection * +atspi_get_a11y_bus (); + +void +atspi_set_timeout (gint val, gint startup_time); + +void +atspi_set_main_context (GMainContext *cnx); + +gchar * atspi_role_get_name (AtspiRole role); +G_END_DECLS + +#endif /* _ATSPI_MISC_H_ */ diff --git a/atspi/atspi-object.c b/atspi/atspi-object.c new file mode 100644 index 0000000..3545845 --- /dev/null +++ b/atspi/atspi-object.c @@ -0,0 +1,64 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include "atspi-private.h" + +G_DEFINE_TYPE (AtspiObject, atspi_object, G_TYPE_OBJECT) + +static void +atspi_object_init (AtspiObject *obj) +{ +} + +static void +atspi_object_dispose (GObject *object) +{ + AtspiObject *aobj = ATSPI_OBJECT (object); + + if (aobj->app) + { + g_object_unref (aobj->app); + aobj->app = NULL; + } + + G_OBJECT_CLASS (atspi_object_parent_class)->dispose (object); +} + +static void +atspi_object_finalize (GObject *object) +{ + AtspiObject *aobj = ATSPI_OBJECT (object); + + g_free (aobj->path); + + G_OBJECT_CLASS (atspi_object_parent_class)->finalize (object); +} + +static void +atspi_object_class_init (AtspiObjectClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = atspi_object_dispose; + object_class->finalize = atspi_object_finalize; +} diff --git a/atspi/atspi-object.h b/atspi/atspi-object.h new file mode 100644 index 0000000..69dd551 --- /dev/null +++ b/atspi/atspi-object.h @@ -0,0 +1,60 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_OBJECT_H_ +#define _ATSPI_OBJECT_H_ + +#include "glib-object.h" + +#include "atspi-application.h" +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_OBJECT (atspi_object_get_type ()) +#define ATSPI_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_OBJECT, AtspiObject)) +#define ATSPI_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_OBJECT, AtspiObjectClass)) +#define ATSPI_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_OBJECT)) +#define ATSPI_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_OBJECT)) +#define ATSPI_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_OBJECT, AtspiObjectClass)) + +typedef struct _AtspiObject AtspiObject; +struct _AtspiObject +{ + GObject parent; + AtspiApplication *app; + char *path; +}; + +typedef struct _AtspiObjectClass AtspiObjectClass; +struct _AtspiObjectClass +{ + GObjectClass parent_class; +}; + +GType atspi_object_get_type (void); + +G_END_DECLS + +#endif /* _ATSPI_OBJECT_H_ */ diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h new file mode 100644 index 0000000..2cf5693 --- /dev/null +++ b/atspi/atspi-private.h @@ -0,0 +1,43 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_PRIVATE_H_ +#define _ATSPI_PRIVATE_H_ + +#include +#include "atspi-device-listener-private.h" +#include "atspi-event-listener-private.h" +#include "atspi-matchrule-private.h" +#include "atspi-misc-private.h" + +#include "glib/gi18n.h" + +#include "atspi.h" +#include "atspi-accessible-private.h" + +G_BEGIN_DECLS +void _atspi_reregister_device_listeners (); +G_END_DECLS + +#endif /* _ATSPI_PRIVATE_H_ */ diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c new file mode 100644 index 0000000..c9b11f0 --- /dev/null +++ b/atspi/atspi-registry.c @@ -0,0 +1,542 @@ + +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +/* atspi_registry.c: Global functions wrapping the registry */ + +#include "atspi-private.h" + +typedef struct +{ + AtspiDeviceListener *listener; + GArray *key_set; + AtspiKeyMaskType modmask; + AtspiKeyEventMask event_types; + gint sync_type; +} DeviceListenerEntry; + +static GList *device_listeners; + +/** + * atspi_get_desktop_count: + * + * Gets the number of virtual desktops. + * NOTE: multiple virtual desktops are not implemented yet; as a + * consequence, this function always returns 1. + * + * Returns: a #gint indicating the number of active virtual desktops. + **/ +gint +atspi_get_desktop_count () +{ + return 1; +} + +/** + * atspi_get_desktop: + * @i: a #gint indicating which of the accessible desktops is to be returned. + * + * Gets the virtual desktop indicated by index @i. + * NOTE: currently multiple virtual desktops are not implemented; + * as a consequence, any @i value different from 0 will not return a + * virtual desktop - instead it will return NULL. + * + * Returns: (transfer full): a pointer to the @i-th virtual desktop's + * #AtspiAccessible representation. + **/ +AtspiAccessible* +atspi_get_desktop (gint i) +{ + if (i != 0) return NULL; + return _atspi_ref_accessible (atspi_bus_registry, atspi_path_root); +} + +/** + * atspi_get_desktop_list: + * + * Gets the list of virtual desktops. On return, @list will point + * to a newly-created, NULL terminated array of virtual desktop + * pointers. + * It is the responsibility of the caller to free this array when + * it is no longer needed. + * NOTE: currently multiple virtual desktops are not implemented; + * this implementation always returns a #Garray with a single + * #AtspiAccessible desktop. + * + * Returns: (element-type AtspiAccessible*) (transfer full): a #GArray of + * desktops. + **/ +GArray * +atspi_get_desktop_list () +{ + GArray *array = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *)); + AtspiAccessible *desktop; + + desktop = _atspi_ref_accessible (atspi_bus_registry, atspi_path_root); + if (array) + g_array_index (array, AtspiAccessible *, 0) = desktop; + return array; +} + +static gboolean +notify_keystroke_listener (DeviceListenerEntry *e) +{ + gchar *path = _atspi_device_listener_get_path (e->listener); + dbus_uint32_t d_modmask = e->modmask; + dbus_uint32_t d_event_types = e->event_types; + AtspiEventListenerMode listener_mode; + gboolean retval = FALSE; + DBusError d_error; + + listener_mode.synchronous = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0); + listener_mode.preemptive = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0); + listener_mode.global = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0); + + dbus_error_init (&d_error); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "RegisterKeystrokeListener", &d_error, + "oa(iisi)uu(bbb)=>b", path, e->key_set, + d_modmask, d_event_types, &listener_mode, + &retval); + if (dbus_error_is_set (&d_error)) + { + g_warning ("RegisterKeystrokeListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + g_free (path); + + return retval; +} + +static void +device_listener_entry_free (DeviceListenerEntry *e) +{ + g_array_free (e->key_set, TRUE); + g_free (e); +} + +static void +unregister_listener (gpointer data, GObject *object) +{ + GList *l; + AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object); + + for (l = device_listeners; l;) + { + DeviceListenerEntry *e = l->data; + if (e->listener == listener) + { + GList *next = l->next; + device_listener_entry_free (e); + device_listeners = g_list_delete_link (device_listeners, l); + l = next; + } + else + l = l->next; + } +} + +/** + * atspi_register_keystroke_listener: + * @listener: a pointer to the #AtspiDeviceListener for which + * keystroke events are requested. + * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the + * #AtspiKeyDefinition array indicating which keystroke events are + * requested, or NULL + * to indicate that all keycodes and keyvals for the specified + * modifier set are to be included. + * @modmask: an #AtspiKeyMaskType mask indicating which + * key event modifiers must be set in combination with @keys, + * events will only be reported for key events for which all + * modifiers in @modmask are set. If you wish to listen for + * events with multiple modifier combinations, you must call + * #atspi_register_keystroke_listener once for each + * combination. + * @event_types: an #AtspiKeyMaskType mask indicating which + * types of key events are requested (%ATSPI_KEY_PRESSED etc.). + * @sync_type: an #AtspiKeyListenerSyncType parameter indicating + * the behavior of the notification/listener transaction. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Registers a listener for keystroke events, either pre-emptively for + * all windows (%ATSPI_KEYLISTENER_ALL_WINDOWS), + * non-preemptively (%ATSPI_KEYLISTENER_NOSYNC), or + * pre-emptively at the toolkit level (%ATSPI_KEYLISTENER_CANCONSUME). + * If ALL_WINDOWS or CANCONSUME are used, the event is consumed + * upon receipt if one of @listener's callbacks returns %TRUE + * (other sync_type values may be available in the future). + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_register_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_types, + AtspiKeyListenerSyncType sync_type, + GError **error) +{ + DeviceListenerEntry *e; + + g_return_val_if_fail (listener != NULL, FALSE); + + e = g_new0 (DeviceListenerEntry, 1); + e->listener = listener; + e->modmask = modmask; + e->event_types = event_types; + e->sync_type = sync_type; + if (key_set) + { + gint i; + e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), + key_set->len); + e->key_set->len = key_set->len; + for (i = 0; i < key_set->len; i++) + { + AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i; + AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) e->key_set->data) + i; + d_kd->keycode = kd->keycode; + d_kd->keysym = kd->keysym; + if (kd->keystring) + { + d_kd->keystring = kd->keystring; + } + else + { + d_kd->keystring = ""; + } + } + } + else + { + e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); + } + + g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL); + device_listeners = g_list_prepend (device_listeners, e); + return notify_keystroke_listener (e); +} + +/** + * atspi_deregister_keystroke_listener: + * @listener: a pointer to the #AtspiDeviceListener for which + * keystroke events are requested. + * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the + * #AtspiKeyDefinition array indicating which keystroke events are + * requested, or %NULL + * to indicate that all keycodes and keyvals for the specified + * modifier set are to be included. + * @modmask: the key modifier mask for which this listener is to be + * 'deregistered' (of type #AtspiKeyMaskType). + * @event_types: an #AtspiKeyMaskType mask indicating which + * types of key events were requested (%ATSPI_KEY_PRESSED, etc.). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Removes a keystroke event listener from the registry's listener queue, + * ceasing notification of events with modifiers matching @modmask. + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_deregister_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_types, + GError **error) +{ + GArray *d_key_set; + gchar *path = _atspi_device_listener_get_path (listener); + gint i; + dbus_uint32_t d_modmask = modmask; + dbus_uint32_t d_event_types = event_types; + DBusError d_error; + GList *l; + + dbus_error_init (&d_error); + if (!listener) + { + return FALSE; + } + + /* copy the keyval filter values from the C api into the DBind KeySet */ + if (key_set) + { + d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len); + d_key_set->len = key_set->len; + for (i = 0; i < key_set->len; ++i) + { + AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i; + AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) d_key_set->data) + i; + d_kd->keycode = kd->keycode; + d_kd->keysym = kd->keysym; + if (kd->keystring) + { + d_kd->keystring = kd->keystring; + } + else + { + d_kd->keystring = ""; + } + } + } + else + { + d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); + } + + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "DeregisterKeystrokeListener", &d_error, + "oa(iisi)uu", path, d_key_set, d_modmask, + d_event_types); + if (dbus_error_is_set (&d_error)) + { + g_warning ("DeregisterKeystrokeListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + unregister_listener (listener, NULL); + for (l = device_listeners; l;) + { + /* TODO: This code is all wrong / doesn't match what is in + * deviceeventcontroller.c. It would be nice to deprecate these methods + * in favor of methods that return an ID for the registration that can + * be passed to a deregister function, for instance. */ + DeviceListenerEntry *e = l->data; + if (e->modmask == modmask && e->event_types == event_types) + { + GList *next = l->next; + device_listener_entry_free (e); + device_listeners = g_list_delete_link (device_listeners, l); + l = next; + } + else + l = l->next; + } + g_array_free (d_key_set, TRUE); + g_free (path); + return TRUE; +} + +/** + * atspi_register_device_event_listener: + * @listener: a pointer to the #AtspiDeviceListener which requests + * the events. + * @event_types: an #AtspiDeviceEventMask mask indicating which + * types of key events are requested (%ATSPI_KEY_PRESSED, etc.). + * @filter: (allow-none): Unused parameter. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Registers a listener for device events, for instance button events. + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_register_device_event_listener (AtspiDeviceListener *listener, + AtspiDeviceEventMask event_types, + void *filter, GError **error) +{ + gboolean retval = FALSE; + dbus_uint32_t d_event_types = event_types; + gchar *path = _atspi_device_listener_get_path (listener); + DBusError d_error; + + dbus_error_init (&d_error); + if (!listener) + { + return retval; + } + + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_types, &retval); + if (dbus_error_is_set (&d_error)) + { + g_warning ("RegisterDeviceEventListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + g_free (path); + return retval; +} + +/** + * atspi_deregister_device_event_listener: + * @listener: a pointer to the #AtspiDeviceListener for which + * device events are requested. + * @filter: (allow-none): Unused parameter. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Removes a device event listener from the registry's listener queue, + * ceasing notification of events of the specified type. + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_deregister_device_event_listener (AtspiDeviceListener *listener, + void *filter, GError **error) +{ + dbus_uint32_t event_types = 0; + gchar *path = _atspi_device_listener_get_path (listener); + DBusError d_error; + + dbus_error_init (&d_error); + + if (!listener) + { + return FALSE; + } + + event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT); + event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT); + + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types); + if (dbus_error_is_set (&d_error)) + { + g_warning ("DeregisterDeviceEventListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + g_free (path); + return TRUE; +} + +/** + * atspi_generate_keyboard_event: + * @keyval: a #gint indicating the keycode or keysym of the key event + * being synthesized. + * @keystring: (allow-none): an (optional) UTF-8 string which, if + * @synth_type is %ATSPI_KEY_STRING, indicates a 'composed' + * keyboard input string being synthesized; this type of + * keyboard event synthesis does not emulate hardware + * keypresses but injects the string as though a composing + * input method (such as XIM) were used. + * @synth_type: an #AtspiKeySynthType flag indicating whether @keyval + * is to be interpreted as a keysym rather than a keycode + * (%ATSPI_KEY_SYM) or a string (%ATSPI_KEY_STRING), or + * whether to synthesize %ATSPI_KEY_PRESS, + * %ATSPI_KEY_RELEASE, or both (%ATSPI_KEY_PRESSRELEASE). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Synthesizes a keyboard event (as if a hardware keyboard event occurred in the + * current UI context). + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_generate_keyboard_event (glong keyval, + const gchar *keystring, + AtspiKeySynthType synth_type, GError **error) +{ + dbus_uint32_t d_synth_type = synth_type; + dbus_int32_t d_keyval = keyval; + DBusError d_error; + + dbus_error_init (&d_error); + if (!keystring) + keystring = ""; + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateKeyboardEvent", &d_error, "isu", d_keyval, keystring, d_synth_type); + if (dbus_error_is_set (&d_error)) + { + g_warning ("GenerateKeyboardEvent failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + return TRUE; +} + +/** + * atspi_generate_mouse_event: + * @x: a #glong indicating the screen x coordinate of the mouse event. + * @y: a #glong indicating the screen y coordinate of the mouse event. + * @name: a string indicating which mouse event to be synthesized + * (e.g. "b1p", "b1c", "b2r", "rel", "abs"). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL + * + * Synthesizes a mouse event at a specific screen coordinate. + * Most AT clients should use the #AccessibleAction interface when + * tempted to generate mouse events, rather than this method. + * Event names: b1p = button 1 press; b2r = button 2 release; + * b3c = button 3 click; b2d = button 2 double-click; + * abs = absolute motion; rel = relative motion. + * + * Returns: %TRUE if successful, otherwise %FALSE. + **/ +gboolean +atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error) +{ + dbus_int32_t d_x = x, d_y = y; + DBusError d_error; + + dbus_error_init (&d_error); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "GenerateMouseEvent", &d_error, "iis", + d_x, d_y, name); + if (dbus_error_is_set (&d_error)) + { + g_warning ("GenerateMouseEvent failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + return TRUE; +} + +AtspiKeyDefinition * +atspi_key_definition_copy (AtspiKeyDefinition *src) +{ + AtspiKeyDefinition *dst; + + dst = g_new0 (AtspiKeyDefinition, 1); + dst->keycode = src->keycode; + dst->keysym = src->keysym; + if (src->keystring) + dst->keystring = g_strdup (src->keystring); + dst->unused = src->unused; + return dst; +} + +void +atspi_key_definition_free (AtspiKeyDefinition *kd) +{ + if (kd->keystring) + g_free (kd->keystring); + g_free (kd); +} + +void +_atspi_reregister_device_listeners () +{ + GList *l; + DeviceListenerEntry *e; + + for (l = device_listeners; l; l = l->next) + { + e = l->data; + notify_keystroke_listener (e); + } +} +G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free) diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h new file mode 100644 index 0000000..18e32a6 --- /dev/null +++ b/atspi/atspi-registry.h @@ -0,0 +1,76 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_REGISTRY_H_ +#define _ATSPI_REGISTRY_H_ + +#include "atspi-accessible.h" +#include "atspi-types.h" +#include "atspi-device-listener.h" + +G_BEGIN_DECLS + +GType atspi_key_definition_get_type (); + +gint atspi_get_desktop_count (); + +AtspiAccessible* atspi_get_desktop (gint i); + +GArray *atspi_get_desktop_list (); + +gboolean +atspi_register_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_types, + AtspiKeyListenerSyncType sync_type, + GError **error); + +gboolean +atspi_deregister_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_types, + GError **error); + +gboolean +atspi_register_device_event_listener (AtspiDeviceListener *listener, + AtspiDeviceEventMask event_types, + void *filter, GError **error); + +gboolean +atspi_deregister_device_event_listener (AtspiDeviceListener *listener, + void *filter, GError **error); + +gboolean +atspi_generate_keyboard_event (glong keyval, + const gchar *keystring, + AtspiKeySynthType synth_type, GError **error); + +gboolean +atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_REGISTRY_H_ */ diff --git a/atspi/atspi-relation.c b/atspi/atspi-relation.c new file mode 100644 index 0000000..82bb668 --- /dev/null +++ b/atspi/atspi-relation.c @@ -0,0 +1,135 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_relation_get_relation_type: + * @obj: a pointer to the #AtspiRelation object to query. + * + * Gets the type of relationship represented by an #AtspiRelation. + * + * Returns: an #AtspiRelationType indicating the type of relation + * encapsulated in this #AtspiRelation object. + * + **/ +AtspiRelationType +atspi_relation_get_relation_type (AtspiRelation *obj) +{ + return obj->relation_type; +} + +/** + * atspi_relation_get_n_targets: + * @obj: a pointer to the #AtspiRelation object to query. + * + * Gets the number of objects which this relationship has as its + * target objects (the subject is the #AtspiAccessible from which this + * #AtspiRelation originated). + * + * Returns: a #gint indicating how many target objects which the + * originating #AtspiAccessible object has the #AtspiRelation + * relationship with. + **/ +gint +atspi_relation_get_n_targets (AtspiRelation *obj) +{ + return obj->targets->len; +} + +/** + * atspi_relation_get_target: + * @obj: a pointer to the #AtspiRelation object to query. + * @i: a (zero-index) #gint indicating which (of possibly several) target is requested. + * + * Gets the @i-th target of a specified #AtspiRelation relationship. + * + * Returns: (transfer full): an #AtspiAccessible which is the @i-th object + * with which the originating #AtspiAccessible has relationship + * specified in the #AtspiRelation object. + * + **/ +AtspiAccessible * +atspi_relation_get_target (AtspiRelation *obj, gint i) +{ + g_return_val_if_fail (obj, NULL); + + g_return_val_if_fail (i >= 0 && i < obj->targets->len, NULL); + return g_object_ref (g_array_index (obj->targets, AtspiAccessible *, i)); +} + +AtspiRelation * +_atspi_relation_new_from_iter (DBusMessageIter *iter) +{ + DBusMessageIter iter_struct, iter_array; + dbus_uint32_t d_type; + AtspiRelation *relation = g_object_new (ATSPI_TYPE_RELATION, NULL); + + if (!relation) + return NULL; + + dbus_message_iter_recurse (iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_type); + relation->relation_type = d_type; + dbus_message_iter_next (&iter_struct); + + relation->targets = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *)); + dbus_message_iter_recurse (&iter_struct, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *accessible; + accessible = _atspi_dbus_return_accessible_from_iter (&iter_array); + relation->targets = g_array_append_val (relation->targets, accessible); + /* Iter was moved already, so no need to call dbus_message_iter_next */ + } + return relation; +} + +G_DEFINE_TYPE (AtspiRelation, atspi_relation, G_TYPE_OBJECT) + +static void +atspi_relation_init (AtspiRelation *relation) +{ +} + +static void +atspi_relation_finalize (GObject *object) +{ + AtspiRelation *relation = ATSPI_RELATION (object); + gint i; + + for (i = 0; i < relation->targets->len; i++) + g_object_unref (g_array_index (relation->targets, AtspiAccessible *, i)); + g_array_free (relation->targets, TRUE); + + G_OBJECT_CLASS (atspi_relation_parent_class)->finalize (object); +} + +static void +atspi_relation_class_init (AtspiRelationClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = atspi_relation_finalize; +} diff --git a/atspi/atspi-relation.h b/atspi/atspi-relation.h new file mode 100644 index 0000000..4eecad3 --- /dev/null +++ b/atspi/atspi-relation.h @@ -0,0 +1,67 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_RELATION_H_ +#define _ATSPI_RELATION_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_RELATION (atspi_relation_get_type ()) +#define ATSPI_IS_RELATION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_RELATION) +#define ATSPI_RELATION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_RELATION, AtspiRelation) +#define ATSPI_RELATION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_RELATION, AtspiRelation)) + +GType atspi_relation_get_type (); + +typedef struct _AtspiRelation AtspiRelation; +struct _AtspiRelation +{ + GObject parent; + AtspiRelationType relation_type; + GArray *targets; +}; + +typedef struct _AtspiRelationClass AtspiRelationClass; +struct _AtspiRelationClass +{ + GObjectClass parent_class; +}; + +AtspiRelationType atspi_relation_get_relation_type (AtspiRelation *obj); + +gint atspi_relation_get_n_targets (AtspiRelation *obj); + +AtspiAccessible * atspi_relation_get_target (AtspiRelation *obj, gint i); + +/* private */ +AtspiRelation * _atspi_relation_new_from_iter (DBusMessageIter *iter); + +G_END_DECLS + +#endif /* _ATSPI_RELATION_H_ */ diff --git a/atspi/atspi-selection.c b/atspi/atspi-selection.c new file mode 100644 index 0000000..7318989 --- /dev/null +++ b/atspi/atspi-selection.c @@ -0,0 +1,264 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_selection_get_n_selected_children: + * @obj: a pointer to the #AtspiSelection implementor on which to operate. + * + * Gets the number of children of an #AtspiSelection implementor which are + * currently selected. + * + * Returns: a #gint indicating the number of #Accessible children + * of the #AtspiSelection implementor which are currently selected. + * + **/ +gint +atspi_selection_get_n_selected_children (AtspiSelection *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_selection, "NSelectedChildren", error, "i", &retval); + + return retval; +} + +/** + * atspi_selection_get_selected_child: + * @obj: a pointer to the #AtspiSelection on which to operate. + * @selected_child_index: a #gint indicating which of the selected + * children is specified. + * + * Gets the i-th selected #AtspiAccessible child of an #AtspiSelection. + * Note that @selected_child_index refers to the index in the list + * of 'selected' + * children and generally differs from that used in + * #atspi_accessible_get_child_at_index or returned by + * #atspi_accessible_get_index_in_parent. + * @selected_child_index must lie between 0 + * and #atspi_selection_get_n_selected_children - 1, inclusive. + * + * Returns: (transfer full): a pointer to a selected #AtspiAccessible child + * object, specified by @selected_child_index. + * + **/ +AtspiAccessible * +atspi_selection_get_selected_child (AtspiSelection *obj, + gint selected_child_index, GError **error) +{ + dbus_int32_t d_selected_child_index = selected_child_index; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_selection, + "GetSelectedChild", error, "i", + d_selected_child_index); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_selection_select_child: + * @obj: a pointer to the #AtspiSelection on which to operate. + * @child_index: a #gint indicating which child of the #Accessible + * is to be selected. + * + * Adds a child to the selected children list of an #AtspiSelection. + * For #AtspiSelection implementors that only allow + * single selections, this may replace the (single) current + * selection. + * + * Returns: #TRUE if the child was successfully selected, #FALSE otherwise. + **/ +gboolean +atspi_selection_select_child (AtspiSelection *obj, + gint child_index, + GError **error) +{ + dbus_int32_t d_child_index = child_index; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "SelectChild", error, "i=>b", d_child_index, &retval); + + return retval; +} + +/** + * atspi_selection_deselect_selected_child: + * @obj: a pointer to the #AtspiSelection on which to operate. + * @selected_child_index: a #gint indicating which of the selected children + * of the #Accessible is to be selected. + * + * Removes a child from the selected children list of an #AtspiSelection. + * Note that @child_index is the index in the selected-children list, + * not the index in the parent container. @selectedChildIndex in this + * method, and @child_index in #atspi_selection_select_child + * are asymmetric. + * + * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise. + **/ +gboolean +atspi_selection_deselect_selected_child (AtspiSelection *obj, + gint selected_child_index, + GError **error) +{ + dbus_int32_t d_selected_child_index = selected_child_index; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "DeselectSelectedChild", error, "i=>b", d_selected_child_index, &retval); + + return retval; +} + +/** + * atspi_selection_deselect_child: + * @obj: a pointer to the #AtspiSelection on which to operate. + * @child_index: a #gint indicating which of the children + * of the #AtspiAccessible is to be de-selected. + * + * Deselects a specific child of an #AtspiSelection. + * Note that @child_index is the index of the child + * in the parent container. + * + * See #atspi_selection_deselect_selected_child + * + * Returns: #TRUE if the child was successfully deselected, #FALSE otherwise. + **/ +gboolean +atspi_selection_deselect_child (AtspiSelection *obj, + gint child_index, + GError **error) +{ + dbus_int32_t d_child_index = child_index; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "DeselectChild", error, "i=>b", d_child_index, &retval); + + return retval; +} + +/** + * atspi_selection_is_child_selected: + * @obj: a pointer to the #AtspiSelection implementor on which to operate. + * @child_index: an index into the #AtspiSelection's list of children. + * + * Determines whether a particular child of an #AtspiSelection implementor + * is currently selected. Note that @child_index is the index into the + * standard #AtspiAccessible container's list of children. + * + * Returns: #TRUE if the specified child is currently selected, + * #FALSE otherwise. + **/ +gboolean +atspi_selection_is_child_selected (AtspiSelection *obj, + gint child_index, + GError **error) +{ + dbus_int32_t d_child_index = child_index; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "IsChildSelected", error, "i=>b", d_child_index, &retval); + + return retval; +} + +/** + * atspi_selection_select_all: + * @obj: a pointer to the #AtspiSelection implementor on which to operate. + * + * Attempts to select all of the children of an #AtspiSelection implementor. + * Not all #AtspiSelection implementors support this operation. + * + * Returns: #TRUE if successful, #FALSE otherwise. + * + **/ +gboolean +atspi_selection_select_all (AtspiSelection *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "SelectAll", error, "=>b", &retval); + + return retval; +} + +/** + * atspi_selection_clear_selection: + * @obj: a pointer to the #AtspiSelection implementor on which to operate. + * + * Clears the current selection, removing all selected children from the + * specified #AtspiSelection implementor's selection list. + * + * Returns: #TRUE if successful, #FALSE otherwise. + * + **/ +gboolean +atspi_selection_clear_selection (AtspiSelection *obj, GError **error) +{ + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_selection, "ClearSelection", error, "=>b", &retval); + + return retval; +} + +static void +atspi_selection_base_init (AtspiSelection *klass) +{ +} + +GType +atspi_selection_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiSelection), + (GBaseInitFunc) atspi_selection_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiSelection", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-selection.h b/atspi/atspi-selection.h new file mode 100644 index 0000000..8ac7e44 --- /dev/null +++ b/atspi/atspi-selection.h @@ -0,0 +1,69 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_SELECTION_H_ +#define _ATSPI_SELECTION_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_SELECTION (atspi_selection_get_type ()) +#define ATSPI_IS_SELECTION(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_SELECTION) +#define ATSPI_SELECTION(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_SELECTION, AtspiSelection) +#define ATSPI_SELECTION_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_SELECTION, AtspiSelection)) + +GType atspi_selection_get_type (); + +struct _AtspiSelection +{ + GTypeInterface parent; +}; + +gint atspi_selection_get_n_selected_children (AtspiSelection *obj, GError **error); + +AtspiAccessible * atspi_selection_get_selected_child (AtspiSelection *obj, gint selected_child_index, GError **error); + +gboolean atspi_selection_select_child (AtspiSelection *obj, gint child_index, GError **error); + +gboolean atspi_selection_deselect_selected_child (AtspiSelection *obj, gint selected_child_index, GError **error); + +gboolean atspi_selection_deselect_child (AtspiSelection *obj, gint child_index, GError **error); + +gboolean +atspi_selection_is_child_selected (AtspiSelection *obj, + gint child_index, GError **error); + +gboolean atspi_selection_select_all (AtspiSelection *obj, GError **error); + +gboolean atspi_selection_clear_selection (AtspiSelection *obj, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_SELECTION_H_ */ diff --git a/atspi/atspi-stateset.c b/atspi/atspi-stateset.c new file mode 100644 index 0000000..366c48b --- /dev/null +++ b/atspi/atspi-stateset.c @@ -0,0 +1,278 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +static void atspi_state_set_class_init (AtspiStateSetClass *klass); + +G_DEFINE_TYPE (AtspiStateSet, atspi_state_set, G_TYPE_OBJECT) + +static void +atspi_state_set_init (AtspiStateSet *set) +{ + set->states = 0; +} + +static void +atspi_state_set_class_init (AtspiStateSetClass* klass) +{ +} + +/** + * atspi_state_set_new: + * @states: (element-type AtspiStateType): An array of states with which the + * method initializes the state set. + * + * Generates an #AtspiStateSet with the given @states. + * + * Returns: A new #AtspiStateSet with the given states. + **/ +AtspiStateSet * +atspi_state_set_new (GArray *states) +{ + AtspiStateSet *set = g_object_new (ATSPI_TYPE_STATE_SET, NULL); + gint i; + + if (!set || !states) + return set; + + for (i = 0; i < states->len; i++) + atspi_state_set_add (set, g_array_index (states, AtspiStateType, i)); + return set; +} + +AtspiStateSet * +_atspi_state_set_new_internal (AtspiAccessible *accessible, gint64 states) +{ + AtspiStateSet *set; + + set = g_object_new (ATSPI_TYPE_STATE_SET, NULL); + g_return_val_if_fail (set != NULL, NULL); + + set->accessible = accessible; + set->states = states; + return set; +} + +/** + * atspi_state_set_set_by_name: + * @set: a pointer to the #AtspiStateSet object on which to operate. + * @name: a string corresponding to a state name. + * @enabled: if #TRUE, @name should be enabled in the @set in question; + * otherwise, it should be disabled. + * + * Enables/disables a state in an #AtspiStateSet according to its @name. + **/ +void +atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled) +{ + GTypeClass *type_class; + GEnumValue *value; + + if (set->accessible && + !(set->accessible->cached_properties & ATSPI_CACHE_STATES)) + return; + + type_class = g_type_class_ref (ATSPI_TYPE_STATE_TYPE); + + value = g_enum_get_value_by_nick (G_ENUM_CLASS (type_class), name); + + if (!value) + { + g_warning ("AT-SPI: Attempt to set unknown state '%s'", name); + } + else + if (enabled) + set->states |= ((gint64)1 << value->value); + else + set->states &= ~((gint64)1 << value->value); + + g_type_class_unref (type_class); +} + +static void +refresh_states (AtspiStateSet *set) +{ + GArray *state_array; + dbus_uint32_t *states; + + if (!set->accessible || + (set->accessible->cached_properties & ATSPI_CACHE_STATES)) + return; + + if (!_atspi_dbus_call (set->accessible, atspi_interface_accessible, "GetState", NULL, "=>au", &state_array)) + return; + + states = (dbus_uint32_t *) state_array->data; + + set->states = ((gint64)states [1]) << 32; + set->states |= (gint64) states [0]; + g_array_free (state_array, TRUE); +} + +/** + * atspi_state_set_add: + * @set: a pointer to the #AtspiStateSet object on which to operate. + * @state: an #AtspiStateType to be added to the specified #AtspiStateSet. + * + * Adds a particular #AtspiState to an #AtspiStateSet (i.e. sets the + * given state to #TRUE in the stateset). + * + **/ +void +atspi_state_set_add (AtspiStateSet *set, AtspiStateType state) +{ + g_return_if_fail (set != NULL); + set->states |= (((gint64)1) << state); +} + +/** + * atspi_state_set_compare: + * @set: a pointer to the first #AtspiStateSet object on which to operate. + * @set2: a pointer to the second #AtspiStateSet object on which to operate. + * + * Determines the differences between two instances of #AtspiStateSet. + * + * @see #atspi_state_set_equals. + * + * Returns: (transfer full): an #AtspiStateSet object containing all states + * contained on one of the two sets but not the other. + * + **/ +AtspiStateSet * +atspi_state_set_compare (AtspiStateSet *set, + AtspiStateSet *set2) +{ + g_return_val_if_fail (set != NULL, NULL); + g_return_val_if_fail (set2 != NULL, NULL); + + return _atspi_state_set_new_internal (NULL, set->states ^ set2->states); +} + +/** + * atspi_state_set_contains: + * @set: a pointer to the #AtspiStateSet object on which to operate. + * @state: an #AtspiStateType for which the specified #AtspiStateSet + * will be queried. + * + * Determines whether a given #AtspiStateSet includes a given state; that is, + * whether @state is true for the @set in question. + * + * Returns: #TRUE if @state is true/included in the given #AtspiStateSet, + * otherwise #FALSE. + * + **/ +gboolean +atspi_state_set_contains (AtspiStateSet *set, + AtspiStateType state) +{ + if (!set) + return FALSE; + refresh_states (set); + return (set->states & ((gint64)1 << state)) ? TRUE : FALSE; +} + +/** + * atspi_state_set_equals: + * @set: a pointer to the first #AtspiStateSet object on which to operate. + * @set2: a pointer to the second #AtspiStateSet object on which to operate. + * + * Determines whether two instances of #AtspiStateSet are equivalent (i.e. + * consist of the same #AtspiStates). Useful for checking multiple + * state variables at once. + * + * @see #atspi_state_set_compare. + * + * Returns: #TRUE if the two #AtspiStateSets are equivalent, + * otherwise #FALSE. + * + **/ +gboolean +atspi_state_set_equals (AtspiStateSet *set, + AtspiStateSet *set2) +{ + if (set == set2) + return TRUE; + if (set == NULL || set2 == NULL) + return FALSE; + return (set->states == set2->states); +} + +/** + * atspi_state_set_get_states: + * @set: The #AtspiStateSet to be queried. + * + * Returns the states in an #AtspiStateSet as an array. + * + * Returns: (element-type AtspiStateType) (transfer full): A #GArray of state + * types representing the current state. + **/ +GArray * +atspi_state_set_get_states (AtspiStateSet *set) +{ + gint i = 0; + guint64 val = 1; + GArray *ret; + + g_return_val_if_fail (set != NULL, NULL); + refresh_states (set); + ret = g_array_new (TRUE, TRUE, sizeof (AtspiStateType)); + if (!ret) + return NULL; + for (i = 0; i < 64; i++) + { + if (set->states & val) + ret = g_array_append_val (ret, i); + val <<= 1; + } + return ret; +} + +/** + * atspi_state_set_is_empty: + * @set: The #AtspiStateSet to query. + * + * Returns: #TRUE if the state set contains no states; #FALSE otherwise. + **/ +gboolean +atspi_state_set_is_empty (AtspiStateSet *set) +{ + return (set->states == 0); +} + +/** + * atspi_state_set_remove: + * @set: a pointer to the #AtspiStateSet object on which to operate. + * @state: an #AtspiStateType to remove from the specified @set. + * + * Removes a particular #AtspiState to an #AtspiStateSet (i.e. sets the + * given state to #FALSE in the stateset.) + * + **/ +void +atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state) +{ + g_return_if_fail (set != NULL); + set->states &= ~((gint64)1 << state); +} diff --git a/atspi/atspi-stateset.h b/atspi/atspi-stateset.h new file mode 100644 index 0000000..f6fd32f --- /dev/null +++ b/atspi/atspi-stateset.h @@ -0,0 +1,75 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_STATE_SET_H_ +#define _ATSPI_STATE_SET_H_ + +#define ATSPI_TYPE_STATE_SET (atspi_state_set_get_type ()) +#define ATSPI_STATE_SET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSet)) +#define ATSPI_STATE_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ATSPI_TYPE_STATE_SET, AtspiStateSetClass)) +#define ATSPI_IS_STATE_SET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_STATE_SET)) +#define ATSPI_IS_STATE_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_STATE_SET)) +#define ATSPI_STATE_SET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_STATE_SET, AtspiStateSetClass)) + +G_BEGIN_DECLS + +typedef struct _AtspiStateSet AtspiStateSet; +struct _AtspiStateSet +{ + GObject parent; + struct _AtspiAccessible *accessible; + gint64 states; +}; + +typedef struct _AtspiStateSetClass AtspiStateSetClass; +struct _AtspiStateSetClass +{ + GObjectClass parent_class; +}; + +GType atspi_state_set_get_type (void); + +AtspiStateSet * atspi_state_set_new (GArray *states); + +void atspi_state_set_set_by_name (AtspiStateSet *set, const gchar *name, gboolean enabled); + +void atspi_state_set_add (AtspiStateSet *set, AtspiStateType state); + +AtspiStateSet * atspi_state_set_compare (AtspiStateSet *set, AtspiStateSet *set2); + +gboolean atspi_state_set_contains (AtspiStateSet *set, AtspiStateType state); + +gboolean atspi_state_set_equals (AtspiStateSet *set, AtspiStateSet *set2); + +GArray * atspi_state_set_get_states (AtspiStateSet *set); + +gboolean atspi_state_set_is_empty (AtspiStateSet *set); + +void atspi_state_set_remove (AtspiStateSet *set, AtspiStateType state); + +AtspiStateSet * _atspi_state_set_new_internal (struct _AtspiAccessible *accessible, gint64 states); + +G_END_DECLS + +#endif /* _ATSPI_STATE_SET_H_ */ diff --git a/atspi/atspi-table-cell.c b/atspi/atspi-table-cell.c new file mode 100644 index 0000000..1df1fa9 --- /dev/null +++ b/atspi/atspi-table-cell.c @@ -0,0 +1,288 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2013 SUSE LLC. + * + * 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. + */ + +#include /* for malloc */ +#include "atspi-private.h" + +static GPtrArray * +get_object_array_and_unref (DBusMessage *reply) +{ + DBusMessageIter iter, iter_array; + GPtrArray *array; + + if (!reply) + return NULL; + + if (strcmp (dbus_message_get_signature (reply), "(so)") != 0) + { + dbus_message_unref (reply); + return NULL; + } + + array = g_ptr_array_new (); + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *accessible = _atspi_dbus_return_accessible_from_iter (&iter_array); + g_ptr_array_add (array, accessible); + } + dbus_message_unref (reply); + return array; +} + +/** + * atspi_table_cell_get_column_span: + * @obj: a GObject instance that implements AtspiTableCellIface + * + * Returns the number of columns occupied by this cell accessible. + * + * Returns: a gint representing the number of columns occupied by this cell, + * or 0 if the cell does not implement this method. + */ +gint +atspi_table_cell_get_column_span (AtspiTableCell *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table_cell, "ColumnSpan", + error, "i", &retval); + + return retval; +} + +/** + * atspi_table_cell_get_column_header_cells: + * @obj: a GObject instance that implements AtspiTableCellIface + * + * Returns the column headers as an array of cell accessibles. + * + * Returns: (element-type AtspiAccessible) (transfer full): a GPtrArray of + * AtspiAccessibles representing the column header cells. + */ +GPtrArray * +atspi_table_cell_get_column_header_cells (AtspiTableCell *obj, GError **error) +{ + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_table_cell, "GetColumnHeaderCells", error, ""); + + return get_object_array_and_unref (reply); +} + +/** + * atspi_table_cell_get_row_span: + * @obj: a GObject instance that implements AtspiTableCellIface + * + * Returns the number of rows occupied by this cell accessible. + * + * Returns: a gint representing the number of rows occupied by this cell, + * or 0 if the cell does not implement this method. + */ +gint +atspi_table_cell_get_row_span (AtspiTableCell *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table_cell, "RowSpan", + error, "i", &retval); + + return retval; +} + +/** + * atspi_table_cell_get_row_header_cells: + * @obj: a GObject instance that implements AtspiTableCellIface + * + * Returns the row headers as an array of cell accessibles. + * + * Returns: (element-type AtspiAccessible) (transfer full): a GPtrArray of + * AtspiAccessibles representing the row header cells. + */ +GPtrArray * +atspi_table_cell_get_row_header_cells (AtspiTableCell *obj, GError **error) +{ + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_table_cell, "GetRowHeaderCells", error, ""); + + return get_object_array_and_unref (reply); +} + +/** + * atspi_table_cell_get_position: + * @obj: a GObject instance that implements AtspiTableCellIface + * @row: (out): the row of the given cell. + * @column: (out): the column of the given cell. + * + * Retrieves the tabular position of this cell. + * + * Returns: TRUE if successful, FALSE otherwise. + */ +gint +atspi_table_cell_get_position (AtspiTableCell *obj, + gint *row, + gint *column, + GError **error) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_struct, iter_variant; + dbus_int32_t d_row = -1, d_column = -1; + char *iter_sig; + + g_return_val_if_fail (obj != NULL, -1); + + reply = _atspi_dbus_call_partial (obj, "org.freedesktop.DBus.Properties", + "Get", error, "ss", + atspi_interface_table_cell, "Position"); + + if (!reply) + return -1; + + dbus_message_iter_init (reply, &iter); + + /* TODO: Return error here */ + if (dbus_message_iter_get_arg_type (&iter) != 'v') + return FALSE; + + dbus_message_iter_recurse (&iter, &iter_variant); + iter_sig = dbus_message_iter_get_signature (&iter_variant); + /* TODO: Also report error here */ + if (strcmp (iter_sig, "(ii)") != 0) + { + dbus_free (iter_sig); + return FALSE; + } + dbus_free (iter_sig); + + dbus_message_iter_recurse (&iter_variant, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_row); + if (row) + *row = d_row; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &d_column); + if (column) + *column = d_column; + dbus_message_unref (reply); + return TRUE; +} + +/** + * atspi_table_cell_get_row_column_span: + * @obj: a GObject instance that implements AtspiTableCellIface + * @row: (out): the row index of the given cell. + * @column: (out): the column index of the given cell. + * @row_span: (out): the number of rows occupied by this cell. + * @column_span: (out): the number of columns occupied by this cell. + * + * Gets the row and column indexes and extents of this cell accessible. + */ +void +atspi_table_cell_get_row_column_span (AtspiTableCell *obj, + gint *row, + gint *column, + gint *row_span, + gint *column_span, + GError **error) +{ + dbus_int32_t d_row = 0, d_column = 0, d_row_span = 0, d_column_span = 0; + + if (row) + *row = -1; + if (column) + *column = -1; + if (row_span) + *row_span = -1; + if (column_span) + *column_span = -1; + + g_return_if_fail (obj != NULL); + + _atspi_dbus_call (obj, atspi_interface_table_cell, "GetRowColumnSpan", + error, "=>iiii", &d_row, &d_column, + &d_row_span, &d_column_span); + + if (row) + *row = d_row; + if (column) + *column = d_column; + if (row_span) + *row_span = d_row_span; + if (column_span) + *column_span = d_column_span; +} + +/** + * atspi_table_cell_get_table: + * @obj: a GObject instance that implements AtspiTableCellIface + * + * Returns a reference to the accessible of the containing table. + * + * Returns: (transfer full): the AtspiAccessible for the containing table. + */ +AtspiAccessible * +atspi_table_cell_get_table (AtspiTableCell *obj, GError **error) +{ + AtspiAccessible *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_get_property (obj, atspi_interface_table_cell, "Table", + error, "(so)", &retval); + + return retval; +} + +static void +atspi_table_cell_base_init (AtspiTableCell *klass) +{ +} + +GType +atspi_table_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiTableCell), + (GBaseInitFunc) atspi_table_cell_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiTableCell", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-table-cell.h b/atspi/atspi-table-cell.h new file mode 100644 index 0000000..757ab0d --- /dev/null +++ b/atspi/atspi-table-cell.h @@ -0,0 +1,77 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_TABLE_CELL_H_ +#define _ATSPI_TABLE_CELL_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_TABLE_CELL (atspi_table_cell_get_type ()) +#define ATSPI_IS_TABLE_CELL(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TABLE_CELL) +#define ATSPI_TABLE_CELL(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TABLE_CELL, AtspiTableCell) +#define ATSPI_TABLE_CELL_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TABLE_CELL, AtspiTableCell)) + +GType atspi_table_cell_get_type (); + +struct _AtspiTableCell +{ + GTypeInterface parent; +}; + +gint atspi_table_cell_get_column_span (AtspiTableCell *obj, GError **error); + +GPtrArray *atspi_table_cell_get_column_header_cells (AtspiTableCell *obj, + GError **error); + +gint atspi_table_cell_get_column_index (AtspiTableCell *obj, GError **error); + +gint atspi_table_cell_get_row_span (AtspiTableCell *obj, GError **error); + +GPtrArray *atspi_table_cell_get_row_header_cells (AtspiTableCell *obj, + GError **error); + +gint atspi_table_cell_get_position (AtspiTableCell *obj, + gint *row, + gint *column, + GError **error); + +void atspi_table_cell_get_row_column_span (AtspiTableCell *obj, + gint *row, + gint *column, + gint *row_span, + gint *column_span, + GError **error); + +AtspiAccessible *atspi_table_cell_get_table (AtspiTableCell *obj, + GError **error); +G_END_DECLS + +#endif /* _ATSPI_TABLE_CELL_H_ */ diff --git a/atspi/atspi-table.c b/atspi/atspi-table.c new file mode 100644 index 0000000..b17e2f1 --- /dev/null +++ b/atspi/atspi-table.c @@ -0,0 +1,745 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include /* for malloc */ +#include "atspi-private.h" + +/** + * atspi_table_get_caption: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Gets an accessible representation of the caption for an #AtspiTable. + * + * Returns: (transfer full): an #AtspiAccessible object that serves as + * the table's caption. + * + **/ +AtspiAccessible * +atspi_table_get_caption (AtspiTable *obj, GError **error) +{ + AtspiAccessible *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_get_property (obj, atspi_interface_table, "Caption", error, "(so)", &retval); + return retval; +} + +/** + * atspi_table_get_summary: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Gets an accessible object which summarizes the contents of an #AtspiTable. + * + * Returns: (transfer full): an #AtspiAccessible object that serves as the + * table's summary (often a reduced #AtspiTable). + **/ +AtspiAccessible * +atspi_table_get_summary (AtspiTable *obj, GError **error) +{ + AtspiAccessible *retval; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_get_property (obj, atspi_interface_table, "Summary", error, "(so)", &retval); + + return retval; +} + +/** + * atspi_table_get_n_rows: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Gets the number of rows in an #AtspiTable, + * exclusive of any rows that are programmatically hidden, but inclusive + * of rows that may be outside of the current scrolling window or viewport. + * + * Returns: a #gint indicating the number of rows in the table. + **/ +gint +atspi_table_get_n_rows (AtspiTable *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table, "NRows", error, "i", &retval); + + return retval; +} + +/** + * atspi_table_get_n_columns: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Gets the number of columns in an #AtspiTable, + * exclusive of any columns that are programmatically hidden, but inclusive + * of columns that may be outside of the current scrolling window or viewport. + * + * Returns: a #gint indicating the number of columns in the table. + **/ +gint +atspi_table_get_n_columns (AtspiTable *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table, "NColumns", error, "i", &retval); + + return retval; +} + +/** + * atspi_table_get_accessible_at: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * @column: the specified table column, zero-indexed. + * + * Gets the table cell at the specified row and column indices. + * To get the accessible object at a particular (x, y) screen + * coordinate, use #atspi_component_get_accessible_at_point. + * + * Returns: (transfer full): an #AtspiAccessible object representing the + * specified table cell. + **/ +AtspiAccessible * +atspi_table_get_accessible_at (AtspiTable *obj, + gint row, + gint column, + GError **error) +{ + dbus_int32_t d_row = row, d_column = column; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetAccessibleAt", error, "ii", d_row, d_column); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_table_get_index_at: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * @column: the specified table column, zero-indexed. + * + * Gets the 1-D child index corresponding to the specified 2-D row and + * column indices. To get the accessible object at a particular (x, y) screen + * coordinate, use #atspi_component_get_accessible_at_point. + * + * @see #atspi_table_get_row_at_index, #atspi_table_get_column_at_index + * + * Returns: a #gint which serves as the index of a specified cell in the + * table, in a form usable by #atspi_get_child_at_index. + **/ +gint +atspi_table_get_index_at (AtspiTable *obj, + gint row, + gint column, + GError **error) +{ + dbus_int32_t d_row = row, d_column = column; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_table, "GetIndexAt", error, "ii=>i", d_row, d_column, &retval); + + return retval; +} + +/** + * atspi_table_get_row_at_index: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @index: the specified child index, zero-indexed. + * + * Gets the table row index occupied by the child at a particular 1-D + * child index. + * + * @see #atspi_table_get_index_at, #atspi_table_get_column_at_index + * + * Returns: a #gint indicating the first row spanned by the child of a + * table, at the specified 1-D (zero-offset) @index. + **/ +gint +atspi_table_get_row_at_index (AtspiTable *obj, + gint index, + GError **error) +{ + dbus_int32_t d_index = index; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_table, "GetRowAtIndex", error, "i=>i", d_index, &retval); + + return retval; +} + +/** + * atspi_table_get_column_at_index: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @index: the specified child index, zero-indexed. + * + * Gets the table column index occupied by the child at a particular 1-D + * child index. + * + * @see #atspi_table_get_index_at, #atspi_table_get_row_at_index + * + * Returns: a #gint indicating the first column spanned by the child of a + * table, at the specified 1-D (zero-offset) @index. + **/ +gint +atspi_table_get_column_at_index (AtspiTable *obj, + gint index, + GError **error) +{ + dbus_int32_t d_index = index; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_table, "GetColumnAtIndex", error, "i=>i", d_index, &retval); + + return retval; +} + +/** + * atspi_table_get_row_description: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * + * Gets a text description of a particular table row. This differs from + * #atspi_table_get_row_header, which returns an #AtspiAccessible. + * + * Returns: a UTF-8 string describing the specified table row, if available. + **/ +gchar * +atspi_table_get_row_description (AtspiTable *obj, + gint row, + GError **error) +{ + dbus_int32_t d_row = row; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_table, "GetRowDescription", error, "i=>s", d_row, &retval); + + return retval; +} + +/** + * atspi_table_get_column_description: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @column: the specified table column, zero-indexed. + * + * Gets a text description of a particular table column. This differs from + * #atspi_table_get_column_header, which returns an #Accessible. + * + * Returns: a UTF-8 string describing the specified table column, if available. + **/ +gchar * +atspi_table_get_column_description (AtspiTable *obj, + gint column, GError **error) +{ + dbus_int32_t d_column = column; + char *retval = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_table, "GetColumnDescription", error, "i=>s", d_column, &retval); + + return retval; +} + +/** + * atspi_table_get_row_extent_at: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * @column: the specified table column, zero-indexed. + * + * Gets the number of rows spanned by the table cell at the specific row + * and column. (some tables can have cells which span multiple rows + * and/or columns). + * + * Returns: a #gint indicating the number of rows spanned by the specified cell. + **/ +gint +atspi_table_get_row_extent_at (AtspiTable *obj, + gint row, + gint column, + GError **error) +{ + dbus_int32_t d_row = row, d_column = column; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_table, "GetRowExtentAt", error, "ii=>i", d_row, d_column, &retval); + + return retval; +} + +/** + * atspi_table_get_column_extent_at: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * @column: the specified table column, zero-indexed. + * + * Gets the number of columns spanned by the table cell at the specific + * row and column (some tables can have cells which span multiple + * rows and/or columns). + * + * Returns: a #gint indicating the number of columns spanned by the specified cell. + **/ +gint +atspi_table_get_column_extent_at (AtspiTable *obj, + gint row, + gint column, + GError **error) +{ + dbus_int32_t d_row = row, d_column = column; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_table, "GetColumnExtentAt", error, "ii=>i", d_row, d_column, &retval); + + return retval; +} + +/** + * atspi_table_get_row_header: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the specified table row, zero-indexed. + * + * Gets the header associated with a table row, if available. This differs from + * #atspi_table_get_row_description, which returns a string. + * + * Returns: (transfer full): an #AtspiAccessible representation of the specified + * table row, if available. + **/ +AtspiAccessible * +atspi_table_get_row_header (AtspiTable *obj, + gint row, + GError **error) +{ + dbus_int32_t d_row = row; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetRowHeader", error, "i", d_row); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_table_get_column_header: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @column: the specified table column, zero-indexed. + * + * Gets the header associated with a table column, if available. + * This differs from #atspi_table_get_column_description, which + * returns a string. + * + * Returns: (transfer full): an #AtspiAccessible representation of the + * specified table column, if available. + **/ +AtspiAccessible * +atspi_table_get_column_header (AtspiTable *obj, + gint column, + GError **error) +{ + dbus_int32_t d_column = column; + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_table, "GetColumnHeader", error, "i", d_column); + + return _atspi_dbus_return_accessible_from_message (reply); +} + +/** + * atspi_table_get_n_selected_rows: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Query a table to find out how many rows are currently selected. + * Not all tables support row selection. + * + * Returns: a #gint indicating the number of rows currently selected. + **/ +gint +atspi_table_get_n_selected_rows (AtspiTable *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table, "NSelectedRows", error, "i", &retval); + + return retval; +} + +/** + * atspi_table_get_selected_rows: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Queries a table for a list of indices of rows which are currently selected. + * + * Returns: (element-type gint) (transfer full): an array of #gint values, + * specifying which rows are currently selected. + **/ +GArray * +atspi_table_get_selected_rows (AtspiTable *obj, + GError **error) +{ + GArray *rows = NULL; + + g_return_val_if_fail (obj != NULL, 0); + + _atspi_dbus_call (obj, atspi_interface_table, "GetSelectedRows", error, "=>ai", &rows); + + return rows; +} + +/** + * atspi_table_get_selected_columns: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Queries a table for a list of indices of columns which are currently + * selected. + * + * Returns: (element-type gint) (transfer full): an array of #gint values, + * specifying which columns are currently selected. + **/ +GArray * +atspi_table_get_selected_columns (AtspiTable *obj, + GError **error) +{ + GArray *columns = NULL; + + g_return_val_if_fail (obj != NULL, 0); + + _atspi_dbus_call (obj, atspi_interface_table, "GetSelectedColumns", error, "=>ai", &columns); + + return columns; +} + +/** + * atspi_table_get_n_selected_columns: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * + * Queries a table to find out how many columns are currently selected. + * Not all tables support column selection. + * + * Returns: a #gint indicating the number of columns currently selected. + **/ +gint +atspi_table_get_n_selected_columns (AtspiTable *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_table, "NSelectedColumns", error, "i", &retval); + + return retval; +} + +/** + * atspi_table_is_row_selected: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the zero-indexed row number of the row being queried. + * + * Determines whether a table row is selected. Not all tables support + * row selection. + * + * Returns: #TRUE if the specified row is currently selected, #FALSE if not. + **/ +gboolean +atspi_table_is_row_selected (AtspiTable *obj, + gint row, + GError **error) +{ + dbus_int32_t d_row = row; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "IsRowSelected", error, "i=>b", d_row, &retval); + + return retval; +} + +/** + * atspi_table_is_column_selected: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @column: the zero-indexed column number of the column being queried. + * + * Determines whether specified table column is selected. + * Not all tables support column selection. + * + * Returns: #TRUE if the specified column is currently selected, #FALSE if not. + **/ +gboolean +atspi_table_is_column_selected (AtspiTable *obj, + gint column, + GError **error) +{ + dbus_int32_t d_column = column; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "IsColumnSelected", error, "i=>b", d_column, &retval); + + return retval; +} + +/** + * atspi_table_add_row_selection: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the zero-indexed row number of the row being selected. + * + * Selects the specified row, adding it to the current row selection. + * Not all tables support row selection. + * + * Returns: #TRUE if the specified row was successfully selected, #FALSE if not. + **/ +gboolean +atspi_table_add_row_selection (AtspiTable *obj, + gint row, + GError **error) +{ + dbus_int32_t d_row = row; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "AddRowSelection", error, "i=>b", d_row, &retval); + + return retval; +} + +/** + * atspi_table_add_column_selection: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @column: the zero-indexed column number of the column being selected. + * + * Selects the specified column, adding it to the current column selection. + * Not all tables support column selection. + * + * Returns: #TRUE if the specified column was successfully selected, #FALSE if not. + **/ +gboolean +atspi_table_add_column_selection (AtspiTable *obj, + gint column, + GError **error) +{ + dbus_int32_t d_column = column; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "AddColumnSelection", error, "i=>b", d_column, &retval); + + return retval; +} + +/** + * atspi_table_remove_row_selection: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the zero-indexed number of the row being de-selected. + * + * De-selects the specified row, removing it from the current row selection. + * Not all tables support row selection. + * + * Returns: #TRUE if the specified row was successfully de-selected, + * #FALSE if not. + **/ +gboolean +atspi_table_remove_row_selection (AtspiTable *obj, + gint row, + GError **error) +{ + dbus_int32_t d_row = row; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "RemoveRowSelection", error, "i=>b", d_row, &retval); + + return retval; +} + +/** + * atspi_table_remove_column_selection: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @column: the zero-indexed column number of the column being de-selected. + * + * De-selects the specified column, removing it from the current column + * selection. + * Not all tables support column selection. + * + * Returns: #TRUE if the specified column was successfully de-selected, + * #FALSE if not. + **/ +gboolean +atspi_table_remove_column_selection (AtspiTable *obj, + gint column, + GError **error) +{ + dbus_int32_t d_column = column; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "RemoveColumnSelection", error, "i=>b", d_column, &retval); + + return retval; +} + +/** + * atspi_table_get_row_column_extents_at_index: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @index: the index of the #AtspiTable child whose row/column + * extents are requested. + * @row: (out): back-filled with the first table row associated with + * the cell with child index. + * @col: (out): back-filled with the first table column associated + * with the cell with child index. + * @row_extents: (out): back-filled with the number of table rows + * across which child i extends. + * @col_extents: (out): back-filled with the number of table columns + * across which child i extends. + * @is_selected: (out): a boolean which is back-filled with #TRUE + * if the child at index i corresponds to a selected table cell, + * #FALSE otherwise. + * + * Given a child index, determines the row and column indices and + * extents, and whether the cell is currently selected. If + * the child at index is not a cell (for instance, if it is + * a summary, caption, etc.), #FALSE is returned. + * + * Example: + * If the #AtspiTable child at index '6' extends across columns 5 and 6 of + * row 2 of an #AtspiTable instance, and is currently selected, then + * + * retval = atspi_table_get_row_column_extents_at_index (table, 6, + * row, col, + * row_extents, + * col_extents, + * is_selected); + * + * will return #TRUE, and after the call + * row, col, row_extents, col_extents, + * and is_selected will contain 2, 5, 1, 2, and + * #TRUE, respectively. + * + * Returns: #TRUE if the index is associated with a valid table + * cell, #FALSE if the index does not correspond to a cell. If + * #FALSE is returned, the values of the out parameters are + * undefined. + **/ +gboolean +atspi_table_get_row_column_extents_at_index (AtspiTable *obj, + gint index, gint *row, gint *col, + gint *row_extents, gint *col_extents, + gboolean *is_selected, GError **error) +{ + dbus_int32_t d_index = index; + dbus_bool_t retval = FALSE; + dbus_int32_t d_row = 0, d_col = 0, d_row_extents = 0, d_col_extents = 0; + dbus_bool_t d_is_selected = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "GetRowColumnExtentsAtIndex", + error, "i=>biiiib", d_index, &retval, &d_row, &d_col, + &d_row_extents, &d_col_extents, &d_is_selected); + + *row = d_row; + *col = d_col; + *row_extents = d_row_extents;; + *col_extents = d_col_extents; + *is_selected = d_is_selected;; + + return retval; +} + + +/** + * atspi_table_is_selected: + * @obj: a pointer to the #AtspiTable implementor on which to operate. + * @row: the zero-indexed row of the cell being queried. + * @column: the zero-indexed column of the cell being queried. + * + * Determines whether the cell at a specific row and column is selected. + * + * Returns: #TRUE if the specified cell is currently selected, #FALSE if not. + **/ +gboolean +atspi_table_is_selected (AtspiTable *obj, + gint row, + gint column, + GError **error) +{ + dbus_int32_t d_row = row, d_column = column; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_table, "IsSelected", error, "ii=>b", d_row, d_column, &retval); + + return retval; +} + +static void +atspi_table_base_init (AtspiTable *klass) +{ +} + +GType +atspi_table_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiTable), + (GBaseInitFunc) atspi_table_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiTable", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-table.h b/atspi/atspi-table.h new file mode 100644 index 0000000..1295df1 --- /dev/null +++ b/atspi/atspi-table.h @@ -0,0 +1,105 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_TABLE_H_ +#define _ATSPI_TABLE_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_TABLE (atspi_table_get_type ()) +#define ATSPI_IS_TABLE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TABLE) +#define ATSPI_TABLE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TABLE, AtspiTable) +#define ATSPI_TABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TABLE, AtspiTable)) + +GType atspi_table_get_type (); + +struct _AtspiTable +{ + GTypeInterface parent; +}; + +AtspiAccessible * atspi_table_get_caption (AtspiTable *obj, GError **error); + +AtspiAccessible * atspi_table_get_summary (AtspiTable *obj, GError **error); + +gint atspi_table_get_n_rows (AtspiTable *obj, GError **error); + +gint atspi_table_get_n_columns (AtspiTable *obj, GError **error); + +AtspiAccessible * atspi_table_get_accessible_at (AtspiTable *obj, gint row, gint column, GError **error); + +gint atspi_table_get_index_at (AtspiTable *obj, gint row, gint column, GError **error); + +gint atspi_table_get_row_at_index (AtspiTable *obj, gint index, GError **error); + +gint atspi_table_get_column_at_index (AtspiTable *obj, gint index, GError **error); + +gchar * atspi_table_get_row_description (AtspiTable *obj, gint row, GError **error); + +gchar * atspi_table_get_column_description (AtspiTable *obj, gint column, GError **error); + +gint +atspi_table_get_row_extent_at (AtspiTable *obj, gint row, gint column, GError **error); + +gint +atspi_table_get_column_extent_at (AtspiTable *obj, gint row, gint column, GError **error); + +AtspiAccessible * atspi_table_get_row_header (AtspiTable *obj, gint row, GError **error); + +AtspiAccessible * atspi_table_get_column_header (AtspiTable *obj, gint column, GError **error); + +gint atspi_table_get_n_selected_rows (AtspiTable *obj, GError **error); + +GArray *atspi_table_get_selected_rows (AtspiTable *obj, GError **error); + +GArray * atspi_table_get_selected_columns (AtspiTable *obj, GError **error); + +gint atspi_table_get_n_selected_columns (AtspiTable *obj, GError **error); + +gboolean atspi_table_is_row_selected (AtspiTable *obj, gint row, GError **error); + +gboolean atspi_table_is_column_selected (AtspiTable *obj, gint column, GError **error); + +gboolean atspi_table_add_row_selection (AtspiTable *obj, gint row, GError **error); + +gboolean atspi_table_add_column_selection (AtspiTable *obj, gint column, GError **error); + +gboolean atspi_table_remove_row_selection (AtspiTable *obj, gint row, GError **error); + +gboolean atspi_table_remove_column_selection (AtspiTable *obj, gint column, GError **error); + +gboolean atspi_table_get_row_column_extents_at_index (AtspiTable *obj, gint index, gint *row, gint *col, gint *row_extents, gint *col_extents, gboolean *is_selected, GError **error); + +gboolean atspi_table_is_selected (AtspiTable *obj, gint row, gint column, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_TABLE_H_ */ diff --git a/atspi/atspi-text.c b/atspi/atspi-text.c new file mode 100644 index 0000000..1e887d3 --- /dev/null +++ b/atspi/atspi-text.c @@ -0,0 +1,917 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" +/** + * atspi_range_copy: + * @src: a pointer to the source #AtspiRange object that will be copied. + * + * Gets a copy of an #AtspiRange object. + * + * Returns: the #AtspiRange copy of an #AtspiRange object. + **/ +AtspiRange * +atspi_range_copy (AtspiRange *src) +{ + AtspiRange *dst = g_new (AtspiRange, 1); + + dst->start_offset = src->start_offset; + dst->end_offset = src->end_offset; + return dst; +} + +G_DEFINE_BOXED_TYPE (AtspiRange, atspi_range, atspi_range_copy, g_free) + +static AtspiTextRange * +atspi_text_range_copy (AtspiTextRange *src) +{ + AtspiTextRange *dst = g_new (AtspiTextRange, 1); + + dst->content = g_strdup (src->content); + dst->start_offset = src->start_offset; + dst->end_offset = src->end_offset; + return dst; +} + +static void +atspi_text_range_free (AtspiTextRange *range) +{ + g_free (range->content); + g_free (range); +} + +G_DEFINE_BOXED_TYPE (AtspiTextRange, atspi_text_range, atspi_text_range_copy, + atspi_text_range_free) + +/** + * atspi_text_get_character_count: + * @obj: a pointer to the #AtspiText object to query. + * + * Gets the character count of an #AccessibleText object. + * + * Returns: a #gint indicating the total number of + * characters in the #AccessibleText object. + **/ +gint +atspi_text_get_character_count (AtspiText *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_text, "CharacterCount", error, "i", &retval); + + return retval; +} + +/** + * atspi_text_get_text: + * @obj: a pointer to the #AtspiText object to query. + * @start_offset: a #gint indicating the start of the desired text range. + * @end_offset: a #gint indicating the first character past the desired range. + * + * Gets a range of text from an #AtspiText object. The number of bytes + * in the returned string may exceed either end_offset or start_offset, since + * UTF-8 is a variable-width encoding. + * + * Returns: a text string containing characters from @start_offset + * to @end_offset-1, inclusive, encoded as UTF-8. + **/ +gchar * +atspi_text_get_text (AtspiText *obj, + gint start_offset, + gint end_offset, + GError **error) +{ + gchar *retval = NULL; + dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset; + + g_return_val_if_fail (obj != NULL, g_strdup ("")); + + _atspi_dbus_call (obj, atspi_interface_text, "GetText", error, "ii=>s", d_start_offset, d_end_offset, &retval); + + if (!retval) + retval = g_strdup (""); + + return retval; +} + +/** + * atspi_text_get_caret_offset: + * @obj: a pointer to the #AtspiText object to query. + * + * Gets the current offset of the text caret in an #AtspiText object. + * + * Returns: a #gint indicating the current position of the text caret. + **/ +gint +atspi_text_get_caret_offset (AtspiText *obj, GError **error) +{ + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_get_property (obj, atspi_interface_text, "CaretOffset", error, "i", &retval); + + return retval; +} + +/** + * atspi_text_get_attributes: (rename-to atspi_text_get_text_attributes) + * @obj: a pointer to the #AtspiText object to query. + * @offset: a #gint indicating the offset from which the attribute + * search is based. + * @start_offset: (out): a #gint pointer indicating the start of the desired text + * range. + * @end_offset: (out): a #gint pointer indicating the first character past the desired + * range. + * + * Gets the attributes applied to a range of text from an #AtspiText + * object. The text attributes correspond to CSS attributes + * where possible. + * DEPRECATED + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable + * describing the attributes at the given character offset. + * + * Deprecated: 2.10: Use atspi_text_get_text_attributes instead. + **/ +GHashTable * +atspi_text_get_attributes (AtspiText *obj, + gint offset, + gint *start_offset, + gint *end_offset, + GError **error) +{ + return atspi_text_get_text_attributes (obj, offset, start_offset, end_offset, error); +} + +/** + * atspi_text_get_text_attributes: + * @obj: a pointer to the #AtspiText object to query. + * @offset: a #gint indicating the offset from which the attribute + * search is based. + * @start_offset: (out): a #gint pointer indicating the start of the desired text + * range. + * @end_offset: (out): a #gint pointer indicating the first character past the desired + * range. + * + * Gets the attributes applied to a range of text from an #AtspiText + * object. The text attributes correspond to CSS attributes + * where possible. + * DEPRECATED + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable + * describing the attributes at the given character offset. + **/ +GHashTable * +atspi_text_get_text_attributes (AtspiText *obj, + gint offset, + gint *start_offset, + gint *end_offset, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_int32_t d_start_offset, d_end_offset; + DBusMessage *reply; + DBusMessageIter iter; + GHashTable *ret = NULL; + + if (obj == NULL) + return NULL; + + reply = _atspi_dbus_call_partial (obj, atspi_interface_text, "GetAttributes", error, "i", d_offset); + _ATSPI_DBUS_CHECK_SIG (reply, "a{ss}ii", error, ret) + + dbus_message_iter_init (reply, &iter); + ret = _atspi_dbus_hash_from_iter (&iter); + dbus_message_iter_next (&iter); + + dbus_message_iter_get_basic (&iter, &d_start_offset); + if (start_offset) + *start_offset = d_start_offset; + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &d_end_offset); + if (end_offset) + *end_offset = d_end_offset; + + dbus_message_unref (reply); + return ret; +} + +/** + * atspi_text_get_attribute_run: + * @obj: a pointer to the #AtspiText object to query. + * @offset: a #gint indicating the offset from which the attribute + * search is based. + * @include_defaults: a #bool that, when set as #FALSE, indicates the call + * should only return those attributes which are explicitly set on the current + * attribute run, omitting any attributes which are inherited from the + * default values. + * @start_offset: (out): a #gint pointer indicating the start of the desired text + * range. + * @end_offset: (out): a #gint pointer indicating the first character past the desired + * range. + * + * Gets a set of attributes applied to a range of text from an #AtspiText object, optionally + * including its 'default' attributes. + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable with attributes + * defined at the indicated offset, optionally including the 'default' ones. + **/ +GHashTable * +atspi_text_get_attribute_run (AtspiText *obj, + gint offset, + gboolean include_defaults, + gint *start_offset, + gint *end_offset, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_int32_t d_start_offset, d_end_offset; + DBusMessage *reply; + DBusMessageIter iter; + GHashTable *ret = NULL; + + if (obj == NULL) + return NULL; + + reply = _atspi_dbus_call_partial (obj, atspi_interface_text, + "GetAttributeRun", error, "ib", d_offset, + include_defaults); + _ATSPI_DBUS_CHECK_SIG (reply, "a{ss}ii", error, ret) + + dbus_message_iter_init (reply, &iter); + ret = _atspi_dbus_hash_from_iter (&iter); + dbus_message_iter_next (&iter); + + dbus_message_iter_get_basic (&iter, &d_start_offset); + if (start_offset) + *start_offset = d_start_offset; + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &d_end_offset); + if (end_offset) + *end_offset = d_end_offset; + + dbus_message_unref (reply); + return ret; +} + +/** + * atspi_text_get_attribute_value: (rename-to atspi_text_get_text_attribute_value) + * @obj: a pointer to the #AtspiText object to query. + * @offset: The character offset at which to query the attribute. + * @attribute_name: The attribute to query. + * + * Gets the value of a named attribute at a given offset. + * + * Returns: (nullable): the value of a given attribute at the given + * offset, or %NULL if not present. + * + * Deprecated: 2.10: Use atspi_text_get_text_attribute_value instead. + **/ +gchar * +atspi_text_get_attribute_value (AtspiText *obj, + gint offset, + gchar *attribute_value, + GError **error) +{ + return atspi_text_get_text_attribute_value (obj, offset, attribute_value, + error); +} + +/** + * atspi_text_get_text_attribute_value: + * @obj: a pointer to the #AtspiText object to query. + * @offset: The character offset at which to query the attribute. + * @attribute_name: The attribute to query. + * + * Gets the value of a named attribute at a given offset. + * + * Returns: (nullable): the value of a given attribute at the given offset, or %NULL if + * not present. + **/ +gchar * +atspi_text_get_text_attribute_value (AtspiText *obj, + gint offset, + gchar *attribute_value, + GError **error) +{ + gchar *retval = NULL; + dbus_int32_t d_i = offset; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_text, "GetAttributeValue", error, "is=>s", d_i, (const gchar *)attribute_value, &retval); + + if (!retval) + retval = g_strdup (""); + + return retval; +} + +/** + * atspi_text_get_default_attributes: + * @obj: a pointer to the #AtspiText object to query. + * + * Gets the default attributes applied to an #AtspiText + * object. The text attributes correspond to CSS attributes + * where possible. The combination of this attribute set and + * the attributes reported by #atspi_text_get_attributes + * describes the entire set of text attributes over a range. + * + * Returns: (element-type gchar* gchar*) (transfer full): a #GHashTable + * containing the default attributes applied to a text object, + * (exclusive of explicitly-set attributes), encoded as UTF-8. + **/ +GHashTable * +atspi_text_get_default_attributes (AtspiText *obj, GError **error) +{ + DBusMessage *reply; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_text, "GetDefaultAttributes", error, ""); + return _atspi_dbus_return_hash_from_message (reply); +} + + +/** + * atspi_text_set_caret_offset: + * @obj: a pointer to the #AtspiText object on which to operate. + * @new_offset: the offset to which the text caret is to be moved. + * + * Moves the text caret to a given position. + * + * Returns: #TRUE if successful, #FALSE otherwise. + **/ +gboolean +atspi_text_set_caret_offset (AtspiText *obj, + gint new_offset, + GError **error) +{ + dbus_int32_t d_new_offset = new_offset; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_text, "SetCaretOffset", error, "i=>b", d_new_offset, &retval); + + return retval; +} + +/** + * atspi_text_get_text_before_offset: + * @obj: a pointer to the #AtspiText object on which to operate. + * @offset: a #gint indicating the offset from which the delimiter + * search is based. + * @type: an #AtspiTextBoundaryType indicating whether the desired + * text string is a word, sentence, line, or attribute run. + * + * Gets delimited text from an #AtspiText object which precedes a given + * text offset. + * + * Returns: an #AtspiTextRange containing a UTF-8 string representing the + * delimited text, both of whose delimiting boundaries are before the + * current offset, or an empty string if no such text exists. + **/ +AtspiTextRange * +atspi_text_get_text_before_offset (AtspiText *obj, + gint offset, + AtspiTextBoundaryType type, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_uint32_t d_type = type; + dbus_int32_t d_start_offset = -1, d_end_offset = -1; + AtspiTextRange *range = g_new0 (AtspiTextRange, 1); + + range->start_offset = range->end_offset = -1; + if (!obj) + return range; + + _atspi_dbus_call (obj, atspi_interface_text, "GetTextBeforeOffset", error, + "iu=>sii", d_offset, d_type, &range->content, + &d_start_offset, &d_end_offset); + + range->start_offset = d_start_offset; + range->end_offset = d_end_offset; + if (!range->content) + range->content = g_strdup (""); + + return range; +} + +/** + * atspi_text_get_string_at_offset: + * @obj: an #AtspiText + * @offset: position + * @granularity: An #AtspiTextGranularity + * + * Gets a portion of the text exposed through an #AtspiText according to a given @offset + * and a specific @granularity, along with the start and end offsets defining the + * boundaries of such a portion of text. + * + * If @granularity is ATSPI_TEXT_GRANULARITY_CHAR the character at the + * offset is returned. + * + * If @granularity is ATSPI_TEXT_GRANULARITY_WORD the returned string + * is from the word start at or before the offset to the word start after + * the offset. + * + * The returned string will contain the word at the offset if the offset + * is inside a word and will contain the word before the offset if the + * offset is not inside a word. + * + * If @granularity is ATSPI_TEXT_GRANULARITY_SENTENCE the returned string + * is from the sentence start at or before the offset to the sentence + * start after the offset. + * + * The returned string will contain the sentence at the offset if the offset + * is inside a sentence and will contain the sentence before the offset + * if the offset is not inside a sentence. + * + * If @granularity is ATSPI_TEXT_GRANULARITY_LINE the returned string + * is from the line start at or before the offset to the line + * start after the offset. + * + * If @granularity is ATSPI_TEXT_GRANULARITY_PARAGRAPH the returned string + * is from the start of the paragraph at or before the offset to the start + * of the following paragraph after the offset. + * + * Since: 2.9.90 + * + * Returns: a newly allocated string containing the text at the @offset bounded + * by the specified @granularity. Use g_free() to free the returned string. + * Returns %NULL if the offset is invalid or no implementation is available. + **/ +AtspiTextRange * +atspi_text_get_string_at_offset (AtspiText *obj, + gint offset, + AtspiTextGranularity granularity, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_uint32_t d_granularity = granularity; + dbus_int32_t d_start_offset = -1, d_end_offset = -1; + AtspiTextRange *range = g_new0 (AtspiTextRange, 1); + + range->start_offset = range->end_offset = -1; + if (!obj) + return range; + + _atspi_dbus_call (obj, atspi_interface_text, "GetStringAtOffset", error, + "iu=>sii", d_offset, d_granularity, &range->content, + &d_start_offset, &d_end_offset); + + range->start_offset = d_start_offset; + range->end_offset = d_end_offset; + if (!range->content) + range->content = g_strdup (""); + + return range; +} + +/** + * atspi_text_get_text_at_offset: + * @obj: a pointer to the #AtspiText object on which to operate. + * @offset: a #gint indicating the offset from which the delimiter + * search is based. + * @type: an #AtspiTextBoundaryType indicating whether the desired + * text string is a word, sentence, line, or attribute run. + * + * Gets delimited text from an #AtspiText object which includes a given + * text offset. + * + * Returns: an #AtspiTextRange containing a UTF-8 string representing the + * delimited text, whose delimiting boundaries bracket the + * current offset, or an empty string if no such text exists. + * + * Deprecated: 2.10: Use atspi_text_get_string_at_offset. + **/ +AtspiTextRange * +atspi_text_get_text_at_offset (AtspiText *obj, + gint offset, + AtspiTextBoundaryType type, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_uint32_t d_type = type; + dbus_int32_t d_start_offset = -1, d_end_offset = -1; + AtspiTextRange *range = g_new0 (AtspiTextRange, 1); + + range->start_offset = range->end_offset = -1; + if (!obj) + return range; + + _atspi_dbus_call (obj, atspi_interface_text, "GetTextAtOffset", error, + "iu=>sii", d_offset, d_type, &range->content, + &d_start_offset, &d_end_offset); + + range->start_offset = d_start_offset; + range->end_offset = d_end_offset; + if (!range->content) + range->content = g_strdup (""); + + return range; +} + +/** + * atspi_text_get_text_after_offset: + * @obj: a pointer to the #AtspiText object on which to operate. + * @offset: a #gint indicating the offset from which the delimiter + * search is based. + * @type: an #AtspiTextBoundaryType indicating whether the desired + * text string is a word, sentence, line, or attribute run. + * + * Gets delimited text from an #AtspiText object which follows a given + * text offset. + * + * Returns: an #AtspiTextRange containing a UTF-8 string representing the + * delimited text, both of whose delimiting boundaries are after or + * inclusive of the current offset, or an empty string if no such + * text exists. + **/ +AtspiTextRange * +atspi_text_get_text_after_offset (AtspiText *obj, + gint offset, + AtspiTextBoundaryType type, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_uint32_t d_type = type; + dbus_int32_t d_start_offset = -1, d_end_offset = -1; + AtspiTextRange *range = g_new0 (AtspiTextRange, 1); + + range->start_offset = range->end_offset = -1; + if (!obj) + return range; + + _atspi_dbus_call (obj, atspi_interface_text, "GetTextAfterOffset", error, + "iu=>sii", d_offset, d_type, &range->content, + &d_start_offset, &d_end_offset); + + range->start_offset = d_start_offset; + range->end_offset = d_end_offset; + if (!range->content) + range->content = g_strdup (""); + + return range; +} + +/** + * atspi_text_get_character_at_offset: + * @obj: a pointer to the #AtspiText object on which to operate. + * @offset: a #gint indicating the text offset where the desired + * character is located. + * + * Gets the character at a given offset for an #AtspiText object. + * + * Returns: a #guint representing the + * UCS-4 unicode code point of the given character, or + * 0xFFFFFFFF if the character in question cannot be represented + * in the UCS-4 encoding. + **/ +guint +atspi_text_get_character_at_offset (AtspiText *obj, + gint offset, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_text, "GetCharacterAtOffset", error, "i=>i", d_offset, &retval); + + return retval; +} + +/** + * atspi_text_get_character_extents: + * @obj: a pointer to the #AtspiText object on which to operate. + * @offset: a #gint indicating the offset of the text character for + * whom boundary information is requested. + * @type: an #AccessibleCoordType indicating the coordinate system to use + * for the returned values. + * + * Gets a bounding box containing the glyph representing + * the character at a particular text offset. + * + * Returns: An #AtspiRect specifying the position and size of the character. + * + **/ +AtspiRect * +atspi_text_get_character_extents (AtspiText *obj, + gint offset, + AtspiCoordType type, + GError **error) +{ + dbus_int32_t d_offset = offset; + dbus_uint32_t d_type = type; + dbus_int32_t d_x, d_y, d_width, d_height; + AtspiRect ret; + + ret.x = ret.y = ret.width = ret.height = -1; + + if (obj == NULL) + return atspi_rect_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_text, "GetCharacterExtents", error, "iu=>iiii", d_offset, d_type, &d_x, &d_y, &d_width, &d_height); + + ret.x = d_x; + ret.y = d_y; + ret.width = d_width; + ret.height = d_height; + return atspi_rect_copy (&ret); +} + +/** + * atspi_text_get_offset_at_point: + * @obj: a pointer to the #AtspiText object on which to operate. + * @x: the x coordinate of the point to be queried. + * @y: the y coordinate of the point to be queried. + * @type: an #AtspiCoordType indicating the coordinate system in which + * the values should be returned. + * + * Gets the character offset into the text at a given point. + * + * Returns: the offset (as a #gint) at the point (@x, @y) + * in the specified coordinate system. + * + **/ +gint +atspi_text_get_offset_at_point (AtspiText *obj, + gint x, + gint y, + AtspiCoordType type, + GError **error) +{ + dbus_int32_t d_x = x, d_y = y; + dbus_uint32_t d_type = type; + dbus_int32_t retval = -1; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_text, "GetOffsetAtPoint", error, "iiu=>i", d_x, d_y, d_type, &retval); + + return retval; +} + +/** + * atspi_text_get_range_extents: + * @obj: a pointer to the #AtspiText object on which to operate. + * @start_offset: a #gint indicating the offset of the first text character for + * whom boundary information is requested. + * @end_offset: a #gint indicating the offset of the text character + * after the last character for whom boundary information is requested. + * @type: an #AtspiCoordType indicating the coordinate system to use + * for the returned values. + * + * Gets the bounding box for text within a range in an #AtspiText object. + * + * Returns: An #AtspiRect giving the position and size of the specified range + * of text. + * + **/ +AtspiRect * +atspi_text_get_range_extents (AtspiText *obj, + gint start_offset, + gint end_offset, + AtspiCoordType type, + GError **error) +{ + dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset; + dbus_uint32_t d_type = type; + dbus_int32_t d_x, d_y, d_width, d_height; + AtspiRect ret; + + ret.x = ret.y = ret.width = ret.height = -1; + + if (obj == NULL) + return atspi_rect_copy (&ret); + + _atspi_dbus_call (obj, atspi_interface_text, "GetRangeExtents", error, "iiu=>iiii", d_start_offset, d_end_offset, d_type, &d_x, &d_y, &d_width, &d_height); + + ret.x = d_x; + ret.y = d_y; + ret.width = d_width; + ret.height = d_height; + return atspi_rect_copy (&ret); +} + +/** + * atspi_text_get_bounded_ranges: + * @obj: a pointer to the #AtspiText object on which to operate. + * @x: the 'starting' x coordinate of the bounding box. + * @y: the 'starting' y coordinate of the bounding box. + * @width: the x extent of the bounding box. + * @height: the y extent of the bounding box. + * @type: an #AccessibleCoordType indicating the coordinate system to use + * for the returned values. + * @clipTypeX: an #AtspiTextClipType indicating how to treat characters that + * intersect the bounding box's x extents. + * @clipTypeY: an #AtspiTextClipType indicating how to treat characters that + * intersect the bounding box's y extents. + * + * Gets the ranges of text from an #AtspiText object which lie within the + * bounds defined by (@x, @y) and (@x+@width, @y+@height). + * + * Returns: (transfer full) (element-type AtspiTextRange*): a null-terminated list of + * pointers to #AtspiTextRange structs detailing the bounded text. + **/ +GArray * +atspi_text_get_bounded_ranges (AtspiText *obj, + gint x, + gint y, + gint width, + gint height, + AtspiCoordType type, + AtspiTextClipType clipTypeX, + AtspiTextClipType clipTypeY, + GError **error) +{ + dbus_int32_t d_x = x, d_y = y, d_width = width, d_height = height; + dbus_uint32_t d_type = type; + dbus_uint32_t d_clipTypeX = clipTypeX, d_clipTypeY = clipTypeY; + GArray *range_seq = NULL; + + g_return_val_if_fail (obj != NULL, NULL); + + _atspi_dbus_call (obj, atspi_interface_text, "GetBoundedRanges", error, "iiiiuuu=>a(iisv)", d_x, d_y, d_width, d_height, d_type, d_clipTypeX, d_clipTypeY, &range_seq); + + return range_seq; +} + +/** + * atspi_text_get_n_selections: + * @obj: a pointer to the #AtspiText object on which to operate. + * + * Gets the number of active non-contiguous selections for an + * #AtspiText object. + * + * Returns: a #gint indicating the current + * number of non-contiguous text selections active + * within an #AtspiText object. + **/ +gint +atspi_text_get_n_selections (AtspiText *obj, GError **error) +{ + dbus_int32_t retval = 0; + + g_return_val_if_fail (obj != NULL, -1); + + _atspi_dbus_call (obj, atspi_interface_text, "GetNSelections", error, "=>i", &retval); + + return retval; +} + +/** + * atspi_text_get_selection: + * @obj: a pointer to the #AtspiText object on which to operate. + * @selection_num: a #gint indicating which selection to query. + * + * Gets the bounds of the @selection_num-th active text selection for an + * #AtspiText object. + **/ +AtspiRange * +atspi_text_get_selection (AtspiText *obj, + gint selection_num, + GError **error) +{ + dbus_int32_t d_selection_num = selection_num; + dbus_int32_t d_start_offset, d_end_offset; + AtspiRange *ret = g_new (AtspiRange, 1); + + ret->start_offset = ret->end_offset = -1; + + if (!obj) + return ret; + + _atspi_dbus_call (obj, atspi_interface_text, "GetSelection", error, "i=>ii", d_selection_num, &d_start_offset, &d_end_offset); + + ret->start_offset = d_start_offset; + ret->end_offset = d_end_offset; + return ret; +} + +/** + * atspi_text_add_selection: + * @obj: a pointer to the #AtspiText object on which to operate. + * @start_offset: the starting offset of the desired new selection. + * @end_offset: the offset of the first character after the new selection. + * + * Selects some text (adds a text selection) in an #AtspiText object. + * + * Returns: #TRUE if successful, #FALSE otherwise. + **/ +gboolean +atspi_text_add_selection (AtspiText *obj, + gint start_offset, gint end_offset, + GError **error) +{ + dbus_int32_t d_start_offset = start_offset, d_end_offset = end_offset; + dbus_bool_t retval = FALSE; + + _atspi_dbus_call (obj, atspi_interface_text, "AddSelection", error, "ii=>b", d_start_offset, d_end_offset, &retval); + + return retval; +} + +/** + * atspi_text_remove_selection: + * @obj: a pointer to the #AtspiText object on which to operate. + * @selection_num: a #gint indicating which text selection to remove. + * + * De-selects a text selection. + * + * Returns: #TRUE if successful, #FALSE otherwise. + **/ +gboolean +atspi_text_remove_selection (AtspiText *obj, + gint selection_num, + GError **error) +{ + dbus_int32_t d_selection_num = selection_num; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_text, "RemoveSelection", error, "i=>b", d_selection_num, &retval); + + return retval; +} + +/** + * atspi_text_set_selection: + * @obj: a pointer to the #AtspiText object on which to operate. + * @selection_num: a zero-offset index indicating which text selection to modify. + * @start_offset: a #gint indicating the new starting offset for the selection. + * @end_offset: a #gint indicating the desired new offset of the first character + * after the selection. + * + * Changes the bounds of an existing #AtspiText text selection. + * + * Returns: #TRUE if successful, #FALSE otherwise. + **/ +gboolean +atspi_text_set_selection (AtspiText *obj, + gint selection_num, + gint start_offset, + gint end_offset, + GError **error) +{ + dbus_int32_t d_selection_num = selection_num, d_start_offset = start_offset, d_end_offset = end_offset; + dbus_bool_t retval = FALSE; + + g_return_val_if_fail (obj != NULL, FALSE); + + _atspi_dbus_call (obj, atspi_interface_text, "SetSelection", error, "iii=>b", d_selection_num, d_start_offset, d_end_offset, &retval); + + return retval; +} + +static void +atspi_text_base_init (AtspiText *klass) +{ +} + +GType +atspi_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiText), + (GBaseInitFunc) atspi_text_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiText", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-text.h b/atspi/atspi-text.h new file mode 100644 index 0000000..8e11eb0 --- /dev/null +++ b/atspi/atspi-text.h @@ -0,0 +1,142 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_TEXT_H_ +#define _ATSPI_TEXT_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +typedef struct _AtspiRange AtspiRange; +struct _AtspiRange +{ + gint start_offset; + gint end_offset; +}; + +/** + * ATSPI_TYPE_RANGE: + * + * The #GType for a boxed type holding a range within a text bock. + */ +#define ATSPI_TYPE_RANGE atspi_range_get_type () + +GType atspi_range_get_type (); + +AtspiRange * +atspi_range_copy (AtspiRange *src); + +typedef struct _AtspiTextRange AtspiTextRange; +struct _AtspiTextRange +{ + gint start_offset; + gint end_offset; + gchar *content; +}; + +/** + * ATSPI_TYPE_TEXT_RANGE: + * + * The #GType for a boxed type holding a range within a text bock. + */ +#define ATSPI_TYPE_TEXT_RANGE atspi_text_range_get_type () + +#define ATSPI_TYPE_TEXT (atspi_text_get_type ()) +#define ATSPI_IS_TEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_TEXT) +#define ATSPI_TEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_TEXT, AtspiText) +#define ATSPI_TEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_TEXT, AtspiText)) + +GType atspi_text_get_type (); + +struct _AtspiText +{ + GTypeInterface parent; +}; + + +GType atspi_text_range_get_type (); + +gint atspi_text_get_character_count (AtspiText *obj, GError **error); + +gchar * atspi_text_get_text (AtspiText *obj, gint start_offset, gint end_offset, GError **error); + +gint atspi_text_get_caret_offset (AtspiText *obj, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +GHashTable *atspi_text_get_attributes (AtspiText *obj, gint offset, gint *start_offset, gint *end_offset, GError **error); +#endif + +GHashTable *atspi_text_get_text_attributes (AtspiText *obj, gint offset, gint *start_offset, gint *end_offset, GError **error); + +GHashTable *atspi_text_get_attribute_run (AtspiText *obj, gint offset, gboolean include_defaults, gint *start_offset, gint *end_offset, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +gchar * atspi_text_get_attribute_value (AtspiText *obj, gint offset, gchar *attribute_name, GError **error); +#endif + +gchar * atspi_text_get_text_attribute_value (AtspiText *obj, gint offset, gchar *attribute_name, GError **error); + +GHashTable * atspi_text_get_default_attributes (AtspiText *obj, GError **error); + +gboolean atspi_text_set_caret_offset (AtspiText *obj, gint new_offset, GError **error); + +#ifndef ATSPI_DISABLE_DEPRECATED +AtspiTextRange * atspi_text_get_text_before_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error); + +AtspiTextRange * atspi_text_get_text_at_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error); + +AtspiTextRange * atspi_text_get_text_after_offset (AtspiText *obj, gint offset, AtspiTextBoundaryType type, GError **error); +#endif + +AtspiTextRange * atspi_text_get_string_at_offset (AtspiText *obj, gint offset, AtspiTextGranularity granularity, GError **error); + +guint atspi_text_get_character_at_offset (AtspiText *obj, gint offset, GError **error); + +AtspiRect * atspi_text_get_character_extents (AtspiText *obj, gint offset, AtspiCoordType type, GError **error); + +gint atspi_text_get_offset_at_point (AtspiText *obj, gint x, gint y, AtspiCoordType type, GError **error); + +AtspiRect * atspi_text_get_range_extents (AtspiText *obj, gint start_offset, gint end_offset, AtspiCoordType type, GError **error); + +GArray * atspi_text_get_bounded_ranges (AtspiText *obj, gint x, gint y, gint width, gint height, AtspiCoordType type, AtspiTextClipType clipTypeX, AtspiTextClipType clipTypeY, GError **error); + +gint atspi_text_get_n_selections (AtspiText *obj, GError **error); + +AtspiRange * atspi_text_get_selection (AtspiText *obj, gint selection_num, GError **error); + +gboolean atspi_text_add_selection (AtspiText *obj, gint start_offset, gint end_offset, GError **error); + +gboolean atspi_text_remove_selection (AtspiText *obj, gint selection_num, GError **error); + +gboolean atspi_text_set_selection (AtspiText *obj, gint selection_num, gint start_offset, gint end_offset, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_TEXT_H_ */ diff --git a/atspi/atspi-types.h b/atspi/atspi-types.h new file mode 100644 index 0000000..e458a8e --- /dev/null +++ b/atspi/atspi-types.h @@ -0,0 +1,158 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 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 _ATSPI_TYPES_H_ +#define _ATSPI_TYPES_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +typedef struct _AtspiAccessible AtspiAccessible; +typedef struct _AtspiAction AtspiAction; +typedef struct _AtspiCollection AtspiCollection; +typedef struct _AtspiComponent AtspiComponent; +typedef struct _AtspiDocument AtspiDocument; +typedef struct _AtspiEditableText AtspiEditableText; +typedef struct _AtspiHyperlink AtspiHyperlink; +typedef struct _AtspiHypertext AtspiHypertext; +typedef struct _AtspiImage AtspiImage; +typedef struct _AtspiSelection AtspiSelection; +typedef struct _AtspiTable AtspiTable; +typedef struct _AtspiTableCell AtspiTableCell; +typedef struct _AtspiText AtspiText; +typedef struct _AtspiValue AtspiValue; + +typedef guint AtspiControllerEventMask; + +typedef guint AtspiKeyMaskType; + +typedef guint AtspiKeyEventMask; +typedef guint AtspiDeviceEventMask; + +// TODO: auto-generate the below structs +typedef struct _AtspiDeviceEvent AtspiDeviceEvent; +struct _AtspiDeviceEvent +{ + AtspiEventType type; + guint id; + gushort hw_code; + gushort modifiers; + guint timestamp; + gchar * event_string; + gboolean is_text; +}; + +typedef struct _AtspiEventListenerMode AtspiEventListenerMode; +struct _AtspiEventListenerMode +{ + gboolean synchronous; + gboolean preemptive; + gboolean global; +}; + +typedef struct _AtspiKeyDefinition AtspiKeyDefinition; +struct _AtspiKeyDefinition +{ + gint keycode; + gint keysym; + gchar *keystring; + gint unused; +}; + +typedef struct _AtspiEvent AtspiEvent; +struct _AtspiEvent +{ + gchar *type; + AtspiAccessible *source; + gint detail1; + gint detail2; + GValue any_data; +}; + +/** + * ATSPI_TYPE_DEVICE_EVENT: + * + * The #GType for a boxed type holding a #AtspiDeviceEvent. + */ +#define ATSPI_TYPE_DEVICE_EVENT (atspi_device_event_get_type ()) + +/** + * ATSPI_TYPE_EVENT: + * + * The #GType for a boxed type holding a #AtspiEvent. + */ +#define ATSPI_TYPE_EVENT (atspi_event_get_type ()) + +typedef void AtspiKeystrokeListener; + +/** + * AtspiKeySet: + * @keysyms: + * @keycodes: + * @len: + * + * Structure containing identifying information about a set of keycode or + * keysyms. + **/ +typedef struct _AtspiKeySet +{ + guint *keysyms; + gushort *keycodes; + gchar **keystrings; + gshort len; +} AtspiKeySet; + +/** + *AtspiKeyListenerSyncType: + * @ATSPI_KEYLISTENER_NOSYNC: Events may be delivered asynchronously, + * which means in some cases they may already have been delivered to the + * application before the AT client receives the notification. + * @ATSPI_KEYLISTENER_SYNCHRONOUS: Events are delivered synchronously, before the + * currently focussed application sees them. + * @ATSPI_KEYLISTENER_CANCONSUME: Events may be consumed by the AT client. Presumes and + * requires #ATSPI_KEYLISTENER_SYNCHRONOUS, incompatible with #ATSPI_KEYLISTENER_NOSYNC. + * @ATSPI_KEYLISTENER_ALL_WINDOWS: Events are received not from the application toolkit layer, but + * from the device driver or windowing system subsystem; such notifications are 'global' in the + * sense that they are not broken or defeated by applications that participate poorly + * in the accessibility APIs, or not at all; however because of the intrusive nature of + * such snooping, it can have side-effects on certain older platforms. If unconditional + * event notifications, even when inaccessible or "broken" applications have focus, are not + * required, it may be best to avoid this enum value/flag. + * + * Specifies the type of a key listener event. + * The values above can and should be bitwise-'OR'-ed + * together, observing the compatibility limitations specified in the description of + * each value. For instance, #ATSPI_KEYLISTENER_ALL_WINDOWS | #ATSPI_KEYLISTENER_CANCONSUME is + * a commonly used combination which gives the AT complete control over the delivery of matching + * events. However, such filters should be used sparingly as they may have a negative impact on + * system performance. + **/ +typedef enum { + ATSPI_KEYLISTENER_NOSYNC = 0, + ATSPI_KEYLISTENER_SYNCHRONOUS = 1 << 0, + ATSPI_KEYLISTENER_CANCONSUME = 1 << 1, + ATSPI_KEYLISTENER_ALL_WINDOWS = 1 << 2 +} AtspiKeyListenerSyncType; +#endif /* _ATSPI_TYPES_H_ */ diff --git a/atspi/atspi-value.c b/atspi/atspi-value.c new file mode 100644 index 0000000..642533d --- /dev/null +++ b/atspi/atspi-value.c @@ -0,0 +1,177 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2010, 2011 Novell, 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. + */ + +#include "atspi-private.h" + +/** + * atspi_value_get_minimum_value: + * @obj: a pointer to the #AtspiValue implementor on which to operate. + * + * Gets the minimum allowed value for an #AtspiValue. + * + * Returns: the minimum allowed value for this object. + * + **/ +gdouble +atspi_value_get_minimum_value (AtspiValue *obj, GError **error) +{ + double retval; + + g_return_val_if_fail (obj != NULL, 0.0); + _atspi_dbus_get_property (obj, atspi_interface_value, "MinimumValue", error, "d", &retval); + + return retval; +} + +/** + * atspi_value_get_current_value: + * @obj: a pointer to the #AtspiValue implementor on which to operate. + * + * Gets the current value for an #AtspiValue. + * + * Returns: the current value for this object. + **/ +gdouble +atspi_value_get_current_value (AtspiValue *obj, GError **error) +{ + double retval; + + g_return_val_if_fail (obj != NULL, 0.0); + + _atspi_dbus_get_property (obj, atspi_interface_value, "CurrentValue", error, "d", &retval); + + return retval; +} + +/** + * atspi_value_get_maximum_value: + * @obj: a pointer to the #AtspiValue implementor on which to operate. + * + * Gets the maximum allowed value for an #AtspiValue. + * + * Returns: the maximum allowed value for this object. + **/ +gdouble +atspi_value_get_maximum_value (AtspiValue *obj, GError **error) +{ + double retval; + + g_return_val_if_fail (obj != NULL, 0.0); + + _atspi_dbus_get_property (obj, atspi_interface_value, "MaximumValue", error, "d", &retval); + + return retval; +} + +/** + * atspi_value_set_current_value: + * @obj: a pointer to the #AtspiValue implementor on which to operate. + * @new_value: a #gdouble value which is the desired new value of the object. + * + * Sets the current value of an #AtspiValue. + * + * Returns: #TRUE if the value could be assigned the specified value, + * #FALSE otherwise. + **/ +gboolean +atspi_value_set_current_value (AtspiValue *obj, gdouble new_value, GError **error) +{ + double d_new_value = new_value; + DBusMessage *message, *reply; + DBusMessageIter iter, iter_variant; + static const char *str_curval = "CurrentValue"; + AtspiAccessible *accessible = ATSPI_ACCESSIBLE (obj); + + g_return_val_if_fail (accessible != NULL, FALSE); + + if (!accessible->parent.app || !accessible->parent.app->bus_name) +{ + g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_APPLICATION_GONE, + _("The application no longer exists")); + return FALSE; + } + + message = dbus_message_new_method_call (accessible->parent.app->bus_name, + accessible->parent.path, + DBUS_INTERFACE_PROPERTIES, "Set"); + if (!message) + return FALSE; + dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_value, + DBUS_TYPE_STRING, &str_curval, + DBUS_TYPE_INVALID); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "d", &iter_variant); + dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_DOUBLE, &d_new_value); + dbus_message_iter_close_container (&iter, &iter_variant); + reply = _atspi_dbus_send_with_reply_and_block (message, error); + dbus_message_unref (reply); + + return TRUE; +} + +/** + * atspi_value_get_minimum_increment: + * @obj: a pointer to the #AtspiValue implementor on which to operate. + * + * Gets the minimum increment by which an #AtspiValue can be adjusted. + * + * Returns: the minimum increment by which the value may be changed, or + * zero if the minimum increment cannot be determined. + * + **/ +gdouble +atspi_value_get_minimum_increment (AtspiValue *obj, GError **error) +{ + double retval; + + g_return_val_if_fail (obj != NULL, 0.0); + + _atspi_dbus_get_property (obj, atspi_interface_value, "MinimumIncrement", error, "d", &retval); + + return retval; +} + +static void +atspi_value_base_init (AtspiValue *klass) +{ +} + +GType +atspi_value_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo tinfo = + { + sizeof (AtspiValue), + (GBaseInitFunc) atspi_value_base_init, + (GBaseFinalizeFunc) NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, "AtspiValue", &tinfo, 0); + + } + return type; +} diff --git a/atspi/atspi-value.h b/atspi/atspi-value.h new file mode 100644 index 0000000..6a1e531 --- /dev/null +++ b/atspi/atspi-value.h @@ -0,0 +1,61 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 Novell, 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 _ATSPI_VALUE_H_ +#define _ATSPI_VALUE_H_ + +#include "glib-object.h" + +#include "atspi-constants.h" + +#include "atspi-types.h" + +G_BEGIN_DECLS + +#define ATSPI_TYPE_VALUE (atspi_value_get_type ()) +#define ATSPI_IS_VALUE(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATSPI_TYPE_VALUE) +#define ATSPI_VALUE(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), ATSPI_TYPE_VALUE, AtspiValue) +#define ATSPI_VALUE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), ATSPI_TYPE_VALUE, AtspiValue)) + +GType atspi_value_get_type (); + +struct _AtspiValue +{ + GTypeInterface parent; +}; + +gdouble atspi_value_get_minimum_value (AtspiValue *obj, GError **error); + +gdouble atspi_value_get_current_value (AtspiValue *obj, GError **error); + +gdouble atspi_value_get_maximum_value (AtspiValue *obj, GError **error); + +gboolean atspi_value_set_current_value (AtspiValue *obj, gdouble new_value, GError **error); + +gdouble atspi_value_get_minimum_increment (AtspiValue *obj, GError **error); + +G_END_DECLS + +#endif /* _ATSPI_VALUE_H_ */ diff --git a/atspi/atspi.h b/atspi/atspi.h new file mode 100644 index 0000000..dc92de0 --- /dev/null +++ b/atspi/atspi.h @@ -0,0 +1,56 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 _ATSPI_H +#define _ATSPI_H + +#include "glib.h" + +#include "atspi-constants.h" +#include "atspi-types.h" +#include "atspi-accessible.h" +#include "atspi-action.h" +#include "atspi-collection.h" +#include "atspi-component.h" +#include "atspi-device-listener.h" +#include "atspi-document.h" +#include "atspi-editabletext.h" +#include "atspi-event-listener.h" +#include "atspi-hyperlink.h" +#include "atspi-hypertext.h" +#include "atspi-image.h" +#include "atspi-matchrule.h" +#include "atspi-misc.h" +#include "atspi-registry.h" +#include "atspi-relation.h" +#include "atspi-selection.h" +#include "atspi-stateset.h" +#include "atspi-table.h" +#include "atspi-table-cell.h" +#include "atspi-text.h" +#include "atspi-value.h" + +#include "atspi-gmain.h" + +#include "atspi-enum-types.h" +#endif diff --git a/atspi/meson.build b/atspi/meson.build new file mode 100644 index 0000000..17bfc45 --- /dev/null +++ b/atspi/meson.build @@ -0,0 +1,114 @@ +atspi_sources = [ + 'atspi-accessible.c', + 'atspi-action.c', + 'atspi-application.c', + 'atspi-collection.c', + 'atspi-component.c', + 'atspi-device-listener.c', + 'atspi-document.c', + 'atspi-editabletext.c', + 'atspi-event-listener.c', + 'atspi-gmain.c', + 'atspi-hyperlink.c', + 'atspi-hypertext.c', + 'atspi-image.c', + 'atspi-matchrule.c', + 'atspi-misc.c', + 'atspi-object.c', + 'atspi-registry.c', + 'atspi-relation.c', + 'atspi-selection.c', + 'atspi-stateset.c', + 'atspi-table.c', + 'atspi-table-cell.c', + 'atspi-text.c', + 'atspi-value.c', +] + +atspi_headers = [ + 'atspi.h', + 'atspi-accessible.h', + 'atspi-action.h', + 'atspi-application.h', + 'atspi-collection.h', + 'atspi-component.h', + 'atspi-constants.h', + 'atspi-device-listener.h', + 'atspi-document.h', + 'atspi-editabletext.h', + 'atspi-event-listener.h', + 'atspi-gmain.h', + 'atspi-hyperlink.h', + 'atspi-hypertext.h', + 'atspi-image.h', + 'atspi-matchrule.h', + 'atspi-misc.h', + 'atspi-object.h', + 'atspi-registry.h', + 'atspi-relation.h', + 'atspi-selection.h', + 'atspi-stateset.h', + 'atspi-table.h', + 'atspi-table-cell.h', + 'atspi-text.h', + 'atspi-types.h', + 'atspi-value.h', +] + +atspi_includedir = join_paths(get_option('prefix'), get_option('includedir'), 'at-spi-2.0', 'atspi') + +install_headers(atspi_headers, subdir: atspi_includedir) + +atspi_enums = gnome.mkenums('atspi-enum-types', + sources: [ 'atspi-constants.h', 'atspi-types.h' ], + c_template: 'atspi-enum-types.c.template', + h_template: 'atspi-enum-types.h.template', + install_dir: atspi_includedir, + install_header: true) +atspi_enum_h = atspi_enums[1] + +atspi = library('atspi', atspi_sources + atspi_enums, + version: soversion, + soversion: soversion.split('.')[0], + include_directories: [ root_inc, registryd_inc ], + dependencies: [ libdbus_dep, gobject_dep, dbind_dep, x11_deps ], + install: true) + +atspi_dep = declare_dependency(link_with: atspi, + sources: atspi_enum_h, + include_directories: root_inc, + dependencies: [ libdbus_dep, gobject_dep, ]) + +if have_gir + gir_sources = atspi_sources + atspi_enums + atspi_headers + + gir_incs = [ + 'DBus-1.0', + 'GLib-2.0', + 'GObject-2.0' + ] + + gir_extra_args = [ + '--c-include=atspi/atspi.h', + '--pkg-export=atspi-2' + ] + + gir_dir = join_paths(atspi_datadir, 'gir-1.0') + typelib_dir = join_paths(get_option('libdir'), 'girepository-1.0') + + libatspi_gir = gnome.generate_gir( + atspi, + sources: gir_sources, + nsversion: '2.0', + namespace: atspi_gir_ns, + symbol_prefix: atspi_gir_ns.to_lower(), + identifier_prefix: atspi_gir_ns, + includes: gir_incs, + include_directories: root_inc, + install: true, + install_dir_gir: gir_dir, + install_dir_typelib: typelib_dir, + extra_args: gir_extra_args + ) +endif + diff --git a/bus/README b/bus/README new file mode 100644 index 0000000..40b9ad6 --- /dev/null +++ b/bus/README @@ -0,0 +1,10 @@ +The a11y bus is accessed via two mechanisms: + +1) The DBus session bus, service "org.a11y.Bus", method "GetAddress") +2) The X11 root window property AT_SPI_BUS + +If the "toolkit-accessibility" variable is set, the bus is launched +immediately (and will be accessible immediately via the X11 property). +Otherwise, it will be spawned dynamically. + + diff --git a/bus/accessibility.conf.in b/bus/accessibility.conf.in new file mode 100644 index 0000000..31b6a79 --- /dev/null +++ b/bus/accessibility.conf.in @@ -0,0 +1,35 @@ + + + + accessibility + +@DATADIR@/dbus-1/accessibility-services + EXTERNAL + + unix:tmpdir=/tmp + + + + + + + + + + + + + 1000000000 + 1000000000 + 1000000000 + 120000 + 240000 + 100000 + 10000 + 100000 + 10000 + 50000 + 50000 + 50000 + 300000 + diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c new file mode 100644 index 0000000..eb2b8e3 --- /dev/null +++ b/bus/at-spi-bus-launcher.c @@ -0,0 +1,826 @@ +/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*- + * + * at-spi-bus-launcher: Manage the a11y bus as a child process + * + * Copyright 2011 Red Hat, 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. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_X11 +#include +#include +#endif + +typedef enum { + A11Y_BUS_STATE_IDLE = 0, + A11Y_BUS_STATE_READING_ADDRESS, + A11Y_BUS_STATE_RUNNING, + A11Y_BUS_STATE_ERROR +} A11yBusState; + +typedef struct { + GMainLoop *loop; + gboolean launch_immediately; + gboolean a11y_enabled; + gboolean screen_reader_enabled; + GDBusConnection *session_bus; + GSettings *a11y_schema; + GSettings *interface_schema; + + GDBusProxy *client_proxy; + + A11yBusState state; + /* -1 == error, 0 == pending, > 0 == running */ + int a11y_bus_pid; + char *a11y_bus_address; + int pipefd[2]; + char *a11y_launch_error_message; +} A11yBusLauncher; + +static A11yBusLauncher *_global_app = NULL; + +static const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + "" + "" + "" + "" + ""; +static GDBusNodeInfo *introspection_data = NULL; + +static void +respond_to_end_session (GDBusProxy *proxy) +{ + GVariant *parameters; + + parameters = g_variant_new ("(bs)", TRUE, ""); + + g_dbus_proxy_call (proxy, + "EndSessionResponse", parameters, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, NULL, NULL); +} + +static void +g_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + + if (g_strcmp0 (signal_name, "QueryEndSession") == 0) + respond_to_end_session (proxy); + else if (g_strcmp0 (signal_name, "EndSession") == 0) + respond_to_end_session (proxy); + else if (g_strcmp0 (signal_name, "Stop") == 0) + g_main_loop_quit (app->loop); +} + +static void +client_proxy_ready_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + GError *error = NULL; + + app->client_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (error != NULL) + { + g_warning ("Failed to get a client proxy: %s", error->message); + g_error_free (error); + + return; + } + + g_signal_connect (app->client_proxy, "g-signal", + G_CALLBACK (g_signal_cb), app); +} + +static void +register_client (A11yBusLauncher *app) +{ + GDBusProxyFlags flags; + GDBusProxy *sm_proxy; + GError *error; + const gchar *app_id; + const gchar *autostart_id; + gchar *client_startup_id; + GVariant *parameters; + GVariant *variant; + gchar *object_path; + + flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS; + + error = NULL; + sm_proxy = g_dbus_proxy_new_sync (app->session_bus, flags, NULL, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, &error); + + if (error != NULL) + { + g_warning ("Failed to get session manager proxy: %s", error->message); + g_error_free (error); + + return; + } + + app_id = "at-spi-bus-launcher"; + autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID"); + + if (autostart_id != NULL) + { + client_startup_id = g_strdup (autostart_id); + g_unsetenv ("DESKTOP_AUTOSTART_ID"); + } + else + { + client_startup_id = g_strdup (""); + } + + parameters = g_variant_new ("(ss)", app_id, client_startup_id); + g_free (client_startup_id); + + error = NULL; + variant = g_dbus_proxy_call_sync (sm_proxy, + "RegisterClient", parameters, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, &error); + + g_object_unref (sm_proxy); + + if (error != NULL) + { + g_warning ("Failed to register client: %s", error->message); + g_error_free (error); + + return; + } + + g_variant_get (variant, "(o)", &object_path); + g_variant_unref (variant); + + flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES; + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, flags, NULL, + "org.gnome.SessionManager", object_path, + "org.gnome.SessionManager.ClientPrivate", + NULL, client_proxy_ready_cb, app); + + g_free (object_path); +} + +static void +name_appeared_handler (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + + register_client (app); +} + +static void +setup_bus_child (gpointer data) +{ + A11yBusLauncher *app = data; + (void) app; + + close (app->pipefd[0]); + dup2 (app->pipefd[1], 3); + close (app->pipefd[1]); + + /* On Linux, tell the bus process to exit if this process goes away */ +#ifdef __linux +#include + prctl (PR_SET_PDEATHSIG, 15); +#endif +} + +/** + * unix_read_all_fd_to_string: + * + * Read all data from a file descriptor to a C string buffer. + */ +static gboolean +unix_read_all_fd_to_string (int fd, + char *buf, + ssize_t max_bytes) +{ + ssize_t bytes_read; + + while (max_bytes > 1 && (bytes_read = read (fd, buf, MIN (4096, max_bytes - 1)))) + { + if (bytes_read < 0) + return FALSE; + buf += bytes_read; + max_bytes -= bytes_read; + } + *buf = '\0'; + return TRUE; +} + +static void +on_bus_exited (GPid pid, + gint status, + gpointer data) +{ + A11yBusLauncher *app = data; + + app->a11y_bus_pid = -1; + app->state = A11Y_BUS_STATE_ERROR; + if (app->a11y_launch_error_message == NULL) + { + if (WIFEXITED (status)) + app->a11y_launch_error_message = g_strdup_printf ("Bus exited with code %d", WEXITSTATUS (status)); + else if (WIFSIGNALED (status)) + app->a11y_launch_error_message = g_strdup_printf ("Bus killed by signal %d", WTERMSIG (status)); + else if (WIFSTOPPED (status)) + app->a11y_launch_error_message = g_strdup_printf ("Bus stopped by signal %d", WSTOPSIG (status)); + } + g_main_loop_quit (app->loop); +} + +static gboolean +ensure_a11y_bus (A11yBusLauncher *app) +{ + GPid pid; + char *argv[] = { DBUS_DAEMON, NULL, "--nofork", "--print-address", "3", NULL }; + char addr_buf[2048]; + GError *error = NULL; + const char *config_path = NULL; + + if (app->a11y_bus_pid != 0) + return FALSE; + + if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS)) + config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf"; + else + config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf"; + + argv[1] = config_path; + + if (pipe (app->pipefd) < 0) + g_error ("Failed to create pipe: %s", strerror (errno)); + + if (!g_spawn_async (NULL, + argv, + NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, + setup_bus_child, + app, + &pid, + &error)) + { + app->a11y_bus_pid = -1; + app->a11y_launch_error_message = g_strdup (error->message); + g_clear_error (&error); + goto error; + } + + close (app->pipefd[1]); + app->pipefd[1] = -1; + + g_child_watch_add (pid, on_bus_exited, app); + + app->state = A11Y_BUS_STATE_READING_ADDRESS; + app->a11y_bus_pid = pid; + g_debug ("Launched a11y bus, child is %ld", (long) pid); + if (!unix_read_all_fd_to_string (app->pipefd[0], addr_buf, sizeof (addr_buf))) + { + app->a11y_launch_error_message = g_strdup_printf ("Failed to read address: %s", strerror (errno)); + kill (app->a11y_bus_pid, SIGTERM); + goto error; + } + close (app->pipefd[0]); + app->pipefd[0] = -1; + app->state = A11Y_BUS_STATE_RUNNING; + + /* Trim the trailing newline */ + app->a11y_bus_address = g_strchomp (g_strdup (addr_buf)); + g_debug ("a11y bus address: %s", app->a11y_bus_address); + +#ifdef HAVE_X11 + { + Display *display = XOpenDisplay (NULL); + if (display) + { + Atom bus_address_atom = XInternAtom (display, "AT_SPI_BUS", False); + XChangeProperty (display, + XDefaultRootWindow (display), + bus_address_atom, + XA_STRING, 8, PropModeReplace, + (guchar *) app->a11y_bus_address, strlen (app->a11y_bus_address)); + XFlush (display); + XCloseDisplay (display); + } + } +#endif + + return TRUE; + + error: + close (app->pipefd[0]); + close (app->pipefd[1]); + app->state = A11Y_BUS_STATE_ERROR; + + return FALSE; +} + +static void +handle_method_call (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + + if (g_strcmp0 (method_name, "GetAddress") == 0) + { + ensure_a11y_bus (app); + if (app->a11y_bus_pid > 0) + g_dbus_method_invocation_return_value (invocation, + g_variant_new ("(s)", app->a11y_bus_address)); + else + g_dbus_method_invocation_return_dbus_error (invocation, + "org.a11y.Bus.Error", + app->a11y_launch_error_message); + } +} + +static GVariant * +handle_get_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GError **error, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + + if (g_strcmp0 (property_name, "IsEnabled") == 0) + return g_variant_new ("b", app->a11y_enabled); + else if (g_strcmp0 (property_name, "ScreenReaderEnabled") == 0) + return g_variant_new ("b", app->screen_reader_enabled); + else + return NULL; +} + +static void +handle_a11y_enabled_change (A11yBusLauncher *app, gboolean enabled, + gboolean notify_gsettings) +{ + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + + if (enabled == app->a11y_enabled) + return; + + app->a11y_enabled = enabled; + + if (notify_gsettings && app->interface_schema) + { + g_settings_set_boolean (app->interface_schema, "toolkit-accessibility", + enabled); + g_settings_sync (); + } + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + g_variant_builder_add (&builder, "{sv}", "IsEnabled", + g_variant_new_boolean (enabled)); + + g_dbus_connection_emit_signal (app->session_bus, NULL, "/org/a11y/bus", + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", "org.a11y.Status", + &builder, + &invalidated_builder), + NULL); + + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); +} + +static void +handle_screen_reader_enabled_change (A11yBusLauncher *app, gboolean enabled, + gboolean notify_gsettings) +{ + GVariantBuilder builder; + GVariantBuilder invalidated_builder; + + if (enabled == app->screen_reader_enabled) + return; + + /* If the screen reader is being enabled, we should enable accessibility + * if it isn't enabled already */ + if (enabled) + handle_a11y_enabled_change (app, enabled, notify_gsettings); + + app->screen_reader_enabled = enabled; + + if (notify_gsettings && app->a11y_schema) + { + g_settings_set_boolean (app->a11y_schema, "screen-reader-enabled", + enabled); + g_settings_sync (); + } + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); + g_variant_builder_add (&builder, "{sv}", "ScreenReaderEnabled", + g_variant_new_boolean (enabled)); + + g_dbus_connection_emit_signal (app->session_bus, NULL, "/org/a11y/bus", + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", "org.a11y.Status", + &builder, + &invalidated_builder), + NULL); + + g_variant_builder_clear (&builder); + g_variant_builder_clear (&invalidated_builder); +} + +static gboolean +handle_set_property (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + const gchar *type = g_variant_get_type_string (value); + gboolean enabled; + + if (g_strcmp0 (type, "b") != 0) + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "org.a11y.Status.%s expects a boolean but got %s", property_name, type); + return FALSE; + } + + enabled = g_variant_get_boolean (value); + + if (g_strcmp0 (property_name, "IsEnabled") == 0) + { + handle_a11y_enabled_change (app, enabled, TRUE); + return TRUE; + } + else if (g_strcmp0 (property_name, "ScreenReaderEnabled") == 0) + { + handle_screen_reader_enabled_change (app, enabled, TRUE); + return TRUE; + } + else + { + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, + "Unknown property '%s'", property_name); + return FALSE; + } +} + +static const GDBusInterfaceVTable bus_vtable = +{ + handle_method_call, + NULL, /* handle_get_property, */ + NULL /* handle_set_property */ +}; + +static const GDBusInterfaceVTable status_vtable = +{ + NULL, /* handle_method_call */ + handle_get_property, + handle_set_property +}; + +static void +on_bus_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + GError *error; + guint registration_id; + + if (connection == NULL) + { + g_main_loop_quit (app->loop); + return; + } + app->session_bus = connection; + + if (app->launch_immediately) + { + ensure_a11y_bus (app); + if (app->state == A11Y_BUS_STATE_ERROR) + { + g_main_loop_quit (app->loop); + return; + } + } + + error = NULL; + registration_id = g_dbus_connection_register_object (connection, + "/org/a11y/bus", + introspection_data->interfaces[0], + &bus_vtable, + _global_app, + NULL, + &error); + if (registration_id == 0) + { + g_error ("%s", error->message); + g_clear_error (&error); + } + + g_dbus_connection_register_object (connection, + "/org/a11y/bus", + introspection_data->interfaces[1], + &status_vtable, + _global_app, + NULL, + NULL); +} + +static void +on_name_lost (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + A11yBusLauncher *app = user_data; + if (app->session_bus == NULL + && connection == NULL + && app->a11y_launch_error_message == NULL) + app->a11y_launch_error_message = g_strdup ("Failed to connect to session bus"); + g_main_loop_quit (app->loop); +} + +static void +on_name_acquired (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_bus_watch_name (G_BUS_TYPE_SESSION, + "org.gnome.SessionManager", + G_BUS_NAME_WATCHER_FLAGS_NONE, + name_appeared_handler, NULL, + user_data, NULL); +} + +static int sigterm_pipefd[2]; + +static void +sigterm_handler (int signum) +{ + write (sigterm_pipefd[1], "X", 1); +} + +static gboolean +on_sigterm_pipe (GIOChannel *channel, + GIOCondition condition, + gpointer data) +{ + A11yBusLauncher *app = data; + + g_main_loop_quit (app->loop); + + return FALSE; +} + +static void +init_sigterm_handling (A11yBusLauncher *app) +{ + GIOChannel *sigterm_channel; + + if (pipe (sigterm_pipefd) < 0) + g_error ("Failed to create pipe: %s", strerror (errno)); + signal (SIGTERM, sigterm_handler); + + sigterm_channel = g_io_channel_unix_new (sigterm_pipefd[0]); + g_io_add_watch (sigterm_channel, + G_IO_IN | G_IO_ERR | G_IO_HUP, + on_sigterm_pipe, + app); +} + +static gboolean +already_running () +{ +#ifdef HAVE_X11 + Atom AT_SPI_BUS; + Atom actual_type; + Display *bridge_display; + int actual_format; + unsigned char *data = NULL; + unsigned long nitems; + unsigned long leftover; + gboolean result = FALSE; + + bridge_display = XOpenDisplay (NULL); + if (!bridge_display) + return FALSE; + + AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", False); + XGetWindowProperty (bridge_display, + XDefaultRootWindow (bridge_display), + AT_SPI_BUS, 0L, + (long) BUFSIZ, False, + (Atom) 31, &actual_type, &actual_format, + &nitems, &leftover, &data); + + if (data) + { + GDBusConnection *bus; + bus = g_dbus_connection_new_for_address_sync ((const gchar *)data, 0, + NULL, NULL, NULL); + if (bus != NULL) + { + result = TRUE; + g_object_unref (bus); + } + } + + XCloseDisplay (bridge_display); + return result; +#else + return FALSE; +#endif +} + +static GSettings * +get_schema (const gchar *name) +{ + const char * const *schemas = NULL; + gint i; + + schemas = g_settings_list_schemas (); + for (i = 0; schemas[i]; i++) + { + if (!strcmp (schemas[i], name)) + return g_settings_new (schemas[i]); + } + + return NULL; +} + +static void +gsettings_key_changed (GSettings *gsettings, const gchar *key, void *user_data) +{ + gboolean new_val = g_settings_get_boolean (gsettings, key); + A11yBusLauncher *app = user_data; + + if (!strcmp (key, "toolkit-accessibility")) + handle_a11y_enabled_change (_global_app, new_val, FALSE); + else if (!strcmp (key, "screen-reader-enabled")) + handle_screen_reader_enabled_change (_global_app, new_val, FALSE); +} + +int +main (int argc, + char **argv) +{ + GError *error = NULL; + GMainLoop *loop; + GDBusConnection *session_bus; + int name_owner_id; + gboolean a11y_set = FALSE; + gboolean screen_reader_set = FALSE; + gint i; + + if (already_running ()) + return 0; + + _global_app = g_slice_new0 (A11yBusLauncher); + _global_app->loop = g_main_loop_new (NULL, FALSE); + + for (i = 1; i < argc; i++) + { + if (!strcmp (argv[i], "--launch-immediately")) + _global_app->launch_immediately = TRUE; + else if (sscanf (argv[i], "--a11y=%d", &_global_app->a11y_enabled) == 1) + a11y_set = TRUE; + else if (sscanf (argv[i], "--screen-reader=%d", + &_global_app->screen_reader_enabled) == 1) + screen_reader_set = TRUE; + else + g_error ("usage: %s [--launch-immediately] [--a11y=0|1] [--screen-reader=0|1]", argv[0]); + } + + _global_app->interface_schema = get_schema ("org.gnome.desktop.interface"); + _global_app->a11y_schema = get_schema ("org.gnome.desktop.a11y.applications"); + + if (!a11y_set) + { + _global_app->a11y_enabled = _global_app->interface_schema + ? g_settings_get_boolean (_global_app->interface_schema, "toolkit-accessibility") + : _global_app->launch_immediately; + } + + if (!screen_reader_set) + { + _global_app->screen_reader_enabled = _global_app->a11y_schema + ? g_settings_get_boolean (_global_app->a11y_schema, "screen-reader-enabled") + : FALSE; + } + + if (_global_app->interface_schema) + g_signal_connect (_global_app->interface_schema, + "changed::toolkit-accessibility", + G_CALLBACK (gsettings_key_changed), _global_app); + + if (_global_app->a11y_schema) + g_signal_connect (_global_app->a11y_schema, + "changed::screen-reader-enabled", + G_CALLBACK (gsettings_key_changed), _global_app); + + init_sigterm_handling (_global_app); + + introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); + g_assert (introspection_data != NULL); + + name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + "org.a11y.Bus", + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, + on_bus_acquired, + on_name_acquired, + on_name_lost, + _global_app, + NULL); + + g_main_loop_run (_global_app->loop); + + if (_global_app->a11y_bus_pid > 0) + kill (_global_app->a11y_bus_pid, SIGTERM); + + /* Clear the X property if our bus is gone; in the case where e.g. + * GDM is launching a login on an X server it was using before, + * we don't want early login processes to pick up the stale address. + */ +#ifdef HAVE_X11 + { + Display *display = XOpenDisplay (NULL); + if (display) + { + Atom bus_address_atom = XInternAtom (display, "AT_SPI_BUS", False); + XDeleteProperty (display, + XDefaultRootWindow (display), + bus_address_atom); + + XFlush (display); + XCloseDisplay (display); + } + } +#endif + + if (_global_app->a11y_launch_error_message) + { + g_printerr ("Failed to launch bus: %s", _global_app->a11y_launch_error_message); + return 1; + } + return 0; +} diff --git a/bus/at-spi-dbus-bus.desktop.in b/bus/at-spi-dbus-bus.desktop.in new file mode 100644 index 0000000..b3c90bd --- /dev/null +++ b/bus/at-spi-dbus-bus.desktop.in @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Name=AT-SPI D-Bus Bus +Exec=@libexecdir@/at-spi-bus-launcher --launch-immediately +OnlyShowIn=GNOME;Unity; +NoDisplay=true +AutostartCondition=GSETTINGS org.gnome.desktop.interface toolkit-accessibility +X-GNOME-AutoRestart=true +X-GNOME-Autostart-Phase=Initialization diff --git a/bus/at-spi-dbus-bus.service.in b/bus/at-spi-dbus-bus.service.in new file mode 100644 index 0000000..28ffa1c --- /dev/null +++ b/bus/at-spi-dbus-bus.service.in @@ -0,0 +1,7 @@ +[Unit] +Description=Accessibility services bus + +[Service] +Type=dbus +BusName=org.a11y.Bus +ExecStart=@libexecdir@/at-spi-bus-launcher diff --git a/bus/meson.build b/bus/meson.build new file mode 100644 index 0000000..909103c --- /dev/null +++ b/bus/meson.build @@ -0,0 +1,55 @@ +libexec_conf = configuration_data() +libexec_conf.set('libexecdir', atspi_libexecdir) + +accessibility_conf = configuration_data() +accessibility_conf.set('DATADIR', atspi_datadir) + +busconfig_dir = join_paths(atspi_datadir, 'defaults/at-spi2') +session_dir = join_paths(atspi_sysconfdir, 'xdg/autostart') + +configure_file(input: 'accessibility.conf.in', + output: 'accessibility.conf', + configuration: accessibility_conf, + install: true, + install_dir: busconfig_dir) + +configure_file(input: 'at-spi-dbus-bus.desktop.in', + output: 'at-spi-dbus-bus.desktop', + configuration: libexec_conf, + install: true, + install_dir: session_dir) + +configure_file(input: 'org.a11y.Bus.service.in', + output: 'org.a11y.Bus.service', + configuration: libexec_conf, + install: true, + install_dir: dbus_services_dir) + +configure_file(input: 'at-spi-dbus-bus.service.in', + output: 'at-spi-dbus-bus.service', + configuration: libexec_conf, + install: true, + install_dir: systemd_user_dir) + +if get_option('dbus_daemon') != 'default' + dbus_daemon = get_option('dbus_daemon') +else + dbus_daemon = find_program('dbus-daemon', + '/sbin/dbus-daemon', + '/usr/sbin/dbus-daemon', + '/libexec/dbus-daemon', + '/usr/libexec/dbus-daemon', + '/usr/pkg/bin/dbus-daemon', + required: true).path() +endif + +executable('at-spi-bus-launcher', 'at-spi-bus-launcher.c', + include_directories: [ root_inc, include_directories('.') ], + dependencies: [ gio_dep, x11_deps ], + c_args: [ + '-DSYSCONFDIR="@0@"'.format(atspi_sysconfdir), + '-DDATADIR="@0@"'.format(atspi_datadir), + '-DDBUS_DAEMON="@0@"'.format(dbus_daemon), + ], + install: true, + install_dir: atspi_libexecdir) diff --git a/bus/org.a11y.Bus.service.in b/bus/org.a11y.Bus.service.in new file mode 100644 index 0000000..86724da --- /dev/null +++ b/bus/org.a11y.Bus.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.a11y.Bus +Exec=@libexecdir@/at-spi-bus-launcher +SystemdService=at-spi-dbus-bus.service diff --git a/config/NONCE b/config/NONCE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/config/NONCE diff --git a/dbind/dbind-any.c b/dbind/dbind-any.c new file mode 100644 index 0000000..ae499d7 --- /dev/null +++ b/dbind/dbind-any.c @@ -0,0 +1,783 @@ +/* + * Copyright 2008-2011 Novell, 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. + */ + +/* type driven marshalling */ +#include +#include + +#include "config.h" +#include "dbind-any.h" + +#undef DEBUG + +/* Align a value upward to a boundary, expressed as a number of bytes. + * E.g. align to an 8-byte boundary with argument of 8. + * + * (this + boundary - 1) + * & + * ~(boundary - 1) + */ +#define ALIGN_VALUE(this, boundary) \ + (( ((gulong)(this)) + (((gulong)(boundary)) -1)) & (~(((gulong)(boundary))-1))) + +#define ALIGN_ADDRESS(this, boundary) \ + ((gpointer)ALIGN_VALUE(this, boundary)) + +#define PTR_PLUS(ptr, offset) \ + ((gpointer) (((guchar *)(ptr)) + (offset))) + +#define DBIND_POD_CASES \ + DBUS_TYPE_BYTE: \ + case DBUS_TYPE_INT16: \ + case DBUS_TYPE_UINT16: \ + case DBUS_TYPE_INT32: \ + case DBUS_TYPE_UINT32: \ + case DBUS_TYPE_BOOLEAN: \ + case DBUS_TYPE_INT64: \ + case DBUS_TYPE_UINT64: \ + case DBUS_TYPE_DOUBLE + +/*---------------------------------------------------------------------------*/ + +static void +warn_braces () +{ + fprintf (stderr, "Error: dbus flags structures & dicts with braces rather than " + " an explicit type member of 'struct'\n"); +} + +/*---------------------------------------------------------------------------*/ + +static unsigned int +dbind_find_c_alignment_r (const char **type) +{ + unsigned int retval = 1; + + char t = **type; + (*type)++; + +#ifdef DEBUG + fprintf (stderr, "\tfind align for %c (0x%x)\n", t, t); +#endif + + switch (t) { + case DBUS_TYPE_BYTE: + return ALIGNOF_CHAR; + case DBUS_TYPE_BOOLEAN: + return ALIGNOF_DBUS_BOOL_T; + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + return ALIGNOF_DBUS_INT16_T; + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return ALIGNOF_DBUS_INT32_T; + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + return ALIGNOF_DBUS_INT64_T; + case DBUS_TYPE_DOUBLE: + return ALIGNOF_DOUBLE; + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + return ALIGNOF_DBIND_POINTER; + case DBUS_STRUCT_BEGIN_CHAR: + /* TODO: I think this would break with a nested struct */ +#if ALIGNOF_DBIND_STRUCT > 1 + retval = MAX (retval, ALIGNOF_DBIND_STRUCT); +#endif + while (**type != DBUS_STRUCT_END_CHAR) { + int elem_align = dbind_find_c_alignment_r (type); + retval = MAX (retval, elem_align); + } + (*type)++; + return retval; + case DBUS_DICT_ENTRY_BEGIN_CHAR: +#if ALIGNOF_DBIND_STRUCT > 1 + retval = MAX (retval, ALIGNOF_DBIND_STRUCT); +#endif + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + int elem_align = dbind_find_c_alignment_r (type); + retval = MAX (retval, elem_align); + } + (*type)++; + return retval; + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + return ALIGNOF_DBIND_POINTER; + case '\0': + g_assert_not_reached(); + break; + default: + return 1; + } +} + +/*---------------------------------------------------------------------------*/ + +/* gather immediate allocation information for this type */ +static size_t +dbind_gather_alloc_info_r (const char **type) +{ + char t = **type; + (*type)++; + if (t == DBUS_TYPE_ARRAY) + { + switch (**type) + { + case DBUS_STRUCT_BEGIN_CHAR: + while (**type != DBUS_STRUCT_END_CHAR && **type != '\0') (*type)++; + if (**type != '\0') (*type)++; + break; + case DBUS_DICT_ENTRY_BEGIN_CHAR: + while (**type != DBUS_DICT_ENTRY_END_CHAR && **type != '\0') (*type)++; + if (**type != '\0') (*type)++; + break; + case '\0': + break; + default: + (*type)++; + break; + } + } + + switch (t) { + case DBUS_TYPE_BYTE: + return sizeof (char); + case DBUS_TYPE_BOOLEAN: + return sizeof (dbus_bool_t); + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + return sizeof (dbus_int16_t); + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + return sizeof (dbus_int32_t); + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + return sizeof (dbus_int64_t); + case DBUS_TYPE_DOUBLE: + return sizeof (double); + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + return sizeof (void *); + case DBUS_STRUCT_BEGIN_CHAR: { + int sum = 0, stralign; + + stralign = dbind_find_c_alignment (*type - 1); + + while (**type != DBUS_STRUCT_END_CHAR) { + sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type)); + sum += dbind_gather_alloc_info_r (type); + } + sum = ALIGN_VALUE (sum, stralign); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + return sum; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + int sum = 0, stralign; + + stralign = dbind_find_c_alignment (*type - 1); + + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + sum = ALIGN_VALUE (sum, dbind_find_c_alignment (*type)); + sum += dbind_gather_alloc_info_r (type); + } + sum = ALIGN_VALUE (sum, stralign); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + return sum; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + default: + return 0; + } +} + +static size_t +dbind_gather_alloc_info (const char *type) +{ + return dbind_gather_alloc_info_r (&type); +} + +/*---------------------------------------------------------------------------*/ + +static void +dbind_any_free_r (const char **type, void **data) +{ +#ifdef DEBUG + fprintf (stderr, "any free '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + *data = ((guchar *)*data) + dbind_gather_alloc_info (*type); + (*type)++; + break; + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: +#ifdef DEBUG + fprintf (stderr, "string free %p\n", **(void ***)data); +#endif + g_free (**(void ***)data); + *data = ((guchar *)*data) + dbind_gather_alloc_info (*type); + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + int i; + GArray *vals = **(void ***)data; + size_t elem_size, elem_align; + const char *saved_child_type; + + (*type)++; + saved_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + + for (i = 0; i < vals->len; i++) { + void *ptr = vals->data + elem_size * i; + *type = saved_child_type; /* rewind type info */ + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_free_r (type, &ptr); + } + g_array_free (vals, TRUE); + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + + stralign = dbind_find_c_alignment (*type); + (*type)++; + + offset = 0 ; + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_free_r (type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + + stralign = dbind_find_c_alignment (*type); + (*type)++; + + offset = 0 ; + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_free_r (type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_marshal (DBusMessageIter *iter, + const char **type, + void **data) +{ + size_t len; + +#ifdef DEBUG + fprintf (stderr, "any marshal '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_append_basic (iter, **type, *data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + int i; + GArray *vals = **(void ***)data; + size_t elem_size, elem_align; + DBusMessageIter sub; + const char *saved_child_type; + char *child_type_string; + + (*type)++; + saved_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + + /* wow this part of the API sucks too ... */ + child_type_string = g_strndup (saved_child_type, *type - saved_child_type); + /* fprintf (stderr, "array child type '%s'\n", child_type_string); */ + dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, + child_type_string, &sub); + for (i = 0; i < vals->len; i++) { + void *ptr = vals->data + elem_size * i; + *type = saved_child_type; /* rewind type info */ + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_marshal (&sub, type, &ptr); + } + + dbus_message_iter_close_container (iter, &sub); + g_free (child_type_string); + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter sub; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, &sub); + + offset = 0 ; + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_marshal (&sub, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + dbus_message_iter_close_container (iter, &sub); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter sub; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, &sub); + + offset = 0 ; + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_marshal (&sub, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + dbus_message_iter_close_container (iter, &sub); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_marshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args) +{ + const char *p = *arg_types; + + /* Guard against null arg types + Fix for - http://bugs.freedesktop.org/show_bug.cgi?id=23027 + */ + if (p == NULL) + p = ""; + + { + /* special case base-types since we need to walk the stack worse-luck */ + for (;*p != '\0' && *p != '=';) { + int intarg; + void *ptrarg; + double doublearg; + dbus_int64_t int64arg; + void *arg = NULL; + + switch (*p) { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + intarg = va_arg (args, int); + arg = &intarg; + break; + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + int64arg = va_arg (args, dbus_int64_t); + arg = &int64arg; + break; + case DBUS_TYPE_DOUBLE: + doublearg = va_arg (args, double); + arg = &doublearg; + break; + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT_ENTRY: + ptrarg = va_arg (args, void *); + arg = &ptrarg; + break; + case DBUS_STRUCT_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + arg = ptrarg; + break; + case DBUS_DICT_ENTRY_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + arg = ptrarg; + break; + + case DBUS_TYPE_VARIANT: + fprintf (stderr, "No variant support yet - very toolkit specific\n"); + ptrarg = va_arg (args, void *); + arg = &ptrarg; + break; + default: + fprintf (stderr, "Unknown / invalid arg type %c\n", *p); + break; + } + if (arg != NULL) + dbind_any_marshal (iter, &p, &arg); + } + if (*arg_types) + *arg_types = p; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_demarshal (DBusMessageIter *iter, + const char **type, + void **data) +{ + size_t len; + +#ifdef DEBUG + fprintf (stderr, "any demarshal '%c' to %p\n", **type, *data); +#endif + + switch (**type) { + case DBIND_POD_CASES: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_get_basic (iter, *data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + len = dbind_gather_alloc_info (*type); + dbus_message_iter_get_basic (iter, *data); +#ifdef DEBUG + fprintf (stderr, "dup string '%s' (%p)\n", **(void ***)data, **(void ***)data); +#endif + **(void ***)data = g_strdup (**(void ***)data); + *data = ((guchar *)*data) + len; + (*type)++; + break; + case DBUS_TYPE_ARRAY: { + GArray *vals; + DBusMessageIter child; + size_t elem_size, elem_align; + const char *stored_child_type; + int i; + + (*type)++; + stored_child_type = *type; + + elem_size = dbind_gather_alloc_info (*type); + elem_align = dbind_find_c_alignment_r (type); + vals = g_array_new (FALSE, FALSE, elem_size); + (**(void ***)data) = vals; + *data = ((guchar *)*data) + sizeof (void *); + + i = 0; + dbus_message_iter_recurse (iter, &child); + while (dbus_message_iter_get_arg_type (&child) != DBUS_TYPE_INVALID) { + void *ptr; + const char *subt = stored_child_type; + g_array_set_size (vals, i + 1); + ptr = vals->data + elem_size * i; + ptr = ALIGN_ADDRESS (ptr, elem_align); + dbind_any_demarshal (&child, &subt, &ptr); + i++; + }; + break; + } + case DBUS_STRUCT_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter child; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_recurse (iter, &child); + + while (**type != DBUS_STRUCT_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_demarshal (&child, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_STRUCT_END_CHAR); + (*type)++; + + break; + } + case DBUS_DICT_ENTRY_BEGIN_CHAR: { + gconstpointer data0 = *data; + int offset = 0, stralign; + DBusMessageIter child; + + stralign = dbind_find_c_alignment (*type); + + (*type)++; + + dbus_message_iter_recurse (iter, &child); + + while (**type != DBUS_DICT_ENTRY_END_CHAR) { + const char *subt = *type; + offset = ALIGN_VALUE (offset, dbind_find_c_alignment (*type)); + *data = PTR_PLUS (data0, offset); + dbind_any_demarshal (&child, type, data); + offset += dbind_gather_alloc_info (subt); + } + + offset = ALIGN_VALUE (offset, stralign); + *data = PTR_PLUS (data0, offset); + + g_assert (**type == DBUS_DICT_ENTRY_END_CHAR); + (*type)++; + + break; + case DBUS_TYPE_VARIANT: + /* skip; unimplemented for now */ + (*type)++; + break; + } + case DBUS_TYPE_STRUCT: + case DBUS_TYPE_DICT_ENTRY: + warn_braces (); + break; + } + dbus_message_iter_next (iter); +} + +static const char * +pass_complex_arg (const char *p, char begin, char end) +{ + int level = 1; + + p++; + while (*p && level > 0) + { + if (*p == begin) + level++; + else if (*p == end) + level--; + p++; + } + if (*p == end) + p++; + return p; +} + +static const char * +pass_arg (const char *p) +{ + switch (*p) + { + case '(': + return pass_complex_arg (p, '(', ')'); + case '{': + return pass_complex_arg (p, '{', '}'); + case 'a': + return pass_arg (p+1); + default: + return p + 1; + } +} + +/*---------------------------------------------------------------------------*/ + +void +dbind_any_demarshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args) +{ + const char *p = *arg_types; + + /* Pass in args */ + for (;*p != '\0' && *p != '=';) { + int intarg; + void *ptrarg; + double doublearg; + dbus_int64_t int64arg; + void *arg = NULL; + + switch (*p) { + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT16: + case DBUS_TYPE_UINT16: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + intarg = va_arg (args, int); + break; + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + int64arg = va_arg (args, dbus_int64_t); + break; + case DBUS_TYPE_DOUBLE: + doublearg = va_arg (args, double); + break; + /* ptr types */ + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT_ENTRY: + ptrarg = va_arg (args, void *); + break; + case DBUS_STRUCT_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + break; + case DBUS_DICT_ENTRY_BEGIN_CHAR: + ptrarg = va_arg (args, void *); + break; + + case DBUS_TYPE_VARIANT: + fprintf (stderr, "No variant support yet - very toolkit specific\n"); + ptrarg = va_arg (args, void *); + break; + default: + fprintf (stderr, "Unknown / invalid arg type %c\n", *p); + break; + } + p = pass_arg (p); + } + + if (p [0] == '=' && p[1] == '>') + p += 2; + + for (;*p != '\0';) { + void *arg = va_arg (args, void *); + dbind_any_demarshal (iter, &p, &arg); + } +} + +/*---------------------------------------------------------------------------*/ + +/* nice deep free ... */ +void +dbind_any_free (const char *type, + void *ptr) +{ + dbind_any_free_r (&type, &ptr); +} + +/* should this be the default normalization ? */ +void +dbind_any_free_ptr (const char *type, void *ptr) +{ + dbind_any_free (type, &ptr); +} + +/*---------------------------------------------------------------------------*/ + +unsigned int +dbind_find_c_alignment (const char *type) +{ + return dbind_find_c_alignment_r (&type); +} + +/*END------------------------------------------------------------------------*/ diff --git a/dbind/dbind-any.h b/dbind/dbind-any.h new file mode 100644 index 0000000..dd2a27b --- /dev/null +++ b/dbind/dbind-any.h @@ -0,0 +1,50 @@ +/* + * Copyright 2008-2011 Novell, 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 _DBIND_ANY_H_ +#define _DBIND_ANY_H_ + +#define DBUS_API_SUBJECT_TO_CHANGE +#include + +unsigned int dbind_find_c_alignment (const char *type); + +void dbind_any_marshal (DBusMessageIter *iter, + const char **type, + void **val); + +void dbind_any_marshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args); + +void dbind_any_demarshal (DBusMessageIter *iter, + const char **type, + void **val); + +void dbind_any_demarshal_va (DBusMessageIter *iter, + const char **arg_types, + va_list args); + +void dbind_any_free (const char *type, + void *ptr_to_ptr); + +void dbind_any_free_ptr (const char *type, + void *ptr); + +#endif /* _DBIND_ANY_H_ */ diff --git a/dbind/dbind.c b/dbind/dbind.c new file mode 100644 index 0000000..9d7304e --- /dev/null +++ b/dbind/dbind.c @@ -0,0 +1,321 @@ +/* + * Copyright 2008-2011 Novell, 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. + */ + +#include +#include +#include +#include +#include + +#include "config.h" +#include "dbind/dbind.h" +#include "atspi/atspi-gmain.h" + +static int dbind_timeout = -1; + +/* + * FIXME: compare types - to ensure they match & + * do dynamic padding of structures etc. + */ + +/*---------------------------------------------------------------------------*/ + +typedef struct _SpiReentrantCallClosure +{ + DBusMessage *reply; +} SpiReentrantCallClosure; + +static void +set_reply (DBusPendingCall * pending, void *user_data) +{ + SpiReentrantCallClosure* closure = (SpiReentrantCallClosure *) user_data; + + closure->reply = dbus_pending_call_steal_reply (pending); + dbus_pending_call_unref (pending); +} + +static gint +time_elapsed (struct timeval *origin) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return (tv.tv_sec - origin->tv_sec) * 1000 + (tv.tv_usec - origin->tv_usec) / 1000; +} + +DBusMessage * +dbind_send_and_allow_reentry (DBusConnection * bus, DBusMessage * message, DBusError *error) +{ + DBusPendingCall *pending; + SpiReentrantCallClosure *closure; + const char *unique_name = dbus_bus_get_unique_name (bus); + const char *destination = dbus_message_get_destination (message); + struct timeval tv; + DBusMessage *ret; + static gboolean in_dispatch = FALSE; + + if (unique_name && destination && + strcmp (destination, unique_name) != 0) + { + ret = dbus_connection_send_with_reply_and_block (bus, message, + dbind_timeout, error); + if (g_main_depth () == 0 && !in_dispatch) + { + in_dispatch = TRUE; + while (dbus_connection_dispatch (bus) == DBUS_DISPATCH_DATA_REMAINS); + in_dispatch = FALSE; + } + return ret; + } + + closure = g_new0 (SpiReentrantCallClosure, 1); + closure->reply = NULL; + if (!dbus_connection_send_with_reply (bus, message, &pending, dbind_timeout) + || !pending) + { + g_free (closure); + return NULL; + } + dbus_pending_call_set_notify (pending, set_reply, (void *) closure, g_free); + + closure->reply = NULL; + gettimeofday (&tv, NULL); + dbus_pending_call_ref (pending); + while (!closure->reply) + { + if (!dbus_connection_read_write_dispatch (bus, dbind_timeout)) + { + //dbus_pending_call_set_notify (pending, NULL, NULL, NULL); + dbus_pending_call_cancel (pending); + dbus_pending_call_unref (pending); + return NULL; + } + if (time_elapsed (&tv) > dbind_timeout) + { + //dbus_pending_call_set_notify (pending, NULL, NULL, NULL); + dbus_pending_call_cancel (pending); + dbus_pending_call_unref (pending); + dbus_set_error_const (error, "org.freedesktop.DBus.Error.NoReply", + "timeout from dbind"); + return NULL; + } + } + + ret = closure->reply; + dbus_pending_call_unref (pending); + return ret; +} + +dbus_bool_t +dbind_method_call_reentrant_va (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + va_list args) +{ + dbus_bool_t success = FALSE; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter; + DBusError *err, real_err; + const char *p; + va_list args_demarshal; + + dbus_error_init (&real_err); + + va_copy (args_demarshal, args); + if (opt_error) + err = opt_error; + else { + err = &real_err; + } + + msg = dbus_message_new_method_call (bus_name, path, interface, method); + if (!msg) + goto out; + + p = arg_types; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + reply = dbind_send_and_allow_reentry (cnx, msg, err); + if (!reply) + goto out; + + if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + { + goto out; + } + /* demarshal */ + if (p[0] == '=' && p[1] == '>') + { + DBusMessageIter iter; + dbus_message_iter_init (reply, &iter); + if (strcmp (p + 2, dbus_message_get_signature (reply)) != 0) + { + g_warning ("dbind: Call to \"%s\" returned signature %s; expected %s", + method, dbus_message_get_signature (reply), p + 2); + if (opt_error) + dbus_set_error (opt_error, DBUS_ERROR_INVALID_ARGS, + "Call to \"%s\" returned signature %s; expected %s", + method, dbus_message_get_signature (reply), + p + 2); + goto out; + } + p = arg_types; + dbind_any_demarshal_va (&iter, &p, args_demarshal); + } + + success = TRUE; +out: + if (msg) + dbus_message_unref (msg); + + if (reply) + dbus_message_unref (reply); + + if (dbus_error_is_set (&real_err)) + dbus_error_free (&real_err); + + va_end (args_demarshal); + return success; +} + +/** + * dbind_method_call_reentrant: + * + * @cnx: A D-Bus Connection used to make the method call. + * @bus_name: The D-Bus bus name of the program where the method call should + * be made. + * @path: The D-Bus object path that should handle the method. + * @interface: The D-Bus interface used to scope the method name. + * @method: Method to be invoked. + * @opt_error: D-Bus error. + * @arg_types: Variable length arguments interleaving D-Bus argument types + * and pointers to argument data. + * + * Makes a D-Bus method call using the supplied location data, method name and + * argument data.This function is re-entrant. It continuously reads from the D-Bus + * bus and dispatches messages until a reply has been recieved. + **/ +dbus_bool_t +dbind_method_call_reentrant (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + ...) +{ + dbus_bool_t success = FALSE; + va_list args; + + va_start (args, arg_types); + success = dbind_method_call_reentrant_va (cnx, + bus_name, + path, + interface, + method, + opt_error, + arg_types, + args); + va_end (args); + + return success; +} + +/*---------------------------------------------------------------------------*/ + +/* TODO: opt_error is unused; should be removed */ +dbus_bool_t +dbind_emit_signal_va (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + va_list args) +{ + dbus_bool_t success = FALSE; + DBusMessage *msg = NULL; + DBusMessageIter iter; + const char *p; + + msg = dbus_message_new_signal (path, interface, signal); + if (!msg) + goto out; + + p = arg_types; + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal_va (&iter, &p, args); + + if (!dbus_connection_send (cnx, msg, NULL)) + goto out; + + success = TRUE; +out: + + if (msg) + dbus_message_unref (msg); + + return success; +} + +/** + * dbind_emit_signal: + * + * @cnx: A D-Bus Connection used to make the method call. + * @path: The D-Bus object path that this signal is emitted from. + * @interface: The D-Bus interface used to scope the method name. + * @signal: Name of signal to emit. + * @opt_error: D-Bus error. + * @arg_types: Variable length arguments interleaving D-Bus argument types + * and pointers to argument data. + * + * Emits a D-Bus signal using the supplied signal name and argument data. + **/ +dbus_bool_t +dbind_emit_signal (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + ...) +{ + dbus_bool_t success = FALSE; + va_list args; + + va_start (args, arg_types); + success = dbind_emit_signal_va (cnx, path, interface, signal, opt_error, arg_types, args); + va_end (args); + + return success; +} +void +dbind_set_timeout (int timeout) +{ + dbind_timeout = timeout; +} + + +/*END------------------------------------------------------------------------*/ diff --git a/dbind/dbind.h b/dbind/dbind.h new file mode 100644 index 0000000..f7298d0 --- /dev/null +++ b/dbind/dbind.h @@ -0,0 +1,69 @@ +/* + * Copyright 2008-2011 Novell, 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 _DBIND_H_ +#define _DBIND_H_ + +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include + +DBusMessage * +dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error); + +dbus_bool_t +dbind_method_call_reentrant_va (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + va_list args); + +dbus_bool_t +dbind_method_call_reentrant (DBusConnection *cnx, + const char *bus_name, + const char *path, + const char *interface, + const char *method, + DBusError *opt_error, + const char *arg_types, + ...); + +dbus_bool_t +dbind_emit_signal_va (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + va_list args); + +dbus_bool_t +dbind_emit_signal (DBusConnection *cnx, + const char *path, + const char *interface, + const char *signal, + DBusError *opt_error, + const char *arg_types, + ...); + +void dbind_set_timeout (int timeout); +#endif /* _DBIND_H_ */ diff --git a/dbind/dbtest.c b/dbind/dbtest.c new file mode 100644 index 0000000..abd241a --- /dev/null +++ b/dbind/dbtest.c @@ -0,0 +1,420 @@ +/* + * Copyright 2008-2011 Novell, 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. + */ + +#include +#include +#include +#include + +/* Wow! dbus is unpleasant to use */ + +#define DESKICE_PATH "/Novell/ICEDesktop/Daemon" +#define DESKICE_NAMESPACE "Novell.ICEDesktop.Daemon" + +void marshal (DBusMessage *msg, char *type, void *ptr) +{ + DBusMessageIter iter; + + dbus_message_iter_init_append (msg, &iter); + dbind_any_marshal (&iter, &type, &ptr); +} + +void demarshal (DBusMessage *msg, char *type, void *ptr) +{ + DBusMessageIter iter; + + if (!dbus_message_iter_init (msg, &iter)) + fprintf (stderr, "no data in msg\n"); + else + dbind_any_demarshal (&iter, &type, &ptr); +} + +#if 0 +dbus_bool_t dbus_message_marshal (DBusMessage *msg, + char **marshalled_data_p, + int *len_p); + +void dump_msg (DBusMessage *msg) +{ + char *data = NULL; + int len, i, j; + + dbus_message_marshal (msg, &data, &len); + for (i = 0; i < (len+15)/16; i++) { + fprintf (stderr, "%4.d | ", i * 16); + for (j = 0; j < 16; j++) { + unsigned char c = (i*16+j <= len) ? data[i*16+j] : 0; + fprintf (stderr, "0x%.2x ", c); + } + fprintf (stderr, " | "); + for (j = 0; j < 16; j++) { + char c = (i*16+j <= len) ? data[i*16+j] : '\0'; + fprintf (stderr, "%c", g_ascii_isprint (c) ? c : '.'); + } + } +} +#endif + +void test_simple () +{ + dbus_int32_t v1, v2; + DBusMessage *msg; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + v1 = 42; + marshal (msg, "i", &v1); + demarshal (msg, "i", &v2); + g_assert (v2 == 42); + g_assert (v1 == v2); + + dbind_any_free ("i", &v2); /* nop */ + dbus_message_unref (msg); + + fprintf (stderr, "simple ok\n"); +} + +void test_array () +{ + GArray *a1, *a2; + DBusMessage *msg; + + /* pod types */ + a1 = g_array_new (FALSE, FALSE, sizeof (dbus_int32_t)); + g_array_set_size (a1, 4); + g_array_index (a1, dbus_int32_t, 0) = 42; + g_array_index (a1, dbus_int32_t, 1) = 17; + g_array_index (a1, dbus_int32_t, 2) = 26; + g_array_index (a1, dbus_int32_t, 3) = 38; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, "ai", &a1); + demarshal (msg, "ai", &a2); + + g_assert (a2 != NULL); + g_assert (a2->len == 4); + g_assert (g_array_index (a2, dbus_int32_t, 0) == 42); + g_assert (g_array_index (a2, dbus_int32_t, 1) == 17); + g_assert (g_array_index (a2, dbus_int32_t, 2) == 26); + g_assert (g_array_index (a2, dbus_int32_t, 3) == 38); + g_array_free (a1, TRUE); + + dbind_any_free ("ai", &a2); + dbus_message_unref (msg); + + fprintf (stderr, "array ok\n"); +} + +/* this taught me that the struct type is a mis-nomer, + it is generated by brackets */ +void test_struct_native () +{ + DBusMessage *msg; + DBusMessageIter iter, arr, str; + + /* manually create ar(ss) */ + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + + dbus_message_iter_init_append (msg, &iter); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &arr); + { + char *foo; + dbus_message_iter_open_container (&arr, DBUS_TYPE_STRUCT, NULL, &str); + + foo = "foo"; + dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo); + foo = "baa"; + dbus_message_iter_append_basic (&str, DBUS_TYPE_STRING, &foo); + + dbus_message_iter_close_container (&arr, &str); + } + dbus_message_iter_close_container (&iter, &arr); + + fprintf (stderr, "native struct marshalling ok\n"); + + dbus_message_unref (msg); +} + + +void test_struct_simple () +{ + typedef struct { + char *foo; + char *baa; + char *baz; + } FooBaa; + GArray *a1 = NULL, *a2 = NULL; + DBusMessage *msg; + + a1 = g_array_new (FALSE, FALSE, sizeof (FooBaa)); + g_array_set_size (a1, 2); + g_array_index (a1, FooBaa, 0).foo = "foo"; + g_array_index (a1, FooBaa, 0).baa = "baa"; + g_array_index (a1, FooBaa, 0).baz = "baz"; + g_array_index (a1, FooBaa, 1).foo = "Foo"; + g_array_index (a1, FooBaa, 1).baa = "baA"; + g_array_index (a1, FooBaa, 1).baz = "BaZ"; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, "a(sss)", &a1); + demarshal (msg, "a(sss)", &a2); + + g_assert (a2 != NULL); + g_assert (a2 != a1); + g_assert (a2->len == 2); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).foo, "foo")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baa, "baa")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 0).baz, "baz")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).foo, "Foo")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baa, "baA")); + g_assert (!strcmp (g_array_index (a2, FooBaa, 1).baz, "BaZ")); + + fprintf (stderr, "simple struct ok\n"); + + dbind_any_free ("a(sss)", &a2); + dbus_message_unref (msg); +} + +void test_struct_complex () +{ + typedef struct { + dbus_int32_t x, y; + } Point; + typedef struct { + unsigned char pad1; + double val; + Point tl, br; + char pad2; + char *name; + } Complex; +#define TYPEOF_POINT \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING +#define TYPEOF_COMPLEX \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_TYPE_DOUBLE_AS_STRING \ + TYPEOF_POINT \ + TYPEOF_POINT \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + + DBusMessage *msg; + Complex c1, c2; + + memset (&c1, 0, sizeof (c1)); + memset (&c2, 0, sizeof (c2)); + + c1.pad1 = 2; + c1.val = 0.1327569; + c1.tl.x = 1; + c1.tl.y = 17; + c1.br.x = 2587; + c1.br.y = -1; + c1.pad2 = 1; + c1.name = "stroustrup"; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, TYPEOF_COMPLEX, &c1); + demarshal (msg, TYPEOF_COMPLEX, &c2); + + g_assert (c2.pad1 == 2); + g_assert (c2.val == c1.val); + g_assert (c2.val != 0); + g_assert (c2.tl.x == 1); + g_assert (c2.tl.y == 17); + g_assert (c2.br.x == 2587); + g_assert (c2.br.y == -1); + g_assert (c2.pad2 == 1); + g_assert (!strcmp (c1.name, "stroustrup")); + + fprintf (stderr, "complex struct ok\n"); + + dbind_any_free (TYPEOF_COMPLEX, &c2); + dbus_message_unref (msg); +} + +void test_struct_with_array () +{ + typedef struct { + GArray *vals; + unsigned char pad1; + } ArrayStruct; +#define TYPEOF_ARRAYSTRUCT \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_TYPE_UINT32_AS_STRING \ + DBUS_TYPE_BYTE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + + DBusMessage *msg; + GArray *a1, *a2; + ArrayStruct *p, *q; + + + a1 = g_array_new (FALSE, FALSE, sizeof (ArrayStruct)); + g_array_set_size (a1, 2); + p = &g_array_index (a1, ArrayStruct, 0); + p[0].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t)); + g_array_set_size (p[0].vals, 2); + g_array_index (p[0].vals, dbus_uint32_t, 0) = 1; + g_array_index (p[0].vals, dbus_uint32_t, 1) = 1000; + p[0].pad1 = 2; + p[1].vals = g_array_new (FALSE, FALSE, sizeof (dbus_uint32_t)); + g_array_set_size (p[1].vals, 2); + g_array_index (p[1].vals, dbus_uint32_t, 0) = 1000000; + g_array_index (p[1].vals, dbus_uint32_t, 1) = 1000000000; + p[1].pad1 = 8; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + marshal (msg, TYPEOF_ARRAYSTRUCT, &a1); + demarshal (msg, TYPEOF_ARRAYSTRUCT, &a2); + + q = &g_array_index (a2, ArrayStruct, 0); + g_assert (p[0].pad1 == 2); + g_assert (g_array_index (p[1].vals, dbus_uint32_t, 1) == 1000000000); + + fprintf (stderr, "struct with array ok\n"); + + dbind_any_free (TYPEOF_ARRAYSTRUCT, &a2); + dbus_message_unref (msg); + g_array_free (p[0].vals, TRUE); + g_array_free (p[1].vals, TRUE); +} + +void test_twovals () +{ + typedef struct { + dbus_int32_t v1; + dbus_int32_t v2; + } TwoVal; +#define TYPEOF_TWOVAL \ + DBUS_TYPE_INT32_AS_STRING \ + DBUS_TYPE_INT32_AS_STRING \ + + DBusMessage *msg; + DBusMessageIter iter; + TwoVal i, o; + char *type_twoval = TYPEOF_TWOVAL; + char *type; + void *ptr; + + msg = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + i.v1 = 42; + i.v2 = 1764; + dbus_message_iter_init_append (msg, &iter); + type = type_twoval; + ptr = &i; + dbind_any_marshal (&iter, &type, &ptr); + dbind_any_marshal (&iter, &type, &ptr); + dbus_message_iter_init (msg, &iter); + type = type_twoval; + ptr = &o; + dbind_any_demarshal (&iter, &type, &ptr); + dbind_any_demarshal (&iter, &type, &ptr); + g_assert (o.v1 == 42); + g_assert (o.v2 == 1764); + g_assert (i.v1 == o.v1); + g_assert (i.v2 == o.v2); + + dbind_any_free ("ii", &o); /* nop */ + dbus_message_unref (msg); + + fprintf (stderr, "two-val ok\n"); +} + +void test_marshalling () +{ + test_simple (); + test_array (); + test_struct_native (); + test_struct_simple (); + test_struct_complex (); + test_struct_with_array (); + test_twovals (); + + fprintf (stderr, "Marshalling ok\n"); +} + +void test_teamspaces (DBusConnection *bus) +{ + GArray *spaces; + DBusError error; + int i; + typedef struct { + char *name; + char *id; + char *url; + } TeamSpace; + + dbus_error_init (&error); + if (!dbind_method_call_reentrant (bus, + NULL, + DESKICE_PATH, + DESKICE_NAMESPACE, + "GetTeamList", + &error, + "=>a(sss)", + &spaces)) { + fprintf (stderr, "Error getting team spaces %s: %s\n", + error.name, error.message); + dbus_error_free (&error); + return; + } + + if (!spaces) { + fprintf (stderr, "no teamspaces\n"); + return; + } + fprintf (stderr, "%d teamspace(s)\n", spaces->len); + for (i = 0; i < spaces->len; i++) { + TeamSpace *space = &g_array_index (spaces, TeamSpace, i); + fprintf (stderr, "\t%d: %s, %s, %s\n", i, space->name, space->id, space->url); + } + + dbind_any_free_ptr ("a(sss)", spaces); +} + +void test_helpers () +{ + dbind_find_c_alignment ("(sss)"); + dbind_find_c_alignment ("a(sss)"); + dbind_find_c_alignment ("(s(s)yd(d)s)"); + dbind_find_c_alignment ("a{ss}"); + fprintf (stderr, "helpers passed\n"); +} + +int main (int argc, char **argv) +{ + DBusConnection *bus; + + bus = dbus_bus_get (DBUS_BUS_SESSION, NULL); + + test_helpers (); + test_marshalling (); + test_teamspaces (bus); + + return 0; +} diff --git a/dbind/meson.build b/dbind/meson.build new file mode 100644 index 0000000..5a9f02d --- /dev/null +++ b/dbind/meson.build @@ -0,0 +1,14 @@ +dbind_sources = [ + 'dbind.c', + 'dbind-any.c', +] + +dbind_dep = declare_dependency(sources: dbind_sources, + include_directories: root_inc, + compile_args: [ '-DG_LOG_DOMAIN="dbind"' ], + dependencies: [ libdbus_dep, glib_dep ]) + +test('dbind-test', + executable('dbind-test', [ 'dbtest.c', '../atspi/atspi-gmain.c' ], + include_directories: root_inc, + dependencies: [ libdbus_dep, glib_dep, dbind_dep ])) diff --git a/doc/libatspi/Makefile.am b/doc/libatspi/Makefile.am new file mode 100644 index 0000000..93270f4 --- /dev/null +++ b/doc/libatspi/Makefile.am @@ -0,0 +1,97 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# The name of the module, e.g. 'glib'. +DOC_MODULE=libatspi + +# Uncomment for versioned docs and specify the version of the module, e.g. '2'. +#DOC_MODULE_VERSION=2 + + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# Directories containing the source code, relative to $(srcdir). +# gtk-doc will search all .c and .h files beneath these paths +# for inline comments documenting functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk +DOC_SOURCE_DIR=$(top_srcdir)/atspi + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS= + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-mkhtml +MKHTML_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/atspi/*.h +CFILE_GLOB=$(top_srcdir)/atspi/*.c + +# Extra header to include when scanning, which are not under DOC_SOURCE_DIR +# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h +EXTRA_HFILES= + +# Header files to ignore when scanning. Use base file name, no paths +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES= + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files= + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +GTKDOC_CFLAGS=$(GLIB_CFLAGS) $(GOBJ_CFLAGS) $(DBUS_CFLAGS) +GTKDOC_LIBS=$(GLIB_LIBS) $(GOBJ_LIBS) $(DBUS_LIBS) $(top_builddir)/atspi/libatspi.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += meson.build + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += + +# Comment this out if you want your docs-status tested during 'make check' +if ENABLE_GTK_DOC +#TESTS_ENVIRONMENT = cd $(srcdir) && +#TESTS = $(GTKDOC_CHECK) +endif + +-include $(top_srcdir)/git.mk diff --git a/doc/libatspi/libatspi-docs.sgml b/doc/libatspi/libatspi-docs.sgml new file mode 100644 index 0000000..8b9ff0d --- /dev/null +++ b/doc/libatspi/libatspi-docs.sgml @@ -0,0 +1,59 @@ + + + +]> + + + libatspi Reference Manual + + for libatspi &version;. + The latest version of this documentation can be found on-line at + http://developer.gnome.org/libatspi/. + + + + + API reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Object Hierarchy + + + + API Index + + + + + diff --git a/doc/libatspi/libatspi-sections.txt b/doc/libatspi/libatspi-sections.txt new file mode 100644 index 0000000..78abe76 --- /dev/null +++ b/doc/libatspi/libatspi-sections.txt @@ -0,0 +1,603 @@ +
+atspi-text +AtspiRange +ATSPI_TYPE_RANGE +atspi_range_copy +AtspiTextRange +ATSPI_TYPE_TEXT_RANGE +atspi_text_get_type +AtspiText +atspi_text_range_get_type +atspi_text_get_character_count +atspi_text_get_text +atspi_text_get_caret_offset +atspi_text_get_attributes +atspi_text_get_attribute_run +atspi_text_get_attribute_value +atspi_text_get_default_attributes +atspi_text_set_caret_offset +atspi_text_get_text_before_offset +atspi_text_get_text_at_offset +atspi_text_get_text_after_offset +atspi_text_get_character_at_offset +atspi_text_get_character_extents +atspi_text_get_offset_at_point +atspi_text_get_range_extents +atspi_text_get_bounded_ranges +atspi_text_get_n_selections +atspi_text_get_selection +atspi_text_add_selection +atspi_text_remove_selection +atspi_text_set_selection + +ATSPI_TEXT +ATSPI_IS_TEXT +ATSPI_TYPE_TEXT +atspi_range_get_type +ATSPI_TEXT_GET_IFACE +
+ +
+atspi-stateset +AtspiStateSet +AtspiStateSet +AtspiStateSetClass +atspi_state_set_new +atspi_state_set_set_by_name +atspi_state_set_add +atspi_state_set_compare +atspi_state_set_contains +atspi_state_set_equals +atspi_state_set_get_states +atspi_state_set_is_empty +atspi_state_set_remove + +ATSPI_STATE_SET +ATSPI_IS_STATE_SET +ATSPI_TYPE_STATE_SET +atspi_state_set_get_type +ATSPI_STATE_SET_CLASS +ATSPI_IS_STATE_SET_CLASS +ATSPI_STATE_SET_GET_CLASS +
+ +
+atspi-application +AtspiApplication +AtspiApplication +AtspiApplicationClass + +ATSPI_APPLICATION +ATSPI_IS_APPLICATION +ATSPI_TYPE_APPLICATION +ATSPI_APPLICATION_CLASS +ATSPI_IS_APPLICATION_CLASS +ATSPI_APPLICATION_GET_CLASS +
+ +
+atspi-collection +AtspiCollection +atspi_collection_is_ancestor_of +atspi_collection_get_matches +atspi_collection_get_matches_to +atspi_collection_get_matches_from +atspi_collection_get_active_descendant + +ATSPI_COLLECTION +ATSPI_IS_COLLECTION +ATSPI_TYPE_COLLECTION +atspi_collection_get_type +ATSPI_COLLECTION_GET_IFACE +
+ +
+atspi-action +AtspiAction +atspi_action_get_n_actions +atspi_action_get_description +atspi_action_get_key_binding +atspi_action_get_name +atspi_action_do_action + +ATSPI_ACTION +ATSPI_IS_ACTION +ATSPI_TYPE_ACTION +atspi_action_get_type +ATSPI_ACTION_GET_IFACE +
+ +
+atspi-relation +AtspiRelation +AtspiRelation +AtspiRelationClass +atspi_relation_get_relation_type +atspi_relation_get_n_targets +atspi_relation_get_target + +ATSPI_RELATION +ATSPI_IS_RELATION +ATSPI_TYPE_RELATION +atspi_relation_get_type +ATSPI_RELATION_GET_IFACE +
+ +
+atspi-image +AtspiImage +atspi_image_get_image_description +atspi_image_get_image_size +atspi_image_get_image_position +atspi_image_get_image_extents +atspi_image_get_image_locale + +ATSPI_IMAGE +ATSPI_IS_IMAGE +ATSPI_TYPE_IMAGE +atspi_image_get_type +ATSPI_IMAGE_GET_IFACE +
+ +
+atspi-matchrule +AtspiMatchRule +AtspiMatchRule +AtspiMatchRuleClass +atspi_match_rule_new + +ATSPI_MATCH_RULE +ATSPI_IS_MATCH_RULE +ATSPI_TYPE_MATCH_RULE +atspi_match_rule_get_type +ATSPI_MATCH_RULE_CLASS +ATSPI_IS_MATCH_RULE_CLASS +ATSPI_MATCH_RULE_GET_CLASS +
+ +
+atspi-document +AtspiDocument +atspi_document_get_locale +atspi_document_get_attribute_value +atspi_document_get_attributes + +ATSPI_DOCUMENT +ATSPI_IS_DOCUMENT +ATSPI_TYPE_DOCUMENT +atspi_document_get_type +ATSPI_DOCUMENT_GET_IFACE +
+ +
+atspi-object +AtspiObject +AtspiObject +AtspiObjectClass + +ATSPI_OBJECT +ATSPI_IS_OBJECT +ATSPI_TYPE_OBJECT +atspi_object_get_type +ATSPI_OBJECT_CLASS +ATSPI_IS_OBJECT_CLASS +ATSPI_OBJECT_GET_CLASS +
+ +
+atspi-accessible +AtspiAccessible +AtspiAccessible +AtspiAccessibleClass +atspi_accessible_new +atspi_role_get_name +atspi_accessible_get_name +atspi_accessible_get_description +atspi_accessible_get_parent +atspi_accessible_get_child_count +atspi_accessible_get_child_at_index +atspi_accessible_get_index_in_parent +atspi_accessible_get_relation_set +atspi_accessible_get_role +atspi_accessible_get_role_name +atspi_accessible_get_localized_role_name +atspi_accessible_get_state_set +atspi_accessible_get_attributes +atspi_accessible_get_attributes_as_array +atspi_accessible_get_locale +atspi_accessible_get_toolkit_name +atspi_accessible_get_toolkit_version +atspi_accessible_get_application +atspi_accessible_get_action +atspi_accessible_get_collection +atspi_accessible_get_component +atspi_accessible_get_document +atspi_accessible_get_editable_text +atspi_accessible_get_hyperlink +atspi_accessible_get_hypertext +atspi_accessible_get_image +atspi_accessible_get_selection +atspi_accessible_get_table +atspi_accessible_get_text +atspi_accessible_get_value +atspi_accessible_get_interfaces + +ATSPI_ACCESSIBLE +ATSPI_IS_ACCESSIBLE +ATSPI_TYPE_ACCESSIBLE +atspi_accessible_get_type +ATSPI_ACCESSIBLE_CLASS +ATSPI_IS_ACCESSIBLE_CLASS +ATSPI_ACCESSIBLE_GET_CLASS +
+ +
+atspi-device-listener +AtspiDeviceListener +AtspiDeviceListenerCB +AtspiDeviceListenerSimpleCB +AtspiDeviceListener +AtspiDeviceListenerClass +atspi_device_listener_new +atspi_device_listener_new_simple +atspi_device_listener_add_callback +atspi_device_listener_remove_callback + +ATSPI_DEVICE_LISTENER +ATSPI_IS_DEVICE_LISTENER +ATSPI_TYPE_DEVICE_LISTENER +atspi_device_listener_get_type +ATSPI_DEVICE_LISTENER_CLASS +ATSPI_IS_DEVICE_LISTENER_CLASS +ATSPI_DEVICE_LISTENER_GET_CLASS +
+ +
+atspi-hyperlink +AtspiHyperlink +AtspiHyperlink +AtspiHyperlinkClass +atspi_hyperlink_new +atspi_hyperlink_get_n_anchors +atspi_hyperlink_get_uri +atspi_hyperlink_get_object +atspi_hyperlink_get_index_range +atspi_hyperlink_get_start_index +atspi_hyperlink_get_end_index +atspi_hyperlink_is_valid + +ATSPI_HYPERLINK +ATSPI_IS_HYPERLINK +ATSPI_TYPE_HYPERLINK +atspi_hyperlink_get_type +ATSPI_HYPERLINK_CLASS +ATSPI_IS_HYPERLINK_CLASS +ATSPI_HYPERLINK_GET_CLASS +
+ +
+atspi-editabletext +AtspiEditableText +atspi_editable_text_set_attributes +atspi_editable_text_insert_text +atspi_editable_text_copy_text +atspi_editable_text_cut_text +atspi_editable_text_delete_text +atspi_editable_text_paste_text + +ATSPI_EDITABLE_TEXT +ATSPI_IS_EDITABLE_TEXT +ATSPI_TYPE_EDITABLE_TEXT +atspi_editable_text_get_type +ATSPI_EDITABLE_TEXT_GET_IFACE +
+ +
+atspi-value +AtspiValue +atspi_value_get_minimum_value +atspi_value_get_current_value +atspi_value_get_maximum_value +atspi_value_set_current_value +atspi_value_get_minimum_increment + +ATSPI_VALUE +ATSPI_IS_VALUE +ATSPI_TYPE_VALUE +atspi_value_get_type +ATSPI_VALUE_GET_IFACE +
+ +
+atspi-table +AtspiTable +atspi_table_get_caption +atspi_table_get_summary +atspi_table_get_n_rows +atspi_table_get_n_columns +atspi_table_get_accessible_at +atspi_table_get_index_at +atspi_table_get_row_at_index +atspi_table_get_column_at_index +atspi_table_get_row_description +atspi_table_get_column_description +atspi_table_get_row_extent_at +atspi_table_get_column_extent_at +atspi_table_get_row_header +atspi_table_get_column_header +atspi_table_get_n_selected_rows +atspi_table_get_selected_rows +atspi_table_get_selected_columns +atspi_table_get_n_selected_columns +atspi_table_is_row_selected +atspi_table_is_column_selected +atspi_table_add_row_selection +atspi_table_add_column_selection +atspi_table_remove_row_selection +atspi_table_remove_column_selection +atspi_table_get_row_column_extents_at_index +atspi_table_is_selected + +ATSPI_TABLE +ATSPI_IS_TABLE +ATSPI_TYPE_TABLE +atspi_table_get_type +ATSPI_TABLE_GET_IFACE +
+ +atspi-table-cell +AtspiTableCell +atspi_table_cell_get_column_span +atspi_table_cell_get_column_header_cells +atspi_table_cell_get_column_index +atspi_table_cell_get_row_span +atspi_table_cell_get_row_header_cells +atspi_table_cell_get_position +atspi_table_cell_get_row_column_span +atspi_table_cell_get_table + +ATSPI_TABLE +ATSPI_IS_TABLE +ATSPI_TYPE_TABLE +atspi_table_get_type +ATSPI_TABLE_GET_IFACE + +
+atspi-selection +AtspiSelection +atspi_selection_get_n_selected_children +atspi_selection_get_selected_child +atspi_selection_select_child +atspi_selection_deselect_selected_child +atspi_selection_deselect_child +atspi_selection_is_child_selected +atspi_selection_select_all +atspi_selection_clear_selection + +ATSPI_SELECTION +ATSPI_IS_SELECTION +ATSPI_TYPE_SELECTION +atspi_selection_get_type +ATSPI_SELECTION_GET_IFACE +
+ +
+atspi-event-listener +AtspiEventListener +AtspiEventListenerCB +AtspiEventListenerSimpleCB +AtspiEventListener +AtspiEventListenerClass +atspi_event_listener_get_type +atspi_event_listener_new +atspi_event_listener_new_simple +atspi_event_listener_register +atspi_event_listener_register_from_callback +atspi_event_listener_register_no_data +atspi_event_listener_deregister +atspi_event_listener_deregister_from_callback +atspi_event_listener_deregister_no_data + +ATSPI_EVENT_LISTENER +ATSPI_IS_EVENT_LISTENER +ATSPI_TYPE_EVENT_LISTENER +atspi_event_get_type +ATSPI_EVENT_LISTENER_CLASS +ATSPI_IS_EVENT_LISTENER_CLASS +ATSPI_EVENT_LISTENER_GET_CLASS +
+ +
+atspi-hypertext +AtspiHypertext +atspi_hypertext_get_n_links +atspi_hypertext_get_link +atspi_hypertext_get_link_index + +ATSPI_HYPERTEXT +ATSPI_IS_HYPERTEXT +ATSPI_TYPE_HYPERTEXT +atspi_hypertext_get_type +ATSPI_HYPERTEXT_GET_IFACE +
+ +
+atspi-component +AtspiRect +ATSPI_TYPE_RECT +atspi_rect_copy +AtspiPoint +ATSPI_TYPE_POINT +atspi_point_get_type +atspi_point_copy +atspi_component_get_type +AtspiComponent +atspi_component_contains +atspi_component_get_accessible_at_point +atspi_component_get_extents +atspi_component_get_position +atspi_component_get_size +atspi_component_get_layer +atspi_component_get_mdi_z_order +atspi_component_grab_focus +atspi_component_get_alpha + +ATSPI_COMPONENT +ATSPI_IS_COMPONENT +ATSPI_TYPE_COMPONENT +atspi_rect_get_type +ATSPI_COMPONENT_GET_IFACE +
+ +
+atspi-registry +atspi_key_definition_get_type +atspi_get_desktop_count +atspi_get_desktop +atspi_get_desktop_list +atspi_register_keystroke_listener +atspi_deregister_keystroke_listener +atspi_register_device_event_listener +atspi_deregister_device_event_listener +atspi_generate_keyboard_event +atspi_generate_mouse_event +
+ +
+atspi-types +AtspiAccessible +AtspiAction +AtspiCollection +AtspiComponent +AtspiDocument +AtspiEditableText +AtspiHyperlink +AtspiHypertext +AtspiImage +AtspiSelection +AtspiTable +AtspiTableCell +AtspiText +AtspiValue +AtspiControllerEventMask +AtspiKeyMaskType +AtspiKeyEventMask +AtspiDeviceEventMask +AtspiDeviceEvent +AtspiEventListenerMode +AtspiKeyDefinition +AtspiEvent +ATSPI_TYPE_EVENT +AtspiKeystrokeListener +AtspiKeyListenerSyncType +
+ +
+atspi-constants +AtspiLocaleType +ATSPI_LOCALE_TYPE +AtspiCoordType +ATSPI_COORD_TYPE_COUNT +AtspiCollectionSortOrder +ATSPI_SORTORDER_COUNT +AtspiCollectionMatchType +ATSPI_MATCHTYPES_COUNT +AtspiCollectionTreeTraversalType +ATSPI_TREETRAVERSALTYPE +AtspiComponentLayer +ATSPI_COMPONENTLAYER_COUNT +AtspiTextBoundaryType +ATSPI_TEXT_BOUNDARY_TYPE_COUNT +AtspiTextClipType +ATSPI_TEXT_CLIP_TYPE_COUNT +AtspiStateType +ATSPI_STATETYPE_COUNT +AtspiKeyEventType +ATSPI_KEYEVENTTYPE_COUNT +AtspiEventType +ATSPI_EVENTTYPE_COUNT +AtspiKeySynthType +ATSPI_KEYSYNTHTYPE_COUNT +AtspiModifierType +ATSPI_MODIFIERTYPE_COUNT +AtspiRelationType +ATSPI_RELATIONTYPE_COUNT +AtspiRole +ATSPI_ROLE_COUNT +
+ +
+atspi-misc +atspi_init +atspi_event_main +atspi_event_quit +atspi_exit +
+ +
+atspi-misc-private +ATSPI_CACHE_PARENT +ATSPI_CACHE_CHILDREN +ATSPI_CACHE_NAME +ATSPI_CACHE_DESCRIPTION +ATSPI_CACHE_STATES +ATSPI_CACHE_ROLE +ATSPI_CACHE_INTERFACES +AtspiReference +ATSPI_DBUS_NAME_REGISTRY +ATSPI_DBUS_PATH_REGISTRY +ATSPI_DBUS_INTERFACE_REGISTRY +ATSPI_DBUS_PATH_NULL +ATSPI_DBUS_PATH_ROOT +ATSPI_DBUS_PATH_DEC +ATSPI_DBUS_INTERFACE_DEC +ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER +ATSPI_DBUS_INTERFACE_CACHE +ATSPI_DBUS_INTERFACE_ACCESSIBLE +ATSPI_DBUS_INTERFACE_ACTION +ATSPI_DBUS_INTERFACE_APPLICATION +ATSPI_DBUS_INTERFACE_COLLECTION +ATSPI_DBUS_INTERFACE_COMPONENT +ATSPI_DBUS_INTERFACE_DOCUMENT +ATSPI_DBUS_INTERFACE_EDITABLE_TEXT +ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD +ATSPI_DBUS_INTERFACE_EVENT_MOUSE +ATSPI_DBUS_INTERFACE_EVENT_OBJECT +ATSPI_DBUS_INTERFACE_HYPERLINK +ATSPI_DBUS_INTERFACE_HYPERTEXT +ATSPI_DBUS_INTERFACE_IMAGE +ATSPI_DBUS_INTERFACE_SELECTION +ATSPI_DBUS_INTERFACE_TABLE +ATSPI_DBUS_INTERFACE_TEXT +ATSPI_DBUS_INTERFACE_VALUE +ATSPI_DBUS_INTERFACE_SOCKET +atspi_path_dec +atspi_path_registry +atspi_path_root +atspi_bus_registry +atspi_interface_accessible +atspi_interface_action +atspi_interface_application +atspi_interface_collection +atspi_interface_component +atspi_interface_dec +atspi_interface_device_event_listener +atspi_interface_document +atspi_interface_editable_text +atspi_interface_hyperlink +atspi_interface_hypertext +atspi_interface_image +atspi_interface_registry +atspi_interface_selection +atspi_interface_table +atspi_interface_table_cell +atspi_interface_text +atspi_interface_cache +atspi_interface_value +
+ +
+atspi-listener-private +atspi_dbus_handle_deviceEvent +
+ diff --git a/doc/libatspi/libatspi.types b/doc/libatspi/libatspi.types new file mode 100644 index 0000000..abeb3fe --- /dev/null +++ b/doc/libatspi/libatspi.types @@ -0,0 +1,25 @@ +atspi_accessible_get_type +atspi_action_get_type +atspi_collection_get_type +atspi_component_get_type +atspi_device_listener_get_type +atspi_document_get_type +atspi_editable_text_get_type +atspi_event_get_type +atspi_event_listener_get_type +atspi_hyperlink_get_type +atspi_hypertext_get_type +atspi_image_get_type +atspi_key_definition_get_type +atspi_match_rule_get_type +atspi_object_get_type +atspi_point_get_type +atspi_range_get_type +atspi_rect_get_type +atspi_relation_get_type +atspi_selection_get_type +atspi_state_set_get_type +atspi_table_get_type +atspi_text_get_type +atspi_text_range_get_type +atspi_value_get_type diff --git a/doc/libatspi/meson.build b/doc/libatspi/meson.build new file mode 100644 index 0000000..77a860c --- /dev/null +++ b/doc/libatspi/meson.build @@ -0,0 +1,32 @@ +version_xml_conf = configuration_data() +version_xml_conf.set('PACKAGE_VERSION', meson.project_name()) +configure_file(input: 'version.xml.in', + output: 'version.xml', + configuration: version_xml_conf) + +glib_prefix = dependency('glib-2.0').get_pkgconfig_variable('prefix') +glib_docpath = join_paths(glib_prefix, 'share', 'gtk-doc', 'html') +docpath = join_paths(atspi_datadir, 'gtk-doc', 'html') + +gnome.gtkdoc('libatspi', + main_xml: 'libatspi-docs.sgml', + src_dir: [ + join_paths(meson.source_root(), 'atspi'), + join_paths(meson.build_root(), 'atspi'), + ], + dependencies: atspi_dep, + gobject_typesfile: 'libatspi.types', + scan_args: [ + '--rebuild-types', + ], + mkdb_args: [ + '--sgml-mode', + '--output-format=xml', + ], + fixxref_args: [ + '--html-dir=@0@'.format(docpath), + '--extra-dir=@0@'.format(join_paths(glib_docpath, 'glib')), + '--extra-dir=@0@'.format(join_paths(glib_docpath, 'gobject')), + ], + install: true) + diff --git a/doc/libatspi/tmpl/atspi-accessible.sgml b/doc/libatspi/tmpl/atspi-accessible.sgml new file mode 100644 index 0000000..5b3c8ea --- /dev/null +++ b/doc/libatspi/tmpl/atspi-accessible.sgml @@ -0,0 +1,324 @@ + +AtspiAccessible + + +The base interface which is implemented by all accessible objects. + + + +The base interface which is implemented by all accessible objects. +All objects support interfaces for querying their contained 'children' +and position in the accessible-object hierarchy, whether or not they +actually have children. + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + + + + + + +@role: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@child_index: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-action.sgml b/doc/libatspi/tmpl/atspi-action.sgml new file mode 100644 index 0000000..d8802a1 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-action.sgml @@ -0,0 +1,82 @@ + +atspi-action + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-application.sgml b/doc/libatspi/tmpl/atspi-application.sgml new file mode 100644 index 0000000..e6a6316 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-application.sgml @@ -0,0 +1,47 @@ + +atspi-application + + + An interface identifying the root object associated + with a running application. + + + + An interface identifying an object which is the root of the + hierarchy associated with a running application. + + + + + + + + + + + + + + + + + + +@parent: +@hash: +@bus_name: +@bus: +@root: +@cache: +@toolkit_name: +@toolkit_version: +@atspi_version: +@time_added: + + + + + + +@parent_class: + diff --git a/doc/libatspi/tmpl/atspi-collection.sgml b/doc/libatspi/tmpl/atspi-collection.sgml new file mode 100644 index 0000000..1e604b2 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-collection.sgml @@ -0,0 +1,99 @@ + +atspi-collection + + +An interface designed to allow accessibles which satisfy a set of +criteria to be returned. + + + +An interface designed to allow accessibles which satisfy a set of +criteria to be returned. This interface can be used to avoid iteration +or client-side search of the object tree. + + + + + + + + + + + + + + + + + + + + + + + + +@collection: +@test: +@error: +@Returns: + + + + + + + +@collection: +@rule: +@sortby: +@count: +@traverse: +@error: +@Returns: + + + + + + + +@collection: +@current_object: +@rule: +@sortby: +@tree: +@limit_scope: +@count: +@traverse: +@error: +@Returns: + + + + + + + +@collection: +@current_object: +@rule: +@sortby: +@tree: +@count: +@traverse: +@error: +@Returns: + + + + + + + +@collection: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-component.sgml b/doc/libatspi/tmpl/atspi-component.sgml new file mode 100644 index 0000000..546137e --- /dev/null +++ b/doc/libatspi/tmpl/atspi-component.sgml @@ -0,0 +1,194 @@ + +atspi-component + + + An interface implemented by objects which have onscreen visual + representations. + + + + The Component interface is implemented by objects which occupy on-screen + space, e.g. objects which have onscreen visual representations. The methods + in Component allow clients to identify where the objects lie in the onscreen + coordinate system, their relative size, stacking order, and position. It + also provides a mechanism whereby keyboard focus may be transferred to + specific user interface elements programmatically. This is a 2D API. + Coordinates of 3D objects are projected into the 2-dimensional screen view + for purposes of this interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@src: +@Returns: + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + +@src: +@Returns: + + + + + + + +@Returns: + + + + + + + + + + + + + +@obj: +@x: +@y: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@x: +@y: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-constants.sgml b/doc/libatspi/tmpl/atspi-constants.sgml new file mode 100644 index 0000000..8763873 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-constants.sgml @@ -0,0 +1,476 @@ + +atspi-constants + + +Constant definitions needed by multiple interfaces. + + + +Constant definitions needed by multiple interfaces. + + + + + + + + + + + + + + + + + + +@ATSPI_LOCALE_TYPE_MESSAGES: +@ATSPI_LOCALE_TYPE_COLLATE: +@ATSPI_LOCALE_TYPE_CTYPE: +@ATSPI_LOCALE_TYPE_MONETARY: +@ATSPI_LOCALE_TYPE_NUMERIC: +@ATSPI_LOCALE_TYPE_TIME: + + + + + + + + + + + + + +@ATSPI_COORD_TYPE_SCREEN: +@ATSPI_COORD_TYPE_WINDOW: + + + + + + + + + + + + + +@ATSPI_Collection_SORT_ORDER_INVALID: +@ATSPI_Collection_SORT_ORDER_CANONICAL: +@ATSPI_Collection_SORT_ORDER_FLOW: +@ATSPI_Collection_SORT_ORDER_TAB: +@ATSPI_Collection_SORT_ORDER_REVERSE_CANONICAL: +@ATSPI_Collection_SORT_ORDER_REVERSE_FLOW: +@ATSPI_Collection_SORT_ORDER_REVERSE_TAB: +@ATSPI_Collection_SORT_ORDER_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_Collection_MATCH_INVALID: +@ATSPI_Collection_MATCH_ALL: +@ATSPI_Collection_MATCH_ANY: +@ATSPI_Collection_MATCH_NONE: +@ATSPI_Collection_MATCH_EMPTY: +@ATSPI_Collection_MATCH_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_Collection_TREE_RESTRICT_CHILDREN: +@ATSPI_Collection_TREE_RESTRICT_SIBLING: +@ATSPI_Collection_TREE_INORDER: +@ATSPI_Collection_TREE_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_LAYER_INVALID: +@ATSPI_LAYER_BACKGROUND: +@ATSPI_LAYER_CANVAS: +@ATSPI_LAYER_WIDGET: +@ATSPI_LAYER_MDI: +@ATSPI_LAYER_POPUP: +@ATSPI_LAYER_OVERLAY: +@ATSPI_LAYER_WINDOW: +@ATSPI_LAYER_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_TEXT_BOUNDARY_CHAR: +@ATSPI_TEXT_BOUNDARY_WORD_START: +@ATSPI_TEXT_BOUNDARY_WORD_END: +@ATSPI_TEXT_BOUNDARY_SENTENCE_START: +@ATSPI_TEXT_BOUNDARY_SENTENCE_END: +@ATSPI_TEXT_BOUNDARY_LINE_START: +@ATSPI_TEXT_BOUNDARY_LINE_END: + + + + + + + + + + + + + +@ATSPI_TEXT_CLIP_NONE: +@ATSPI_TEXT_CLIP_MIN: +@ATSPI_TEXT_CLIP_MAX: +@ATSPI_TEXT_CLIP_BOTH: + + + + + + + + + + + + + +@ATSPI_STATE_INVALID: +@ATSPI_STATE_ACTIVE: +@ATSPI_STATE_ARMED: +@ATSPI_STATE_BUSY: +@ATSPI_STATE_CHECKED: +@ATSPI_STATE_COLLAPSED: +@ATSPI_STATE_DEFUNCT: +@ATSPI_STATE_EDITABLE: +@ATSPI_STATE_ENABLED: +@ATSPI_STATE_EXPANDABLE: +@ATSPI_STATE_EXPANDED: +@ATSPI_STATE_FOCUSABLE: +@ATSPI_STATE_FOCUSED: +@ATSPI_STATE_HAS_TOOLTIP: +@ATSPI_STATE_HORIZONTAL: +@ATSPI_STATE_ICONIFIED: +@ATSPI_STATE_MODAL: +@ATSPI_STATE_MULTI_LINE: +@ATSPI_STATE_MULTISELECTABLE: +@ATSPI_STATE_OPAQUE: +@ATSPI_STATE_PRESSED: +@ATSPI_STATE_RESIZABLE: +@ATSPI_STATE_SELECTABLE: +@ATSPI_STATE_SELECTED: +@ATSPI_STATE_SENSITIVE: +@ATSPI_STATE_SHOWING: +@ATSPI_STATE_SINGLE_LINE: +@ATSPI_STATE_STALE: +@ATSPI_STATE_TRANSIENT: +@ATSPI_STATE_VERTICAL: +@ATSPI_STATE_VISIBLE: +@ATSPI_STATE_MANAGES_DESCENDANTS: +@ATSPI_STATE_INDETERMINATE: +@ATSPI_STATE_REQUIRED: +@ATSPI_STATE_TRUNCATED: +@ATSPI_STATE_ANIMATED: +@ATSPI_STATE_INVALID_ENTRY: +@ATSPI_STATE_SUPPORTS_AUTOCOMPLETION: +@ATSPI_STATE_SELECTABLE_TEXT: +@ATSPI_STATE_IS_DEFAULT: +@ATSPI_STATE_VISITED: +@ATSPI_STATE_CHECKABLE: +@ATSPI_STATE_HAS_POPUP: +@ATSPI_STATE_READ_ONLY: +@ATSPI_STATE_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_KEY_PRESSED: +@ATSPI_KEY_RELEASED: + + + + + + + + + + + + + +@ATSPI_KEY_PRESSED_EVENT: +@ATSPI_KEY_RELEASED_EVENT: +@ATSPI_BUTTON_PRESSED_EVENT: +@ATSPI_BUTTON_RELEASED_EVENT: + + + + + + + + + + + + + +@ATSPI_KEY_PRESS: +@ATSPI_KEY_RELEASE: +@ATSPI_KEY_PRESSRELEASE: +@ATSPI_KEY_SYM: +@ATSPI_KEY_STRING: + + + + + + + + + + + + + +@ATSPI_MODIFIER_SHIFT: +@ATSPI_MODIFIER_SHIFTLOCK: +@ATSPI_MODIFIER_CONTROL: +@ATSPI_MODIFIER_ALT: +@ATSPI_MODIFIER_META: +@ATSPI_MODIFIER_META2: +@ATSPI_MODIFIER_META3: +@ATSPI_MODIFIER_NUMLOCK: + + + + + + + + + + + + + +@ATSPI_RELATION_NULL: +@ATSPI_RELATION_LABEL_FOR: +@ATSPI_RELATION_LABELLED_BY: +@ATSPI_RELATION_CONTROLLER_FOR: +@ATSPI_RELATION_CONTROLLED_BY: +@ATSPI_RELATION_MEMBER_OF: +@ATSPI_RELATION_TOOLTIP_FOR: +@ATSPI_RELATION_NODE_CHILD_OF: +@ATSPI_RELATION_NODE_PARENT_OF: +@ATSPI_RELATION_EXTENDED: +@ATSPI_RELATION_FLOWS_TO: +@ATSPI_RELATION_FLOWS_FROM: +@ATSPI_RELATION_SUBWINDOW_OF: +@ATSPI_RELATION_EMBEDS: +@ATSPI_RELATION_EMBEDDED_BY: +@ATSPI_RELATION_POPUP_FOR: +@ATSPI_RELATION_PARENT_WINDOW_OF: +@ATSPI_RELATION_DESCRIPTION_FOR: +@ATSPI_RELATION_DESCRIBED_BY: +@ATSPI_RELATION_DETAILS: +@ATSPI_RELATION_DETAILS_FOR: +@ATSPI_RELATION_ERROR_MESSAGE: +@ATSPI_RELATION_ERROR_FOR: +@ATSPI_RELATION_LAST_DEFINED: + + + + + + + + + + + + + +@ATSPI_ROLE_INVALID: +@ATSPI_ROLE_ACCELERATOR_LABEL: +@ATSPI_ROLE_ALERT: +@ATSPI_ROLE_ANIMATION: +@ATSPI_ROLE_ARROW: +@ATSPI_ROLE_CALENDAR: +@ATSPI_ROLE_CANVAS: +@ATSPI_ROLE_CHECK_BOX: +@ATSPI_ROLE_CHECK_MENU_ITEM: +@ATSPI_ROLE_COLOR_CHOOSER: +@ATSPI_ROLE_COLUMN_HEADER: +@ATSPI_ROLE_COMBO_BOX: +@ATSPI_ROLE_DATE_EDITOR: +@ATSPI_ROLE_DESKTOP_ICON: +@ATSPI_ROLE_DESKTOP_FRAME: +@ATSPI_ROLE_DIAL: +@ATSPI_ROLE_DIALOG: +@ATSPI_ROLE_DIRECTORY_PANE: +@ATSPI_ROLE_DRAWING_AREA: +@ATSPI_ROLE_FILE_CHOOSER: +@ATSPI_ROLE_FILLER: +@ATSPI_ROLE_FOCUS_TRAVERSABLE: +@ATSPI_ROLE_FONT_CHOOSER: +@ATSPI_ROLE_FRAME: +@ATSPI_ROLE_GLASS_PANE: +@ATSPI_ROLE_HTML_CONTAINER: +@ATSPI_ROLE_ICON: +@ATSPI_ROLE_IMAGE: +@ATSPI_ROLE_INTERNAL_FRAME: +@ATSPI_ROLE_LABEL: +@ATSPI_ROLE_LAYERED_PANE: +@ATSPI_ROLE_LIST: +@ATSPI_ROLE_LIST_ITEM: +@ATSPI_ROLE_MENU: +@ATSPI_ROLE_MENU_BAR: +@ATSPI_ROLE_MENU_ITEM: +@ATSPI_ROLE_OPTION_PANE: +@ATSPI_ROLE_PAGE_TAB: +@ATSPI_ROLE_PAGE_TAB_LIST: +@ATSPI_ROLE_PANEL: +@ATSPI_ROLE_PASSWORD_TEXT: +@ATSPI_ROLE_POPUP_MENU: +@ATSPI_ROLE_PROGRESS_BAR: +@ATSPI_ROLE_PUSH_BUTTON: +@ATSPI_ROLE_RADIO_BUTTON: +@ATSPI_ROLE_RADIO_MENU_ITEM: +@ATSPI_ROLE_ROOT_PANE: +@ATSPI_ROLE_ROW_HEADER: +@ATSPI_ROLE_SCROLL_BAR: +@ATSPI_ROLE_SCROLL_PANE: +@ATSPI_ROLE_SEPARATOR: +@ATSPI_ROLE_SLIDER: +@ATSPI_ROLE_SPIN_BUTTON: +@ATSPI_ROLE_SPLIT_PANE: +@ATSPI_ROLE_STATUS_BAR: +@ATSPI_ROLE_TABLE: +@ATSPI_ROLE_TABLE_CELL: +@ATSPI_ROLE_TABLE_COLUMN_HEADER: +@ATSPI_ROLE_TABLE_ROW_HEADER: +@ATSPI_ROLE_TEAROFF_MENU_ITEM: +@ATSPI_ROLE_TERMINAL: +@ATSPI_ROLE_TEXT: +@ATSPI_ROLE_TOGGLE_BUTTON: +@ATSPI_ROLE_TOOL_BAR: +@ATSPI_ROLE_TOOL_TIP: +@ATSPI_ROLE_TREE: +@ATSPI_ROLE_TREE_TABLE: +@ATSPI_ROLE_UNKNOWN: +@ATSPI_ROLE_VIEWPORT: +@ATSPI_ROLE_WINDOW: +@ATSPI_ROLE_EXTENDED: +@ATSPI_ROLE_HEADER: +@ATSPI_ROLE_FOOTER: +@ATSPI_ROLE_PARAGRAPH: +@ATSPI_ROLE_RULER: +@ATSPI_ROLE_APPLICATION: +@ATSPI_ROLE_AUTOCOMPLETE: +@ATSPI_ROLE_EDITBAR: +@ATSPI_ROLE_EMBEDDED: +@ATSPI_ROLE_ENTRY: +@ATSPI_ROLE_CHART: +@ATSPI_ROLE_CAPTION: +@ATSPI_ROLE_DOCUMENT_FRAME: +@ATSPI_ROLE_HEADING: +@ATSPI_ROLE_PAGE: +@ATSPI_ROLE_SECTION: +@ATSPI_ROLE_REDUNDANT_OBJECT: +@ATSPI_ROLE_FORM: +@ATSPI_ROLE_LINK: +@ATSPI_ROLE_INPUT_METHOD_WINDOW: +@ATSPI_ROLE_TABLE_ROW: +@ATSPI_ROLE_TREE_ITEM: +@ATSPI_ROLE_DOCUMENT_SPREADSHEET: +@ATSPI_ROLE_DOCUMENT_PRESENTATION: +@ATSPI_ROLE_DOCUMENT_TEXT: +@ATSPI_ROLE_DOCUMENT_WEB: +@ATSPI_ROLE_DOCUMENT_EMAIL: +@ATSPI_ROLE_COMMENT: +@ATSPI_ROLE_LIST_BOX: +@ATSPI_ROLE_GROUPING: +@ATSPI_ROLE_IMAGE_MAP: +@ATSPI_ROLE_NOTIFICATION: +@ATSPI_ROLE_INFO_BAR: +@ATSPI_ROLE_LEVEL_BAR: +@ATSPI_ROLE_TITLE_BAR: +@ATSPI_ROLE_BLOCK_QUOTE: +@ATSPI_ROLE_AUDIO: +@ATSPI_ROLE_VIDEO: +@ATSPI_ROLE_DEFINITION: +@ATSPI_ROLE_ARTICLE: +@ATSPI_ROLE_LANDMARK: +@ATSPI_ROLE_LOG: +@ATSPI_ROLE_MARQUEE: +@ATSPI_ROLE_MATH: +@ATSPI_ROLE_RATING: +@ATSPI_ROLE_TIMER: +@ATSPI_ROLE_STATIC: +@ATSPI_ROLE_MATH_FRACTION: +@ATSPI_ROLE_MATH_ROOT: +@ATSPI_ROLE_SUBSCRIPT: +@ATSPI_ROLE_SUPERSCRIPT: +@ATSPI_ROLE_DESCRIPTION_LIST: +@ATSPI_ROLE_DESCRIPTION_TERM: +@ATSPI_ROLE_DESCRIPTION_VALUE: +@ATSPI_ROLE_LAST_DEFINED: + + + + + + + + diff --git a/doc/libatspi/tmpl/atspi-device-listener.sgml b/doc/libatspi/tmpl/atspi-device-listener.sgml new file mode 100644 index 0000000..f1f3de1 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-device-listener.sgml @@ -0,0 +1,98 @@ + +atspi-devicelistener + + +An interface for creating and manipulating +device listeners. + + + +An interface for creating and manipulating +device listeners with callback functions. + + + + + + + + + + + + + + + + + + +@stroke: +@user_data: +@Returns: + + + + + + + +@stroke: +@Returns: + + + + + + + + + + + + + +@parent_class: +@device_event: + + + + + + +@callback: +@user_data: +@callback_destroyed: +@Returns: + + + + + + + +@callback: +@callback_destroyed: +@Returns: + + + + + + + +@listener: +@callback: +@callback_destroyed: +@user_data: + + + + + + + +@listener: +@callback: + + diff --git a/doc/libatspi/tmpl/atspi-document.sgml b/doc/libatspi/tmpl/atspi-document.sgml new file mode 100644 index 0000000..5162ed2 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-document.sgml @@ -0,0 +1,59 @@ + +atspi-document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@attribute: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-editabletext.sgml b/doc/libatspi/tmpl/atspi-editabletext.sgml new file mode 100644 index 0000000..3fa05bd --- /dev/null +++ b/doc/libatspi/tmpl/atspi-editabletext.sgml @@ -0,0 +1,104 @@ + +atspi-editabletext + + +An interface that provides methods for modifying textual content +of components which support editing. + + + +Derived from atspi-text, the atspi-editabletext interface +provides methods for modifying textual content of components +which support editing. EditableText also interacts with the +system clipboard via copy, cut, and paste methods. + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@attributes: +@start_pos: +@end_pos: +@Returns: + + + + + + + +@obj: +@position: +@text: +@length: +@error: +@Returns: + + + + + + + +@obj: +@start_pos: +@end_pos: +@error: +@Returns: + + + + + + + +@obj: +@start_pos: +@end_pos: +@error: +@Returns: + + + + + + + +@obj: +@start_pos: +@end_pos: +@error: +@Returns: + + + + + + + +@obj: +@position: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-event-listener.sgml b/doc/libatspi/tmpl/atspi-event-listener.sgml new file mode 100644 index 0000000..5cf1a87 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-event-listener.sgml @@ -0,0 +1,156 @@ + +atspi-event-listener + + +A generic interface implemented by objects for the receipt of event +notifications. + + + +A generic interface implemented by objects for the receipt of event +notifications. atspi-event-listener is the interface via which clients of +the atspi-registry receive notification of changes to an application's user +interface and content. + + + + + + + + + + + + + + + + + + +@event: +@user_data: + + + + + + + +@event: + + + + + + + + + + + + + +@parent_class: + + + + + + +@void: +@Returns: + + + + + + + +@callback: +@user_data: +@callback_destroyed: +@Returns: + + + + + + + +@callback: +@callback_destroyed: +@Returns: + + + + + + + +@listener: +@event_type: +@error: +@Returns: + + + + + + + +@callback: +@user_data: +@callback_destroyed: +@event_type: +@error: +@Returns: + + + + + + + +@callback: +@callback_destroyed: +@event_type: +@error: +@Returns: + + + + + + + +@listener: +@event_type: +@error: +@Returns: + + + + + + + +@callback: +@user_data: +@event_type: +@error: +@Returns: + + + + + + + +@callback: +@event_type: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-hyperlink.sgml b/doc/libatspi/tmpl/atspi-hyperlink.sgml new file mode 100644 index 0000000..5942ad3 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-hyperlink.sgml @@ -0,0 +1,114 @@ + +atspi-hyperlink + + +Instances of atspi-hyperlink are the means by which end users +and clients interact with linked content. + + + + Instances of atspi-hyperlink are returned by + atspi-hypertext objects, and are the means by + which end users and clients interact with linked, + and in some cases embedded, content. These instances + may have multiple "anchors", where an anchor corresponds to a + reference to a particular resource with a corresponding resource + identified (URI). + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + + + + + + +@obj: +@i: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-hypertext.sgml b/doc/libatspi/tmpl/atspi-hypertext.sgml new file mode 100644 index 0000000..5448f61 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-hypertext.sgml @@ -0,0 +1,65 @@ + +atspi-hypertext + + +An interface used for objects which implement linking between +multiple resource locations. + + + +An interface used for objects which implement linking between +multiple resource or content locations, or multiple 'markers' +within a single document. A hypertext instance is associated +with one or more hyperlinks which are associated with particular +offests within the hypertext's content. + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@link_index: +@error: +@Returns: + + + + + + + +@obj: +@character_offset: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-image.sgml b/doc/libatspi/tmpl/atspi-image.sgml new file mode 100644 index 0000000..2b7a36e --- /dev/null +++ b/doc/libatspi/tmpl/atspi-image.sgml @@ -0,0 +1,80 @@ + +atspi-image + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@ctype: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-listener-private.sgml b/doc/libatspi/tmpl/atspi-listener-private.sgml new file mode 100644 index 0000000..f529533 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-listener-private.sgml @@ -0,0 +1,22 @@ + +atspi-listener-private + + + + + + + + + + + + + + + + + + + + diff --git a/doc/libatspi/tmpl/atspi-matchrule.sgml b/doc/libatspi/tmpl/atspi-matchrule.sgml new file mode 100644 index 0000000..b52922b --- /dev/null +++ b/doc/libatspi/tmpl/atspi-matchrule.sgml @@ -0,0 +1,54 @@ + +atspi-matchrule + + +An interface that allows the definition of match rules +for accessible objects. + + + +An interface that allows the definition of match rules +for accessible objects. + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + + + + + + +@states: +@statematchtype: +@attributes: +@attributematchtype: +@roles: +@rolematchtype: +@interfaces: +@interfacematchtype: +@invert: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-misc-private.sgml b/doc/libatspi/tmpl/atspi-misc-private.sgml new file mode 100644 index 0000000..aa4c96c --- /dev/null +++ b/doc/libatspi/tmpl/atspi-misc-private.sgml @@ -0,0 +1,357 @@ + +atspi-misc-private + + + + + + + + + + + + + + + + + + + + + + + + + +@name: +@path: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/libatspi/tmpl/atspi-misc.sgml b/doc/libatspi/tmpl/atspi-misc.sgml new file mode 100644 index 0000000..06656a4 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-misc.sgml @@ -0,0 +1,53 @@ + +atspi-misc + + +Miscellaneous methods for using AT-SPI services. + + + +Miscellaneous methods for using AT-SPI services. + + + + + + + + + + + + + + + + + + +@void: +@Returns: + + + + + + + + + + + + + + + + + + + + + +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-object.sgml b/doc/libatspi/tmpl/atspi-object.sgml new file mode 100644 index 0000000..568af9a --- /dev/null +++ b/doc/libatspi/tmpl/atspi-object.sgml @@ -0,0 +1,35 @@ + +AtspiObject + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + diff --git a/doc/libatspi/tmpl/atspi-registry.sgml b/doc/libatspi/tmpl/atspi-registry.sgml new file mode 100644 index 0000000..a8e9569 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-registry.sgml @@ -0,0 +1,133 @@ + +atspi-registry + + +A service through which applications providing accessibility services +can rendezvous with consumers of those services. + + + +A service through which applications providing accessibility services (servers) +can rendezvous with consumers of those services (Assistive Technologies). The +atspi-registry is the first "port of call" for accessible applications and for +assistive technologies wishing to query and interact with those applications. + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + +@Returns: + + + + + + + +@i: +@Returns: + + + + + + + +@Returns: + + + + + + + +@listener: +@key_set: +@modmask: +@event_types: +@sync_type: +@error: +@Returns: + + + + + + + +@listener: +@key_set: +@modmask: +@event_types: +@error: +@Returns: + + + + + + + +@listener: +@event_types: +@filter: +@error: +@Returns: + + + + + + + +@listener: +@filter: +@error: +@Returns: + + + + + + + +@keyval: +@keystring: +@synth_type: +@error: +@Returns: + + + + + + + +@x: +@y: +@name: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-relation.sgml b/doc/libatspi/tmpl/atspi-relation.sgml new file mode 100644 index 0000000..dc548e6 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-relation.sgml @@ -0,0 +1,66 @@ + +atspi-relation + + + An interface via which non-hierarchical relationships + are indicated. + + + + An interface via which non-hierarchical relationships + are indicated. An instance of this interface represents + a "one-to-many" correspondance. + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@Returns: + + + + + + + +@obj: +@i: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-selection.sgml b/doc/libatspi/tmpl/atspi-selection.sgml new file mode 100644 index 0000000..6c7a102 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-selection.sgml @@ -0,0 +1,118 @@ + +atspi-selection + + +An interface which indicates that an object exposes a 'selection' model, +allowing the selection of one or more of its children. + + + +An interface which indicates that an object exposes a 'selection' +model, allowing the selection of one or more of its children. +Read-only Selection instances are possible, in which case the +interface is used to programmatically determine the selected-ness +of its children. + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@selected_child_index: +@error: +@Returns: + + + + + + + +@obj: +@child_index: +@error: +@Returns: + + + + + + + +@obj: +@selected_child_index: +@error: +@Returns: + + + + + + + +@obj: +@child_index: +@error: +@Returns: + + + + + + + +@obj: +@child_index: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-stateset.sgml b/doc/libatspi/tmpl/atspi-stateset.sgml new file mode 100644 index 0000000..dc65b8d --- /dev/null +++ b/doc/libatspi/tmpl/atspi-stateset.sgml @@ -0,0 +1,122 @@ + +atspi-stateset + + +The atspi-stateset objects implement wrappers around a +bitmap of accessible states. + + + +The atspi-stateset objects implement wrappers around a +bitmap of accessible states. + + + + + + + + + + + + + + + + + + + + + + + + +@parent_class: + + + + + + +@states: +@Returns: + + + + + + + +@set: +@name: +@enabled: + + + + + + + +@set: +@state: + + + + + + + +@set: +@set2: +@Returns: + + + + + + + +@set: +@state: +@Returns: + + + + + + + +@set: +@set2: +@Returns: + + + + + + + +@set: +@Returns: + + + + + + + +@set: +@Returns: + + + + + + + +@set: +@state: + + diff --git a/doc/libatspi/tmpl/atspi-table.sgml b/doc/libatspi/tmpl/atspi-table.sgml new file mode 100644 index 0000000..a90cea4 --- /dev/null +++ b/doc/libatspi/tmpl/atspi-table.sgml @@ -0,0 +1,324 @@ + +atspi-table + + +An interface used by containers whose data is arranged in a tabular form. + + + +An interface used by containers whose contained data is arranged +in a tabular (i.e. row-column) form. Tables may resemble +a two-dimensional grid, as in a spreadsheet, or may feature objects +which span multiple rows and/or columns, but whose bounds are +aligned on a row/column matrix. Objects within tables are children +of the table object, and they may be referenced either via a child +index or via a row/column pair. Table 'cells' may implement other +interfaces, such as Text, Action, Image, and Component, and should do +so as appropriate to their onscreen rresentation and/or behavior. + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@row: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@column: +@error: +@Returns: + + + + + + + +@obj: +@index: +@error: +@Returns: + + + + + + + +@obj: +@index: +@error: +@Returns: + + + + + + + +@obj: +@row: +@error: +@Returns: + + + + + + + +@obj: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@error: +@Returns: + + + + + + + +@obj: +@column: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@row: +@error: +@Returns: + + + + + + + +@obj: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@error: +@Returns: + + + + + + + +@obj: +@column: +@error: +@Returns: + + + + + + + +@obj: +@row: +@error: +@Returns: + + + + + + + +@obj: +@column: +@error: +@Returns: + + + + + + + +@obj: +@index: +@row: +@col: +@row_extents: +@col_extents: +@is_selected: +@error: +@Returns: + + + + + + + +@obj: +@row: +@column: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-text.sgml b/doc/libatspi/tmpl/atspi-text.sgml new file mode 100644 index 0000000..961edcb --- /dev/null +++ b/doc/libatspi/tmpl/atspi-text.sgml @@ -0,0 +1,336 @@ + +atspi-text + + +An interface implemented by objects which place textual +information onscreen. + + + +The text interface should be implemented by objects which place textual +information onscreen as character strings or glyphs. The text interface +allows access to textual content including display attributes and +semantic hints associated with runs of text, and to bounding boc +information for glyphs and substrings. It also alows portions of text to +be selected, if the objects StateSet includes STATE_SELECTABLE_TEXT. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@src: +@Returns: + + + + + + + + + + + + + + + + + + + + +@Returns: + + + + + + + + + + + + + +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@start_offset: +@end_offset: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@start_offset: +@end_offset: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@include_defaults: +@start_offset: +@end_offset: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@attribute_name: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@new_offset: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@type: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@type: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@type: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@error: +@Returns: + + + + + + + +@obj: +@offset: +@type: +@error: +@Returns: + + + + + + + +@obj: +@x: +@y: +@type: +@error: +@Returns: + + + + + + + +@obj: +@start_offset: +@end_offset: +@type: +@error: +@Returns: + + + + + + + +@obj: +@x: +@y: +@width: +@height: +@type: +@clipTypeX: +@clipTypeY: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@selection_num: +@error: +@Returns: + + + + + + + +@obj: +@start_offset: +@end_offset: +@error: +@Returns: + + + + + + + +@obj: +@selection_num: +@error: +@Returns: + + + + + + + +@obj: +@selection_num: +@start_offset: +@end_offset: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/atspi-types.sgml b/doc/libatspi/tmpl/atspi-types.sgml new file mode 100644 index 0000000..987b7fa --- /dev/null +++ b/doc/libatspi/tmpl/atspi-types.sgml @@ -0,0 +1,187 @@ + +atspi-types + + +Type definitions needed by multiple interfaces. + + + +Type definitions needed by multiple interfaces. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@type: +@id: +@hw_code: +@modifiers: +@timestamp: +@event_string: +@is_text: + + + + + + +@synchronous: +@preemptive: +@global: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@ATSPI_KEYLISTENER_NOSYNC: +@ATSPI_KEYLISTENER_SYNCHRONOUS: +@ATSPI_KEYLISTENER_CANCONSUME: +@ATSPI_KEYLISTENER_ALL_WINDOWS: + diff --git a/doc/libatspi/tmpl/atspi-value.sgml b/doc/libatspi/tmpl/atspi-value.sgml new file mode 100644 index 0000000..59f3cfc --- /dev/null +++ b/doc/libatspi/tmpl/atspi-value.sgml @@ -0,0 +1,83 @@ + +atspi-value + + +An interface supporting a one-dimensional scalar +to be modified, or which reflects its value. + + + +An interface supporting a one-dimensional scalar +to be modified, or which reflects its value. If +STATE_EDITABLE is not present, the value is +treated as "read only". + + + + + + + + + + + + + + + + + + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + + + + + + +@obj: +@new_value: +@error: +@Returns: + + + + + + + +@obj: +@error: +@Returns: + + diff --git a/doc/libatspi/tmpl/libatspi-unused.sgml b/doc/libatspi/tmpl/libatspi-unused.sgml new file mode 100644 index 0000000..33ae061 --- /dev/null +++ b/doc/libatspi/tmpl/libatspi-unused.sgml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@app: +@path: +@Returns: + + + + + + +@bus: +@message: +@data: +@Returns: + + + + + + + + + + + + +@app: +@path: +@Returns: + + + + + + + diff --git a/doc/libatspi/version.xml.in b/doc/libatspi/version.xml.in new file mode 100644 index 0000000..a24f987 --- /dev/null +++ b/doc/libatspi/version.xml.in @@ -0,0 +1 @@ +@PACKAGE_VERSION@ diff --git a/git.mk b/git.mk new file mode 100644 index 0000000..5638488 --- /dev/null +++ b/git.mk @@ -0,0 +1,318 @@ +# git.mk +# +# Copyright 2009, Red Hat, Inc. +# Copyright 2010,2011,2012,2013 Behdad Esfahbod +# Written by Behdad Esfahbod +# +# Copying and distribution of this file, with or without modification, +# is permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +# +# The latest version of this file can be downloaded from: +# https://raw.github.com/behdad/git.mk/master/git.mk +# Bugs, etc, should be reported upstream at: +# https://github.com/behdad/git.mk +# +# To use in your project, import this file in your git repo's toplevel, +# then do "make -f git.mk". This modifies all Makefile.am files in +# your project to -include git.mk. Remember to add that line to new +# Makefile.am files you create in your project, or just rerun the +# "make -f git.mk". +# +# This enables automatic .gitignore generation. If you need to ignore +# more files, add them to the GITIGNOREFILES variable in your Makefile.am. +# But think twice before doing that. If a file has to be in .gitignore, +# chances are very high that it's a generated file and should be in one +# of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES. +# +# The only case that you need to manually add a file to GITIGNOREFILES is +# when remove files in one of mostlyclean-local, clean-local, distclean-local, +# or maintainer-clean-local make targets. +# +# Note that for files like editor backup, etc, there are better places to +# ignore them. See "man gitignore". +# +# If "make maintainer-clean" removes the files but they are not recognized +# by this script (that is, if "git status" shows untracked files still), send +# me the output of "git status" as well as your Makefile.am and Makefile for +# the directories involved and I'll diagnose. +# +# For a list of toplevel files that should be in MAINTAINERCLEANFILES, see +# Makefile.am.sample in the git.mk git repo. +# +# Don't EXTRA_DIST this file. It is supposed to only live in git clones, +# not tarballs. It serves no useful purpose in tarballs and clutters the +# build dir. +# +# This file knows how to handle autoconf, automake, libtool, gtk-doc, +# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata. +# +# This makefile provides the following targets: +# +# - all: "make all" will build all gitignore files. +# - gitignore: makes all gitignore files in the current dir and subdirs. +# - .gitignore: make gitignore file for the current dir. +# - gitignore-recurse: makes all gitignore files in the subdirs. +# +# KNOWN ISSUES: +# +# - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the +# submodule doesn't find us. If you have configure.{in,ac} files in +# subdirs, add a proxy git.mk file in those dirs that simply does: +# "include $(top_srcdir)/../git.mk". Add more ..'s to your taste. +# And add those files to git. See vte/gnome-pty-helper/git.mk for +# example. +# + + + +############################################################################### +# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES: +############################################################################### + +# +# Most autotools-using modules should be fine including this variable in their +# toplevel MAINTAINERCLEANFILES: +GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/autoscan.log \ + $(srcdir)/configure.scan \ + `AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \ + test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \ + for x in \ + ar-lib \ + compile \ + config.guess \ + config.sub \ + depcomp \ + install-sh \ + ltmain.sh \ + missing \ + mkinstalldirs \ + test-driver \ + ; do echo "$$AUX_DIR/$$x"; done` \ + `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \ + head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done` +# +# All modules should also be fine including the following variable, which +# removes automake-generated Makefile.in files: +GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \ + `cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \ + while read f; do \ + case $$f in Makefile|*/Makefile) \ + test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \ + done` +# +# Modules that use libtool and use AC_CONFIG_MACRO_DIR() may also include this, +# though it's harmless to include regardless. +GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \ + `MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \ + if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \ + for x in \ + libtool.m4 \ + ltoptions.m4 \ + ltsugar.m4 \ + ltversion.m4 \ + lt~obsolete.m4 \ + ; do echo "$$MACRO_DIR/$$x"; done; \ + fi` + + + +############################################################################### +# Default rule is to install ourselves in all Makefile.am files: +############################################################################### + +git-all: git-mk-install + +git-mk-install: + @echo "Installing git makefile" + @any_failed=; \ + find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \ + if grep 'include .*/git.mk' $$x >/dev/null; then \ + echo "$$x already includes git.mk"; \ + else \ + failed=; \ + echo "Updating $$x"; \ + { cat $$x; \ + echo ''; \ + echo '-include $$(top_srcdir)/git.mk'; \ + } > $$x.tmp || failed=1; \ + if test x$$failed = x; then \ + mv $$x.tmp $$x || failed=1; \ + fi; \ + if test x$$failed = x; then : else \ + echo "Failed updating $$x"; >&2 \ + any_failed=1; \ + fi; \ + fi; done; test -z "$$any_failed" + +.PHONY: git-all git-mk-install + + + +############################################################################### +# Actual .gitignore generation: +############################################################################### + +$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk + @echo "git.mk: Generating $@" + @{ \ + if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \ + for x in \ + $(DOC_MODULE)-decl-list.txt \ + $(DOC_MODULE)-decl.txt \ + tmpl/$(DOC_MODULE)-unused.sgml \ + "tmpl/*.bak" \ + xml html \ + ; do echo "/$$x"; done; \ + FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \ + case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \ + fi; \ + if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ + for lc in $(DOC_LINGUAS); do \ + for x in \ + $(if $(DOC_MODULE),$(DOC_MODULE).xml) \ + $(DOC_PAGES) \ + $(DOC_INCLUDES) \ + ; do echo "/$$lc/$$x"; done; \ + done; \ + for x in \ + $(_DOC_OMF_ALL) \ + $(_DOC_DSK_ALL) \ + $(_DOC_HTML_ALL) \ + $(_DOC_MOFILES) \ + $(DOC_H_FILE) \ + "*/.xml2po.mo" \ + "*/*.omf.out" \ + ; do echo /$$x; done; \ + fi; \ + if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \ + for lc in $(HELP_LINGUAS); do \ + for x in \ + $(HELP_FILES) \ + "$$lc.stamp" \ + "$$lc.mo" \ + ; do echo "/$$lc/$$x"; done; \ + done; \ + fi; \ + if test "x$(gsettings_SCHEMAS)" = x; then :; else \ + for x in \ + $(gsettings_SCHEMAS:.xml=.valid) \ + $(gsettings__enum_file) \ + ; do echo "/$$x"; done; \ + fi; \ + if test "x$(appdata_XML)" = x; then :; else \ + for x in \ + $(appdata_XML:.xml=.valid) \ + ; do echo "/$$x"; done; \ + fi; \ + if test -f $(srcdir)/po/Makefile.in.in; then \ + for x in \ + po/Makefile.in.in \ + po/Makefile.in.in~ \ + po/Makefile.in \ + po/Makefile \ + po/Makevars.template \ + po/POTFILES \ + po/Rules-quot \ + po/stamp-it \ + po/.intltool-merge-cache \ + "po/*.gmo" \ + "po/*.header" \ + "po/*.mo" \ + "po/*.sed" \ + "po/*.sin" \ + po/$(GETTEXT_PACKAGE).pot \ + intltool-extract.in \ + intltool-merge.in \ + intltool-update.in \ + ; do echo "/$$x"; done; \ + fi; \ + if test -f $(srcdir)/configure; then \ + for x in \ + autom4te.cache \ + configure \ + config.h \ + stamp-h1 \ + libtool \ + config.lt \ + ; do echo "/$$x"; done; \ + fi; \ + if test "x$(DEJATOOL)" = x; then :; else \ + for x in \ + $(DEJATOOL) \ + ; do echo "/$$x.sum"; echo "/$$x.log"; done; \ + echo /site.exp; \ + fi; \ + if test "x$(am__dirstamp)" = x; then :; else \ + echo "$(am__dirstamp)"; \ + fi; \ + if test "x$(LTCOMPILE)" = x -a "x$(GTKDOC_RUN)" = x; then :; else \ + for x in \ + "*.lo" \ + ".libs" "_libs" \ + ; do echo "$$x"; done; \ + fi; \ + for x in \ + .gitignore \ + $(GITIGNOREFILES) \ + $(CLEANFILES) \ + $(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \ + $(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \ + $(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \ + so_locations \ + $(MOSTLYCLEANFILES) \ + $(TEST_LOGS) \ + $(TEST_LOGS:.log=.trs) \ + $(TEST_SUITE_LOG) \ + "*.$(OBJEXT)" \ + "*.gcda" \ + "*.gcno" \ + $(DISTCLEANFILES) \ + $(am__CONFIG_DISTCLEAN_FILES) \ + $(CONFIG_CLEAN_FILES) \ + TAGS ID GTAGS GRTAGS GSYMS GPATH tags \ + "*.tab.c" \ + $(MAINTAINERCLEANFILES) \ + $(BUILT_SOURCES) \ + $(DEPDIR) \ + $(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \ + $(filter %_vala.stamp,$(DIST_COMMON)) \ + $(filter %.vapi,$(DIST_COMMON)) \ + $(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter %.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \ + Makefile \ + Makefile.in \ + "*.orig" \ + "*.rej" \ + "*.bak" \ + "*~" \ + ".*.sw[nop]" \ + ".dirstamp" \ + ; do echo "/$$x"; done; \ + } | \ + sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \ + sed 's@/[.]/@/@g' | \ + LC_ALL=C sort | uniq > $@.tmp && \ + mv $@.tmp $@; + +all: $(srcdir)/.gitignore gitignore-recurse-maybe +gitignore: $(srcdir)/.gitignore gitignore-recurse + +gitignore-recurse-maybe: + @for subdir in $(DIST_SUBDIRS); do \ + case " $(SUBDIRS) " in \ + *" $$subdir "*) :;; \ + *) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir");; \ + esac; \ + done +gitignore-recurse: + @for subdir in $(DIST_SUBDIRS); do \ + test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir"); \ + done + +maintainer-clean: gitignore-clean +gitignore-clean: + -rm -f $(srcdir)/.gitignore + +.PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe diff --git a/idl/accessible.didl b/idl/accessible.didl new file mode 100644 index 0000000..eee462f --- /dev/null +++ b/idl/accessible.didl @@ -0,0 +1,234 @@ + +/* + The base interface which is implemented by all accessible objects. + */ + +interface org.freestandards.atspi.Accessible { + + enum Role { + ROLE_INVALID = 0, + ROLE_ACCELERATOR_LABEL, + ROLE_ALERT, + ROLE_ANIMATION, + ROLE_ARROW, + ROLE_CALENDAR, + ROLE_CANVAS, + ROLE_CHECK_BOX, + ROLE_CHECK_MENU_ITEM, + ROLE_COLOR_CHOOSER, + ROLE_COLUMN_HEADER, + ROLE_COMBO_BOX, + ROLE_DATE_EDITOR, + ROLE_DESKTOP_ICON, + ROLE_DESKTOP_FRAME, + ROLE_DIAL, + ROLE_DIALOG, + ROLE_DIRECTORY_PANE, + ROLE_DRAWING_AREA, + ROLE_FILE_CHOOSER, + ROLE_FILLER, + ROLE_FOCUS_TRAVERSABLE, + ROLE_FONT_CHOOSER, + ROLE_FRAME, + ROLE_GLASS_PANE, + ROLE_HTML_CONTAINER, + ROLE_ICON, + ROLE_IMAGE, + ROLE_INTERNAL_FRAME, + ROLE_LABEL, + ROLE_LAYERED_PANE, + ROLE_LIST, + ROLE_LIST_ITEM, + ROLE_MENU, + ROLE_MENU_BAR, + ROLE_MENU_ITEM, + ROLE_OPTION_PANE, + ROLE_PAGE_TAB, + ROLE_PAGE_TAB_LIST, + ROLE_PANEL, + ROLE_PASSWORD_TEXT, + ROLE_POPUP_MENU, + ROLE_PROGRESS_BAR, + ROLE_PUSH_BUTTON, + ROLE_RADIO_BUTTON, + ROLE_RADIO_MENU_ITEM, + ROLE_ROOT_PANE, + ROLE_ROW_HEADER, + ROLE_SCROLL_BAR, + ROLE_SCROLL_PANE, + ROLE_SEPARATOR, + ROLE_SLIDER, + ROLE_SPIN_BUTTON, + ROLE_SPLIT_PANE, + ROLE_STATUS_BAR, + ROLE_TABLE, + ROLE_TABLE_CELL, + ROLE_TABLE_COLUMN_HEADER, + ROLE_TABLE_ROW_HEADER, + ROLE_TEAROFF_MENU_ITEM, + ROLE_TERMINAL, + ROLE_TEXT, + ROLE_TOGGLE_BUTTON, + ROLE_TOOL_BAR, + ROLE_TOOL_TIP, + ROLE_TREE, + ROLE_TREE_TABLE, + ROLE_UNKNOWN + } + + /* + RelationType specifies a relationship between objects outside of the normal + parent/child hierarchical relationship. It allows better semantic + identification of how objects are associated with one another. + */ + enum RelationType { + RELATION_NULL = 0, + RELATION_LABEL_FOR, + RELATION_LABELLED_BY, + RELATION_CONTROLLER_FOR, + RELATION_CONTROLLED_BY, + RELATION_MEMBER_OF, + RELATION_TOOLTIP_FOR, + RELATION_NODE_CHILD_OF, + RELATION_NODE_PARENT_OF, + RELATION_EXTENDED, + RELATION_FLOWS_TO, + RELATION_FLOWS_FROM, + RELATION_SUBWINDOW_OF, + RELATION_EMBEDS, + RELATION_EMBEDDED_BY, + RELATION_POPUP_FOR, + RELATION_PARENT_WINDOW_OF, + RELATION_DESCRIPTION_FOR, + RELATION_DESCRIBED_BY, + RELATION_LAST_DEFINED + } + + /* + Describes a one-to-many relationship between accessible objects. + */ + struct Relation { + RelationType type; + Reference objects []; + } + + enum uint32 StateType { + STATE_INVALID = 0, + STATE_ACTIVE, + STATE_ARMED, + STATE_BUSY, + STATE_CHECKED, + STATE_COLLAPSED, + STATE_DEFUNCT, + STATE_EDITABLE, + STATE_ENABLED, + STATE_EXPANDABLE, + STATE_EXPANDED, + STATE_FOCUSABLE, + STATE_FOCUSED, + STATE_HAS_TOOLTIP, + STATE_HORIZONTAL, + STATE_ICONIFIED, + STATE_MODAL, + STATE_MULTI_LINE, + STATE_MULTISELECTABLE, + STATE_OPAQUE, + STATE_PRESSED, + STATE_RESIZABLE, + STATE_SELECTABLE, + STATE_SELECTED, + STATE_SENSITIVE, + STATE_SHOWING, + STATE_SINGLE_LINE, + STATE_STALE, + STATE_TRANSIENT, + STATE_VERTICAL, + STATE_VISIBLE, + STATE_MANAGES_DESCENDANTS, + STATE_INDETERMINATE, + STATE_REQUIRED, + STATE_TRUNCATED, + STATE_ANIMATED, + STATE_INVALID_ENTRY, + STATE_SUPPORTS_AUTOCOMPLETION, + STATE_SELECTABLE_TEXT, + STATE_IS_DEFAULT, + STATE_VISITED, + STATE_LAST_DEFINED + } + + /* + A two integer array representing a bit-field of currently held states. + */ + typedef State uint32 []; + + /* A short string representing the object's name. */ + read property string Name; + + /* A string describing the object in more detail. */ + read property string Description; + + /* The accessible object which is this objects containing parent */ + read property Reference Parent; + + /* The number of children contained by this object */ + read property int32 ChildCount; + + /* Get the accessible child of this object at the given index */ + method GetChildAtIndex { + int32 index; + } reply { + Reference child; + } + + /* Get the index of this accessible object within its containing objects child list. */ + method GetIndexInParent reply { + int32 index; + } + + /* Access this objects non-hierarchical relationships to other accessible objects */ + method GetRelationSet reply { + RelationSet relations; + } + + /* Get the Role indicating the type of UI role played by this object. */ + method GetRole reply { + Role role; + } + + /* Get a string indicating the type of UI role played by this object */ + method GetRoleName reply { + string role; + } + + /* + Get a string indicating the type of UI role played by this object, + transalted to the current locale. + */ + method GetLocalizedRoleName { + string role; + } + + /* Access the states currently held by this object. */ + method GetState reply { + State state; + } + + /* + Get a properties applied to this object as a whole, as an + set name-value pairs. As such these attributes may be considered + weakly-typed properties or annotations, as distinct + from the strongly-typed interface instance data. + */ + method GetAttributes reply { + Attributes attributes; + } + + /* + Get the containing Application for this object. + */ + method GetApplication reply { + Reference application; + } +} + diff --git a/idl/action.didl b/idl/action.didl new file mode 100644 index 0000000..48e89aa --- /dev/null +++ b/idl/action.didl @@ -0,0 +1,60 @@ + +/* + An interface through which a user-actionable UI component can be manipulated. + + Typical actions include "click", "press", "release" or "open". +*/ +interface org.freestandards.atspi.Action { + /* + Represents a single action. + */ + struct Action { + /* String containing short description of action. */ + string name; + /* The description of an action may provide information about the result. */ + string description; + /* A string containing the key-binding or "" if none exists */ + string key_binding; + } + + property read int32 NActions; + + /* Get the description for the specified action. */ + method GetDescription { + int32 index; + } reply { + string description + } + + /* Get the name of the specified action */ + method GetName { + int32 index; + } reply { + string name; + } + + method GetLocalizedName { + int32 index; + } reply { + string name; + } + + /* Get the key-binding for the specified action. */ + method GetKeyBinding { + int32 index; + } reply { + string key_binding; + } + + /* Retrieves the actions associated with the object. */ + method GetActions reply { + Action actions []; + } + + /* Causes the object to perform the specified action. */ + method GetActions { + int32 index; + } reply { + boolean success; + } +} diff --git a/idl/application.didl b/idl/application.didl new file mode 100644 index 0000000..546fcfd --- /dev/null +++ b/idl/application.didl @@ -0,0 +1,24 @@ + +/* + An interface identifying an object which is the root of the + hierarchy associated with a running application. +*/ +interface org.freestandards.atspi.Application { + + /* A string indicating the type of user interface toolkit used by the application. */ + read property string ToolkitName; + + /* A string indicating the version of the applications accessibility bridge. */ + read property string Version; + + /* A string indicating the version of the AT-SPI specification + supported by the application */ + read property string AtspiVersion; + + /* Gets the locale in which the application is currently running. */ + method GetLocale { + LocaleType locale_type; + } reply { + string locale; + } +} diff --git a/idl/cache.didl b/idl/cache.didl new file mode 100644 index 0000000..3cf9b11 --- /dev/null +++ b/idl/cache.didl @@ -0,0 +1,27 @@ + +interface org.freestandards.atspi.Cache { + + struct CacheItem { + object path; + Reference parent; + int index_in_parent; + int child_count; + string[] interfaces; + string name; + Role role; + string description; + StateSet states; + } + + method GetItems reply { + CacheItem[] items; + } + + signal AddAccessible { + CacheItem item; + } + + signal RemoveAccessible { + Reference item; + } +} diff --git a/idl/collection.didl b/idl/collection.didl new file mode 100644 index 0000000..f3eee6e --- /dev/null +++ b/idl/collection.didl @@ -0,0 +1,69 @@ + +/* TODO - Need to define the 'MatchRule' struct. */ + +namespace org.freestandards.atspi { + interface Collection { + enum SortOrder { + SORT_ORDER_INVALID = 0, + SORT_ORDER_CANONICAL, + SORT_ORDER_FLOW, + SORT_ORDER_TAB, + SORT_ORDER_REVERSE_CANONICAL, + SORT_ORDER_REVERSE_FLOW, + SORT_ORDER_REVERSE_TAB, + SORT_ORDER_LAST_DEFINED + } + + enum MatchType { + MATCH_INVALID = 0, + MATCH_ALL, + MATCH_ANY, + MATCH_NONE, + MATCH_EMPTY, + MATCH_LAST_DEFINED + } + + enum TreeTraversalType { + TREE_RESTRICT_CHILDREN, + TREE_RESTRICT_SIBLING, + TREE_INORDER, + TREE_LAST_DEFINED + } + + method GetMatches { + MatchRule rule; + SortOrder sort_by; + int32 count; + boolean traverse; + } reply { + Reference matches []; + } + + method GetMatchesTo { + object current_object; + MatchRule rule; + SortOrder sort_by; + TreeTraversalType type; + boolean recurse; + int32 count; + boolean traverse; + } reply { + Reference matches []; + } + + method GetMatchesFrom { + object current_object; + MatchRule rule; + SortOrder sort_by; + TreeTraversalType type; + int32 count; + boolean traverse; + } reply { + Reference matches []; + } + + method GetActiveDescendent reply { + Reference descendent; + } + } +} diff --git a/idl/component.didl b/idl/component.didl new file mode 100644 index 0000000..aa40e78 --- /dev/null +++ b/idl/component.didl @@ -0,0 +1,139 @@ + +using org.freestandards.atspi.Accessible.Reference = Reference; + +/* + The Component interface is implemented by objects which occupy on-screen space, e.g. objects + which have onscreen visual representations. The methods in Component allow clients to identify + where the objects lie in the onscreen coordinate system, their relative size, stacking order, and + position. It also provides a mechanism whereby keyboard focus may be transferred to specific + user interface elements programmatically. This is a 2D API, coordinates of 3D objects are projected into the + 2-dimensional screen view for purposes of this interface. +*/ +interface org.freestandards.atspi.Component { + + /* + Used by Component, Image and Text interfaces to specify whether coordinates are + relative to the window or screen. + */ + enum CoordType { + COORD_TYPE_SCREEN = 0, + COORD_TYPE_WINDOW = 1 + } + + /* + Used by Component and Text interfaces, a struct defining a bounding rectange. + The coordinate system is determined by the context of the API call. + */ + struct BoundingBox { + int32 x; + int32 y; + int32 width; + int32 height; + } + + /* + Indicates the relative stacking order with respect to the onscreen visual representation. + + The order of layers, from bottom to top is: + LAYER_BACKGROUND + LAYER_WINDOW + LAYER_MDI + LAYER_CANVAS + LAYER_WIDGET + LAYER_POPUP + LAYER_OVERLAY + */ + enum ComponentLayer { + LAYER_INVALID, + LAYER_BACKGROUND, + LAYER_CANVAS, + LAYER_WIDGET, + LAYER_MDI, + LAYER_POPUP, + LAYER_OVERLAY, + LAYER_WINDOW, + LAYER_LAST_DEFINED + } + + /* + True if the specified point lies within the components bounding box. + */ + method Contains { + int32 x; + int32 y; + CoordType coord_type; + } reply { + boolean within; + } + + /* + Return the accessible child whose bounding box contains the specified point. + */ + method GetAccessibleAtPoint { + int32 x; + int32 y; + CoordType coord_type; + } reply { + Reference child; + } + + /* + Obtain the components bounding box, in pixels, relative to the specified coordinate system. + */ + method GetExtents { + CoordType cood_type; + } reply { + BoundingBox box; + } + + /* + Obtain the position of the current component in the specified coordinate system. + */ + method GetPosition { + CoordType coord_type; + } reply { + int32 x; + int32 y; + } + + /* + Obtain the size in the specified coordinate system. + Fully contains teh object's visual representation without accounting for viewport clipping. + */ + method GetSize reply { + int32 width; + int32 height; + } + + /* + The component layer in which this object resides. + */ + method GetLayer reply { + ComponentLayer layer; + } + + /* + Obtain the relative stacking order (i.e 'Z' order) of an object. + Larger values indicate that an object is on 'top' of the stack. + Only relevenat for objects in LAYER_MDI or LAYER_WINDOW. + */ + method GetMDIZOrder reply { + int16 order; + } + + /* + Request that an object obtain keyboard focus. + */ + method GrabFocus reply { + boolean success; + } + + /* + Obtain the alpha value of the component. + Alpha values are used with Z-Order to determine whether an obeject obscures + anothers visual representation. + */ + method GetAlpha reply { + double alpha; + } +} diff --git a/idl/controller.didl b/idl/controller.didl new file mode 100644 index 0000000..53b5f71 --- /dev/null +++ b/idl/controller.didl @@ -0,0 +1,95 @@ + +interface org.freestandards.atspi.DeviceEventController { + + enum KeySynthType { + KEY_PRESS=0, + KEY_RELEASE, + KEY_PRESSRELEASE, + KEY_SYM, + KEY_STRING + } + + /* + Consumption of events and syncronous event delivery is a sore-thumb. + + The client should really have no say over what the DeviceEventController + does with regards to event delivery as such the 'syncronous' flag is redundant. + + The 'global' flag is now useless as XEVIE is no longer maintained. As such + the DeviceEventController will not recieve any device events from applications + not participating. + + The only possibly useful flag is 'preemptive'. However all keyboard events are + sent as pre-emptive from gail so its debateable whether even this flag is really + in-use. + */ + struct EventListenerMode { + /* Controller should block while delivering this event. */ + boolean syncronous; + /* Clients are allowed to consume this event. */ + boolean preemptive; + /* + Event notifications should be sent regardless of whether + focused application participates in AT-SPI accessibility. + */ + boolean global; + } + + struct KeyDefinition { + int32 keycode; + int32 keysym; + string keystring; + int32 unused; + } + + method RegisterKeystrokeListener { + object listener; + KeyDefinition[] keys; + uint32 mask; + EventType[] type; + EventListenerMode mode; + } reply { + boolean success; + } + + method DeregisterKeystrokeListener { + object listener; + KeyDefinition[] keys; + uint32 mask; + EventType[] type; + } + + method RegisterDeviceEventListener { + object listener; + EventType[] type; + } reply { + boolean success; + } + + method DeregisterDeviceEventListener { + object listener; + EventType[] type; + } + + method NotifyListenersSync { + DeviceEvent event; + } reply { + boolean consumed; + } + + method NotifyListenersAsync { + DeviceEvent event; + } + + method GenerateKeyboardEvent { + int32 keycode; + string keystring; + KeySynthType type; + } + + method GenerateMouseEvent { + int32 x; + int32 y; + string event_name; + } +} diff --git a/idl/device.didl b/idl/device.didl new file mode 100644 index 0000000..78bdd12 --- /dev/null +++ b/idl/device.didl @@ -0,0 +1,33 @@ + +namespace org.freestandards.atspi { + + enum EventType { + KEY_PRESSED_EVENT=0, + KEY_RELEASED_EVENT, + BUTTON_PRESSED_EVENT, + BUTTON_RELEASED_EVENT + } + + enum ModifierType { + MODIFIER_SHIFT=0, + MODIFIER_SHIFTLOCK, + MODIFIER_CONTROL, + MODIFIER_ALT, + MODIFIER_META, + MODIFIER_META2, + MODIFIER_META3, + MODIFIER_NUMLOCK + } + + struct DeviceEvent { + EventType type; + /* An identifier for the event, corresponds to XEvent serial number. */ + int32 stream_id; + /* A numeric code identifying the hardware or button on which the event occured. */ + int16 hw_code; + ModifierType modifiers; + int32 timestamp; + string event_string; + boolean is_text; + } +} diff --git a/idl/document.didl b/idl/document.didl new file mode 100644 index 0000000..ce2a4f0 --- /dev/null +++ b/idl/document.didl @@ -0,0 +1,25 @@ + +/* + Indicates the start of a document. + + Children are part of the document content. +*/ +interface org.freestandards.atspi.Document { + + /* Gets the locale associated with the documents content. */ + method GetLocale reply { + string locale; + } + + /* Gets the value of a single attribute. */ + method GetAttributeValue { + string key; + } reply { + string value; + } + + /* Gets all attributes for the document as a whole. These are constant for all elements within the document.*/ + method GetAttributes reply { + Attributes attributes; + } +} diff --git a/idl/event.didl b/idl/event.didl new file mode 100644 index 0000000..d4c75cc --- /dev/null +++ b/idl/event.didl @@ -0,0 +1,79 @@ + +namespace org.freestandards.atspi.Event { + + struct Event { + string minor; + int32 detail1; + int32 detail2; + variant val; + Reference application; + } + + interface Object { + signal PropertyChange {Event event;} + signal BoundsChanged {Event event;} + signal LinkSelected {Event event;} + signal StateChanged {Event event;} + signal ChildrenChanged {Event event;} + signal VisibleDataChanged {Event event;} + signal SelectionChanged {Event event;} + signal ModelChanged {Event event;} + signal ActiveDescendantChanged {Event event;} + signal RowInserted {Event event;} + signal RowDeleted {Event event;} + signal RowReordered {Event event;} + signal ColumnInserted {Event event;} + signal ColumnDeleted {Event event;} + signal ColumnReordered {Event event;} + signal TextBoundsChanged {Event event;} + signal TextSelectionChanged {Event event;} + signal TextChanged {Event event;} + signal TextAttributesChanged {Event event;} + signal TextCaretMoved {Event event;} + signal AttributesChanged {Event event;} + } + + interface Window { + signal PropertyChange {Event event;} + signal Minimize {Event event;} + signal Maximize {Event event;} + signal Restore {Event event;} + signal Close {Event event;} + signal Create {Event event;} + signal Reparent {Event event;} + signal DesktopCreate {Event event;} + signal DesktopDestroy {Event event;} + signal Destroy {Event event;} + signal Activate {Event event;} + signal Deactivate {Event event;} + signal Raise {Event event;} + signal Lower {Event event;} + signal Move {Event event;} + signal Resize {Event event;} + signal Shade {Event event;} + signal Ushade {Event event;} + signal Restyle {Event event;} + } + + interface Mouse { + signal Abs {Event event;} + signal Rel {Event event;} + signal Button {Event event;} + } + + interface Keyboard { + signal Modifiers {Event event;} + } + + interface Document { + signal LoadComplete {Event event;} + signal Reload {Event event;} + signal LoadStopped {Event event;} + signal ContentChanged {Event event;} + signal AttributesChanged {Event event;} + } + + interface Focus { + signal Focus {Event event;} + } +} diff --git a/idl/hypertext.didl b/idl/hypertext.didl new file mode 100644 index 0000000..334dafd --- /dev/null +++ b/idl/hypertext.didl @@ -0,0 +1,82 @@ + +namespace org.freestandards.atspi { + /* + Instances of Hyperlink are returned by Hypertext object and + are the means by which end users and clients interact with linked + content. + + Hyperlink instances DO NOT neccessarily implement the Accessible interface. + */ + interface HyperLink { + /* The number of separate anchors associated with this Hyperlink. */ + read property int32 NAnchors; + + /* + The starting offset within the contianing Hypertext, + with which this Hyperlink is associated. + */ + read property int32 StartIndex; + + /* + The ending offset within the containing Hypertext with which + this Hyperlink is associated. + */ + read property int32 EndIndex; + + /* + Gets the i'th object associated with a Hyperlink. + Objects returned should implement the Action interface. + */ + method GetObject { + int32 index; + } reply { + Reference anchor; + } + + /* + Obtain a resource locator, URI, which can be used to access the content + which this link points to. + */ + method GetUri { + int32 index; + } reply { + string uri; + } + + /* + Check the hyperlink to see if a connection to its backing content can be + established or if its URI is valid. + */ + method IsValid reply { + boolean valid; + } + } + + /* + An interface used for objects which implement linking between multiple resource locations. + A hypertext instance is associated with one or more hyperlinks which are associated with + particular offests within the text. + */ + interface Hypertext { + + method GetNLinks reply { + int32 n_links; + } + + method GetLink { + int32 index; + } reply { + Reference hyperlink; + } + + /* + Get the hyperlink index, if any, associated with a particular text offset. + */ + method GetLinkIndex { + int32 offset; + } reply { + /* -1 if no hyperlink is associated. */ + int32 index; + } + } +} diff --git a/idl/image.didl b/idl/image.didl new file mode 100644 index 0000000..9dee626 --- /dev/null +++ b/idl/image.didl @@ -0,0 +1,33 @@ + +/* + An interface implemented by objects which render image data or + pictoral information on to the screen. +*/ +interface org.freestandards.atspi.Image { + /* A textual description of what is visually depicted on the screen. */ + read property string ImageDescription; + + /* A string corresponding to the local used by the image description. */ + read property string ImageLocale; + + /* Obtain a bounding box which entirely contains the image contents. */ + method GetImageExtents { + CoordType coord_type; + } reply { + BoundingBox; + } + + /* Get the coordinates of the image on the screen */ + method GetImagePosition { + CoordType coord_type; + } reply { + int32 x; + int32 y; + } + + /* Get the size of the current on-screen view of the image. */ + method GetImageSize reply { + int32 width; + int32 height; + } +} diff --git a/idl/listener.didl b/idl/listener.didl new file mode 100644 index 0000000..7e3f6a1 --- /dev/null +++ b/idl/listener.didl @@ -0,0 +1,9 @@ + +interface org.freestandards.atspi.DeviceEventListener { + + method NotifyEvent { + DeviceEvent event; + } reply { + boolean success; + } +} diff --git a/idl/selection.didl b/idl/selection.didl new file mode 100644 index 0000000..66fbef7 --- /dev/null +++ b/idl/selection.didl @@ -0,0 +1,54 @@ + +/* + An interface which indicates that an object exposes a 'selection' model, + allowing the 'selection' of one or more of its children. +*/ +interface org.freestandards.atspi.Selection { + /* The number of children that are currently selected. */ + read property int32 NSelectedChildren; + + /* Gets the ith SELECTED child. This is different to the index of all children. */ + method GetSelectedChild { + int32 index; + } reply { + Reference child; + } + + /* Select the child, add it to the list of selected children. */ + method SelectChild { + int32 index; + } reply { + boolean success; + } + + /* Deselect a child. The index refers to the index into the list of selected children. */ + method DeselectSelectedChild { + int32 index; + } reply { + boolean success; + } + + /* Determine whether a particular child is currently selected. */ + method IsChildSelected { + int32 index; + } reply { + boolean selected; + } + + /* Apptemt to select all of the containers children. */ + method SelectAll reply { + boolean success; + } + + /* Attempt to deselect all selected children. */ + method ClearSelection reply { + boolean success; + } + + /* Deselect a child. The index refers to the index into the list of all children. */ + method DeselectChild { + int32 index; + } reply { + boolean success; + } +} diff --git a/idl/socket.didl b/idl/socket.didl new file mode 100644 index 0000000..336ca6c --- /dev/null +++ b/idl/socket.didl @@ -0,0 +1,31 @@ + +namespace org.freestandards.atspi { + /* + Accessible objects with the socket interface are capable of embeding other + accessible heirarchies as one of their children. This allows + applications to embed themselves in the heirarchy of the desktop object. + */ + interface Socket { + method Embed { + Reference plug; + } reply { + Reference socket; + } + + method Unembed { + Reference plug; + } + + /* + The available signal indicates that a socket has been + made available, it is for discovering new sockets. + This is used for when the process containing the desktop + object is re-started. + + D-Bus bus name must have been granted by the D-Bus bus. + It is used to identify the new socket. + */ + signal Available { + Reference socket; + } +} diff --git a/idl/table.didl b/idl/table.didl new file mode 100644 index 0000000..ae1b8f0 --- /dev/null +++ b/idl/table.didl @@ -0,0 +1,186 @@ + +namespace org.freestandards.atspi { + + /* + An interface used by containers whose data is arranged in a tabular form. + Objects within tables are always children of the table object. + */ + interface Table { + read property int32 NRows; + + read property int32 NColumns; + + read property Reference caption; + + read property Reference summary; + + /* Number of rows where all cells are selected. */ + read property int32 NSelectedRows; + + /* Number of columns where all cells are selected. */ + read property int32 NSelectedColumns; + + method GetAccessibleAt { + int32 row; + int32 column; + } reply { + Reference cell; + } + + /* + Cells in a table are also children of the table in the standard heirarchy. + This method gets the child index of the given cell. + */ + method GetIndexAt { + int32 row; + int32 column; + } reply { + int32 index; + } + + /* + Indicates which row the child specified by index is on. + */ + method GetRowAtIndex { + int32 index; + } reply { + int32 row; + } + + /* + Indicates which column the child specified by index is on. + */ + method GetColumnAtIndex { + int32 index; + } reply { + int32 column; + } + + /* + Get a textual description of a row. + */ + method GetRowDescription { + int32 row; + } reply { + string description; + } + + /* + Get a textual description of a particular column. + */ + method GetColumnDescription { + int32 column; + } reply { + string description; + } + + /* + Get the number of rows spanned by the table cell at the specific row and column. + method GetRowExtentAt { + int32 row; + int32 column; + } reply { + int32 rowspan; + } + + /* + Get the number of columns spanned by the table cell at the specific row and column. + */ + method GetColumnExtentAt { + int32 row; + int32 column; + } reply { + int32 column_span; + } + + /* + Get the header object associated with a particular table row. + */ + method GetRowHeader { + int32 row; + } reply { + Reference header; + } + + /* + Get the header object associated with a particular table column. + */ + method GetColumnHeader { + int32 column; + } reply { + Reference header; + } + + /* + Obtain the indicies of all rows which are currently selected. + */ + method GetSelectedRows reply { + int32 indicies []; + } + + /* + Obtain the indicies of all columns which are currently selected. + */ + method GetSelectedColumns reply { + int32 indicies []; + } + + method IsRowSelected { + int32 row; + } reply { + boolean selected; + } + + method IsColumnSelected { + int32 column; + } reply { + boolean selected; + } + + method IsSelected { + int32 row; + int32 column; + } reply { + boolean selected; + } + + method AddRowSelection { + int32 row; + } reply { + boolean success; + } + + method AddColumnSelection { + int32 column; + } reply { + boolean success; + } + + method RemoveRowSelection { + int32 row; + } reply { + boolean success; + } + + method RemoveColumnSelection { + int32 column; + } reply { + boolean success; + } + + /* + Given a child index determine the row and column indicies and extents + and whether the cell is currently selected. + */ + method GetRowColumnExtentsAtIndex { + int32 index; + } reply { + boolean valid; + int32 row; + int32 column; + int32 row_span; + int32 column_span; + boolean selected; + } + } +} diff --git a/idl/text.didl b/idl/text.didl new file mode 100644 index 0000000..07ce85e --- /dev/null +++ b/idl/text.didl @@ -0,0 +1,311 @@ + +namespace org.freestandards.atspi { + /* + The text interface should be implemented by objects which place textual information onscreen + as character strings or glyphs. The text interface allows access to textual content including + display attributes and semantic hints associated with runs of text, and to bounding boc information + for glyphs and substrings. It also alows portions of text to be selected, if the objects StateSet + includes STATE_SELECTABLE_TEXT. + */ + interface Text { + /* + Specified the boundary conditions determining a run of text + as returned from: + GetTextAtOffset + GetTextAfterOffset + GetTextBeforeOffset + */ + enum TextBoundaryType { + TEXT_BOUNDARY_CHAR, + TEXT_BOUNDARY_WORD_START, + TEXT_BOUNDARY_WORD_END, + TEXT_BOUNDARY_SENTENCE_START, + TEXT_BOUNDARY_SENTENCE_END, + TEXT_BOUNDARY_LINE_START, + TEXT_BOUNDARY_LINE_END + } + + enum TextClipType { + TEXT_CLIP_NONE, + TEXT_CLIP_MIN, + TEXT_CLIP_MAX, + TEXT_CLIP_BOTH + } + + /* + A structure used to define a contiguous range of text, including + its (unattributed) textual content. + */ + struct Range { + int32 start_offset; + int32 end_offset; + int32 content; + variant data; + } + + /* The total number of character in the text object including whitespace. */ + read property int32 CharacterCount; + + /* The current offset of the text caret in the Text object. */ + read property int32 CaretOffset; + + /* Move the text caret to a given position. */ + method SetCaretOffset { + int32 offset; + } reply { + boolean success; + } + + /* + Obtain the subset of text content that entirely precedes the given offset, + delimited by character word, line or sentente boundaries. + */ + method GetTextBeforeOffset { + int32 offset; + TextBoundaryType type; + } reply { + string s; + int32 start_offset; + int32 end_offset; + } + + /* + Obtain the subset of text content that includes the given offset, + delimited by character word, line or sentente boundaries. + */ + method GetTextAtOffset { + int32 offset; + TextBoundaryType type; + } reply { + string s; + int32 start_offset; + int32 end_offset; + } + + /* + Obtain the subset of text content that entirely follows the given offset, + delimited by character word, line or sentente boundaries. + */ + method GetTextAfterOffset { + int32 offset; + TextBoundaryType type; + } reply { + string s; + int32 start_offset; + int32 end_offset; + } + + method GetCharacterAtOffset { + int32 offset; + } reply { + /* UCS-4 representation of the character or 0 if offset out-of-range. */ + int32 c; + } + + /* + Get the value of a named attribute at a given offset. + */ + method GetAttributeValue { + int32 offset; + string attribute_key; + } reply { + string attribute_value; + } + + /* Deprecated in favor of GetAttributeRun. */ + method GetAttributes { + int32 offset; + } reply { + Attributes attributes; + int32 start_offset; + int32 end_offset; + } + + /* Deprecated in facor of GetDefaultAttributeSet. */ + method GetDefaultAttributes reply { + Attributes attributes; + } + + /* + Obtain a bounding box of the character glyph at a particular character offset, + in the given coordinate system. + */ + method GetCharacterExtents { + int32 offset; + CoordType coord; + } reply { + int32 x; + int32 y; + int32 width; + int32 height; + } + + /* + Get the offset of the character at a given on-screen coordinate. The coordinate + system used is determined by the give coordinate type. + */ + method GetOffsetAtPoint { + int32 x; + int32 y; + CoordType coord; + } reply { + /* -1 if the point is outside the bounds of any glyph. */ + int32 offset; + } + + /* + Obtain the number of separate, contiguous selections in the current Text object. + */ + method GetNSelections reply { + int32 n_selections; + } + + method GetSelection { + int32 selection_index; + } reply { + int32 start_offset; + int32 end_offset; + } + + method AddSelection { + int32 start_offset; + int32 end_offset; + } reply { + boolean success; + } + + method RemoveSelection { + int32 selection_index; + } reply { + boolean success; + } + + method SetSelection { + int32 selection_index; + int32 start_offset; + int32 end_offset; + } reply { + boolean success; + } + + /* + Obtain the bounding box which entirely contains the given text range. + Negative values may be obtained in the event that part of the text range is + off-screen. + */ + method GetRangeExtents { + int32 start_offset; + int32 end_offset; + CoordType coord; + } reply { + int32 x; + int32 y; + int32 width; + int32 height; + } + + /* + Return the text content within a bounding box. + + Depending on the clip type glyphs which are clipped by the bounding box + may, or may not be inclide in the ranges returned. + */ + method GetBoundedRanges { + int32 x; + int32 y; + int32 width; + int32 height; + CoordType coord; + ClipType x_clip; + ClipType y_clip; + } reply { + RangeType ranges []; + } + + /* + Gets the attributes of a particular text objects defined at a given offset. + The attributes are invariant over the offsets returned. + */ + method GetAttributeRun { + int32 offset; + boolean include_defaults; + } reply { + Attributes attributes; + int32 start_offset; + int32 end_offset; + } + + /* + Gets the default attributes that apply to the entire text. + */ + method GetAttributeSet reply { + Attributes attributes' + } + } + + /* + All objects supporting EditableText should also support the + Text interface. + + Provides methods for modifying textual content of components which support editing. + EditableText also interacts with the system clipboard. + */ + interface EditableText { + /* + Replace the text contents with a new string, discarding the old contents. + */ + method SetTextContents { + string new_contents; + } reply { + boolean success; + } + + /* + Insert new text contents into a given location. + */ + method InsertText { + int32 position; + string text; + int32 length; + } reply { + boolean success; + } + + /* + Copy a range of text in to the system clipboard. + */ + method CopyText { + int32 start_pos; + int32 end_pos; + } + + /* + Excise a range of text, copying it to the system clipboard. + */ + method CutText { + int32 start_pos; + int32 end_pos; + } reply { + boolean success; + } + + /* + Excise a range of text from the object without copying to the system clipboard. + */ + method DeleteText { + int32 start_pos; + int32 end_pos; + } reply { + boolean success; + } + + /* + Copy the contents of the system clip-board in to the text object. + */ + method PasteText { + int32 position; + } reply { + boolean success; + } + } +} diff --git a/idl/types.didl b/idl/types.didl new file mode 100644 index 0000000..b8c4129 --- /dev/null +++ b/idl/types.didl @@ -0,0 +1,25 @@ +/* + Type definitions needed by multiple interfaces. +*/ + +namespace org.freestandards.atspi { + + /* + A connection independent reference to a D-Bus object. + + The D-Bus object that is referenced will support at-least + the org.freestandards.atspi.Accessible interface. + */ + struct Reference { + /* The D-Bus connection name where the object resides. */ + string name; + /* The D-Bus path of the object. */ + object path; + } + + /* + Attributes are weakly typed properties of an object consisting of string-string + key-value pairs. + */ + typedef Attributes dict ; +} diff --git a/idl/value.didl b/idl/value.didl new file mode 100644 index 0000000..476cb43 --- /dev/null +++ b/idl/value.didl @@ -0,0 +1,15 @@ + +/* + An interface supporting a one-dimensional scalar quantity + to be modified, or which reflects a scalar value. + */ +interface org.freestandards.atspi.Value { + + read property double MinimumValue; + + read property double MaximumValue; + + read property double MinimumIncrement; + + read property double currentValue; +} diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/m4/.gitignore diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..86e2a4a --- /dev/null +++ b/meson.build @@ -0,0 +1,140 @@ +project('at-spi2-core', 'c', + version: '2.28.0', + license: 'LGPLv2.1+', + default_options: [ + 'buildtype=debugoptimized', + 'warning_level=1', + 'c_std=c99', + ], + meson_version: '>= 0.40.1') + +add_project_arguments([ '-D_POSIX_C_SOURCE=200809L', '-D_DEFAULT_SOURCE' ], language: 'c') + +atspi_gir_ns = 'Atspi' + +cc = meson.get_compiler('c') +host_system = host_machine.system() + +soversion = '0.0.1' + +at_spi_conf = configuration_data() +at_spi_conf.set('GETTEXT_PACKAGE', meson.project_name()) + +root_inc = include_directories('.') +registryd_inc = include_directories('registryd') + +atspi_prefix = get_option('prefix') +atspi_datadir = join_paths(atspi_prefix, get_option('datadir')) +atspi_libexecdir = join_paths(atspi_prefix, get_option('libexecdir')) +atspi_sysconfdir = join_paths(atspi_prefix, get_option('sysconfdir')) +atspi_libdir = join_paths(atspi_prefix, get_option('libdir')) +atspi_includedir = join_paths(atspi_prefix, get_option('includedir')) + +if get_option('dbus_services_dir') != 'default' + dbus_services_dir = get_option('dbus_services_dir') +else + dbus_services_dir = join_paths(get_option('datadir'), 'dbus-1/services') +endif + +if get_option('systemd_user_dir') != 'default' + systemd_user_dir = get_option('systemd_user_dir') +else + systemd_user_dir = join_paths(get_option('prefix'), 'lib/systemd/user') +endif + +# Dependencies +libdbus_req_version = '>= 1.5' +glib_req_version = '>= 2.32.0' +gobject_req_version = '>= 2.0.0' +gio_req_version = '>= 2.28.0' + +libdbus_dep = dependency('dbus-1', version: libdbus_req_version) +glib_dep = dependency('glib-2.0', version: glib_req_version) +gobject_dep = dependency('gobject-2.0', version: gobject_req_version) +gio_dep = dependency('gio-2.0', version: gio_req_version) +dl_dep = cc.find_library('dl', required: false) + +x11_deps = [] +x11_option = get_option('enable-x11') +if x11_option != 'no' + x11_dep = dependency('x11', required: false) + + if x11_dep.found() + x11_deps += x11_dep + at_spi_conf.set('HAVE_X11', 1) + xtest_dep = dependency('xtst') + x11_deps += xtest_dep + + if cc.has_function('XkbGetMap', dependencies: x11_deps) + at_spi_conf.set('HAVE_XKB', 1) + endif + + xinput_dep = dependency('xi') + x11_deps += xinput_dep + endif +endif + +# Alignments +at_spi_conf.set('ALIGNOF_CHAR', cc.alignment('char')) +at_spi_conf.set('ALIGNOF_DOUBLE', cc.alignment('double')) + +dbus_alignments = [ + 'dbus_bool_t', + 'dbus_int16_t', + 'dbus_int32_t', + 'dbus_int64_t', +] + +foreach a: dbus_alignments + at_spi_conf.set('ALIGNOF_' + a.underscorify().to_upper(), + cc.alignment(a, prefix: '#include ', dependencies: libdbus_dep)) +endforeach + +at_spi_conf.set('ALIGNOF_DBIND_POINTER', cc.alignment('dbind_pointer', prefix: 'typedef void *dbind_pointer;')) +at_spi_conf.set('ALIGNOF_DBIND_STRUCT', cc.alignment('dbind_struct', prefix: 'typedef struct { char s1; } dbind_struct;')) + +# introspection support +have_gir = false + +introspection_option = get_option('enable-introspection') +if introspection_option != 'no' + gir_dep = dependency('gobject-introspection-1.0', version: '>= 0.6.7', required: false) + + if gir_dep.found() + have_gir = true + endif +endif + +xgettext = find_program('xgettext', required : false) + +configure_file(output: 'config.h', configuration: at_spi_conf) + +# Compat variables for pkgconfig +pkgconf = configuration_data() +pkgconf.set('prefix', get_option('prefix')) +pkgconf.set('exec_prefix', get_option('prefix')) +pkgconf.set('libdir', atspi_libdir) +pkgconf.set('includedir', atspi_includedir) +pkgconf.set('VERSION', meson.project_version()) + +configure_file(input: 'atspi-2.pc.in', + output: 'atspi-2.pc', + configuration: pkgconf, + install: true, + install_dir: join_paths(get_option('libdir'), 'pkgconfig')) + +gnome = import('gnome') + +subdir('dbind') +subdir('atspi') +subdir('bus') +subdir('registryd') +subdir('test') + +if get_option('enable_docs') + subdir('doc/libatspi') +endif + +if xgettext.found() + subdir('po') +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..c9afe2f --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,20 @@ +option('dbus_services_dir', + description: 'Location of the DBus services', + type: 'string', + value: 'default') +option('dbus_daemon', + description: 'The path of the DBus daemon', + type: 'string', + value: 'default') +option('systemd_user_dir', + description: 'Location of the systemd user services', + type: 'string', + value: 'default') +option('enable_docs', + description: 'Generate API reference for atspi (requires GTK-Doc)', + type: 'boolean', + value: false) + +option('enable-introspection', type: 'combo', choices: ['yes', 'no', 'auto'], value: 'auto', description: 'Enable GObject Introspection (depends on GObject)') + +option('enable-x11', type: 'combo', choices: ['yes', 'no', 'auto'], value: 'auto', description: 'Enable X11 support') diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..4e2efbd --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,71 @@ +an +as +ast +be +bg +bn_IN +bs +ca +ca@valencia +cs +da +de +el +en_CA +en_GB +eo +es +et +eu +fa +fi +fr +fur +ga +gd +gl +gu +he +hi +hr +hu +id +it +ja +kk +km +kn +ko +lt +lv +ml +mr +ms +nb +ne +nl +oc +or +pa +pl +pt +pt_BR +ro +ru +sk +sl +sq +sr +sr@latin +sv +ta +te +tg +tr +ug +uk +uz@cyrillic +vi +zh_CN +zh_HK +zh_TW diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..9a29d19 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,7 @@ +# List of source files containing translatable strings. +# Please keep this file sorted alphabetically. +atspi/atspi-accessible.c +atspi/atspi-component.c +atspi/atspi-event-listener.c +atspi/atspi-misc.c +atspi/atspi-value.c diff --git a/po/an.po b/po/an.po new file mode 100644 index 0000000..40ed472 --- /dev/null +++ b/po/an.po @@ -0,0 +1,29 @@ +# Aragonese translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Daniel Martinez Cucalon , 2011. +# FULL NAME , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-08 15:47+0000\n" +"PO-Revision-Date: 2014-02-08 19:04+0100\n" +"Last-Translator: Jorge Pérez Pérez \n" +"Language-Team: Aragonese \n" +"Language: an\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.3\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'aplicacion ya no existe" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "S'ha prohibiu l'intento de gritada sincrona" diff --git a/po/as.po b/po/as.po new file mode 100644 index 0000000..e8bf4db --- /dev/null +++ b/po/as.po @@ -0,0 +1,94 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Nilamdyuti Goswami , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-02-13 22:32+0630\n" +"Last-Translator: Nilamdyuti Goswami \n" +"Language-Team: Assamese \n" +"Language: as\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "এপ্লিকেচনৰ আৰু অস্তিত্ব নাই" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "নিষিদ্ধ ঠাইত সংমিহলিত কলৰ চেষ্টা" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: RemoveAccessible -ৰ কাৰণে অজ্ঞাত স্বাক্ষৰ %s" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: %s -ৰ বাবে getRoot -ক মাততে ত্ৰুটি: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems -ত ত্ৰুটি, পঠুৱা=%s, ত্ৰুটি=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_accessible_from_message -ক অদ্ভুত স্বাক্ষৰ %s -ৰ " +#~ "সৈতে মতা হ'ল" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:_atspi_dbus_return_hyperlink_from_message -ক অদ্ভুত স্বাক্ষৰ %s -ৰ " +#~ "সৈতে মতা হ'ল" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: অজ্ঞাত স্বাক্ষৰ %s -ৰ সৈতে AddAccessible\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: প্ৰদৰ্শন কৰিবলে অক্ষম\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI: প্ৰৱেশিকা বাচ পোৱা নগল - ব্যৱহাৰ কৰা হৈছে অভিবৰ্তন বাচ.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: %s বাচৰ সৈতে সংযোগ কৰিবলে ব্যৰ্থ \n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: %s বাচৰ সৈতে ৰেজিস্টাৰ কৰিবলে ব্যৰ্থ\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: আন্তঃপৃষ্ট %s -ৰ পৰা %s -ক আনোতে এটা অপৰৰ প্ৰত্যাশা কৰা হৈছিল; %s -ক " +#~ "পোৱা গল\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: ভুল ধৰণ : প্ৰত্যাশা কৰা হৈছিল %s, পোৱা গল %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: অজ্ঞাত আন্তঃপৃষ্ট %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: অৱস্থাসমূহৰ এৰেত ২টা মানৰ প্ৰত্যাশা কৰা হৈছিল; পোৱা গল %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Streamable সমল, প্ৰণয়ন কৰা হোৱা নাই" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "এটা NULL event_type -ৰ সৈতে atspi_event_listener_register_from_callback -" +#~ "ক মতা হৈছিল " + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "সংকেত %s -ৰ কাৰণে আন্তঃপৃষ্ট %s -ৰ পৰা অবৈধ স্বাক্ষৰ %s পোৱা গল\n" diff --git a/po/ast.po b/po/ast.po new file mode 100644 index 0000000..8dc1d17 --- /dev/null +++ b/po/ast.po @@ -0,0 +1,97 @@ +# Asturian translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Xandru Armesto , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-04-22 21:34+0000\n" +"PO-Revision-Date: 2011-04-25 08:22+0200\n" +"Last-Translator: Xandru Armesto \n" +"Language-Team: Softastur alministradores@softastur.org\n" +"Language: ast\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Virtaal 0.5.2\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: robla %s desconocida pa RemoveAccessible" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: fallu al llamar a getRoot pa %s: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: fallu en GetItems, emisor=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: llamada a _atspi_dbus_return_accessible_from_message con una robla %" +"s estraña" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: llamada a _atspi_dbus_return_hyperlink_from_message con una robla %s " +"estraña" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: AddAccessible con robla %s desconocida\n" + +#: ../atspi/atspi-misc.c:934 ../atspi/atspi-misc.c:985 +#: ../atspi/atspi-misc.c:1026 +msgid "The application no longer exists" +msgstr "L'aplicación yá nun esiste" + +#: ../atspi/atspi-misc.c:1062 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: esperábase una variante al guetar %s de la interfaz %s; obtúvose %s\n" + +#: ../atspi/atspi-misc.c:1068 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: tipu incorreutu: esperábase %s, obtúvose %c\n" + +#: ../atspi/atspi-misc.c:1211 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: interfaz %s desconocida" + +#: ../atspi/atspi-misc.c:1231 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: esperábense 2 valores nel array d'estaos; obtúvose %d\n" + +#: ../atspi/atspi-accessible.c:1035 +msgid "Streamable content not implemented" +msgstr "El conteníu de fluxu distribuyible nun ta implementáu" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"llamóse a atspi_event_listener_register_from_callback con un event_type nulu" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "Obtúvose una robla %s non válida pa la señal %s de la interfaz %s\n" diff --git a/po/be.po b/po/be.po new file mode 100644 index 0000000..f7bc9c1 --- /dev/null +++ b/po/be.po @@ -0,0 +1,79 @@ +# Yuras Shumovich , 2017. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core.master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-03-13 21:58+0000\n" +"PO-Revision-Date: 2017-03-26 18:30+0300\n" +"Last-Translator: Yuras Shumovich \n" +"Language-Team: Belarusian \n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Poedit 1.8.11\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1073 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Праграма больш не існуе" + +#: ../atspi/atspi-misc.c:1832 +msgid "Attempted synchronous call where prohibited" +msgstr "Спроба зрабіць сінхронны выклік, там дзе гэта забаронена" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Невядомы подпіс %s для RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Памылка выкліку getRoot для %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Памылка ў GetItems, адпраўнік=%s, памылка=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Функцыя _atspi_dbus_return_accessible_from_message выкліканая з " +#~ "дзіўным подпісам %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Функцыя _atspi_dbus_return_hyperlink_from_message выкліканая з " +#~ "дзіўным подпісам %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible з дзіўным подпісам %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: пры сцягванні %s з інтэрфейсу %s чакаўся варыянт; атрыманы %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Няправільны тып: чакаўся %s, атрыманы %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Невядомы інтэрфейс %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: чакаліся 2 значэнні ў масіве станаў; атрымана %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Падтрымка струмененага змесціва не ажыццёўленая" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "функцыя atspi_event_listener_register_from_callback выкліканая з " +#~ "event_type = NULL" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Атрыманы хібны подпіс %s для сігналу %s інтэрфейсу %s\n" diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 0000000..44cc7f1 --- /dev/null +++ b/po/bg.po @@ -0,0 +1,27 @@ +# Bulgarian translation of at-spi2-core po-file. +# Copyright (C) 2011, 2015 Free Software Foundation +# This file is distributed under the same license as the at-spi2-core package. +# Alexander Shopov , 2011, 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-03-09 19:17+0200\n" +"PO-Revision-Date: 2015-03-09 19:17+0200\n" +"Last-Translator: Alexander Shopov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Програмата вече не съществува" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Заявеното асинхронно действие е забранено" diff --git a/po/bn_IN.po b/po/bn_IN.po new file mode 100644 index 0000000..4e58021 --- /dev/null +++ b/po/bn_IN.po @@ -0,0 +1,122 @@ +# Bengali (India) translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=at-spi&component=general\n" +"POT-Creation-Date: 2011-02-09 20:49+0000\n" +"PO-Revision-Date: 2011-02-10 15:39+0530\n" +"Last-Translator: \n" +"Language-Team: Bengali (India) \n" +"Language: bn_IN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible-র জন্য অজানা স্বাক্ষর %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s-র জন্য getRoot প্রাপ্ত করতে ত্রুটি: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems-এ ত্রুটি, প্রেরক=%s, ত্রুটি=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: অজানা স্বাক্ষর %s সহ _atspi_dbus_return_accessible_from_message কল " +"করা হয়েছে" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: অজানা স্বাক্ষর %s সহ _atspi_dbus_return_hyperlink_from_message কল " +"করা হয়েছে" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: অজানা স্বাক্ষর %s সহ AddAccessible\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: প্রদর্শন প্রাপ্ত করতে ব্যর্থ\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "" +"AT-SPI: অ্যাকসেসিবিলিটি বাস পাওয়া যায়নি - সেশান বাস ব্যবহার করা হচ্ছে।\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: বাসের সাথে সংযোগ স্থাপন করতে ব্যর্থ: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: বাসের সাথে নিবন্ধন করতে ব্যর্থ: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "অ্যাপ্লিকেশনটি বর্তমানে উপস্থিত নেই" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "" +"AT-SPI: %s প্রাপ্ত করার সময় %s ইন্টারফেস থেকে একটি ভেরিয়েন্ট প্রত্যাশিত ছিল; %s " +"প্রাপ্ত হয়েছে\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "" +"atspi_dbus_get_property: ধরন সঠিক নয়: %s প্রত্যাশিত, %c প্রাপ্ত হয়েছে\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: অজানা ইন্টারফেস %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "" +"AT-SPI: states অ্যারের মধ্যে ২-টি মান প্রত্যাশিত; %d-টি প্রাপ্ত হয়েছে\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "স্ট্রিম করার যোগ্য সামগ্রী বাস্তবায়িত হয়নি" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"NULL event_type সহ atspi_event_listener_register_from_callback কল করা হয়েছে" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "অবৈধ স্বাক্ষর %s প্রাপ্ত হয়েছে %s সিগন্যালের জন্য %s ইন্টারফেস থেকে\n" + diff --git a/po/bs.po b/po/bs.po new file mode 100644 index 0000000..bc864e8 --- /dev/null +++ b/po/bs.po @@ -0,0 +1,29 @@ +# Bosnian translation for bosnianuniversetranslation +# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013 +# This file is distributed under the same license as the bosnianuniversetranslation package. +# FIRST AUTHOR , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: bosnianuniversetranslation\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-02-27 03:49+0000\n" +"PO-Revision-Date: 2015-02-05 01:25+0000\n" +"Last-Translator: Samir Ribić \n" +"Language-Team: Bosnian \n" +"Language: bs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2015-02-05 07:02+0000\n" +"X-Generator: Launchpad (build 17331)\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Program više ne postoji" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Pokušan sinhroni poziv kada je zabranjen" diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 0000000..6e1116d --- /dev/null +++ b/po/ca.po @@ -0,0 +1,27 @@ +# Catalan translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# David Planella , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-03-15 18:24+0000\n" +"PO-Revision-Date: 2014-03-15 21:31+0100\n" +"Last-Translator: Joan Montané \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'aplicació ja no existeix" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "S'ha intentat una crida síncrona on és prohibit" diff --git a/po/ca@valencia.po b/po/ca@valencia.po new file mode 100644 index 0000000..ca0b97f --- /dev/null +++ b/po/ca@valencia.po @@ -0,0 +1,26 @@ +# Catalan translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# David Planella , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-06-27 21:34+0000\n" +"PO-Revision-Date: 2014-03-15 21:31+0100\n" +"Last-Translator: Xavi Ivars \n" +"Language-Team: Catalan \n" +"Language: ca-valencia\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: atspi/atspi-component.c:326 atspi/atspi-misc.c:1073 atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'aplicació ja no existeix" + +#: atspi/atspi-misc.c:1843 +msgid "Attempted synchronous call where prohibited" +msgstr "S'ha intentat una crida síncrona on és prohibit" diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 0000000..406ebc5 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,29 @@ +# Czech translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Marek Černocký , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-02-08 07:39+0100\n" +"Last-Translator: Marek Černocký \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikace již neexistuje" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Pokus o synchronní volání tam, kde je zakázáno" diff --git a/po/da.po b/po/da.po new file mode 100644 index 0000000..1724397 --- /dev/null +++ b/po/da.po @@ -0,0 +1,83 @@ +# Danish translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Kris Thomsen , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: " +"https://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-06-27 21:34+0000\n" +"PO-Revision-Date: 2014-03-15 14:12+0100\n" +"Last-Translator: Kris Thomsen \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: atspi/atspi-component.c:326 atspi/atspi-misc.c:1073 atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Programmet findes ikke længere" + +#: atspi/atspi-misc.c:1843 +msgid "Attempted synchronous call where prohibited" +msgstr "Et forsøgt synkront kald blev forbudt" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Ukendt signatur %s for RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Fejl under kald af getRoot for %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Fejl i GetItems, sender=%s, fejl=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Kaldte _atspi_dbus_return_accessible_from_message med en mærkelig " +#~ "signatur %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Kaldte _atspi_dbus_return_hyperlink_from_message med en mærkelig " +#~ "signatur %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible med ukendt signatur %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: forventede en variant under hentning af %s fra grænseflade %s; fik " +#~ "%s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Forkert type: forventede %s, fik %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Ukendt grænseflade %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: forventede 2 værdier i statusarray; fik %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Strømbart indhold er ikke implementeret" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "kaldte atspi_event_listener_register_from_callback event_type med en " +#~ "NULL-værdi" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Modtog ugyldig signatur %s for signalet %s fra grænseflade %s\n" + + diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..5f0bdff --- /dev/null +++ b/po/de.po @@ -0,0 +1,102 @@ +# German translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Christian Kirbach , 2011. +# Mario Blättermann , 2011. +# Wolfgang Stöggl , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-08-14 08:27+0100\n" +"Last-Translator: Wolfgang Stoeggl \n" +"Language-Team: Deutsch \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.6.7\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Die Anwendung existiert nicht mehr" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Versuchter synchroner Aufruf an verbotener Stelle" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Unbekannte Signatur »%s« für RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Fehler beim Aufruf von getRoot für %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Fehler in GetItems, Sender=%s, Fehler=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_accessible_from_message wurde mit seltsamer " +#~ "Signatur %s aufgerufen" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_hyperlink_from_message wurde mit seltsamer " +#~ "Signatur %s aufgerufen" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: Unbekannte Signatur »%s« für AddAccessible\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: Es wurde eine Variante beim Holen von %s vom Interface %s " +#~ "erwartet; erhalten wurde %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Falcher Typ: erwartet wurde %s, erhalten wurde " +#~ "%c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Unbekanntes Interface %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "" +#~ "AT-SPI: 2 Werte wurden im Feld der Status erwartet; erhalten wurden %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Streamfähiger Inhalt ist nicht implementiert" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "atspi_event_listener_register_from_callback aufgerufen mit event_type NULL" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "Ungültige Signatur %s wurde für Signal %s von Interface %s erhalten\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Die Anzeige konnte nicht erlangt werden\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Der Bus der Barrierefreiheit wurde nicht gefunden - Der " +#~ "Sitzungsbus wird verwendet.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "" +#~ "AT-SPI: Verbindung mit dem Bus konnte nicht hergestellt werden: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Es konnte nicht am Bus registriert werden: %s\n" diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..4ea573c --- /dev/null +++ b/po/el.po @@ -0,0 +1,91 @@ +# Greek translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Michael Kotsarinis , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-03-07 11:54+0000\n" +"PO-Revision-Date: 2014-03-06 16:40+0200\n" +"Last-Translator: maria thukididu \n" +"Language-Team: team@gnome.gr\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.6.1\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Η εφαρμογή δεν υπάρχει πλέον" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "Απόπειρα συγχρονισμένης κλήσης όπου απαγορεύεται" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Άγνωστη υπογραφή %s για RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Σφάλμα κλήσης του getRoot για %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Σφάλμα στο GetItems, sender=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Κλήση του _atspi_dbus_return_accessible_from_message με περίεργη " +#~ "υπογραφή %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Κλήση του _atspi_dbus_return_hyperlink_from_message με περίεργη " +#~ "υπογραφή %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible με άγνωστη υπογραφή signature %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Αδυναμία λήψης της απεικόνισης\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Δεν βρέθηκε δίαυλος προσιτότητας - Χρήση του διαύλου συνεδρίας.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Αδυναμία σύνδεσης στο δίαυλο: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Αδυναμία εγγραφής στο δίαυλο: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: αναμενόταν μια μεταβλητή κατά τη λήψη του %s από τη διεπαφή %s· " +#~ "ελήφθη %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Λάθος τύπος: αναμενόταν %s, ελήφθη %c\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI: Ελήφθη σφάλμα: %s\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Άγνωστη διεπαφή %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: αναμενόταν 2 τιμές στον πίνακα καταστάσεων· ελήφθησαν %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Δεν έχει υλοποιηθεί η ροή περιεχομένου" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Ελήφθη μη έγκυρη υπογραφή %s για το σήμα %s από τη διεπαφή %s\n" diff --git a/po/en_CA.po b/po/en_CA.po new file mode 100644 index 0000000..b1277f3 --- /dev/null +++ b/po/en_CA.po @@ -0,0 +1,24 @@ +# English translations for at-spi package. +# Copyright (C) 2011 THE at-spi'S COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi package. +# Tiffany , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi 2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-09-16 19:03-0400\n" +"PO-Revision-Date: 2011-09-16 19:03-0400\n" +"Last-Translator: Tiffany \n" +"Language-Team: English\n" +"Language: en_CA\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:941 +#: ../atspi/atspi-misc.c:992 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "The application no longer exists" diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..d8f362f --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,91 @@ +# British English translationn of at-spi2-core +# Copyright (C) 2011 at-spi2-core'S COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Bruce Cowan , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2016-09-18 12:38+0200\n" +"Last-Translator: David King \n" +"Language-Team: British English \n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.6.1\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "The application no longer exists" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Attempted synchronous call where prohibited" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Unknown signature %s for RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Error calling getRoot for %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Error in GetItems, sender=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible with unknown signature %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Could not get the display\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI: Accessibility bus not found - Using session bus.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Couldn't connect to bus: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Couldn't register with bus: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Unknown interface %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: expected 2 values in states array; got %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Streamable content not implemented" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Got invalid signature %s for signal %s from interface %s\n" diff --git a/po/eo.po b/po/eo.po new file mode 100644 index 0000000..3212f05 --- /dev/null +++ b/po/eo.po @@ -0,0 +1,24 @@ +# Esperanto translation for at-spi2-core. +# Copyright (C) 2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Kristjan SCHMIDT , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-05-14 17:03+0000\n" +"PO-Revision-Date: 2011-05-15 15:32+0200\n" +"Last-Translator: Kristjan SCHMIDT \n" +"Language-Team: Esperanto \n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +#: ../atspi/atspi-misc.c:937 ../atspi/atspi-misc.c:988 +#: ../atspi/atspi-misc.c:1029 +msgid "The application no longer exists" +msgstr "La aplikaĵo ne plu ekzistas" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..666ad58 --- /dev/null +++ b/po/es.po @@ -0,0 +1,102 @@ +# Spanish translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Jorge González , 2011. +# Daniel Mustieles , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-02-05 13:08+0100\n" +"Last-Translator: Daniel Mustieles \n" +"Language-Team: Español \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Generator: Gtranslator 2.91.5\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "La aplicación ya no existe" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Se ha prohibido el intento de llamada síncrona" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: firma %s desconocida para RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: error al llamar a getRoot para %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: error en GetItems, emisor=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: llamada a _atspi_dbus_return_accessible_from_message con una " +#~ "firma %s extraña" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: llamada a _atspi_dbus_return_hyperlink_from_message con una firma " +#~ "%s extraña" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible con firma %s desconocida\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: no se pudo obtener la pantalla\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: no se encontró el bus de accesibilidad. Usando el bus de sesión.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: no se pudo conectar al bus: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: no se pudo registrar en el bus: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: se esperaba una variante al buscar %s de la interfaz %s; se " +#~ "obtuvo %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: tipo incorrecto: se esperaba %s, se obtuvo %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: interfaz %s desconocida" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "" +#~ "AT-SPI: se esperaban 2 valores en el array de estados; se obtuvo %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "El contenido de flujo distribuible no está implementado" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "se llamó a atspi_event_listener_register_from_callback con un event_type " +#~ "nulo" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "Se obtuvo una firma %s no válida para la señal %s de la interfaz %s\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI: error obtenido: %s\n" diff --git a/po/et.po b/po/et.po new file mode 100644 index 0000000..e1f67bd --- /dev/null +++ b/po/et.po @@ -0,0 +1,26 @@ +# Estonian translation for at-spi2-core. +# Copyright (C) 2012 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Mattias Põldaru , 2012, 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-03-15 03:48+0000\n" +"PO-Revision-Date: 2015-03-15 09:52+0300\n" +"Last-Translator: Mattias Põldaru \n" +"Language-Team: Estonian <>\n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Generator: Poedit 1.5.4\n" + +msgid "The application no longer exists" +msgstr "Seda rakendust pole enam olemas" + +msgid "Attempted synchronous call where prohibited" +msgstr "Üritati teha sünkroonne kutse, kuid see keelati" diff --git a/po/eu.po b/po/eu.po new file mode 100644 index 0000000..863613e --- /dev/null +++ b/po/eu.po @@ -0,0 +1,83 @@ +# Basque translation for at-spi2-core. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Iñaki Larrañaga Murgoitio , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-03-30 12:10+0200\n" +"PO-Revision-Date: 2014-03-30 12:12+0200\n" +"Last-Translator: Iñaki Larrañaga Murgoitio \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikazioa ez da gehiago existitzen" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "Dei sinkronizatuen saiakera debekatuta dago" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: RemoveAccessible-ren %s sinadura ezezaguna" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: errorea %s(r)en getRoot deitzean: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: errorea GetItems-en, bidaltzailea=%s, errorea=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_accessible_from_message deituta %s sinadura " +#~ "bitxiarekin" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_hyperlink_from_message deituta %s sinadura " +#~ "bitxiarekin" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible %s sinadura ezezagunarekin\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: aldagai bat espero zen %2$s interfazetik %1$s lortzean: %3$s " +#~ "lortuta\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: okerreko mota: %s espero zen, %c lortuta\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: %s interfaze ezezaguna" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: 2 balio espero ziren egoeraren matrizea; %d lortuta\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Korrontean igortzeko edukia ez dago inplementatuta" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "atspi_event_listener_register_from_callback deituta event_type NULUArekin" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "%2$s seinalearen baliogabeko %1$s sinadura lortu da %3$s interfazetik\n" diff --git a/po/fa.po b/po/fa.po new file mode 100644 index 0000000..d857288 --- /dev/null +++ b/po/fa.po @@ -0,0 +1,93 @@ +# Persian translation for at-spi2-core. +# Copyright (C) 2011 Iranian Free Software Users Group (IFSUG.org)translation team. +# This file is distributed under the same license as the at-spi2-core package. +# Arash Mousavi , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2015-09-16 23:23+0430\n" +"Last-Translator: Arash Mousavi \n" +"Language-Team: Persian \n" +"Language: fa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Generator: Poedit 1.8.4\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "برنامه دیگر وجود ندارد" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "تلاش برای تماس همزمان ممنوع است" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: امضا ناشناس %s برای RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: خطا در فراخوانی getRoot برای %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: خطا در GetItems، فرستنده=%s، خطا=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: فراخوانی _atspi_dbus_return_accessible_from_message همراه با امضا " +#~ "عجیب %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: فراخوانی _atspi_dbus_return_hyperlink_from_message همراه با امضا %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible همراه با امضا ناشناس %s\n" + +#~ msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: انتظار نوع دیگری در هنگام آوردن %s از رابط %s بود؛ اما %s دریافت شد\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: نوع اشتباه: مورد انتظار %s، دریافت شده %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: رابط ناشناس %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: در انتظار ۲ مقدار در حالات آریه بود؛ %Id دریافت شد\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "محتویات جریان‌پذیر پیاده نشده است" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "مورد atspi_event_listener_register_from_callback با یک event_type نوع NULL " +#~ "فراخوانده شد" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "یک امضا نادرست %s برای سیگنال %s از رابط %s دریافت شد\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: نمی‌توان نمایشگر را پیدا کرد\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: گذرگاه دسترسی‌پذیری قابل یافت نیست - درحال استفاده از گذرگاه نشست.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: عدم توانایی در اتصال به گذرگاه: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: عدم امکان در ثبت همراه گذرگاه: %s\n" diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 0000000..faf8a8c --- /dev/null +++ b/po/fi.po @@ -0,0 +1,28 @@ +# Finnish messages for at-spi2-core +# Copyright (C) 2011 Tommi Vainikainen +# This file is distributed under the same license as the package. +# Tommi Vainikainen , 2011. +# +# Gnome 2012-03 Finnish translation sprint participants: +msgid "" +msgstr "" +"" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-12-15 02:37+0000\n" +"PO-Revision-Date: 2012-03-12 08:36:41+0000\n" +"Last-Translator: Tommi Vainikainen \n" +"Language-Team: Finnish \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi\n" +"X-POT-Import-Date: 2012-02-19 13:23:54+0000\n" +"X-Generator: MediaWiki 1.20alpha (r113129); Translate 2012-03-02\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:985 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Sovellusta ei enää ole" + diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..6e1ba90 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,28 @@ +# French translation for at-spi2-core. +# Copyright (C) 2011 Listed translators +# This file is distributed under the same license as the at-spi2-core package. +# Claude Paroz , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-11 22:53+0100\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: GNOME French Team \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'application n'existe plus" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "La tentative d'appel synchrone est interdite" diff --git a/po/fur.po b/po/fur.po new file mode 100644 index 0000000..54b7bad --- /dev/null +++ b/po/fur.po @@ -0,0 +1,28 @@ +# Friulian translation for at-spi2-core. +# Copyright (C) 2013 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core gnome-3-8\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2016-03-23 15:57+0000\n" +"PO-Revision-Date: 2016-03-23 18:16+0100\n" +"Last-Translator: Fabio Tomat \n" +"Language-Team: Friulian \n" +"Language: fur\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.5\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1072 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Le aplicazion no esist plui" + +#: ../atspi/atspi-misc.c:1831 +msgid "Attempted synchronous call where prohibited" +msgstr "Proibît tentatîf di clamade sincrone" diff --git a/po/ga.po b/po/ga.po new file mode 100644 index 0000000..f69b8c1 --- /dev/null +++ b/po/ga.po @@ -0,0 +1,24 @@ +# Irish translations for at-spi2-core package. +# Copyright (C) 2013 Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Seán de Búrca , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core.master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-08-26 03:17-0600\n" +"PO-Revision-Date: 2013-08-26 03:19-0600\n" +"Last-Translator: Seán de Búrca \n" +"Language-Team: Irish \n" +"Language: ga\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=5; plural=n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : " +"4;\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:1085 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Níl an feidhmchlár ann a thuilleadh" diff --git a/po/gd.po b/po/gd.po new file mode 100644 index 0000000..df7e04b --- /dev/null +++ b/po/gd.po @@ -0,0 +1,30 @@ +# Scottish Gaelic translation for at-spi2-core. +# Copyright (C) 2016 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# GunChleoc , 2016. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2016-04-28 02:57+0000\n" +"PO-Revision-Date: 2016-04-28 14:53+0100\n" +"Last-Translator: GunChleoc \n" +"Language-Team: Fòram na Gàidhlig\n" +"Language: gd\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : " +"(n > 2 && n < 20) ? 2 : 3;\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1072 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Chan eil an aplacaid seo ann tuilleadh" + +#: ../atspi/atspi-misc.c:1831 +msgid "Attempted synchronous call where prohibited" +msgstr "Chaidh gairm shioncronaichte a dhiùltadh" diff --git a/po/gl.po b/po/gl.po new file mode 100644 index 0000000..d7a0cf4 --- /dev/null +++ b/po/gl.po @@ -0,0 +1,102 @@ +# Galician translations for at-spi package. +# Copyright (C) 2011 THE at-spi'S COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi package. +# Fran Diéguez , 2011. +# Fran Dieguez , 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi 2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-07 00:01+0100\n" +"PO-Revision-Date: 2014-02-07 00:01+0200\n" +"Last-Translator: Fran Dieguez \n" +"Language-Team: gnome-l10n-gl@gnome.org\n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "O aplicativo xa non existe" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Tentouse unha chamada síncrona onde estaba prohibida" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Sinatura %s descoñecida para RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Erro ao chamar a getRoot para %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Erro en GetItems, emisor=%s, erro=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamouse a _atspi_dbus_return_accessible_from_message cunha " +#~ "sinatura estraña %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamouse a _atspi_dbus_return_hyperlink_from_message cunha " +#~ "sinatura estraña %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible con sinatura %s descoñecida\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Non é posíbel obter a pantalla\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Non foi posíbel atopar o bus de accesibilidade - Usando o bus de " +#~ "sesión.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Non foi posíbel conectarse ao bus: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Non foi posíbel rexistrarse ao bus: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: agardábase unha variante ao obter %s desde a interface %s; porén " +#~ "obtívose %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Tipo incorrecto: esperábase %s, obtívose %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Interface %s descoñecida" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "" +#~ "AT-SPI: agardábanse 2 valores na matriz de estados; porén obtivéronse %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Contido en fluxo non implementado" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "chamouse a atspi_event_listener_register_from_callback con un event_type " +#~ "nulo" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "Obtívose unha sinatura non válida %s para o sinal %s desde a interface " +#~ "%s\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI: Obtívose o erro: %s\n" diff --git a/po/gu.po b/po/gu.po new file mode 100644 index 0000000..6fa0d65 --- /dev/null +++ b/po/gu.po @@ -0,0 +1,111 @@ +# translation of gu.po to Gujarati +# Gujarati translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Sweta Kothari , 2011. +msgid "" +msgstr "" +"Project-Id-Version: gu\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&component=general\n" +"POT-Creation-Date: 2011-02-07 18:52+0000\n" +"PO-Revision-Date: 2011-02-08 12:04+0530\n" +"Last-Translator: Sweta Kothari \n" +"Language-Team: Gujarati\n" +"Language: gu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible માટે અજ્ઞાત હસ્તાક્ષર %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s માટે getRoot ને કોલ કરતી વખતે ભૂલ: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems માં ભૂલ, sender=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "AT-SPI: વિચિત્ર હસ્તાક્ષર %s સાથે Called _atspi_dbus_return_accessible_from_message" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "AT-SPI: વિચિત્ર હસ્તાક્ષર %s સાથે Called _atspi_dbus_return_hyperlink_from_message" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: અજ્ઞાત હસ્તાક્ષર %s સાથે AddAccessible\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: દેખાવને મેળવી શક્યા નહિં\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: સુલભતા બસ મળી નથી - સત્ર બસને વાપરી રહ્યા છે.\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: બસ ને જોડી શક્યા નહિં: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: બસ સાથે રજીસ્ટર કરી શક્યા નહિં: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "કાર્યક્રમ લાંબા સમય સુધા અસ્તિત્વ ધરાવતુ નથી" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: ફેરફાર (ભિન્નતા) ની ઇચ્છા રાખેલ છે જ્યારે ઇન્ટરફેસ %s માંથી %s ને લાવી રહ્યા હોય; %s મળ્યુ\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: ખોટો પ્રકાર: %s ઇચ્છા રાખેલ છે, %c મળ્યુ\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: અજ્ઞાત ઇન્ટરફેસ %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: એરે જેવી સ્થિતિઓમાં 2 કિંમતોની ઇચ્છા રાખેલ છે; %d મળ્યુ\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "Streamable સમાવિષ્ટનું અમલીકરણ થયેલ નથી" + +#: ../atspi/atspi-event-listener.c:510 +msgid "called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "NULL event_type સાથે atspi_event_listener_register_from_callback કોલ થયેલ છે" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "ઇન્ટરફેસ %s માંથી સંકેત %s માટે અયોગ્ય હસ્તાક્ષર %s મળ્યુ\n" + diff --git a/po/he.po b/po/he.po new file mode 100644 index 0000000..771620b --- /dev/null +++ b/po/he.po @@ -0,0 +1,94 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Yaron Shahrabani , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-03-06 10:15+0200\n" +"PO-Revision-Date: 2014-03-06 10:15+0200\n" +"Last-Translator: Yosef Or Boczko \n" +"Language-Team: Gezer (Hebrew)\n" +"Language: he\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.0-beta4\n" +"X-Poedit-Language: Hebrew\n" +"X-Poedit-Country: ISRAEL\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Project-Style: default\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "The application no longer exists" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "Attempted synchronous call where prohibited" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Unknown signature %s for RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Error calling getRoot for %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Error in GetItems, sender=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible with unknown signature %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Could not get the display\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI: Accessibility bus not found - Using session bus.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Couldn't connect to bus: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Couldn't register with bus: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Unknown interface %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: expected 2 values in states array; got %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Streamable content not implemented" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Got invalid signature %s for signal %s from interface %s\n" diff --git a/po/hi.po b/po/hi.po new file mode 100644 index 0000000..b1fc96b --- /dev/null +++ b/po/hi.po @@ -0,0 +1,27 @@ +# translation of at-spi2-core.po.master.hi.po to Hindi +# Hindi translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# chandankumar(ciypro) , 2012. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core.po.master.hi\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-05-06 16:03+0000\n" +"PO-Revision-Date: 2012-03-26 15:34+0530\n" +"Last-Translator: chandankumar(ciypro) \n" +"Language-Team: Hindi \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.2\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:937 ../atspi/atspi-misc.c:988 +#: ../atspi/atspi-misc.c:1029 +msgid "The application no longer exists" +msgstr "अनुप्रयोग अब मौजूद नहीं है" + diff --git a/po/hr.po b/po/hr.po new file mode 100644 index 0000000..a808b12 --- /dev/null +++ b/po/hr.po @@ -0,0 +1,30 @@ +# Croatian translation for at-spi2-core. +# Copyright (C) 2016 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2016-09-21 16:49+0000\n" +"PO-Revision-Date: 2016-09-24 12:21+0200\n" +"Language-Team: Croatian \n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Last-Translator: gogo \n" +"X-Generator: Poedit 1.8.7.1\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1073 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikacija više ne postoji" + +#: ../atspi/atspi-misc.c:1832 +msgid "Attempted synchronous call where prohibited" +msgstr "Pokušaj usklađenog poziva gdje je zabranjeno" diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..d8b5b9a --- /dev/null +++ b/po/hu.po @@ -0,0 +1,99 @@ +# Hungarian translation of at-spi2-core +# Copyright (C) 2011. Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package +# +# Gabor Kelemen , 2011. +# Balázs Úr , 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-02-23 16:09+0100\n" +"Last-Translator: Balázs Úr \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.2\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Az alkalmazás már nem létezik" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Szinkronizációs hívást próbáltak, ahol tilos" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Ismeretlen aláírás (%s) a RemoveAccessible elemhez" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Hiba a getRoot hívásakor ehhez: %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Hiba a GetItems hívásban, küldő=%s, hiba=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: az _atspi_dbus_return_accessible_from_message furcsa aláírással " +#~ "lett meghívva: %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: az _atspi_dbus_return_hyperlink_from_message furcsa aláírással " +#~ "lett meghívva: %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: Az AddAccessible aláírása (%s) ismeretlen\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: A kijelző nem kérhető le\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Az akadálymentesítési busz nem található – a munkamenetbusz " +#~ "használata.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Nem lehet csatlakozni a buszhoz: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Nem lehet regisztrálni a buszon: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: %s lekérésekor a(z) %s felületről a várt változat helyett %s " +#~ "érkezett\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Hibás típus: a várt %s helyett %c érkezett\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Ismeretlen felület: %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: az állapottömbben a várt 2 érték helyett %d volt\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "A szórható tartalom nincs megvalósítva" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "az atspi_event_listener_register_from_callback NULL értékű event_type-pal " +#~ "hívva" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "Érvénytelen aláírás (%s) érkezett a(z) %s szignálhoz a(z) %s felületről\n" diff --git a/po/id.po b/po/id.po new file mode 100644 index 0000000..1254f7e --- /dev/null +++ b/po/id.po @@ -0,0 +1,30 @@ +# Indonesian translation of at-spi2-core +# Copyright (C) 2011 THE at-spi2-core'S COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Andika Triwidada , 2011. +# Dirgita , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-08 15:47+0000\n" +"PO-Revision-Date: 2014-02-09 06:38+0700\n" +"Last-Translator: Andika Triwidada \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Poedit 1.6.3\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikasi tak ada lagi" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Mencoba pemanggilan sinkron dimana dilarang" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..0e19749 --- /dev/null +++ b/po/it.po @@ -0,0 +1,30 @@ +# Italian translation for at-spi2-core. +# Copyright (C) 2011, 2014 Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Luca Ferretti , 2011. +# Milo Casagrande , 2014 +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-09 12:33+0100\n" +"Last-Translator: Milo Casagrande \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.6.4\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'applicazione non esiste più" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Proibito tentativo di chiamata sincrona" diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000..c444871 --- /dev/null +++ b/po/ja.po @@ -0,0 +1,25 @@ +# Japanese translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Hideki Yamane , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-10-31 21:26+0000\n" +"PO-Revision-Date: 2011-11-06 21:59+0900\n" +"Last-Translator: Hideki Yamane \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:941 +#: ../atspi/atspi-misc.c:992 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "そのアプリケーションは存在しません" diff --git a/po/kk.po b/po/kk.po new file mode 100644 index 0000000..eae37e7 --- /dev/null +++ b/po/kk.po @@ -0,0 +1,28 @@ +# Kazakh translation for at-spi2-core. +# Copyright (C) 2014 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Baurzhan Muftakhidinov , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-10-16 16:03+0000\n" +"PO-Revision-Date: 2014-10-19 15:13+0600\n" +"Last-Translator: Baurzhan Muftakhidinov \n" +"Language-Team: Kazakh \n" +"Language: kk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Қолданба енді жоқ болып тұр" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Рұқсат етілмеген жерде синхронды шақырулар талабы жасалды" diff --git a/po/km.po b/po/km.po new file mode 100644 index 0000000..dc0e287 --- /dev/null +++ b/po/km.po @@ -0,0 +1,25 @@ +# translation of at-spi2-core.master.po to Khmer +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Khoem Sokhem , 2012. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core.master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-01-05 21:00+0000\n" +"PO-Revision-Date: 2012-01-13 10:35+0700\n" +"Last-Translator: Khoem Sokhem \n" +"Language-Team: Khmer \n" +"Language: km\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"X-Language: km-KH\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:941 +#: ../atspi/atspi-misc.c:992 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "The application no longer exists" + diff --git a/po/kn.po b/po/kn.po new file mode 100644 index 0000000..27b44c5 --- /dev/null +++ b/po/kn.po @@ -0,0 +1,123 @@ +# Kannada translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Shankar Prasad , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=at-spi&component=general\n" +"POT-Creation-Date: 2011-02-08 06:35+0000\n" +"PO-Revision-Date: 2011-02-08 16:09+0530\n" +"Last-Translator: Shankar Prasad \n" +"Language-Team: Kannada \n" +"Language: kn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible ಗಾಗಿ ಗೊತ್ತಿರದ ಸಹಿ %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s ಗಾಗಿ getRoot ಅನ್ನು ಕರೆಯುವಲ್ಲಿ ದೋಷ ಉಂಟಾಗಿದೆ: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems ನಲ್ಲಿ ದೋಷ ಕಂಡುಬಂದಿದೆ, ಕಳುಹಿಸಿದವರು=%s, ದೋಷ=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: %s ಎಂಬ ವಿಚಿತ್ರವಾದ ಸಹಿಯೊಂದಿಗೆ " +"_atspi_dbus_return_accessible_from_message ಅನ್ನು ಕರೆಯಲಾಗಿದೆ" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: %s ಎಂಬ ವಿಚಿತ್ರವಾದ ಸಹಿಯೊಂದಿಗೆ " +"_atspi_dbus_return_hyperlink_from_message ಅನ್ನು ಕರೆಯಲಾಗಿದೆ" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: ಗೊತ್ತಿರದ ಸಹಿ %s ಯೊಂದಿಗೆ RemoveAccessible \n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: ಪ್ರದರ್ಶಕವನ್ನು ಪಡೆಯಲಾಗಿಲ್ಲ\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: ನಿಲುಕಣಾ ಬಸ್ ಕಂಡುಬಂದಿಲ್ಲ - ಅಧಿವೇಶನದ ಬಸ್‌ ಅನ್ನು ಬಳಸಲಾಗುತ್ತಿದೆ.\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: ಬಸ್‌ನೊಂದಿಗೆ ಸಂಪರ್ಕಸಾಧಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: ಬಸ್‌ನೊಂದಿಗೆ ನೋಂದಾಯಿಸಲು ಸಾಧ್ಯವಾಗಿಲ್ಲ: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "ಅನ್ವಯವು ಇನ್ನು ಮುಂದೆ ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "" +"AT-SPI: %s ಅನ್ನು %s ಎಂಬ ಸಂಪರ್ಕಸಾಧನದಿಂದ ಪಡೆದುಕೊಳ್ಳುವಾಗ ಒಂದು ವೇರಿಯಂಟ್ ಅನ್ನು " +"ನಿರೀಕ್ಷಿಸಲಾಗಿತ್ತು; %s ದೊರೆತಿದೆ\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "" +"atspi_dbus_get_property: ತಪ್ಪಾದ ಬಗೆ: %s ಅನ್ನು ನಿರೀಕ್ಷಿಸಲಾಗಿತ್ತು, %c " +"ದೊರೆತಿದೆ\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: ಗೊತ್ತಿರದ ಸಂಪರ್ಕಸಾಧನ %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "" +"AT-SPI: ಸ್ಥಿತಿಗಳ ವ್ಯೂಹದಿಂದ 2 ಮೌಲ್ಯಗಳನ್ನು ನಿರೀಕ್ಷಿಸಲಾಗಿತ್ತು; %d ದೊರೆತಿದೆ\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "ಸ್ಟ್ರೀಮ್‌ ಮಾಡಬಹುದಾದ ವಿಷಯವನ್ನು ಅನ್ವಯಿಸಲಾಗಿಲ್ಲ" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"atspi_event_listener_register_from_callback ಅನ್ನು ಒಂದು NULL event_type ಇಂದ " +"ಕರೆಯಲಾಗಿದೆ" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "ಮಾನ್ಯವಾದ ಸಹಿ %s ದೊರೆತಿದೆ, %s ಎಂಬ ಸಂಜ್ಞೆಗಾಗಿ, %s ಎಂಬ ಸಂಪರ್ಕಸಾಧನದಿಂದ\n" + diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 0000000..04a55b7 --- /dev/null +++ b/po/ko.po @@ -0,0 +1,28 @@ +# Korean translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Changwoo Ryu , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-07 01:38+0900\n" +"Last-Translator: Changwoo Ryu \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "프로그램이 더 이상 없습니다" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "동기식 호출을 시도했으나 금지되어 있습니다" diff --git a/po/lt.po b/po/lt.po new file mode 100644 index 0000000..776ad0c --- /dev/null +++ b/po/lt.po @@ -0,0 +1,30 @@ +# Lithuanian translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Aurimas Černius , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-21 15:45+0000\n" +"PO-Revision-Date: 2014-02-21 22:05+0200\n" +"Last-Translator: Aurimas Černius \n" +"Language-Team: Lithuanian \n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Programos nebėra" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "Bandyta atlikti sinchroninį kvietimą, kur tai draudžiama" diff --git a/po/lv.po b/po/lv.po new file mode 100644 index 0000000..3a14aa4 --- /dev/null +++ b/po/lv.po @@ -0,0 +1,92 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Rudolfs , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-07 13:52+0200\n" +"Last-Translator: Rūdolfs Mazurs \n" +"Language-Team: Latvian \n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Šī lietotne vairs neeksistē" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Tika aizliegti mēģinātie sinhronie izsaukumi" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Nezināms paraksts %s priekš RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Kļūda, izsaucot getRoot priekš %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems kļūda, sūtītājs=%s, kļūda=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Izsaukts _atspi_dbus_return_accessible_from_message ar dīvainu " +#~ "parakstu %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Izsaukts _atspi_dbus_return_hyperlink_from_message ar dīvainu " +#~ "parakstu %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible ar nezināmu parakstu %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Neizdevās iegūt displeju\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI: Pieejamības kopne nav atrasta – izmanto sesijas kopni.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Neizdevās savienoties ar kopni: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Neizdevās reģistrēt ar kopni: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: gaidīja variantu, kad saņēma %s no saskarnes %s; saņēma %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Nepareizs tips: gaidīja %s, saņēma %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Nezināma saskarne %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: stāvokļa masīvā gaidīja 2 vērtības; saņēma %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Straumējams saturs nav realizēts" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "izsauca atspi_event_listener_register_from_callback ar NULL event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Saņēma nederīgu parakstu %s signālam %s no saskarnes %s\n" diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..ff50cc2 --- /dev/null +++ b/po/meson.build @@ -0,0 +1,3 @@ +i18n = import('i18n') + +i18n.gettext('at-spi2-core', preset: 'glib') diff --git a/po/ml.po b/po/ml.po new file mode 100644 index 0000000..e3212d0 --- /dev/null +++ b/po/ml.po @@ -0,0 +1,29 @@ +# Malayalam translation for at-spi2-core. +# Copyright (C) 2012 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Anish A , 2012. +# Anish Sheela , 2017. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-06-27 21:34+0000\n" +"PO-Revision-Date: 2017-08-08 13:02+0530\n" +"Last-Translator: Anish Sheela \n" +"Language-Team: Swatantra Malayalam Computing \n" +"Language: ml\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: atspi/atspi-component.c:326 atspi/atspi-misc.c:1073 atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "ഈ പ്രയോഗം ഇപ്പോള്‍ നിലവിലില്ല" + +#: atspi/atspi-misc.c:1843 +msgid "Attempted synchronous call where prohibited" +msgstr "ചെയ്യാന്‍ നോക്കിയ സിങ്ക്റണസ് കോളുകള്‍ തടയപ്പെട്ടു" diff --git a/po/mr.po b/po/mr.po new file mode 100644 index 0000000..3dc7f23 --- /dev/null +++ b/po/mr.po @@ -0,0 +1,93 @@ +# translation of mr.po to Marathi +# Marathi translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Sandeep Shedmake , 2011. +msgid "" +msgstr "" +"Project-Id-Version: mr\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-03-23 10:25+0000\n" +"PO-Revision-Date: 2011-03-23 16:16+0530\n" +"Last-Translator: Sandeep Shedmake \n" +"Language-Team: Marathi \n" +"Language: mr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible करीता अपरिचीत स्वाक्षरी %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s करीता getRoot कॉल करतेवेळी त्रुटी: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems मध्ये त्रुटी आढळली, sender=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "AT-SPI: अपरिचीत स्वाक्षरी %s सह _atspi_dbus_return_accessible_from_message कॉल केले" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "AT-SPI: अपरिचीत स्वाक्षरी %s सह _atspi_dbus_return_hyperlink_from_message कॉल केले" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: अपरिचीत स्वाक्षरी %s सह AddAccessible\n" + +#: ../atspi/atspi-misc.c:934 ../atspi/atspi-misc.c:985 +#: ../atspi/atspi-misc.c:1026 +msgid "The application no longer exists" +msgstr "ॲप्लिकेशन यापुढे अस्तित्वात नाही" + +#: ../atspi/atspi-misc.c:1062 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: संवाद %2$s पासून %1$s प्राप्त करतेवेळी वेरिएंट अपकेक्षीत; %3$s प्राप्त झाले\n" + +#: ../atspi/atspi-misc.c:1068 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: चुकिचे प्रकार: अपेक्षीत %s, %c प्राप्त झाले\n" + +#: ../atspi/atspi-misc.c:1211 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: अपरिचीत संवाद %s" + +#: ../atspi/atspi-misc.c:1231 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: 2 मूल्ये अपक्षेपीत स्टेट्स् अरेमध्ये ; %d प्राप्त केले\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "स्ट्रिमजोगी अंतर्भूत माहिती लागू केले नाही" + +#: ../atspi/atspi-event-listener.c:510 +msgid "called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "NULL event_type सह atspi_event_listener_register_from_callback कॉल केले" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "संवाद %3$s पासून संकेत %2$s करीता अवैध स्वाक्षरी %1$s प्राप्त झाले\n" + diff --git a/po/ms.po b/po/ms.po new file mode 100644 index 0000000..2cbc1c6 --- /dev/null +++ b/po/ms.po @@ -0,0 +1,28 @@ +# Malay translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Ahmed Noor Kader Mustajir Md Eusoff , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-11 19:31+0000\n" +"PO-Revision-Date: 2014-09-16 16:06+0800\n" +"Last-Translator: Umarzuki Bin Mochlis Moktar \n" +"Language-Team: Malay \n" +"Language: ms\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikasi telah tiada" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Panggilan segerak yang dicuba adalah terlarang" diff --git a/po/nb.po b/po/nb.po new file mode 100644 index 0000000..860ee1b --- /dev/null +++ b/po/nb.po @@ -0,0 +1,26 @@ +# Norwegian bokmål translation of at-spi2-core. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Kjartan Maraas , 2011-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core 2.1.x\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-02-10 08:06+0100\n" +"PO-Revision-Date: 2014-02-10 08:07+0100\n" +"Last-Translator: Kjartan Maraas \n" +"Language-Team: Norwegian bokmål \n" +"Language: nb\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Programmet eksisterer ikke lenger" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Forsøkt synkront kall ble hindret" diff --git a/po/ne.po b/po/ne.po new file mode 100644 index 0000000..e2673b0 --- /dev/null +++ b/po/ne.po @@ -0,0 +1,28 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Gnome Nepali Translation Project\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-07-03 20:15+0000\n" +"PO-Revision-Date: 2017-07-25 15:09+0545\n" +"Language-Team: Nepali Translation Team \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.3\n" +"Last-Translator: Pawan Chitrakar \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: ne_NP\n" + +#: atspi/atspi-component.c:326 atspi/atspi-misc.c:1073 atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "अनुप्रयोग अब उप्रान्त उपलब्ध छैन" + +#: atspi/atspi-misc.c:1843 +msgid "Attempted synchronous call where prohibited" +msgstr "निषेधित भए सिंक्रोनस कल कोशिश गर्नुहोस्" diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..0fe1fa6 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,86 @@ +# Dutch translation for at-spi2-core +# +# This file is distributed under the same license as the at-spi2-core package. +# +# Wouter Bolsterlee , 2011 +# +# Dit is echt een verschrikkelijke module: alleen maar technische termen die +# totaal onbegrijpelijk zijn. — Wouter +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=at-spi2-core\n" +"POT-Creation-Date: 2017-09-04 22:34+0000\n" +"PO-Revision-Date: 2015-05-26 17:44+0100\n" +"Last-Translator: Nathan Follens \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.4\n" + +#: atspi/atspi-component.c:326 atspi/atspi-misc.c:1073 atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "De toepassing bestaat niet meer" + +#: atspi/atspi-misc.c:1850 +msgid "Attempted synchronous call where prohibited" +msgstr "Synchrone oproep geprobeerd waar verboden" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: onbekende signature ‘%s’ voor RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Fout bij aanroep van getRoot voor %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Fout in GetItems, sender=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_accessible_from_message aangeroepen met " +#~ "vreemde signature %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_hyperlink_from_message aangeroepen met vreemde " +#~ "signature %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible met onbekende signature %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: een variant verwacht bij opvragen van %s van interface %s; %s " +#~ "verkregen\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Verkeerde type: %s verwacht, %c verkregen\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Onbekende interface %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: 2 waardes verwacht in ‘states array’, %d verkregen\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "‘Streamable content’ niet geïmplementeerd" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "atspi_event_listener_register_from_callback aangeroepn met een NULL " +#~ "event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Ongeldige signature %s ontvangen voor signaal %s van interface %s\n" diff --git a/po/oc.po b/po/oc.po new file mode 100644 index 0000000..7385b86 --- /dev/null +++ b/po/oc.po @@ -0,0 +1,31 @@ +# Occitan translation for at-spi2-core. +# Copyright (C) 2011 Listed translators +# This file is distributed under the same license as the at-spi2-core package. +# Claude Paroz , 2011. +# Cédric Valmary (Tot en òc) , 2015. +# Cédric Valmary (totenoc.eu) , 2016. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2016-05-23 23:38+0000\n" +"PO-Revision-Date: 2016-05-29 20:29+0200\n" +"Last-Translator: Cédric Valmary (totenoc.eu) \n" +"Language-Team: Tot En Òc\n" +"Language: oc\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1073 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "L'aplicacion existís pas mai" + +#: ../atspi/atspi-misc.c:1832 +msgid "Attempted synchronous call where prohibited" +msgstr "La temptativa d'apèl sincròn es interdita" diff --git a/po/or.po b/po/or.po new file mode 100644 index 0000000..eaed22d --- /dev/null +++ b/po/or.po @@ -0,0 +1,121 @@ +# Oriya translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Manoj Kumar Giri , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=at-spi&component=general\n" +"POT-Creation-Date: 2011-02-12 19:29+0000\n" +"PO-Revision-Date: 2011-03-17 15:23+0530\n" +"Last-Translator: Manoj Kumar Giri \n" +"Language-Team: Oriya \n" +"Language: or\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible ପାଇଁ ଅଜଣା ହସ୍ତାକ୍ଷର %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s ପାଇଁ ତ୍ରୁଟି ଡାକ getRoot: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems ରେ ତ୍ରୁଟି, ପ୍ରେରକ=%s, ତ୍ରୁଟି=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: ଅଜ୍ଞାତ ହସ୍ତାକ୍ଷର %s ବିଶିଷ୍ଟ Called " +"_atspi_dbus_return_accessible_from_message" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: ଅଜ୍ଞାତ ହସ୍ତାକ୍ଷର %s ବିଶିଷ୍ଟ Called " +"_atspi_dbus_return_hyperlink_from_message" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: ଅଜ୍ଞାତ ହସ୍ତାକ୍ଷର %s ସହିତ AddAccessible\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: ପ୍ରଦର୍ଶନୀ ପାଇଲା ନାହିଁ\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: ଅଭିଗମ୍ୟ ବସ ମିଳିଲା ନାହିଁ - ଅଧିବେଶନ ବସକୁ ବ୍ୟବହାର କରି।\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: ବସ: %s ସହିତ ସଂଯୁକ୍ତ ହୋଇପାରିଲା ନାହିଁ\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: ବସ: %s ସହିତ ପଞ୍ଜିକରଣ କରିପାରିଲା ନାହିଁ\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "ଏହି ପ୍ରୟୋଗଟି ବର୍ତ୍ତମାନ ନାହିଁ" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "" +"AT-SPI: %s କୁ ଅନ୍ତରାପୃଷ୍ଠ %s ରୁ କାଢ଼ିବା ସମୟରେ ଗୋଟିଏ ପ୍ରାଚଳକୁ ଆଶାକରାଯିଥିଲା; " +"%s ମିଳିଲା\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: ଭୁଲ ପ୍ରକାର: %s କୁ ଆଶାକରାଯାଇଥିଲା, %c ମିଳିଲା\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: ଅଜଣା ଅନ୍ତରାପ୍ରୁଷ୍ଠ %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: ଆରେରେ 2 ଟି ମୂଲ୍ୟ ଆଶାକରାଯାଇଥିଲା; %d ମିଳିଲା\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "କଢ଼ାଯୋଗ୍ଯ ବିଷୟବସ୍ତୁକୁ କାର୍ଯ୍ୟକାରୀ କରାଯାଇନାହିଁ" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"atspi_event_listener_register_from_callback କୁ ଗୋଟିଏ NULL event_type ସହିତ " +"ଡକା ଯାଇଛି" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "ସଙ୍କେତ %s ପାଇଁ ଅନ୍ତରାପୃଷ୍ଠ %s ରୁ ଅବୈଧ ହସ୍ତାକ୍ଷର %s ପାଇଛି\n" + + diff --git a/po/pa.po b/po/pa.po new file mode 100644 index 0000000..5453c10 --- /dev/null +++ b/po/pa.po @@ -0,0 +1,91 @@ +# Punjabi translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# A S Alam , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-09-21 08:49-0500\n" +"Last-Translator: A S Alam \n" +"Language-Team: Punjabi/Panjabi \n" +"Language: pa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.5\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "ਐਪਲੀਕੇਸ਼ਨ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ ਹੈ" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "ਸੈਕਰੋਨਾਈਸ ਕਾਲ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ, ਜਿੱਥੇ ਪਾਬੰਦੀ ਹੈ" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: RemoveAccessible ਲਈ ਅਣਜਾਣ %s ਦਸਤਖਤ" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: %s ਲਈ getRoot ਦੌਰਾਨ ਗਲਤੀ: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems ਵਿੱਚ ਗਲਤੀਆਂ, sender=%s, ਗਲਤੀ=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message ਅਜੀਬ ਦਸਤਖਤ %s " +#~ "ਨਾਲ" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_hyperlink_from_message ਅਜੀਬ ਦਸਤਖਤ %s ਨਾਲ ਕਾਲ " +#~ "ਕੀਤਾ" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: ਅਣਜਾਣ ਦਸਤਖਤ %s ਨਾਲ AddAccessible\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "AT-SPI: ਵੇਰੀਏਟ ਦੀ ਲੋੜ ਸੀ, ਜੋ ਕਿ %2$s ਇੰਟਰਫੇਸ ਤੋਂ %1$s ਲੈ ਸਕਦਾ; ਮਿਲਿਆ %3$s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: ਗਲਤ ਕਿਸਮ: ਲੋੜ ਸੀ %s, ਮਿਲਿਆ %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: ਅਣਜਾਣ ਇੰਟਰਫੇਸ %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: states ਅਰੇ 'ਚ 2 ਮੁੱਲ ਚਾਹੀਦੇ ਸਨ; ਮਿਲੇ %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "ਸਟਰੀਮ-ਯੋਗ ਸਮੱਗਰੀ ਹਾਲੇ ਸਥਾਪਤ ਨਹੀਂ" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "atspi_event_listener_register_from_callback NULL event_type ਨਾਲ ਕਾਲ ਕੀਤਾ" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "ਇੰਟਰਫੇਸ %3$s ਤੋਂ %2$s ਸਿਗਨਲ ਲਈ ਗਲਤ ਦਸਤਖਤ %1$s ਮਿਲਿਆ\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: ਡਿਸਪਲੇਅ ਨਹੀਂ ਮਿਲਿਆ\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI: ਅਸੈਸਬਿਲਟੀ ਬਸ ਨਹੀਂ ਲੱਭੀ - ਸ਼ੈਸ਼ਨ ਬਸ ਦੀ ਵਰਤੋਂ।\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: ਬਸ ਨਾਲ ਕੁਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: ਬਸ ਨਾਲ ਰਜਿਸਟਰ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ: %s\n" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..0682229 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,30 @@ +# Polish translation for at-spi2-core. +# Copyright © 2003-2014 the at-spi2-core authors. +# This file is distributed under the same license as the at-spi2-core package. +# Artur Flinta , 2003. +# Piotr Drąg , 2011-2014. +# Aviary.pl , 2011-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-08-22 20:42+0200\n" +"PO-Revision-Date: 2014-03-02 18:35+0100\n" +"Last-Translator: Piotr Drąg \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1073 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Program już nie istnieje" + +#: ../atspi/atspi-misc.c:1832 +msgid "Attempted synchronous call where prohibited" +msgstr "Próbowano synchronicznego wywołania tam, gdzie jest to zabronione" diff --git a/po/pt.po b/po/pt.po new file mode 100644 index 0000000..abe1ff6 --- /dev/null +++ b/po/pt.po @@ -0,0 +1,96 @@ +# Portuguese translation for at-spi2-core. +# Copyright © 2011, 2014 at-spi2-core +# This file is distributed under the same license as the at-spi2-core package. +# Duarte Loreto , 2011, 2014. +# Pedro Albuquerque , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: 3.12\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-06-08 02:51+0000\n" +"PO-Revision-Date: 2015-06-24 06:27+0100\n" +"Last-Translator: Pedro Albuquerque \n" +"Language-Team: Português \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "A aplicação já não existe" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Tentada uma chamada síncrona onde é proibida" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Assinatura %s desconhecida para RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Erro ao invocar getRoot para %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Erro em GetItems, invocador=%s, erro=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamada de _atspi_dbus_return_accessible_from_message com " +#~ "assinatura incomun %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamada de _atspi_dbus_return_hyperlink_from_message com " +#~ "assinatura incomun %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible com assinatura %s desconhecida\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Incapaz de obter o ecrã\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Incapaz de encontrar o canal de acessibilidade - A utilizar o " +#~ "canal de sessão.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Incapaz de se ligar ao canal: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Incapaz de se registar no canal: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: esperada uma variante ao obter %s do interface %s; obtida %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Tipo incorrecto: esperado %s, obtido %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Interface %s desconhecido" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: esperados 2 valores no vector de estados; obtidos %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Conteúdo em fluxo (stream) não está implementado" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "invocação de atspi_event_listener_register_from_callback com event_type " +#~ "NULL" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Obtida assinatura %s inválida para o sinal %s do interface %s\n" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..0cdbeed --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,84 @@ +# Brazilian Portuguese translation for at-spi2-core. +# Copyright (C) 2014 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Enrico nicoletto , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-02-04 13:14-0300\n" +"Last-Translator: Enrico Nicoletto \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 1.6.3\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Este aplicativo não existe mais" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "A tentativa de chamadas síncronas foram proibidas" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Assinatura %s desconhecida para RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Erro ao chamar getRoot para %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Erro em GetItems, remetente=%s, erro=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamada a _atspi_dbus_return_accessible_from_message com " +#~ "assinatura %s estranha" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Chamada a _atspi_dbus_return_hyperlink_from_message com " +#~ "assinatura %s estranha" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible com assinatura %s desconhecida\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: esperava-se uma variante ao obter %s a partir da interface %s; " +#~ "foi obtido %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: Tipo errado: era esperado %s, foi obtido %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Interface %s desconhecida" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: esperava-se 2 valores no vetor de estados; foi obtido %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Não foi implementado o conteúdo em fluxo" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "chamda a atspi_event_listener_register_from_callback com um event_type " +#~ "NULO" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "Foi obtido a assinatura %s inválida para o sinal %s da interface %s\n" diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 0000000..8f504fe --- /dev/null +++ b/po/ro.po @@ -0,0 +1,98 @@ +# Romanian translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Lucian Adrian Grijincu , 2011. +# Daniel Șerbănescu , 2015. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2015-06-22 20:11+0200\n" +"Last-Translator: Daniel Șerbănescu \n" +"Language-Team: Gnome Romanian Translation Team\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2);;\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplicația nu mai există" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "S-a încercat un apel sincron unde a fost interzis" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Semnătura %s este necunoscută pentru RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Eroare la apelul getRoot pentru %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Eroare în GetItems, sender=%s, error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Apelat _atspi_dbus_return_accessible_from_message cu semnătura " +#~ "ciudată %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Apelat _atspi_dbus_return_hyperlink_from_message cu semnătura " +#~ "ciudată %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible cu semnătură necunoscută %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Nu s-a putut obține afișajul\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Magistrala de accesibilitate nu a fost găsită - Se folosește " +#~ "magistrala de sistem.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Nu s-a putut realiza conexiunea la magistrală: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Nu s-a putut realiza înregistrarea la magistrală: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: se aștepta o variantă când s-a preluat %s din interfața %s; s-a " +#~ "primit %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property: Tip greșit: se aștepta %s, s-a primit %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Interfață necunoscută %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: se așteptau 2 valori în vectorul de stare; s-au primit %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Conținutul ce poate fi trimis ca flux nu este implementat" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "apelat atspi_event_listener_register_from_callback cu event_type=NULL" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "" +#~ "S-a primit semnătura validă %s pentru semnalul %s de la interfața %s\n" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..3d5c167 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,98 @@ +# Russian translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Yuri Myasoedov , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-11 15:59+0300\n" +"Last-Translator: Yuri Myasoedov \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Приложение больше не существует" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Попытка сделать синхронный вызов там, где это запрещено" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: неизвестная подпись %s для RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: ошибка вызова getRoot для %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: ошибка в GetItems, отправитель=%s, ошибка=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_accessible_from_message вызвано с " +#~ "подозрительной подписью %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: _atspi_dbus_return_hyperlink_from_message вызвано с " +#~ "подозрительной подписью %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: AddAccessible с неизвестной подписью %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: не удалось получить доступ к экрану\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: шина специальных возможностей не найдена; используется шина " +#~ "сеансов.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: не удалось подключиться к шине: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: не удалось выполнить регистрацию на шине: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: ожидалось получить тип variant при получении %s из интерфейса %s; " +#~ "получено — %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: неверный тип: ожидалось — %s, получено — %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: неизвестный интерфейс %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "" +#~ "AT-SPI: ожидалось получить 2 значения в массиве состояний; получено — %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Потоковое содержание не реализовано" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "atspi_event_listener_register_from_callback вызвано с нулевым event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Получена недопустимая подпись %s для сигнала %s из интерфейса %s\n" diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 0000000..dea424f --- /dev/null +++ b/po/sk.po @@ -0,0 +1,29 @@ +# Slovak translation for at-spi2-core. +# Copyright (C) 2012 Free Software Foundation, Inc +# This file is distributed under the same license as the at-spi2-core package. +# Peter Mráz , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2015-02-28 03:49+0000\n" +"PO-Revision-Date: 2015-02-28 13:16+0100\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" +"X-Generator: Poedit 1.7.4\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Aplikácia už neexistuje" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Pokus o synchrónne volanie tam, kde je zakázané" diff --git a/po/sl.po b/po/sl.po new file mode 100644 index 0000000..38365f4 --- /dev/null +++ b/po/sl.po @@ -0,0 +1,102 @@ +# Slovenian translations for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Ime priimek , 2011-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-28 15:45+0000\n" +"PO-Revision-Date: 2014-02-28 23:11+0100\n" +"Last-Translator: Matej Urbančič \n" +"Language-Team: Slovenian GNOME Translation Team \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Program ne obstaja več" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "Poskus usklajevanja klicev je prepovedan" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: neznan podpis %s za predmet RemoveAccessible" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: napaka klicanja predmeta getRoot za %s: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: napaka v predmetu GetItems, pošiljatelj=%s, napaka=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: predmet called_atatspi_dbus_return_accessible_from_message je " +#~ "izveden z nenavadnim podpisom %s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: predmet called _atspi_dbus_return_hyperlink_from_message je " +#~ "izveden z nenavadnim podpisom %s" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: predmet AddAccessible je izveden z neznanim podpisom %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: ni mogoče pridobiti zaslona\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: vodila dostopnosti ni mogoče najti; uporabljeno bo vodilo seje.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: ni se mogoče povezati z vodilom: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: ni se mogoče vpisati na vodilu: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: pričakovana vrednost med pridobivanjem %s z vmesnika %s; " +#~ "pridobljeno %s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "atspi_dbus_get_property: neveljavna vrsta: pričakovana je vrednost %s, " +#~ "pridobljena pa %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: neznan vmesnik %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: pričakovani sta 2 vrednosti v polju stanj; pridobljeno %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Ni podpore za pretočno vsebino" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "predmet atspi_event_listener_register_from_callback je klican s prazno " +#~ "vrednostjo možnosti event_type" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Pridobljen neveljaven podpis %s za signal %s z vmesnika %s\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI: pridobljena napaka: %s\n" diff --git a/po/sq.po b/po/sq.po new file mode 100644 index 0000000..e54a5d0 --- /dev/null +++ b/po/sq.po @@ -0,0 +1,114 @@ +# Albanian translation for at-spi2-core. +# Copyright (C) 2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Laurent Dhima , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-02-08 19:14+0100\n" +"PO-Revision-Date: 2011-02-08 19:30+0200\n" +"Last-Translator: Laurent Dhima \n" +"Language-Team: gnome-albanian-perkthyesit@lists.sourceforge.net\n" +"Language: sq\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: Firmë e panjohur %s për RemoveAccessible" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: Gabim gjatë thirjes getRoot për %s: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: Gabim në GetItems, sender=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: Është përdorur _atspi_dbus_return_accessible_from_message me firmë " +"të dyshimtë %s" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: Është përdorur _atspi_dbus_return_hyperlink_from_message me firmë të " +"dyshimtë %s" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: AddAccessible me firmë të panjohur %s\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: E pamundur marrja e ekranit\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: Bus i açesibilitetit nuk u gjet - Po përdoret bus i seancës.\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: E pamundur lidhja me bus: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: I pamundur regjistrimi me bus: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "Aplikativi nuk ekziston më" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: pritej një variant gjatë marrjes së %s nga interfaqja %s; u mor %s\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: Lloj i gabuar: pritej %s, u mor %c\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: Interfaqe e panjohur %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: priteshin 2 vlera në matricën e gjëndjes; u mor %d\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "Përmbajtja streamable nuk është implementuar" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"është thirrur atspi_event_listener_register_from_callback me një event_type " +"NULL" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "U mor firma e pavlefshme %s për sinjalin %s nga interfaqja %s\n" diff --git a/po/sr.po b/po/sr.po new file mode 100644 index 0000000..58a4d7d --- /dev/null +++ b/po/sr.po @@ -0,0 +1,93 @@ +# Мирослав Николић , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-15 11:09+0200\n" +"Last-Translator: Мирослав Николић \n" +"Language-Team: Serbian \n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " +"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Програм не постоји више" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Покушан је усаглашени позив где је забрањен" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "АТ-СПИ: Непознат потпис „%s“ за „Уклони доступног“" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "АТ-СПИ: Грешка позивајући „набави Корен“ за „%s“: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "АТ-СПИ: Грешка у „Набави ставку“, пошиљалац=„%s“, грешка=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "АТ-СПИ: Позван „_atspi_dbus_return_accessible_from_message“ са чудним " +#~ "потписом „%s“" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "АТ-СПИ: Позван „_atspi_dbus_return_hyperlink_from_message“ са чудним " +#~ "потписом „%s“" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "АТ-СПИ: „Додај доступног“ са непознатим потписом „%s“\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "АТ-СПИ: Не могу да добијем приказ\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "АТ-СПИ: Није пронађена магистрала приступачности — Користим магистралу " +#~ "сесије.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "АТ-СПИ: Не могу да се повежем на магистралу: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "АТ-СПИ: Не могу да се региструјем са магистралом: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "АТ-СПИ: очекивана варијанта приликом добављања „%s“ са сучеља „%s“; добих " +#~ "„%s“\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "„atspi_dbus_get_property“: Погрешна врста: очекивана „%s“, добијена „%c“\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "АТ-СПИ: Непознато сучеље „%s“" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "АТ-СПИ: очекиване су 2 вредности у низу стања; добивено је %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Усмеравање садржаја није примењено" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "позван је „atspi_event_listener_register_from_callback“ са NULL " +#~ "„event_type“" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Добих неисправан потпис „%s“ за сигнал „%s“ са сучеља „%s“\n" diff --git a/po/sr@latin.po b/po/sr@latin.po new file mode 100644 index 0000000..3f03367 --- /dev/null +++ b/po/sr@latin.po @@ -0,0 +1,93 @@ +# Miroslav Nikolić , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-15 11:09+0200\n" +"Last-Translator: Miroslav Nikolić \n" +"Language-Team: Serbian \n" +"Language: sr@latin\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " +"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Program ne postoji više" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Pokušan je usaglašeni poziv gde je zabranjen" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Nepoznat potpis „%s“ za „Ukloni dostupnog“" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: Greška pozivajući „nabavi Koren“ za „%s“: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: Greška u „Nabavi stavku“, pošiljalac=„%s“, greška=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Pozvan „_atspi_dbus_return_accessible_from_message“ sa čudnim " +#~ "potpisom „%s“" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI: Pozvan „_atspi_dbus_return_hyperlink_from_message“ sa čudnim " +#~ "potpisom „%s“" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI: „Dodaj dostupnog“ sa nepoznatim potpisom „%s“\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: Ne mogu da dobijem prikaz\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Nije pronađena magistrala pristupačnosti — Koristim magistralu " +#~ "sesije.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI: Ne mogu da se povežem na magistralu: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI: Ne mogu da se registrujem sa magistralom: %s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "" +#~ "AT-SPI: očekivana varijanta prilikom dobavljanja „%s“ sa sučelja „%s“; dobih " +#~ "„%s“\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "" +#~ "„atspi_dbus_get_property“: Pogrešna vrsta: očekivana „%s“, dobijena „%c“\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Nepoznato sučelje „%s“" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: očekivane su 2 vrednosti u nizu stanja; dobiveno je %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Usmeravanje sadržaja nije primenjeno" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "pozvan je „atspi_event_listener_register_from_callback“ sa NULL " +#~ "„event_type“" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "Dobih neispravan potpis „%s“ za signal „%s“ sa sučelja „%s“\n" diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 0000000..0ba22db --- /dev/null +++ b/po/sv.po @@ -0,0 +1,30 @@ +# Swedish translation for at-spi2-core. +# Copyright © 2011-2014 Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Daniel Nylander , 2011. +# Sebastian Rasmussen , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-09-13 02:46+0000\n" +"PO-Revision-Date: 2014-09-13 11:33+0100\n" +"Last-Translator: Sebastian Rasmussen \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:326 ../atspi/atspi-misc.c:1037 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Programmet finns inte längre" + +#: ../atspi/atspi-misc.c:1795 +msgid "Attempted synchronous call where prohibited" +msgstr "Försökte göra synkront anrop där det inte är tillåtet" diff --git a/po/ta.po b/po/ta.po new file mode 100644 index 0000000..9bde515 --- /dev/null +++ b/po/ta.po @@ -0,0 +1,26 @@ +# Tamil translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# I Felix , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-09-05 23:00+0000\n" +"PO-Revision-Date: 2011-09-08 11:07+0530\n" +"Last-Translator: I Felix \n" +"Language-Team: Tamil \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta\n" +"X-Generator: Lokalize 1.2\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:941 ../atspi/atspi-misc.c:992 +#: ../atspi/atspi-misc.c:1034 +msgid "The application no longer exists" +msgstr "பயன்பாடு இனியும் உள்ள" + diff --git a/po/te.po b/po/te.po new file mode 100644 index 0000000..4461167 --- /dev/null +++ b/po/te.po @@ -0,0 +1,119 @@ +# Telugu translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Krishnababu Krothapalli , 2011. +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=at-spi&component=general\n" +"POT-Creation-Date: 2011-02-08 18:33+0000\n" +"PO-Revision-Date: 2011-02-09 16:16+0530\n" +"Last-Translator: Krishnababu Krothapalli \n" +"Language-Team: Telugu \n" +"Language: te\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: రిమూవ్‌యాక్సెస్‌బుల్ కొరకు తెలియని సంతకం %s" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s కొరకు getRoot పిలువుటలో దోషం: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems నందు దోషము, పంపునది=%s, దోషం=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: కొత్త సంతకం %sతో _atspi_dbus_return_accessible_from_message " +"పిలువబడింది" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: కొత్త సంతకం %s తో _atspi_dbus_return_hyperlink_from_message " +"పిలువబడింది" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: తెలియని సంతకం %sతో యాడ్‌యాక్సెస్‌బుల్\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: ప్రదర్శనను పొందలేకపోయింది\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: అందుబాటు బస్ కనుగొనబడలేదు - సెషన్ బస్ వుపయోగించి.\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: బస్‌కు అనుసంధానం కాలేకపోయింది: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: బస్‌తో నమోదు కాలేకపోయింది: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "అనువర్తనము యింక లేదు" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "" +"AT-SPI: %sను ఇంటర్ఫేస్ %s నుండి తెస్తున్నప్పుడు వేరియంట్‌ను వూహించడమైంది; " +"పొందినది %s\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: సరికాని రకం: వూహించినది %s, పొందినది %c\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: తెలియని యింటర్ఫేస్ %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: స్టేట్స్ యెరేనందు 2 విలువలను వూహించినది; పొందినది %d\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "స్ట్రీమ్ చేయదగు సారము వృద్దిపరచలేదు" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "" +"atspi_event_listener_register_from_callbackను NULL event_type తో పిలువబడింది" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "చెల్లని సంతకం %s ను సంకేతం %s కొరకు యింటర్ఫేస్ %s నుంది పొందింది\n" + diff --git a/po/tg.po b/po/tg.po new file mode 100644 index 0000000..d70be16 --- /dev/null +++ b/po/tg.po @@ -0,0 +1,24 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Victor Ibragimov , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: Tajik Gnome\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-04 18:50+0000\n" +"PO-Revision-Date: 2013-01-19 17:42+0500\n" +"Last-Translator: Victor Ibragimov \n" +"Language-Team: \n" +"Language: tg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:1062 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Ин барнома дигар вуҷуд надорад" diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 0000000..95d04f8 --- /dev/null +++ b/po/tr.po @@ -0,0 +1,51 @@ +# Turkish translation for at-spi2-core. +# Copyright (C) 2011 the Free Software Foundation, Inc. +# This file is distributed under the same license as the at-spi2-core package. +# Muhammed EKEN , 2011. +# Muhammet Kara , 2011, 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-12-08 23:31+0200\n" +"Last-Translator: Muhammet Kara \n" +"Language-Team: Türkçe \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Artık böyle bir uygulama bulunmuyor" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "Yasak olduğu halde eşzamanlı çağrı yapmaya çalışıldı" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: Bilinmeyen RemoveAccesible imzası %s" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI: %s için getRoot çağırma hatası: %s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems'te hata, gönderen=%s, hata=%s" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI: Bilinmeyen arayüz %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI: durumlar dizisinde 2 değer beklenirken %d değer alındı\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "Akıcı içerik uygulanmamış" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "%3$s arayüzünden %2$s sinyali için geçersiz imza %1$s alındı\n" diff --git a/po/ug.po b/po/ug.po new file mode 100644 index 0000000..d696568 --- /dev/null +++ b/po/ug.po @@ -0,0 +1,104 @@ +# Uyghur translation for at-spi2-core. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Gheyret Kenji , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-03-18 16:31+0000\n" +"PO-Revision-Date: 2011-01-31 15:04+0000\n" +"Last-Translator: Gheyret Kenji \n" +"Language-Team: Uyghur Computer Science Association \n" +"Language: ug\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../atspi/atspi-misc.c:291 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: RemoveAccessible نىڭ ئىمزاسى %s نامەلۇم" + +#: ../atspi/atspi-misc.c:328 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: %s ئۈچۈن getRoot نى چاقىرغاندا خاتالىق كۆرۈلدى: %s" + +#: ../atspi/atspi-misc.c:486 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: GetItems دا خاتالىق بار. ئەۋەتكۈچى=%s، خاتالىق=%s" + +#: ../atspi/atspi-misc.c:588 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "AT-SPI: _atspi_dbus_return_accessible_from_message نى غەلىتە ئىمزا %s بىلەن چاقىردى" + +#: ../atspi/atspi-misc.c:617 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "AT-SPI: _atspi_dbus_return_hyperlink_from_message نى غەلىتە ئىمزا %s بىلەن چاقىردى" + +#: ../atspi/atspi-misc.c:642 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: AddAccessible غەلىتە ئىمزا %s بىلەن بىرگە\n" + +#: ../atspi/atspi-misc.c:935 ../atspi/atspi-misc.c:986 +#: ../atspi/atspi-misc.c:1027 +msgid "The application no longer exists" +msgstr "بۇ پروگرامما مەۋجۇت ئەمەس" + +#: ../atspi/atspi-misc.c:1063 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: %s نى ئارايۈز %s دىن ئالغاندا بىر variant كېلىشى كېرەك ئىدى؛ %s غا ئېرىشتى\n" + +#: ../atspi/atspi-misc.c:1069 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: تىپى خاتا: %s بولۇشى كېرەك ئىدى، %c غا ئېرىشتى\n" + +#: ../atspi/atspi-misc.c:1212 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI:ئارايۈز %s نامەلۇم" + +#: ../atspi/atspi-misc.c:1232 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: ھالەت تىزىقىدا ئىككى قىممەت بولۇشى كېرەك ئىدى؛ %d غا ئېرىشتى\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "ئېقىنلاشتۇرغىلى بولىدىغان مەزمۇننى تېخى ئىشلەتكىلى بولمايدۇ" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "atspi_event_listener_register_from_callback نى نۆل(NULL event_type) بىلەن چاقىردى" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "خاتا ئىمزا %s ئېرىشتى. بۇ سىگنال %s ئۈچۈن كېرەك ئىدى. بۇ سىگنال %s ئارايۈزدىن كەلگەن\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI: ئېكرانغا ئېرىشەلمىدى\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "" +#~ "AT-SPI: Accessibility باش لىنىيىسى تېپىلمىدى، شۇڭا ئەڭگىمە باش لىنىيىسى " +#~ "ئىشلىتىلىدۇ.\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI:باش لىنىيىسىگە باغلىنالمىدى: %s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI:باش لىنىيىسىگە خەتلىتەلمىدى: %s\n" diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 0000000..2da7bed --- /dev/null +++ b/po/uk.po @@ -0,0 +1,116 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Korostil Daniel , 2011. +msgid "" +msgstr "" +"Project-Id-Version: 1.1\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&component=general\n" +"POT-Creation-Date: 2011-02-04 22:21+0000\n" +"PO-Revision-Date: 2011-02-07 17:41+0300\n" +"Last-Translator: Korostil Daniel \n" +"Language-Team: translation@linux.org.ua\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Virtaal 0.6.1\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: невідомий підпис %s для RemoveAccessible" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: помилка виклику getRoot для %s: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: помилка в GetItems, sender=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: викликано _atspi_dbus_return_accessible_from_message з дивним " +"підписом %s" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "" +"AT-SPI: викликано _atspi_dbus_return_hyperlink_from_message з дивним " +"підписом %s" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: AddAccessible з невідомим підписом %s\n" + +#: ../atspi/atspi-misc.c:826 +msgid "AT-SPI: Could not get the display\n" +msgstr "AT-SPI: неможливо перейти до показу\n" + +#: ../atspi/atspi-misc.c:844 +msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +msgstr "AT-SPI: не знайдено шини доступності — використовуйте шину сеансу.\n" + +#: ../atspi/atspi-misc.c:848 ../atspi/atspi-misc.c:857 +#, c-format +msgid "AT-SPI: Couldn't connect to bus: %s\n" +msgstr "AT-SPI: неможливо з'єднатись із шиною: %s\n" + +#: ../atspi/atspi-misc.c:864 +#, c-format +msgid "AT-SPI: Couldn't register with bus: %s\n" +msgstr "AT-SPI: неможливо зареєструватись із шиною: %s\n" + +#: ../atspi/atspi-misc.c:1002 ../atspi/atspi-misc.c:1053 +#: ../atspi/atspi-misc.c:1094 +msgid "The application no longer exists" +msgstr "Програми більше не існує" + +#: ../atspi/atspi-misc.c:1130 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "AT-SPI: очікуваний варіант, коли звантажуємо %s з інтерфейсу %s; отримаємо %" +"s\n" + +#: ../atspi/atspi-misc.c:1136 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: неправильний тип: очікували %s, отримали %c\n" + +#: ../atspi/atspi-misc.c:1279 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: невідомий інтерфейс %s" + +#: ../atspi/atspi-misc.c:1299 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: очікувалось 2 значення в масиві станів; отримали %d\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "Потоковий вміст не реалізовано" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "викликано atspi_event_listener_register_from_callback з NULL event_type" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "Отримано неправильний підпис %s для сигналу %s з інтерфейсу %s\n" diff --git a/po/uz@cyrillic.po b/po/uz@cyrillic.po new file mode 100644 index 0000000..0e59d30 --- /dev/null +++ b/po/uz@cyrillic.po @@ -0,0 +1,23 @@ +# Uzbek (Cyrillic) translation for at-spi2-core. +# Copyright (C) 2012 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Bahodir Mansurov <6ahodir@gmail.com>, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-02-24 22:24+0000\n" +"PO-Revision-Date: 2012-02-24 22:24+0000\n" +"Last-Translator: Bahodir Mansurov <6ahodir@gmail.com>\n" +"Language-Team: Uzbek (Cyrillic) \n" +"Language: uz@cyrillic\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../atspi/atspi-component.c:313 ../atspi/atspi-misc.c:985 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "Бу дастур энди мавжуд эмас" diff --git a/po/vi.po b/po/vi.po new file mode 100644 index 0000000..c232401 --- /dev/null +++ b/po/vi.po @@ -0,0 +1,93 @@ +# Vietnamese translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Nguyễn Thái Ngọc Duy , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2011-05-22 23:37+0000\n" +"PO-Revision-Date: 2011-05-22 23:00+0700\n" +"Last-Translator: Trương Ứng Minh \n" +"Language-Team: Vietnamese \n" +"Language: vi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../atspi/atspi-misc.c:290 +#, c-format +msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +msgstr "AT-SPI: Ký hiệu lạ %s đối với RemoveAccessible" + +#: ../atspi/atspi-misc.c:327 +#, c-format +msgid "AT-SPI: Error calling getRoot for %s: %s" +msgstr "AT-SPI: Lỗi khi gọi getRoot cho %s: %s" + +#: ../atspi/atspi-misc.c:485 +#, c-format +msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +msgstr "AT-SPI: Lỗi trong GetItems, sender=%s, error=%s" + +#: ../atspi/atspi-misc.c:587 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +"signature %s" +msgstr "AT-SPI: _atspi_dbus_return_accessible_from_message được gọi với chữ ký lạ %s" + +#: ../atspi/atspi-misc.c:616 +#, c-format +msgid "" +"AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +"signature %s" +msgstr "AT-SPI: _atspi_dbus_return_hyperlink_from_message được gọi với chữ ký lạ %s" + +#: ../atspi/atspi-misc.c:641 +#, c-format +msgid "AT-SPI: AddAccessible with unknown signature %s\n" +msgstr "AT-SPI: AddAccessible với ký hiệu lạ %s\n" + +#: ../atspi/atspi-misc.c:934 ../atspi/atspi-misc.c:985 +#: ../atspi/atspi-misc.c:1026 +msgid "The application no longer exists" +msgstr "Ứng dụng không còn tồn tại" + +#: ../atspi/atspi-misc.c:1062 +#, c-format +msgid "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +msgstr "" +"AT-SPI: chờ một biến thể xuất hiện khi lấy %s từ giao diện %s; lấy %s\n" + +#: ../atspi/atspi-misc.c:1068 +#, c-format +msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +msgstr "atspi_dbus_get_property: Sai kiểu: muốn %s, được %c\n" + +#: ../atspi/atspi-misc.c:1211 +#, c-format +msgid "AT-SPI: Unknown interface %s" +msgstr "AT-SPI: Giao diện không rõ %s" + +#: ../atspi/atspi-misc.c:1231 +#, c-format +msgid "AT-SPI: expected 2 values in states array; got %d\n" +msgstr "AT-SPI: chờ 2 giá trị trong mảng trạng thái; được %d\n" + +#: ../atspi/atspi-accessible.c:997 +msgid "Streamable content not implemented" +msgstr "Chưa cài đặt streamable content" + +#: ../atspi/atspi-event-listener.c:510 +msgid "" +"called atspi_event_listener_register_from_callback with a NULL event_type" +msgstr "atspi_event_listener_register_from_callback được gọi với event_type là NULL" + +#: ../atspi/atspi-event-listener.c:777 +#, c-format +msgid "Got invalid signature %s for signal %s from interface %s\n" +msgstr "Nhận được chữ ký không hợp lệ %s cho tín hiệu %s từ giao tiếp %s\n" diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 0000000..17f8fa1 --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,93 @@ +# Chinese (China) translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# +# Lele Long , 2011. +# Aron Xu , 2011. +# Sphinx Jiang , 2014. +# + +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-22 03:45+0000\n" +"PO-Revision-Date: 2014-02-23 19:00+0800\n" +"Last-Translator: Sphinx Jiang \n" +"Language-Team: Chinese Simplified \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1036 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "该应用程序已经不存在" + +#: ../atspi/atspi-misc.c:1779 +msgid "Attempted synchronous call where prohibited" +msgstr "试图进行禁止的同步调用" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI:RemoveAccessible 使用了未知签名 %s" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI:为 %1$s 调用 getRoot 出错:%2$s " + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetIterms 出错,sender=%1$s, error=%2$s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:使用未知签名 %s 调用 _atspi_dbus_return_accessible_from_message" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:使用未知签名 %s 调用 _atspi_dbus_return_hyperlink_from_message" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI:AddAccessible 使用了未知签名 %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI:无法获取显示\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI:无法找到辅助功能总线 - 使用会话总线。\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI:无法连接到总线:%s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI:无法在总线上注册:%s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "AT-SPI:期望从接口 %2$s 获取 %1$s 时得到一个变量,实际得到 %3$s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property:错误类型:期望为 %s,实际得到 %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI:未知接口 %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI:期望为状态数组的两个值,而实际得到 %d 个\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "未实现的流式内容" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "使用 NULL event_type 调用 atspi_event_listener_register_from_callback" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "信号 %2$s 从接口%3$s 得到错误签名 %1$s\n" diff --git a/po/zh_HK.po b/po/zh_HK.po new file mode 100644 index 0000000..80e32a4 --- /dev/null +++ b/po/zh_HK.po @@ -0,0 +1,91 @@ +# Chinese (Hong Kong) translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Chao-Hsiung Liao , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core 1.91.91\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-09 11:28+0800\n" +"Last-Translator: Chao-Hsiung Liao \n" +"Language-Team: Chinese (Hong Kong) \n" +"Language: zh_HK\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.3\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "應用程式已不存在" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "在禁止處嘗試同步化" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: RemoveAccessible 有不明的簽章 %s" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI:呼叫 %s 的 getRoot 時發生錯誤:%s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems 中有錯誤,sender=%s,error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:以奇怪的簽章 %s 呼叫了 _atspi_dbus_return_accessible_from_message" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:以奇怪的簽章 %s 呼叫了 _atspi_dbus_return_hyperlink_from_message" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI:AddAccessible 有不明的簽章 %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI:無法取回畫面\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI:找不到無障礙匯流排 - 使用作業階段匯流排。\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI:無法連線至匯流排:%s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI:無法註冊匯流排:%s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "AT-SPI:當從介面 %2$s 取回 %1$s 時預期有一個變數;卻得到 %3$s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property:錯誤的類型:預期為 %s,卻得到 %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI:不明的介面 %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI:預期在狀態陣列中有 2 個數值,卻得到 %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "可串流內容沒有實作" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "以 NULL event_type 呼叫 atspi_event_listener_register_from_callback" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "從介面 %3$s 取得信號 %2$s 的無效簽章 %1$s\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI:得到錯誤:%s\n" diff --git a/po/zh_TW.po b/po/zh_TW.po new file mode 100644 index 0000000..d6fbb03 --- /dev/null +++ b/po/zh_TW.po @@ -0,0 +1,91 @@ +# Chinese (Taiwan) translation for at-spi2-core. +# Copyright (C) 2011 at-spi2-core's COPYRIGHT HOLDER +# This file is distributed under the same license as the at-spi2-core package. +# Chao-Hsiung Liao , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: at-spi2-core 1.91.91\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=at-" +"spi&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2014-02-03 23:50+0000\n" +"PO-Revision-Date: 2014-03-08 22:52+0800\n" +"Last-Translator: Chao-Hsiung Liao \n" +"Language-Team: Chinese (Taiwan) \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.3\n" + +#: ../atspi/atspi-component.c:325 ../atspi/atspi-misc.c:1034 +#: ../atspi/atspi-value.c:111 +msgid "The application no longer exists" +msgstr "應用程式已不存在" + +#: ../atspi/atspi-misc.c:1777 +msgid "Attempted synchronous call where prohibited" +msgstr "在禁止處嘗試同步化" + +#~ msgid "AT-SPI: Unknown signature %s for RemoveAccessible" +#~ msgstr "AT-SPI: RemoveAccessible 有不明的簽章 %s" + +#~ msgid "AT-SPI: Error calling getRoot for %s: %s" +#~ msgstr "AT-SPI:呼叫 %s 的 getRoot 時發生錯誤:%s" + +#~ msgid "AT-SPI: Error in GetItems, sender=%s, error=%s" +#~ msgstr "AT-SPI: GetItems 中有錯誤,sender=%s,error=%s" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_accessible_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:以奇怪的簽章 %s 呼叫了 _atspi_dbus_return_accessible_from_message" + +#~ msgid "" +#~ "AT-SPI: Called _atspi_dbus_return_hyperlink_from_message with strange " +#~ "signature %s" +#~ msgstr "" +#~ "AT-SPI:以奇怪的簽章 %s 呼叫了 _atspi_dbus_return_hyperlink_from_message" + +#~ msgid "AT-SPI: AddAccessible with unknown signature %s\n" +#~ msgstr "AT-SPI:AddAccessible 有不明的簽章 %s\n" + +#~ msgid "AT-SPI: Could not get the display\n" +#~ msgstr "AT-SPI:無法取回畫面\n" + +#~ msgid "AT-SPI: Accessibility bus not found - Using session bus.\n" +#~ msgstr "AT-SPI:找不到無障礙匯流排 - 使用作業階段匯流排。\n" + +#~ msgid "AT-SPI: Couldn't connect to bus: %s\n" +#~ msgstr "AT-SPI:無法連線至匯流排:%s\n" + +#~ msgid "AT-SPI: Couldn't register with bus: %s\n" +#~ msgstr "AT-SPI:無法註冊匯流排:%s\n" + +#~ msgid "" +#~ "AT-SPI: expected a variant when fetching %s from interface %s; got %s\n" +#~ msgstr "AT-SPI:當從介面 %2$s 取回 %1$s 時預期有一個變數;卻得到 %3$s\n" + +#~ msgid "atspi_dbus_get_property: Wrong type: expected %s, got %c\n" +#~ msgstr "atspi_dbus_get_property:錯誤的類型:預期為 %s,卻得到 %c\n" + +#~ msgid "AT-SPI: Unknown interface %s" +#~ msgstr "AT-SPI:不明的介面 %s" + +#~ msgid "AT-SPI: expected 2 values in states array; got %d\n" +#~ msgstr "AT-SPI:預期在狀態陣列中有 2 個數值,卻得到 %d\n" + +#~ msgid "Streamable content not implemented" +#~ msgstr "可串流內容沒有實作" + +#~ msgid "" +#~ "called atspi_event_listener_register_from_callback with a NULL event_type" +#~ msgstr "" +#~ "以 NULL event_type 呼叫 atspi_event_listener_register_from_callback" + +#~ msgid "Got invalid signature %s for signal %s from interface %s\n" +#~ msgstr "從介面 %3$s 取得信號 %2$s 的無效簽章 %1$s\n" + +#~ msgid "AT-SPI: Got error: %s\n" +#~ msgstr "AT-SPI:得到錯誤:%s\n" diff --git a/registryd/de-marshaller.c b/registryd/de-marshaller.c new file mode 100644 index 0000000..fef8e48 --- /dev/null +++ b/registryd/de-marshaller.c @@ -0,0 +1,102 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, 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. + */ + +#include +#include +#include +#include + +#include "de-types.h" + +dbus_bool_t spi_dbus_message_iter_get_struct(DBusMessageIter *iter, ...) +{ + va_list args; + DBusMessageIter iter_struct; + int type; + void *ptr; + + dbus_message_iter_recurse(iter, &iter_struct); + va_start(args, iter); + for (;;) + { + type = va_arg(args, int); + if (type == DBUS_TYPE_INVALID) break; + if (type != dbus_message_iter_get_arg_type(&iter_struct)) + { + va_end(args); + return FALSE; + } + ptr = va_arg(args, void *); + dbus_message_iter_get_basic(&iter_struct, ptr); + dbus_message_iter_next(&iter_struct); + } + dbus_message_iter_next(iter); + va_end(args); + return TRUE; +} + +dbus_bool_t spi_dbus_message_iter_append_struct(DBusMessageIter *iter, ...) +{ + va_list args; + DBusMessageIter iter_struct; + int type; + void *ptr; + + if (!dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &iter_struct)) return FALSE; + va_start(args, iter); + for (;;) + { + type = va_arg(args, int); + if (type == DBUS_TYPE_INVALID) break; + ptr = va_arg(args, void *); + dbus_message_iter_append_basic(&iter_struct, type, ptr); + } + if (!dbus_message_iter_close_container(iter, &iter_struct)) return FALSE; + va_end(args); + return TRUE; +} + +dbus_bool_t spi_dbus_marshal_deviceEvent(DBusMessage *message, const Accessibility_DeviceEvent *e) +{ + DBusMessageIter iter; + + if (!message) return FALSE; + dbus_message_iter_init_append(message, &iter); + return spi_dbus_message_iter_append_struct(&iter, DBUS_TYPE_UINT32, &e->type, DBUS_TYPE_INT32, &e->id, DBUS_TYPE_UINT32, &e->hw_code, DBUS_TYPE_UINT32, &e->modifiers, DBUS_TYPE_INT32, &e->timestamp, DBUS_TYPE_STRING, &e->event_string, DBUS_TYPE_BOOLEAN, &e->is_text, DBUS_TYPE_INVALID); +} + +dbus_bool_t spi_dbus_demarshal_deviceEvent(DBusMessage *message, Accessibility_DeviceEvent *e) +{ + DBusMessageIter iter; + dbus_uint16_t hw_code; + dbus_uint16_t modifiers; + + dbus_message_iter_init(message, &iter); + if (spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_UINT32, &e->type, DBUS_TYPE_INT32, &e->id, DBUS_TYPE_INT32, &e->hw_code, DBUS_TYPE_INT32, &e->modifiers, DBUS_TYPE_INT32, &e->timestamp, DBUS_TYPE_STRING, &e->event_string, DBUS_TYPE_BOOLEAN, &e->is_text, DBUS_TYPE_INVALID)) + return TRUE; + /* TODO: Perhaps remove the below code for 2.1 */ + if (!spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_UINT32, &e->type, DBUS_TYPE_INT32, &e->id, DBUS_TYPE_INT16, &hw_code, DBUS_TYPE_INT16, &modifiers, DBUS_TYPE_INT32, &e->timestamp, DBUS_TYPE_STRING, &e->event_string, DBUS_TYPE_BOOLEAN, &e->is_text, DBUS_TYPE_INVALID)) + return FALSE; + e->hw_code = hw_code; + e->modifiers = modifiers; + return TRUE; +} diff --git a/registryd/de-marshaller.h b/registryd/de-marshaller.h new file mode 100644 index 0000000..9d55a9d --- /dev/null +++ b/registryd/de-marshaller.h @@ -0,0 +1,37 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Codethink Ltd + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_DE_MARSHALLER_H_ +#define SPI_DE_MARSHALLER_H_ + +#include + +#include "de-types.h" + +dbus_bool_t spi_dbus_message_iter_get_struct(DBusMessageIter *iter, ...); +dbus_bool_t spi_dbus_message_iter_append_struct(DBusMessageIter *iter, ...); +dbus_bool_t spi_dbus_marshal_deviceEvent(DBusMessage *message, const Accessibility_DeviceEvent *e); +dbus_bool_t spi_dbus_demarshal_deviceEvent(DBusMessage *message, Accessibility_DeviceEvent *e); + +#endif /* SPI_DE_MARSHALLER_H_ */ diff --git a/registryd/de-types.h b/registryd/de-types.h new file mode 100644 index 0000000..a338e38 --- /dev/null +++ b/registryd/de-types.h @@ -0,0 +1,81 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Codethink Ltd + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_DE_TYPES_H_ +#define SPI_DE_TYPES_H_ + +#include + +typedef unsigned long Accessibility_ControllerEventMask; + +typedef enum { + Accessibility_KEY_PRESSED_EVENT, + Accessibility_KEY_RELEASED_EVENT, + Accessibility_BUTTON_PRESSED_EVENT, + Accessibility_BUTTON_RELEASED_EVENT, +} Accessibility_EventType; + +typedef enum { + Accessibility_KEY_PRESSED, + Accessibility_KEY_RELEASED, +} Accessibility_KeyEventType; + +typedef enum { + Accessibility_KEY_PRESS, + Accessibility_KEY_RELEASE, + Accessibility_KEY_PRESSRELEASE, + Accessibility_KEY_SYM, + Accessibility_KEY_STRING, +} Accessibility_KeySynthType; + +typedef struct _Accessibility_DeviceEvent Accessibility_DeviceEvent; +struct _Accessibility_DeviceEvent +{ + Accessibility_EventType type; + dbus_uint32_t id; + dbus_uint32_t hw_code; + dbus_uint32_t modifiers; + dbus_uint32_t timestamp; + char * event_string; + dbus_bool_t is_text; +}; + +typedef struct _Accessibility_EventListenerMode Accessibility_EventListenerMode; +struct _Accessibility_EventListenerMode +{ + dbus_bool_t synchronous; + dbus_bool_t preemptive; + dbus_bool_t global; +}; + +typedef struct _Accessibility_KeyDefinition Accessibility_KeyDefinition; +struct _Accessibility_KeyDefinition +{ + dbus_int32_t keycode; + dbus_int32_t keysym; + char *keystring; + dbus_int32_t unused; +}; + +#endif /* SPI_DE_TYPES_H_ */ diff --git a/registryd/deviceeventcontroller-x11.c b/registryd/deviceeventcontroller-x11.c new file mode 100644 index 0000000..d9d9a6c --- /dev/null +++ b/registryd/deviceeventcontroller-x11.c @@ -0,0 +1,1415 @@ +/* AT-SPI - Assistive Technology Service Provider Interface + * + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2003 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +/* deviceeventcontroller-x11.c: X-specific DeviceEventController support */ + +#include + +#undef SPI_XKB_DEBUG +#undef SPI_DEBUG +#undef SPI_KEYEVENT_DEBUG + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define XK_MISCELLANY +#define XK_LATIN1 +#include + +#include + +#include + +#include "paths.h" +#include "keymasks.h" +#include "de-types.h" +#include "de-marshaller.h" +#include "display.h" +#include "event-source.h" + +#include "deviceeventcontroller.h" +#include "reentrant-list.h" + +#include "introspection.h" + +static void spi_dec_x11_emit_modifier_event (SpiDEController *controller, + guint prev_mask, + guint current_mask); + +#define CHECK_RELEASE_DELAY 20 +#define BIT(c, x) (c[x/8]&(1<<(x%8))) +static guint check_release_handler = 0; +static Accessibility_DeviceEvent pressed_event; +static void wait_for_release_event (XEvent *event, SpiDEController *controller); + +static int spi_error_code = 0; +struct _SpiPoint { + gint x; + gint y; +}; +typedef struct _SpiPoint SpiPoint; +static SpiPoint last_mouse_pos_static = {0, 0}; +static SpiPoint *last_mouse_pos = &last_mouse_pos_static; +static unsigned int mouse_mask_state = 0; +static unsigned int mouse_button_mask = + Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask; +static unsigned int key_modifier_mask = + Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask | LockMask | ControlMask | SPI_KEYMASK_NUMLOCK; +static unsigned int _numlock_physical_mask = Mod2Mask; /* a guess, will be reset */ + +static XModifierKeymap* xmkeymap = NULL; + + +static int (*x_default_error_handler) (Display *display, XErrorEvent *error_event); + +typedef struct { + Display *xevie_display; + unsigned int last_press_keycode; + unsigned int last_release_keycode; + struct timeval last_press_time; + struct timeval last_release_time; + int have_xkb; + int xkb_major_extension_opcode; + int xkb_base_event_code; + int xkb_base_error_code; + unsigned int xkb_latch_mask; + unsigned int pending_xkb_mod_relatch_mask; + XkbDescPtr xkb_desc; + KeyCode reserved_keycode; + KeySym reserved_keysym; + guint reserved_reset_timeout; +} DEControllerPrivateData; + +static void spi_controller_register_with_devices (SpiDEController *controller); +static gboolean spi_device_event_controller_forward_key_event (SpiDEController *controller, + const XEvent *event); + + +static SpiDEController *saved_controller; + +static unsigned int +keysym_mod_mask (KeySym keysym, KeyCode keycode) +{ + /* we really should use XKB and look directly at the keymap */ + /* this is very inelegant */ + Display *display = spi_get_display (); + unsigned int mods_rtn = 0; + unsigned int retval = 0; + KeySym sym_rtn; + + if (XkbLookupKeySym (display, keycode, 0, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = 0; + } + else if (XkbLookupKeySym (display, keycode, ShiftMask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = ShiftMask; + } + else if (XkbLookupKeySym (display, keycode, Mod2Mask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = Mod2Mask; + } + else if (XkbLookupKeySym (display, keycode, Mod3Mask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = Mod3Mask; + } + else if (XkbLookupKeySym (display, keycode, + ShiftMask | Mod2Mask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = (Mod2Mask | ShiftMask); + } + else if (XkbLookupKeySym (display, keycode, + ShiftMask | Mod3Mask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = (Mod3Mask | ShiftMask); + } + else if (XkbLookupKeySym (display, keycode, + ShiftMask | Mod4Mask, &mods_rtn, &sym_rtn) && + (sym_rtn == keysym)) { + retval = (Mod4Mask | ShiftMask); + } + else + retval = 0xFFFF; + return retval; +} + +static gboolean +replace_map_keysym (DEControllerPrivateData *priv, KeyCode keycode, KeySym keysym) +{ +#ifdef HAVE_XKB + Display *dpy = spi_get_display (); + XkbDescPtr desc; + if (!(desc = XkbGetMap (dpy, XkbAllMapComponentsMask, XkbUseCoreKbd))) + { + fprintf (stderr, "ERROR getting map\n"); + } + XFlush (dpy); + XSync (dpy, False); + if (desc && desc->map) + { + gint offset = desc->map->key_sym_map[keycode].offset; + desc->map->syms[offset] = keysym; + } + else + { + fprintf (stderr, "Error changing key map: empty server structure\n"); + } + XkbSetMap (dpy, XkbAllMapComponentsMask, desc); + /** + * FIXME: the use of XkbChangeMap, and the reuse of the priv->xkb_desc structure, + * would be far preferable. + * HOWEVER it does not seem to work using XFree 4.3. + **/ + /* XkbChangeMap (dpy, priv->xkb_desc, priv->changes); */ + XFlush (dpy); + XSync (dpy, False); + XkbFreeKeyboard (desc, 0, TRUE); + + return TRUE; +#else + return FALSE; +#endif +} + +static gboolean +spi_dec_reset_reserved (gpointer data) +{ + DEControllerPrivateData *priv = data; + replace_map_keysym (priv, priv->reserved_keycode, priv->reserved_keysym); + priv->reserved_reset_timeout = 0; + return FALSE; +} + +static gint +spi_dec_x11_get_keycode (SpiDEController *controller, + gint keysym, + gchar *key_str, + gboolean fix, + guint *modmask) +{ + KeyCode keycode = 0; + if (key_str && key_str[0]) + keysym = XStringToKeysym(key_str); + keycode = XKeysymToKeycode (spi_get_display (), (KeySym) keysym); + if (!keycode && fix) + { + DEControllerPrivateData *priv = controller->priv; + /* if there's no keycode available, fix it */ + if (replace_map_keysym (priv, priv->reserved_keycode, keysym)) + { + keycode = priv->reserved_keycode; + /* + * queue a timer to restore the old keycode. Ugly, but required + * due to races / asynchronous X delivery. + * Long-term fix is to extend the X keymap here instead of replace entries. + */ + priv->reserved_reset_timeout = g_timeout_add (500, spi_dec_reset_reserved, priv); + g_source_set_name_by_id (priv->reserved_reset_timeout, "[at-spi2-core] spi_dec_reset_reserved"); + } + if (modmask) + *modmask = 0; + return keycode; + } + if (modmask) + *modmask = keysym_mod_mask (keysym, keycode); + return keycode; +} + +static void +spi_dec_set_unlatch_pending (SpiDEController *controller, unsigned mask) +{ + DEControllerPrivateData *priv = controller->priv; +#ifdef SPI_XKB_DEBUG + if (priv->xkb_latch_mask) fprintf (stderr, "unlatch pending! %x\n", + priv->xkb_latch_mask); +#endif + priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; +} + +static gboolean +spi_dec_button_update_and_emit (SpiDEController *controller, + guint mask_return) +{ + Accessibility_DeviceEvent mouse_e; + gchar event_detail[3]; + gboolean is_consumed = FALSE; + + if ((mask_return & mouse_button_mask) != + (mouse_mask_state & mouse_button_mask)) + { + int button_number = 0; + gboolean is_down = False; + + if (!(mask_return & Button1Mask) && + (mouse_mask_state & Button1Mask)) + { + mouse_mask_state &= ~Button1Mask; + button_number = 1; + } + else if ((mask_return & Button1Mask) && + !(mouse_mask_state & Button1Mask)) + { + mouse_mask_state |= Button1Mask; + button_number = 1; + is_down = True; + } + else if (!(mask_return & Button2Mask) && + (mouse_mask_state & Button2Mask)) + { + mouse_mask_state &= ~Button2Mask; + button_number = 2; + } + else if ((mask_return & Button2Mask) && + !(mouse_mask_state & Button2Mask)) + { + mouse_mask_state |= Button2Mask; + button_number = 2; + is_down = True; + } + else if (!(mask_return & Button3Mask) && + (mouse_mask_state & Button3Mask)) + { + mouse_mask_state &= ~Button3Mask; + button_number = 3; + } + else if ((mask_return & Button3Mask) && + !(mouse_mask_state & Button3Mask)) + { + mouse_mask_state |= Button3Mask; + button_number = 3; + is_down = True; + } + else if (!(mask_return & Button4Mask) && + (mouse_mask_state & Button4Mask)) + { + mouse_mask_state &= ~Button4Mask; + button_number = 4; + } + else if ((mask_return & Button4Mask) && + !(mouse_mask_state & Button4Mask)) + { + mouse_mask_state |= Button4Mask; + button_number = 4; + is_down = True; + } + else if (!(mask_return & Button5Mask) && + (mouse_mask_state & Button5Mask)) + { + mouse_mask_state &= ~Button5Mask; + button_number = 5; + } + else if ((mask_return & Button5Mask) && + !(mouse_mask_state & Button5Mask)) + { + mouse_mask_state |= Button5Mask; + button_number = 5; + is_down = True; + } + if (button_number) { +#ifdef SPI_DEBUG + fprintf (stderr, "Button %d %s\n", + button_number, (is_down) ? "Pressed" : "Released"); +#endif + snprintf (event_detail, 3, "%d%c", button_number, + (is_down) ? 'p' : 'r'); + /* TODO: FIXME distinguish between physical and + * logical buttons + */ + mouse_e.type = (is_down) ? + Accessibility_BUTTON_PRESSED_EVENT : + Accessibility_BUTTON_RELEASED_EVENT; + mouse_e.id = button_number; + mouse_e.hw_code = button_number; + mouse_e.modifiers = (dbus_uint16_t) mouse_mask_state; + mouse_e.timestamp = 0; + mouse_e.event_string = ""; + mouse_e.is_text = FALSE; + is_consumed = + spi_controller_notify_mouselisteners (controller, + &mouse_e); + if (!is_consumed) + { + dbus_uint32_t x = last_mouse_pos->x, y = last_mouse_pos->y; + spi_dec_dbus_emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Button", event_detail, x, y); + } + else + spi_dec_set_unlatch_pending (controller, mask_return); + } + return TRUE; + } + else + { + return FALSE; + } +} + +static guint +spi_dec_x11_mouse_check (SpiDEController *controller, + int *x, int *y, gboolean *moved) +{ + int win_x_return,win_y_return; + unsigned int mask_return; + Window root_return, child_return; + Display *display = spi_get_display (); + + if (display != NULL) + XQueryPointer(display, DefaultRootWindow (display), + &root_return, &child_return, + x, y, + &win_x_return, &win_y_return, &mask_return); + /* + * Since many clients grab the pointer, and X goes an automatic + * pointer grab on mouse-down, we often must detect mouse button events + * by polling rather than via a button grab. + * The while loop (rather than if) is used since it's possible that + * multiple buttons have changed state since we last checked. + */ + if (mask_return != mouse_mask_state) + { + while (spi_dec_button_update_and_emit (controller, mask_return)); + } + + if (*x != last_mouse_pos->x || *y != last_mouse_pos->y) + { + // TODO: combine these two signals? + dbus_uint32_t ix = *x, iy = *y; + spi_dec_dbus_emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Abs", "", ix, iy); + ix -= last_mouse_pos->x; + iy -= last_mouse_pos->y; + spi_dec_dbus_emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Rel", "", ix, iy); + last_mouse_pos->x = *x; + last_mouse_pos->y = *y; + *moved = True; + } + else + { + *moved = False; + } + + return mask_return; +} + +#ifdef WE_NEED_UGRAB_MOUSE +static int +spi_dec_ungrab_mouse (gpointer data) +{ + Display *display = spi_get_display (); + if (display) + { + XUngrabButton (spi_get_display (), AnyButton, AnyModifier, + XDefaultRootWindow (spi_get_display ())); + } + return FALSE; +} +#endif + +static void +spi_dec_init_mouse_listener (SpiDEController *dec) +{ +#ifdef GRAB_BUTTON + Display *display = spi_get_display (); + + if (display) + { + if (XGrabButton (display, AnyButton, AnyModifier, + spi_get_root_window (), + True, ButtonPressMask | ButtonReleaseMask, + GrabModeSync, GrabModeAsync, None, None) != Success) { +#ifdef SPI_DEBUG + fprintf (stderr, "WARNING: could not grab mouse buttons!\n"); +#endif + ; + } + XSync (display, False); +#ifdef SPI_DEBUG + fprintf (stderr, "mouse buttons grabbed\n"); +#endif + } +#endif +} + +static void +spi_dec_clear_unlatch_pending (SpiDEController *controller) +{ + DEControllerPrivateData *priv = controller->priv; + priv->xkb_latch_mask = 0; +} + +static void +spi_device_event_controller_forward_mouse_event (SpiDEController *controller, + XEvent *xevent) +{ + Accessibility_DeviceEvent mouse_e; + gchar event_detail[3]; + gboolean is_consumed = FALSE; + gboolean xkb_mod_unlatch_occurred; + XButtonEvent *xbutton_event = (XButtonEvent *) xevent; + dbus_uint32_t ix, iy; + + int button = xbutton_event->button; + + unsigned int mouse_button_state = xbutton_event->state; + + switch (button) + { + case 1: + mouse_button_state |= Button1Mask; + break; + case 2: + mouse_button_state |= Button2Mask; + break; + case 3: + mouse_button_state |= Button3Mask; + break; + case 4: + mouse_button_state |= Button4Mask; + break; + case 5: + mouse_button_state |= Button5Mask; + break; + } + + last_mouse_pos->x = ((XButtonEvent *) xevent)->x_root; + last_mouse_pos->y = ((XButtonEvent *) xevent)->y_root; + +#ifdef SPI_DEBUG + fprintf (stderr, "mouse button %d %s (%x)\n", + xbutton_event->button, + (xevent->type == ButtonPress) ? "Press" : "Release", + mouse_button_state); +#endif + snprintf (event_detail, 3, "%d%c", button, + (xevent->type == ButtonPress) ? 'p' : 'r'); + + /* TODO: FIXME distinguish between physical and logical buttons */ + mouse_e.type = (xevent->type == ButtonPress) ? + Accessibility_BUTTON_PRESSED_EVENT : + Accessibility_BUTTON_RELEASED_EVENT; + mouse_e.id = button; + mouse_e.hw_code = button; + mouse_e.modifiers = (dbus_uint16_t) xbutton_event->state; + mouse_e.timestamp = (dbus_uint32_t) xbutton_event->time; + mouse_e.event_string = ""; + mouse_e.is_text = FALSE; + if ((mouse_button_state & mouse_button_mask) != + (mouse_mask_state & mouse_button_mask)) + { + if ((mouse_mask_state & key_modifier_mask) != + (mouse_button_state & key_modifier_mask)) + spi_dec_x11_emit_modifier_event (controller, + mouse_mask_state, mouse_button_state); + mouse_mask_state = mouse_button_state; + is_consumed = + spi_controller_notify_mouselisteners (controller, &mouse_e); + ix = last_mouse_pos->x; + iy = last_mouse_pos->y; + spi_dec_dbus_emit(controller, SPI_DBUS_INTERFACE_EVENT_MOUSE, "Button", event_detail, ix, iy); + } + + xkb_mod_unlatch_occurred = (xevent->type == ButtonPress || + xevent->type == ButtonRelease); + + /* if client wants to consume this event, and XKB latch state was + * unset by this button event, we reset it + */ + if (is_consumed && xkb_mod_unlatch_occurred) + spi_dec_set_unlatch_pending (controller, mouse_mask_state); + + XAllowEvents (spi_get_display (), + (is_consumed) ? SyncPointer : ReplayPointer, + CurrentTime); +} + +static void +global_filter_fn (XEvent *xevent, void *data) +{ + SpiDEController *controller; + DEControllerPrivateData *priv; + Display *display = spi_get_display (); + controller = SPI_DEVICE_EVENT_CONTROLLER (data); + priv = controller->priv; + + if (xevent->type == MappingNotify) + xmkeymap = NULL; + + if (xevent->type == KeyPress || xevent->type == KeyRelease) + { + if (priv->xevie_display == NULL) + { + gboolean is_consumed; + + is_consumed = + spi_device_event_controller_forward_key_event (controller, xevent); + + if (is_consumed) + { + int n_events; + int i; + XEvent next_event; + n_events = XPending (display); + +#ifdef SPI_KEYEVENT_DEBUG + g_print ("Number of events pending: %d\n", n_events); +#endif + for (i = 0; i < n_events; i++) + { + XNextEvent (display, &next_event); + if (next_event.type != KeyPress && + next_event.type != KeyRelease) + g_warning ("Unexpected event type %d in queue", next_event.type); + } + + XAllowEvents (display, AsyncKeyboard, CurrentTime); + if (n_events) + XUngrabKeyboard (display, CurrentTime); + } + else + { + if (xevent->type == KeyPress) + wait_for_release_event (xevent, controller); + XAllowEvents (display, ReplayKeyboard, CurrentTime); + } + } + + return; + } + if (xevent->type == ButtonPress || xevent->type == ButtonRelease) + { + spi_device_event_controller_forward_mouse_event (controller, xevent); + } + if (xevent->type == priv->xkb_base_event_code) + { + XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent; + /* ugly but probably necessary...*/ + XSynchronize (display, TRUE); + + if (xkb_ev->xkb_type == XkbStateNotify) + { + XkbStateNotifyEvent *xkb_snev = + (XkbStateNotifyEvent *) xkb_ev; + /* check the mouse, to catch mouse events grabbed by + * another client; in case we should revert this XKB delatch + */ + if (!priv->pending_xkb_mod_relatch_mask) + { + int x, y; + gboolean moved; + spi_dec_x11_mouse_check (controller, &x, &y, &moved); + } + /* we check again, since the previous call may have + changed this flag */ + if (priv->pending_xkb_mod_relatch_mask) + { + unsigned int feedback_mask; +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "relatching %x\n", + priv->pending_xkb_mod_relatch_mask); +#endif + /* temporarily turn off the latch bell, if it's on */ + XkbGetControls (display, + XkbAccessXFeedbackMask, + priv->xkb_desc); + feedback_mask = priv->xkb_desc->ctrls->ax_options; + if (feedback_mask & XkbAX_StickyKeysFBMask) + { + XkbControlsChangesRec changes = {XkbAccessXFeedbackMask, + 0, False}; + priv->xkb_desc->ctrls->ax_options + &= ~(XkbAX_StickyKeysFBMask); + XkbChangeControls (display, priv->xkb_desc, &changes); + } + /* TODO: account for lock as well as latch */ + XkbLatchModifiers (display, + XkbUseCoreKbd, + priv->pending_xkb_mod_relatch_mask, + priv->pending_xkb_mod_relatch_mask); + if (feedback_mask & XkbAX_StickyKeysFBMask) + { + XkbControlsChangesRec changes = {XkbAccessXFeedbackMask, + 0, False}; + priv->xkb_desc->ctrls->ax_options = feedback_mask; + XkbChangeControls (display, priv->xkb_desc, &changes); + } +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "relatched %x\n", + priv->pending_xkb_mod_relatch_mask); +#endif + priv->pending_xkb_mod_relatch_mask = 0; + } + else + { + priv->xkb_latch_mask = xkb_snev->latched_mods; + } + } + XSynchronize (display, FALSE); + } + + return; +} + +static int +_spi_controller_device_error_handler (Display *display, XErrorEvent *error) +{ + if (error->error_code == BadAccess) + { + g_message ("Could not complete key grab: grab already in use.\n"); + spi_error_code = BadAccess; + return 0; + } + else + { + return (*x_default_error_handler) (display, error); + } +} + +static void +spi_controller_register_with_devices (SpiDEController *controller) +{ + DEControllerPrivateData *priv; + int event_base, error_base, major_version, minor_version; + + priv = controller->priv; + if (XTestQueryExtension (spi_get_display(), &event_base, &error_base, &major_version, &minor_version)) + { + XTestGrabControl (spi_get_display (), True); + } + + /* calls to device-specific implementations and routines go here */ + /* register with: keyboard hardware code handler */ + /* register with: (translated) keystroke handler */ + + priv->have_xkb = XkbQueryExtension (spi_get_display (), + &priv->xkb_major_extension_opcode, + &priv->xkb_base_event_code, + &priv->xkb_base_error_code, NULL, NULL); + if (priv->have_xkb) + { + gint i; + guint64 reserved = 0; + priv->xkb_desc = XkbGetMap (spi_get_display (), XkbKeySymsMask, XkbUseCoreKbd); + XkbSelectEvents (spi_get_display (), + XkbUseCoreKbd, + XkbStateNotifyMask, XkbStateNotifyMask); + _numlock_physical_mask = XkbKeysymToModifiers (spi_get_display (), + XK_Num_Lock); + for (i = priv->xkb_desc->max_key_code; i >= priv->xkb_desc->min_key_code; --i) + { + if (priv->xkb_desc->map->key_sym_map[i].kt_index[0] == XkbOneLevelIndex) + { + if (XkbKeycodeToKeysym (spi_get_display (), i, 0, 0) != 0) + { + /* don't use this one if there's a grab client! */ + + /* Runtime errors are generated from these functions, + * that are then quashed. Equivalent to: + * try + * {Blah} + * except + * {;} + */ + + spi_x_error_trap (); + XGrabKey (spi_get_display (), i, 0, + spi_get_root_window (), + TRUE, + GrabModeSync, GrabModeSync); + XSync (spi_get_display (), TRUE); + XUngrabKey (spi_get_display (), i, 0, + spi_get_root_window ()); + if (!spi_x_error_release ()) + { + reserved = i; + break; + } + } + } + } + if (reserved) + { + priv->reserved_keycode = reserved; + priv->reserved_keysym = XkbKeycodeToKeysym (spi_get_display (), reserved, 0, 0); + } + else + { + priv->reserved_keycode = XKeysymToKeycode (spi_get_display (), XK_numbersign); + priv->reserved_keysym = XK_numbersign; + } +#ifdef SPI_RESERVED_DEBUG + unsigned sym = 0; + sym = XKeycodeToKeysym (spi_get_display (), reserved, 0); + fprintf (stderr, "%x\n", sym); + fprintf (stderr, "setting the reserved keycode to %d (%s)\n", + reserved, + XKeysymToString (XKeycodeToKeysym (spi_get_display (), + reserved, 0))); +#endif + } + + spi_set_filter (global_filter_fn, controller); + spi_set_events (KeyPressMask | KeyReleaseMask); + + x_default_error_handler = XSetErrorHandler (_spi_controller_device_error_handler); +} + +static Accessibility_DeviceEvent +spi_keystroke_from_x_key_event (XKeyEvent *x_key_event) +{ + Accessibility_DeviceEvent key_event; + KeySym keysym; + const int cbuf_bytes = 20; + char cbuf [21]; + int nbytes; + + nbytes = XLookupString (x_key_event, cbuf, cbuf_bytes, &keysym, NULL); + key_event.id = (dbus_int32_t)(keysym); + key_event.hw_code = (dbus_int16_t) x_key_event->keycode; + if (((XEvent *) x_key_event)->type == KeyPress) + { + key_event.type = Accessibility_KEY_PRESSED_EVENT; + } + else + { + key_event.type = Accessibility_KEY_RELEASED_EVENT; + } + key_event.modifiers = (dbus_uint16_t)(x_key_event->state); + key_event.is_text = FALSE; + switch (keysym) + { + case ' ': + key_event.event_string = g_strdup ("space"); + break; + case XK_Tab: + key_event.event_string = g_strdup ("Tab"); + break; + case XK_BackSpace: + key_event.event_string = g_strdup ("Backspace"); + break; + case XK_Return: + key_event.event_string = g_strdup ("Return"); + break; + case XK_Home: + key_event.event_string = g_strdup ("Home"); + break; + case XK_Page_Down: + key_event.event_string = g_strdup ("Page_Down"); + break; + case XK_Page_Up: + key_event.event_string = g_strdup ("Page_Up"); + break; + case XK_F1: + key_event.event_string = g_strdup ("F1"); + break; + case XK_F2: + key_event.event_string = g_strdup ("F2"); + break; + case XK_F3: + key_event.event_string = g_strdup ("F3"); + break; + case XK_F4: + key_event.event_string = g_strdup ("F4"); + break; + case XK_F5: + key_event.event_string = g_strdup ("F5"); + break; + case XK_F6: + key_event.event_string = g_strdup ("F6"); + break; + case XK_F7: + key_event.event_string = g_strdup ("F7"); + break; + case XK_F8: + key_event.event_string = g_strdup ("F8"); + break; + case XK_F9: + key_event.event_string = g_strdup ("F9"); + break; + case XK_F10: + key_event.event_string = g_strdup ("F10"); + break; + case XK_F11: + key_event.event_string = g_strdup ("F11"); + break; + case XK_F12: + key_event.event_string = g_strdup ("F12"); + break; + case XK_End: + key_event.event_string = g_strdup ("End"); + break; + case XK_Escape: + key_event.event_string = g_strdup ("Escape"); + break; + case XK_Up: + key_event.event_string = g_strdup ("Up"); + break; + case XK_Down: + key_event.event_string = g_strdup ("Down"); + break; + case XK_Left: + key_event.event_string = g_strdup ("Left"); + break; + case XK_Right: + key_event.event_string = g_strdup ("Right"); + break; + default: + if (nbytes > 0) + { + gunichar c; + cbuf[nbytes] = '\0'; /* OK since length is cbuf_bytes+1 */ + key_event.event_string = g_strdup (cbuf); + c = keysym2ucs (keysym); + if (c > 0 && !g_unichar_iscntrl (c)) + { + key_event.is_text = TRUE; + /* incorrect for some composed chars? */ + } + } + else + { + key_event.event_string = g_strdup (""); + } + } + + key_event.timestamp = (dbus_uint32_t) x_key_event->time; +#ifdef SPI_KEYEVENT_DEBUG + { + char *pressed_str = "pressed"; + char *released_str = "released"; + char *state_ptr; + + if (key_event.type == Accessibility_KEY_PRESSED_EVENT) + state_ptr = pressed_str; + else + state_ptr = released_str; + + fprintf (stderr, + "Key %lu %s (%c), modifiers %d; string=%s [%x] %s\n", + (unsigned long) keysym, + state_ptr, + keysym ? (int) keysym : '*', + (int) x_key_event->state, + key_event.event_string, + key_event.event_string[0], + (key_event.is_text == TRUE) ? "(text)" : "(not text)"); + } +#endif +#ifdef SPI_DEBUG + fprintf (stderr, "%s%c\n", + (x_key_event->state & Mod1Mask)?"Alt-":"", + ((x_key_event->state & ShiftMask)^(x_key_event->state & LockMask))? + g_ascii_toupper (keysym) : g_ascii_tolower (keysym)); + fprintf (stderr, "serial: %x Time: %x\n", x_key_event->serial, x_key_event->time); +#endif /* SPI_DEBUG */ + return key_event; +} + +static gboolean +spi_dec_x11_grab_key (SpiDEController *controller, + guint key_val, + Accessibility_ControllerEventMask mod_mask) +{ + XGrabKey (spi_get_display (), + key_val, + mod_mask, + spi_get_root_window (), + True, + GrabModeSync, + GrabModeSync); + XSync (spi_get_display (), False); + return spi_clear_error_state (); +} + +static void +spi_dec_x11_ungrab_key (SpiDEController *controller, + guint key_val, + Accessibility_ControllerEventMask mod_mask) +{ + XUngrabKey (spi_get_display (), + key_val, + mod_mask, + spi_get_root_window ()); +} + +static unsigned int +xkb_get_slowkeys_delay (SpiDEController *controller) +{ + unsigned int retval = 0; + DEControllerPrivateData *priv = controller->priv; +#ifdef HAVE_XKB +#ifdef XKB_HAS_GET_SLOW_KEYS_DELAY + retval = XkbGetSlowKeysDelay (spi_get_display (), + XkbUseCoreKbd, &bounce_delay); +#else + if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL)) + { + Status s = XkbGetControls (spi_get_display (), + XkbAllControlsMask, priv->xkb_desc); + if (s == Success) + { + if (priv->xkb_desc->ctrls->enabled_ctrls & XkbSlowKeysMask) + retval = priv->xkb_desc->ctrls->slow_keys_delay; + } + } +#endif +#endif +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "SlowKeys delay: %d\n", (int) retval); +#endif + return retval; +} + +static unsigned int +xkb_get_bouncekeys_delay (SpiDEController *controller) +{ + unsigned int retval = 0; + DEControllerPrivateData *priv = controller->priv; +#ifdef HAVE_XKB +#ifdef XKB_HAS_GET_BOUNCE_KEYS_DELAY + retval = XkbGetBounceKeysDelay (spi_get_display (), + XkbUseCoreKbd, &bounce_delay); +#else + if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL)) + { + Status s = XkbGetControls (spi_get_display (), + XkbAllControlsMask, priv->xkb_desc); + if (s == Success) + { + if (priv->xkb_desc->ctrls->enabled_ctrls & XkbBounceKeysMask) + retval = priv->xkb_desc->ctrls->debounce_delay; + } + } +#endif +#endif +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "BounceKeys delay: %d\n", (int) retval); +#endif + return retval; +} + +static gboolean +spi_dec_x11_synth_keycode_press (SpiDEController *controller, + unsigned int keycode) +{ + unsigned int time = CurrentTime; + unsigned int bounce_delay; + unsigned int elapsed_msec; + struct timeval tv; + DEControllerPrivateData *priv = controller->priv; + + spi_x_error_trap (); + if (keycode == priv->last_release_keycode) + { + bounce_delay = xkb_get_bouncekeys_delay (controller); + if (bounce_delay) + { + gettimeofday (&tv, NULL); + elapsed_msec = + (tv.tv_sec - priv->last_release_time.tv_sec) * 1000 + + (tv.tv_usec - priv->last_release_time.tv_usec) / 1000; +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec, + (long) (tv.tv_usec - priv->last_release_time.tv_usec)); +#endif +#ifdef THIS_IS_BROKEN + if (elapsed_msec < bounce_delay) + time = bounce_delay - elapsed_msec + 1; +#else + time = bounce_delay + 10; + /* fudge for broken XTest */ +#endif +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "waiting %d ms\n", time); +#endif + } + } + XTestFakeKeyEvent (spi_get_display (), keycode, True, time); + priv->last_press_keycode = keycode; + XFlush (spi_get_display ()); + XSync (spi_get_display (), False); + gettimeofday (&priv->last_press_time, NULL); + return TRUE; +} + +static gboolean +spi_dec_x11_synth_keycode_release (SpiDEController *controller, + unsigned int keycode) +{ + unsigned int time = CurrentTime; + unsigned int slow_delay; + unsigned int elapsed_msec; + struct timeval tv; + DEControllerPrivateData *priv = controller->priv; + + spi_x_error_trap (); + if (keycode == priv->last_press_keycode) + { + slow_delay = xkb_get_slowkeys_delay (controller); + if (slow_delay) + { + gettimeofday (&tv, NULL); + elapsed_msec = + (tv.tv_sec - priv->last_press_time.tv_sec) * 1000 + + (tv.tv_usec - priv->last_press_time.tv_usec) / 1000; +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "%d ms elapsed (%ld usec)\n", elapsed_msec, + (long) (tv.tv_usec - priv->last_press_time.tv_usec)); +#endif +#ifdef THIS_IS_BROKEN_DUNNO_WHY + if (elapsed_msec < slow_delay) + time = slow_delay - elapsed_msec + 1; +#else + time = slow_delay + 10; + /* our XTest seems broken, we have to add slop as above */ +#endif +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "waiting %d ms\n", time); +#endif + } + } + XTestFakeKeyEvent (spi_get_display (), keycode, False, time); + priv->last_release_keycode = keycode; + XSync (spi_get_display (), False); + gettimeofday (&priv->last_release_time, NULL); + return TRUE; +} + +static gboolean +spi_dec_x11_lock_modifiers (SpiDEController *controller, unsigned modifiers) +{ + DEControllerPrivateData *priv = controller->priv; + + if (priv->have_xkb) { + return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, + modifiers, modifiers); + } else { + int mod_index; + if (xmkeymap==NULL) + xmkeymap = XGetModifierMapping(spi_get_display ()); + for (mod_index=0;mod_index<8;mod_index++) + if (modifiers & (1<modifiermap[mod_index]); + return TRUE; + } +} + +static gboolean +spi_dec_x11_unlock_modifiers (SpiDEController *controller, unsigned modifiers) +{ + DEControllerPrivateData *priv = controller->priv; + + if (priv->have_xkb) { + return XkbLockModifiers (spi_get_display (), XkbUseCoreKbd, + modifiers, 0); + } else { + int mod_index; + if (xmkeymap==NULL) + xmkeymap = XGetModifierMapping(spi_get_display ()); + + for (mod_index=0;mod_index<8;mod_index++) + if (modifiers & (1<modifiermap[mod_index]); + return TRUE; + } +} + +static KeySym +keysym_for_unichar (SpiDEController *controller, gunichar unichar) +{ + return (KeySym) ucs2keysym ((long) unichar); +} + +static gboolean +spi_dec_x11_synth_keystring (SpiDEController *controller, guint synth_type, gint keycode, const char *keystring) +{ + /* probably we need to create and inject an XIM handler eventually. */ + /* for now, try to match the string to existing + * keycode+modifier states. + */ + KeySym *keysyms; + gint maxlen = 0; + gunichar unichar = 0; + gint i = 0; + gboolean retval = TRUE; + const gchar *c; + KeySym keysym; + + if (!(keystring && *keystring && g_utf8_validate (keystring, -1, &c))) { + retval = FALSE; + } + else { +#ifdef SPI_DEBUG + fprintf (stderr, "[keystring synthesis attempted on %s]\n", keystring); +#endif + maxlen = strlen (keystring) + 1; + keysyms = g_new0 (KeySym, maxlen); + + while (keystring && (unichar = g_utf8_get_char (keystring))) { + char bytes[6]; + gint mbytes; + + mbytes = g_unichar_to_utf8 (unichar, bytes); + bytes[mbytes] = '\0'; +#ifdef SPI_DEBUG + fprintf (stderr, "[unichar %s]", bytes); +#endif + keysym = keysym_for_unichar (controller, unichar); + if (keysym == NoSymbol) { +#ifdef SPI_DEBUG + fprintf (stderr, "no keysym for %s", bytes); +#endif + retval = FALSE; + break; + } + keysyms[i++] = keysym; + keystring = g_utf8_next_char (keystring); + } + keysyms[i++] = 0; + XSynchronize (spi_get_display (), TRUE); + for (i = 0; keysyms[i]; ++i) { + if (!spi_dec_synth_keysym (controller, keysyms[i])) { +#ifdef SPI_DEBUG + fprintf (stderr, "could not synthesize %c\n", + (int) keysyms[i]); +#endif + retval = FALSE; + break; + } + } + XSynchronize (spi_get_display (), FALSE); + + g_free (keysyms); + } + + if (synth_type == Accessibility_KEY_SYM) { + keysym = keycode; + } + else { + keysym = XkbKeycodeToKeysym (spi_get_display (), keycode, 0, 0); + } + if (XkbKeysymToModifiers (spi_get_display (), keysym) == 0) { + spi_dec_clear_unlatch_pending (controller); + } + return retval; +} + +static void +spi_dec_x11_init (SpiDEController *controller) +{ + DEControllerPrivateData *priv = controller->priv; + + spi_events_init (spi_get_display ()); + + gettimeofday (&priv->last_press_time, NULL); + gettimeofday (&priv->last_release_time, NULL); + spi_controller_register_with_devices (controller); + + spi_dec_init_mouse_listener (controller); + + saved_controller = controller; +} + +static void +spi_dec_x11_finalize (SpiDEController *controller) +{ + DEControllerPrivateData *priv = controller->priv; + + /* disconnect any special listeners, get rid of outstanding keygrabs */ + XUngrabKey (spi_get_display (), AnyKey, AnyModifier, DefaultRootWindow (spi_get_display ())); + + if (priv->xkb_desc) + XkbFreeKeyboard (priv->xkb_desc, 0, True); + /* TODO: Should free the keymap */ +} + +static gboolean +spi_device_event_controller_forward_key_event (SpiDEController *controller, + const XEvent *event) +{ + DEControllerPrivateData *priv = controller->priv; + Accessibility_DeviceEvent key_event; + gboolean ret; + + g_assert (event->type == KeyPress || event->type == KeyRelease); + + key_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event); + + if (priv->xevie_display == NULL) + spi_controller_update_key_grabs (controller, &key_event); + + /* relay to listeners, and decide whether to consume it or not */ + ret = spi_controller_notify_keylisteners (controller, &key_event, TRUE); + g_free(key_event.event_string); + return ret; +} + + +static gboolean +is_key_released (long code) +{ + char keys[32]; + int down; + + XQueryKeymap (spi_get_display (), keys); + down = BIT (keys, code); + return (down == 0); +} + +static gboolean +check_release (gpointer data) +{ + gboolean released; + Accessibility_DeviceEvent *event = (Accessibility_DeviceEvent *)data; + KeyCode code = event->hw_code; + + released = is_key_released (code); + + if (released) + { + check_release_handler = 0; + event->type = Accessibility_KEY_RELEASED_EVENT; + spi_controller_notify_keylisteners (saved_controller, event, TRUE); + } + return (released == 0); +} + +static void +wait_for_release_event (XEvent *event, + SpiDEController *controller) +{ + pressed_event = spi_keystroke_from_x_key_event ((XKeyEvent *) event); + check_release_handler = g_timeout_add (CHECK_RELEASE_DELAY, check_release, &pressed_event); + g_source_set_name_by_id (check_release_handler, "[at-spi2-core] check_release"); +} + +static void +spi_dec_x11_emit_modifier_event (SpiDEController *controller, guint prev_mask, + guint current_mask) +{ + dbus_uint32_t d1, d2; + +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "MODIFIER CHANGE EVENT! %x to %x\n", + prev_mask, current_mask); +#endif + + /* set bits for the virtual modifiers like NUMLOCK */ + if (prev_mask & _numlock_physical_mask) + prev_mask |= SPI_KEYMASK_NUMLOCK; + if (current_mask & _numlock_physical_mask) + current_mask |= SPI_KEYMASK_NUMLOCK; + + d1 = prev_mask & key_modifier_mask; + d2 = current_mask & key_modifier_mask; + spi_dec_dbus_emit(controller, SPI_DBUS_INTERFACE_EVENT_KEYBOARD, "Modifiers", "", d1, d2); +} + +static void +spi_dec_x11_generate_mouse_event (SpiDEController *controller, + gint x, + gint y, + const char *eventName) +{ + int button = 0; + gboolean err = FALSE; + Display *display = spi_get_display (); + + switch (eventName[0]) + { + case 'b': + switch (eventName[1]) + { + /* TODO: check number of buttons before parsing */ + case '1': + button = 1; + break; + case '2': + button = 2; + break; + case '3': + button = 3; + break; + case '4': + button = 4; + break; + case '5': + button = 5; + break; + default: + err = TRUE; + } + if (!err) + { + if (x != -1 && y != -1) + { + XTestFakeMotionEvent (display, DefaultScreen (display), + x, y, 0); + } + XTestFakeButtonEvent (display, button, !(eventName[2] == 'r'), 0); + if (eventName[2] == 'c') + XTestFakeButtonEvent (display, button, FALSE, 1); + else if (eventName[2] == 'd') + { + XTestFakeButtonEvent (display, button, FALSE, 1); + XTestFakeButtonEvent (display, button, TRUE, 2); + XTestFakeButtonEvent (display, button, FALSE, 3); + } + } + break; + case 'r': /* relative motion */ + XTestFakeRelativeMotionEvent (display, x, y, 0); + break; + case 'a': /* absolute motion */ + XTestFakeMotionEvent (display, DefaultScreen (display), + x, y, 0); + break; + } +} + +void +spi_dec_setup_x11 (SpiDEControllerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + klass->plat.get_keycode = spi_dec_x11_get_keycode; + klass->plat.mouse_check = spi_dec_x11_mouse_check; + klass->plat.synth_keycode_press = spi_dec_x11_synth_keycode_press; + klass->plat.synth_keycode_release = spi_dec_x11_synth_keycode_release; + klass->plat.lock_modifiers = spi_dec_x11_lock_modifiers; + klass->plat.unlock_modifiers = spi_dec_x11_unlock_modifiers; + klass->plat.synth_keystring = spi_dec_x11_synth_keystring; + klass->plat.grab_key = spi_dec_x11_grab_key; + klass->plat.ungrab_key = spi_dec_x11_ungrab_key; + klass->plat.emit_modifier_event = spi_dec_x11_emit_modifier_event; + klass->plat.generate_mouse_event = spi_dec_x11_generate_mouse_event; + + klass->plat.init = spi_dec_x11_init; + klass->plat.finalize = spi_dec_x11_finalize; + + g_type_class_add_private (object_class, sizeof (DEControllerPrivateData)); +} diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c new file mode 100644 index 0000000..0c965ef --- /dev/null +++ b/registryd/deviceeventcontroller.c @@ -0,0 +1,2050 @@ +/* AT-SPI - Assistive Technology Service Provider Interface + * + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2003 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +/* deviceeventcontroller.c: implement the DeviceEventController interface */ + +#include "config.h" + +#undef SPI_XKB_DEBUG +#undef SPI_DEBUG +#undef SPI_KEYEVENT_DEBUG + +#include +#include +#include +#include + +#include + +#include + +#include "paths.h" +#include "de-types.h" +#include "de-marshaller.h" +#include "keymasks.h" + +#ifdef HAVE_X11 +#include "display.h" +#include "event-source.h" +#endif + +#include "deviceeventcontroller.h" +#include "reentrant-list.h" + +#include "introspection.h" + +#define CHECK_RELEASE_DELAY 20 +#define BIT(c, x) (c[x/8]&(1<<(x%8))) +static SpiDEController *saved_controller; + +/* Our parent Gtk object type */ +#define PARENT_TYPE G_TYPE_OBJECT + +/* A pointer to our parent object class */ +static int spi_error_code = 0; +struct _SpiPoint { + gint x; + gint y; +}; +typedef struct _SpiPoint SpiPoint; + +static unsigned int mouse_mask_state = 0; +static unsigned int key_modifier_mask = + SPI_KEYMASK_MOD1 | SPI_KEYMASK_MOD2 | SPI_KEYMASK_MOD3 | SPI_KEYMASK_MOD4 | + SPI_KEYMASK_MOD5 | SPI_KEYMASK_SHIFT | SPI_KEYMASK_SHIFTLOCK | + SPI_KEYMASK_CONTROL | SPI_KEYMASK_NUMLOCK; +static unsigned int _numlock_physical_mask = SPI_KEYMASK_MOD2; /* a guess, will be reset */ + +static gboolean have_mouse_listener = FALSE; +static gboolean have_mouse_event_listener = FALSE; + + +typedef struct { + guint ref_count : 30; + guint pending_add : 1; + guint pending_remove : 1; + + Accessibility_ControllerEventMask mod_mask; + dbus_uint32_t key_val; /* KeyCode */ +} DEControllerGrabMask; + + +gboolean spi_controller_update_key_grabs (SpiDEController *controller, + Accessibility_DeviceEvent *recv); + +static gboolean eventtype_seq_contains_event (dbus_uint32_t types, + const Accessibility_DeviceEvent *event); +static gboolean spi_dec_poll_mouse_moving (gpointer data); +static gboolean spi_dec_poll_mouse_idle (gpointer data); + +G_DEFINE_TYPE(SpiDEController, spi_device_event_controller, G_TYPE_OBJECT) + +static gint +spi_dec_plat_get_keycode (SpiDEController *controller, + gint keysym, + gchar *key_str, + gboolean fix, + guint *modmask) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.get_keycode) + return klass->plat.get_keycode (controller, keysym, key_str, fix, modmask); + else + return keysym; +} + +static guint +spi_dec_plat_mouse_check (SpiDEController *controller, + int *x, int *y, gboolean *moved) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.mouse_check) + return klass->plat.mouse_check (controller, x, y, moved); + else + return 0; +} + +static gboolean +spi_dec_plat_grab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.grab_key) + return klass->plat.grab_key (controller, key_val, mod_mask); + else + return FALSE; +} + +static void +spi_dec_plat_ungrab_key (SpiDEController *controller, guint key_val, Accessibility_ControllerEventMask mod_mask) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.ungrab_key) + klass->plat.ungrab_key (controller, key_val, mod_mask); +} + +static gboolean +spi_dec_plat_synth_keycode_press (SpiDEController *controller, + unsigned int keycode) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.synth_keycode_press) + return klass->plat.synth_keycode_press (controller, keycode); + else + return FALSE; +} + +static gboolean +spi_dec_plat_synth_keycode_release (SpiDEController *controller, + unsigned int keycode) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.synth_keycode_release) + return klass->plat.synth_keycode_release (controller, keycode); + else + return FALSE; +} + +static gboolean +spi_dec_plat_lock_modifiers (SpiDEController *controller, unsigned modifiers) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.lock_modifiers) + return klass->plat.lock_modifiers (controller, modifiers); + else + return FALSE; +} + +static gboolean +spi_dec_plat_unlock_modifiers (SpiDEController *controller, unsigned modifiers) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.unlock_modifiers) + return klass->plat.unlock_modifiers (controller, modifiers); + else + return FALSE; +} + +static gboolean +spi_dec_plat_synth_keystring (SpiDEController *controller, guint synth_type, gint keycode, const char *keystring) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.synth_keystring) + return klass->plat.synth_keystring (controller, synth_type, keycode, keystring); + else + return FALSE; +} + +static void +spi_dec_plat_emit_modifier_event (SpiDEController *controller, guint prev_mask, + guint current_mask) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.emit_modifier_event) + klass->plat.emit_modifier_event (controller, prev_mask, current_mask); +} + +static void +spi_dec_plat_generate_mouse_event (SpiDEController *controller, + gint x, + gint y, + const char *eventName) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); + if (klass->plat.generate_mouse_event) + klass->plat.generate_mouse_event (controller, x, y, eventName); +} + +DBusMessage * +invalid_arguments_error (DBusMessage *message) +{ + DBusMessage *reply; + gchar *errmsg; + + errmsg= g_strdup_printf ( + "Method \"%s\" with signature \"%s\" on interface \"%s\" was supplied with invalid arguments\n", + dbus_message_get_member (message), + dbus_message_get_signature (message), + dbus_message_get_interface (message)); + reply = dbus_message_new_error (message, + DBUS_ERROR_INVALID_ARGS, + errmsg); + g_free (errmsg); + return reply; +} + +/* Private methods */ +static dbus_bool_t +spi_dbus_add_disconnect_match (DBusConnection *bus, const char *name) +{ + char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name); + if (match) + { + DBusError error; + dbus_error_init (&error); + dbus_bus_add_match (bus, match, &error); + g_free (match); + if (dbus_error_is_set (&error)) + { + dbus_error_free (&error); + return FALSE; + } + else + { + return TRUE; + } + } + else return FALSE; +} + +static dbus_bool_t +spi_dbus_remove_disconnect_match (DBusConnection *bus, const char *name) +{ + char *match = g_strdup_printf ("interface=%s,member=NameOwnerChanged,arg0=%s", DBUS_INTERFACE_DBUS, name); + if (match) + { + DBusError error; + dbus_error_init (&error); + dbus_bus_remove_match (bus, match, &error); + g_free (match); + if (dbus_error_is_set (&error)) + { + dbus_error_free (&error); + return FALSE; + } + else + { + return TRUE; + } + } + else return FALSE; +} + +static DEControllerGrabMask * +spi_grab_mask_clone (DEControllerGrabMask *grab_mask) +{ + DEControllerGrabMask *clone = g_new (DEControllerGrabMask, 1); + + memcpy (clone, grab_mask, sizeof (DEControllerGrabMask)); + + clone->ref_count = 1; + clone->pending_add = TRUE; + clone->pending_remove = FALSE; + + return clone; +} + +static void +spi_grab_mask_free (DEControllerGrabMask *grab_mask) +{ + g_free (grab_mask); +} + +static gint +spi_grab_mask_compare_values (gconstpointer p1, gconstpointer p2) +{ + DEControllerGrabMask *l1 = (DEControllerGrabMask *) p1; + DEControllerGrabMask *l2 = (DEControllerGrabMask *) p2; + + if (p1 == p2) + { + return 0; + } + else + { + return ((l1->mod_mask != l2->mod_mask) || (l1->key_val != l2->key_val)); + } +} + +void +spi_dec_dbus_emit (SpiDEController *controller, const char *interface, + const char *name, const char *minor, int a1, int a2) +{ + DBusMessage *signal = NULL; + DBusMessageIter iter, iter_struct, iter_variant; + int nil = 0; + const char *path = SPI_DBUS_PATH_ROOT; + const char *bus_name = dbus_bus_get_unique_name (controller->bus); + + signal = dbus_message_new_signal (path, interface, name); + + dbus_message_iter_init_append (signal, &iter); + + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a1); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &a2); + dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant); + dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &nil); + dbus_message_iter_close_container (&iter, &iter_variant); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (&iter, &iter_struct); + + dbus_connection_send (controller->bus, signal, NULL); + dbus_message_unref (signal); +} + +static gboolean +spi_dec_poll_mouse_moved (gpointer data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(data); + int x, y; + gboolean moved; + guint mask_return; + + mask_return = spi_dec_plat_mouse_check (controller, &x, &y, &moved); + + if ((mask_return & key_modifier_mask) != + (mouse_mask_state & key_modifier_mask)) + { + spi_dec_plat_emit_modifier_event (controller, mouse_mask_state, mask_return); + mouse_mask_state = mask_return; + } + + return moved; +} + +static gboolean +spi_dec_poll_mouse_idle (gpointer data) +{ + if (!have_mouse_event_listener && !have_mouse_listener) + return FALSE; + else if (!spi_dec_poll_mouse_moved (data)) + return TRUE; + else + { + guint id; + id = g_timeout_add (20, spi_dec_poll_mouse_moving, data); + g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_moving"); + return FALSE; + } +} + +static gboolean +spi_dec_poll_mouse_moving (gpointer data) +{ + if (!have_mouse_event_listener && !have_mouse_listener) + return FALSE; + else if (spi_dec_poll_mouse_moved (data)) + return TRUE; + else + { + guint id; + id = g_timeout_add (100, spi_dec_poll_mouse_idle, data); + g_source_set_name_by_id (id, "[at-spi2-core] check_release"); + return FALSE; + } +} + +/** + * Eventually we can use this to make the marshalling of mask types + * more sane, but for now we just use this to detect + * the use of 'virtual' masks such as numlock and convert them to + * system-specific mask values (i.e. ModMask). + * + **/ +static Accessibility_ControllerEventMask +spi_dec_translate_mask (Accessibility_ControllerEventMask mask) +{ + Accessibility_ControllerEventMask tmp_mask; + gboolean has_numlock; + + has_numlock = (mask & SPI_KEYMASK_NUMLOCK); + tmp_mask = mask; + if (has_numlock) + { + tmp_mask = mask ^ SPI_KEYMASK_NUMLOCK; + tmp_mask |= _numlock_physical_mask; + } + + return tmp_mask; +} + +static DEControllerKeyListener * +spi_dec_key_listener_new (const char *bus_name, + const char *path, + GSList *keys, + const Accessibility_ControllerEventMask mask, + const dbus_uint32_t types, + const Accessibility_EventListenerMode *mode) +{ + DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1); + key_listener->listener.bus_name = g_strdup(bus_name); + key_listener->listener.path = g_strdup(path); + key_listener->listener.type = SPI_DEVICE_TYPE_KBD; + key_listener->keys = keys; + key_listener->mask = spi_dec_translate_mask (mask); + key_listener->listener.types = types; + if (mode) + { + key_listener->mode = (Accessibility_EventListenerMode *) g_malloc(sizeof(Accessibility_EventListenerMode)); + memcpy(key_listener->mode, mode, sizeof(*mode)); + } + else + key_listener->mode = NULL; + +#ifdef SPI_DEBUG + g_print ("new listener, with mask %x, is_global %d, keys %p (%d)\n", + (unsigned int) key_listener->mask, + (int) (mode ? mode->global : 0), + (void *) key_listener->keys, + (int) (key_listener->keys ? g_slist_length(key_listener->keys) : 0)); +#endif + + return key_listener; +} + +static DEControllerListener * +spi_dec_listener_new (const char *bus_name, + const char *path, + dbus_uint32_t types) +{ + DEControllerListener *listener = g_new0 (DEControllerListener, 1); + listener->bus_name = g_strdup(bus_name); + listener->path = g_strdup(path); + listener->type = SPI_DEVICE_TYPE_MOUSE; + listener->types = types; + return listener; +} + +static DEControllerListener * +spi_listener_clone (DEControllerListener *listener) +{ + DEControllerListener *clone = g_new0 (DEControllerListener, 1); + clone->bus_name = g_strdup (listener->bus_name); + clone->path = g_strdup (listener->path); + clone->type = listener->type; + clone->types = listener->types; + return clone; +} + +static GSList *keylist_clone (GSList *s) +{ + GSList *d = NULL; + GSList *l; + + for (l = s; l; l = g_slist_next(l)) + { + Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition)); + if (kd) + { + Accessibility_KeyDefinition *kds = (Accessibility_KeyDefinition *)l->data; + kd->keycode = kds->keycode; + kd->keysym = kds->keysym; + kd->keystring = g_strdup(kds->keystring); + d = g_slist_append(d, kd); + } + } + return d; +} + +static DEControllerKeyListener * +spi_key_listener_clone (DEControllerKeyListener *key_listener) +{ + DEControllerKeyListener *clone = g_new0 (DEControllerKeyListener, 1); + clone->listener.bus_name = g_strdup (key_listener->listener.bus_name); + clone->listener.path = g_strdup (key_listener->listener.path); + clone->listener.type = SPI_DEVICE_TYPE_KBD; + clone->keys = keylist_clone (key_listener->keys); + clone->mask = key_listener->mask; + clone->listener.types = key_listener->listener.types; + if (key_listener->mode) + { + clone->mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode)); + if (clone->mode) memcpy(clone->mode, key_listener->mode, sizeof(Accessibility_EventListenerMode)); + } + else + clone->mode = NULL; + return clone; +} + +static void keylist_free(GSList *keys) +{ + GSList *l; + + for (l = keys; l; l = g_slist_next(l)) + { + Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)l->data; + g_free(kd->keystring); + g_free(kd); + } + g_slist_free (keys); +} + +static void +spi_key_listener_data_free (DEControllerKeyListener *key_listener) +{ + keylist_free(key_listener->keys); + if (key_listener->mode) g_free(key_listener->mode); + g_free (key_listener->listener.bus_name); + g_free (key_listener->listener.path); + g_free (key_listener); +} + +static void +spi_key_listener_clone_free (DEControllerKeyListener *clone) +{ + spi_key_listener_data_free (clone); +} + +static void +spi_listener_clone_free (DEControllerListener *clone) +{ + g_free (clone->path); + g_free (clone->bus_name); + g_free (clone); +} + +static void +spi_dec_listener_free (DEControllerListener *listener) +{ + if (listener->type == SPI_DEVICE_TYPE_KBD) + spi_key_listener_data_free ((DEControllerKeyListener *) listener); + else + { + g_free (listener->bus_name); + g_free (listener->path); + } +} + +static void +_register_keygrab (SpiDEController *controller, + DEControllerGrabMask *grab_mask) +{ + GList *l; + + l = g_list_find_custom (controller->keygrabs_list, grab_mask, + spi_grab_mask_compare_values); + if (l) + { + DEControllerGrabMask *cur_mask = l->data; + + cur_mask->ref_count++; + if (cur_mask->pending_remove) + { + cur_mask->pending_remove = FALSE; + } + } + else + { + controller->keygrabs_list = + g_list_prepend (controller->keygrabs_list, + spi_grab_mask_clone (grab_mask)); + } +} + +static void +_deregister_keygrab (SpiDEController *controller, + DEControllerGrabMask *grab_mask) +{ + GList *l; + + l = g_list_find_custom (controller->keygrabs_list, grab_mask, + spi_grab_mask_compare_values); + + if (l) + { + DEControllerGrabMask *cur_mask = l->data; + + cur_mask->ref_count--; + if (cur_mask->ref_count <= 0) + { + cur_mask->pending_remove = TRUE; + } + } +} + +static void +handle_keygrab (SpiDEController *controller, + DEControllerKeyListener *key_listener, + void (*process_cb) (SpiDEController *controller, + DEControllerGrabMask *grab_mask)) +{ + DEControllerGrabMask grab_mask = { 0 }; + + grab_mask.mod_mask = key_listener->mask; + if (g_slist_length (key_listener->keys) == 0) /* special case means AnyKey/AllKeys */ + { + grab_mask.key_val = 0L; /* AnyKey */ +#ifdef SPI_DEBUG + fprintf (stderr, "AnyKey grab!"); +#endif + process_cb (controller, &grab_mask); + } + else + { + GSList *l; + + for (l = key_listener->keys; l; l = g_slist_next(l)) + { + Accessibility_KeyDefinition *keydef = l->data; + long key_val; + key_val = spi_dec_plat_get_keycode (controller, keydef->keysym, keydef->keystring, FALSE, NULL); + if (!key_val) + key_val = keydef->keycode; + grab_mask.key_val = key_val; + process_cb (controller, &grab_mask); + } + } +} + +static gboolean +spi_controller_register_global_keygrabs (SpiDEController *controller, + DEControllerKeyListener *key_listener) +{ + handle_keygrab (controller, key_listener, _register_keygrab); + return spi_controller_update_key_grabs (controller, NULL); +} + +static void +spi_controller_deregister_global_keygrabs (SpiDEController *controller, + DEControllerKeyListener *key_listener) +{ + handle_keygrab (controller, key_listener, _deregister_keygrab); + spi_controller_update_key_grabs (controller, NULL); +} + +static void +append_keystroke_listener (DBusMessageIter *iter, DEControllerKeyListener *listener) +{ + dbus_uint32_t d_uint; + DBusMessageIter iter_struct, iter_subarray, iter_substruct; + GSList *kl; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct)) + return; + + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, + &listener->listener.bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, + &listener->listener.path); + d_uint = listener->listener.type; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint); + d_uint = listener->listener.types; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint); + if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, + "(iisi)", &iter_subarray)) + { + dbus_message_iter_close_container (iter, &iter_struct); + return; + } + for (kl = listener->keys; kl; kl = kl->next) + { + Accessibility_KeyDefinition *kd = kl->data; + if (!dbus_message_iter_open_container (&iter_subarray, DBUS_TYPE_STRUCT, + NULL, &iter_substruct)) + break; + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keycode); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->keysym); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_STRING, &kd->keystring); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_INT32, &kd->unused); + dbus_message_iter_close_container (&iter_subarray, &iter_substruct); + } + dbus_message_iter_close_container (&iter_struct, &iter_subarray); + d_uint = listener->mask; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint); + if (dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT, + NULL, &iter_substruct)) + { + if (listener->mode) + { + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &listener->mode->synchronous); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &listener->mode->preemptive); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &listener->mode->global); + } + else + { + dbus_bool_t dummy_val = FALSE; + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &dummy_val); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &dummy_val); + dbus_message_iter_append_basic (&iter_substruct, DBUS_TYPE_BOOLEAN, + &dummy_val); + } + dbus_message_iter_close_container (&iter_struct, &iter_substruct); + } + dbus_message_iter_close_container (iter, &iter_struct); +} + +static void +notify_keystroke_listener (SpiDEController *controller, + DEControllerKeyListener *listener, + gboolean enable) +{ + const char *path = SPI_DBUS_PATH_DEC; + const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER; + const char *name = (enable + ? "KeystrokeListenerRegistered" + : "KeystrokeListenerDeregistered"); + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal (path, interface, name); + if (!signal) + return; + dbus_message_iter_init_append (signal, &iter); + append_keystroke_listener (&iter, listener); + dbus_connection_send (controller->bus, signal, NULL); + dbus_message_unref (signal); +} + +static void +append_mouse_listener (DBusMessageIter *iter, DEControllerListener *listener) +{ + DBusMessageIter iter_struct; + dbus_uint32_t d_uint; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct)) + return; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, + &listener->bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, + &listener->path); + d_uint = listener->types; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &d_uint); + dbus_message_iter_close_container (iter, &iter_struct); +} + +static void +notify_mouse_listener (SpiDEController *controller, + DEControllerListener *listener, + gboolean enable) +{ + const char *path = SPI_DBUS_PATH_DEC; + const char *interface = SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER; + const char *name = (enable + ? "DeviceListenerRegistered" + : "DeviceListenerDeregistered"); + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal (path, interface, name); + if (!signal) + return; + dbus_message_iter_init_append (signal, &iter); + append_mouse_listener (&iter, listener); + dbus_connection_send (controller->bus, signal, NULL); + dbus_message_unref (signal); +} + +static gboolean +spi_controller_register_device_listener (SpiDEController *controller, + DEControllerListener *listener) +{ + DEControllerKeyListener *key_listener; + gboolean retval; + + switch (listener->type) { + case SPI_DEVICE_TYPE_KBD: + key_listener = (DEControllerKeyListener *) listener; + + controller->key_listeners = g_list_prepend (controller->key_listeners, + key_listener); + spi_dbus_add_disconnect_match (controller->bus, key_listener->listener.bus_name); + if (key_listener->mode->global) + { + retval = spi_controller_register_global_keygrabs (controller, key_listener); + } + else + retval = TRUE; + if (retval) + notify_keystroke_listener (controller, key_listener, TRUE); + break; + case SPI_DEVICE_TYPE_MOUSE: + controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener); + if (!have_mouse_listener) + { + have_mouse_listener = TRUE; + if (!have_mouse_event_listener) { + guint id; + id = g_timeout_add (100, spi_dec_poll_mouse_idle, controller); + g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle"); + } + } + spi_dbus_add_disconnect_match (controller->bus, listener->bus_name); + notify_mouse_listener (controller, listener, TRUE); + break; + default: + break; + } + return FALSE; +} + +static void +set_reply (DBusPendingCall *pending, void *user_data) +{ + void **replyptr = (void **)user_data; + + *replyptr = dbus_pending_call_steal_reply (pending); +} + +static GSList *hung_processes = NULL; + +static void +reset_hung_process (DBusPendingCall *pending, void *data) +{ + DBusMessage *message = data; + const char *dest = dbus_message_get_destination (message); + GSList *l; + + /* At this point we don't care about the result */ + dbus_pending_call_unref (pending); + + for (l = hung_processes; l; l = l->next) + { + if (!strcmp (l->data, dest)) + { + g_free (l->data); + hung_processes = g_slist_remove (hung_processes, l->data); + break; + } + } +} + +static gint +time_elapsed (struct timeval *origin) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return (tv.tv_sec - origin->tv_sec) * 1000 + (tv.tv_usec - origin->tv_usec) / 1000; +} + +static void +reset_hung_process_from_ping (DBusPendingCall *pending, void *data) +{ + GSList *l; + + for (l = hung_processes; l; l = l->next) + { + if (!strcmp (l->data, data)) + { + g_free (l->data); + hung_processes = g_slist_remove (hung_processes, l->data); + break; + } + } + g_free (data); + dbus_pending_call_unref (pending); +} + +static DBusMessage * +send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error) +{ + DBusPendingCall *pending; + DBusMessage *reply = NULL; + struct timeval tv; + + if (!dbus_connection_send_with_reply (bus, message, &pending, -1)) + { + return NULL; + } + dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL); + gettimeofday (&tv, NULL); + while (!reply) + { + if (!dbus_connection_read_write_dispatch (bus, timeout) || + time_elapsed (&tv) > timeout) + { + const char *dest = dbus_message_get_destination (message); + GSList *l; + gchar *bus_name_dup; + dbus_message_ref (message); + dbus_pending_call_set_notify (pending, reset_hung_process, message, + (DBusFreeFunction) dbus_message_unref); + message = dbus_message_new_method_call (dest, "/", + "org.freedesktop.DBus.Peer", + "Ping"); + if (!message) + return NULL; + dbus_connection_send_with_reply (bus, message, &pending, -1); + dbus_message_unref (message); + if (!pending) + return NULL; + bus_name_dup = g_strdup (dest); + dbus_pending_call_set_notify (pending, reset_hung_process_from_ping, + bus_name_dup, NULL); + for (l = hung_processes; l; l = l->next) + if (!strcmp (l->data, dest)) + return NULL; + hung_processes = g_slist_prepend (hung_processes, g_strdup (dest)); + return NULL; + } + } + dbus_pending_call_unref (pending); + return reply; +} +static gboolean +Accessibility_DeviceEventListener_NotifyEvent(SpiDEController *controller, + SpiRegistry *registry, + DEControllerListener *listener, + const Accessibility_DeviceEvent *key_event) +{ + DBusMessage *message = dbus_message_new_method_call(listener->bus_name, + listener->path, + SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER, + "NotifyEvent"); + dbus_bool_t consumed = FALSE; + GSList *l; + gboolean hung = FALSE; + + for (l = hung_processes; l; l = l->next) + { + if (!strcmp (l->data, listener->bus_name)) + { + dbus_message_set_no_reply (message, TRUE); + hung = TRUE; + break; + } + } + + if (spi_dbus_marshal_deviceEvent(message, key_event)) + { + DBusMessage *reply; + + if (hung) + { + dbus_connection_send (controller->bus, message, NULL); + dbus_message_unref (message); + return FALSE; + } + + reply = send_and_allow_reentry (controller->bus, message, 3000, NULL); + if (reply) + { + dbus_message_get_args(reply, NULL, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + } + } + dbus_message_unref(message); + return consumed; +} + +gboolean +spi_controller_notify_mouselisteners (SpiDEController *controller, + const Accessibility_DeviceEvent *event) +{ + GList *l; + GSList *notify = NULL, *l2; + GList **listeners = &controller->mouse_listeners; + gboolean is_consumed; +#ifdef SPI_KEYEVENT_DEBUG + gboolean found = FALSE; +#endif + if (!listeners) + { + return FALSE; + } + + for (l = *listeners; l; l = l->next) + { + DEControllerListener *listener = l->data; + + if (eventtype_seq_contains_event (listener->types, event)) + { + /* we clone (don't dup) the listener, to avoid refcount inc. */ + notify = g_slist_prepend (notify, + spi_listener_clone (listener)); +#ifdef SPI_KEYEVENT_DEBUG + found = TRUE; +#endif + } + } + +#ifdef SPI_KEYEVENT_DEBUG + if (!found) + { + g_print ("no match for event\n"); + } +#endif + + is_consumed = FALSE; + for (l2 = notify; l2 && !is_consumed; l2 = l2->next) + { + DEControllerListener *listener = l2->data; + + is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, listener, event); + + spi_listener_clone_free ((DEControllerListener *) l2->data); + } + + for (; l2; l2 = l2->next) + { + DEControllerListener *listener = l2->data; + spi_listener_clone_free (listener); + /* clone doesn't have its own ref, so don't use spi_device_listener_free */ + } + + g_slist_free (notify); + +#ifdef SPI_DEBUG + if (is_consumed) g_message ("consumed\n"); +#endif + return is_consumed; +} + +static gboolean +key_set_contains_key (GSList *key_set, + const Accessibility_DeviceEvent *key_event) +{ + gint i; + gint len; + GSList *l; + + if (!key_set) + { +#ifdef SPI_DEBUG + g_print ("null key set!\n"); +#endif + return TRUE; + } + + len = g_slist_length (key_set); + + if (len == 0) /* special case, means "all keys/any key" */ + { +#ifdef SPI_DEBUG + g_print ("anykey\n"); +#endif + return TRUE; + } + + for (l = key_set,i = 0; l; l = g_slist_next(l),i++) + { + Accessibility_KeyDefinition *kd = l->data; +#ifdef SPI_KEYEVENT_DEBUG + g_print ("key_set[%d] event = %d, code = %d; key_event %d, code %d, string %s\n", + i, + (int) kd->keysym, + (int) kd->keycode, + (int) key_event->id, + (int) key_event->hw_code, + key_event->event_string); +#endif + if (kd->keysym == (dbus_uint32_t) key_event->id) + { + return TRUE; + } + if (kd->keycode == (dbus_uint32_t) key_event->hw_code) + { + return TRUE; + } + if (key_event->event_string && key_event->event_string[0] && + !strcmp (kd->keystring, key_event->event_string)) + { + return TRUE; + } + } + + return FALSE; +} + +static gboolean +eventtype_seq_contains_event (dbus_uint32_t types, + const Accessibility_DeviceEvent *event) +{ + if (types == 0) /* special case, means "all events/any event" */ + { + return TRUE; + } + + return (types & (1 << event->type)); +} + +static gboolean +spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event, + DEControllerKeyListener *listener, + dbus_bool_t is_system_global) +{ + if (((key_event->modifiers & 0xFF) == (dbus_uint16_t) (listener->mask & 0xFF)) && + key_set_contains_key (listener->keys, key_event) && + eventtype_seq_contains_event (listener->listener.types, key_event) && + (is_system_global == listener->mode->global)) + { + return TRUE; + } + else + { + return FALSE; + } +} + +gboolean +spi_controller_notify_keylisteners (SpiDEController *controller, + Accessibility_DeviceEvent *key_event, + dbus_bool_t is_system_global) +{ + GList *l; + GSList *notify = NULL, *l2; + GList **key_listeners = &controller->key_listeners; + gboolean is_consumed; + + if (!key_listeners) + { + return FALSE; + } + + /* set the NUMLOCK event mask bit if appropriate: see bug #143702 */ + if (key_event->modifiers & _numlock_physical_mask) + key_event->modifiers |= SPI_KEYMASK_NUMLOCK; + + for (l = *key_listeners; l; l = l->next) + { + DEControllerKeyListener *key_listener = l->data; + + if (spi_key_event_matches_listener (key_event, key_listener, is_system_global)) + { + /* we clone (don't dup) the listener, to avoid refcount inc. */ + notify = g_slist_prepend (notify, + spi_key_listener_clone (key_listener)); + } + } + +#ifdef SPI_KEYEVENT_DEBUG + if (!notify) + { + g_print ("no match for event\n"); + } +#endif + + is_consumed = FALSE; + for (l2 = notify; l2 && !is_consumed; l2 = l2->next) + { + DEControllerKeyListener *key_listener = l2->data; + + is_consumed = Accessibility_DeviceEventListener_NotifyEvent (controller, controller->registry, &key_listener->listener, key_event) && + key_listener->mode->preemptive; + + spi_key_listener_clone_free (key_listener); + } + + for (; l2; l2 = l2->next) + { + DEControllerKeyListener *key_listener = l2->data; + spi_key_listener_clone_free (key_listener); + /* clone doesn't have its own ref, so don't use spi_dec_listener_free */ + } + + g_slist_free (notify); + +#ifdef SPI_DEBUG + if (is_consumed) g_message ("consumed\n"); +#endif + return is_consumed; +} + +gboolean +spi_clear_error_state (void) +{ + gboolean retval = spi_error_code != 0; + spi_error_code = 0; + return retval; +} + +gboolean +spi_controller_update_key_grabs (SpiDEController *controller, + Accessibility_DeviceEvent *recv) +{ + GList *l, *next; + gboolean update_failed = FALSE; + long keycode = 0; + + g_return_val_if_fail (controller != NULL, FALSE); + + /* + * masks known to work with default RH 7.1+: + * 0 (no mods), LockMask, Mod1Mask, Mod2Mask, ShiftMask, + * ShiftMask|LockMask, Mod1Mask|LockMask, Mod2Mask|LockMask, + * ShiftMask|Mod1Mask, ShiftMask|Mod2Mask, Mod1Mask|Mod2Mask, + * ShiftMask|LockMask|Mod1Mask, ShiftMask|LockMask|Mod2Mask, + * + * ControlMask grabs are broken, must be in use already + */ + if (recv) + keycode = spi_dec_plat_get_keycode (controller, recv->id, NULL, TRUE, NULL); + for (l = controller->keygrabs_list; l; l = next) + { + gboolean do_remove; + gboolean re_issue_grab; + DEControllerGrabMask *grab_mask = l->data; + + next = l->next; + + re_issue_grab = recv && + (recv->modifiers & grab_mask->mod_mask) && + (grab_mask->key_val == keycode); + +#ifdef SPI_DEBUG + fprintf (stderr, "mask=%lx %lx (%c%c) %s\n", + (long int) grab_mask->key_val, + (long int) grab_mask->mod_mask, + grab_mask->pending_add ? '+' : '.', + grab_mask->pending_remove ? '-' : '.', + re_issue_grab ? "re-issue": ""); +#endif + + do_remove = FALSE; + + if (grab_mask->pending_add && grab_mask->pending_remove) + { + do_remove = TRUE; + } + else if (grab_mask->pending_remove) + { +#ifdef SPI_DEBUG + fprintf (stderr, "ungrabbing, mask=%x\n", grab_mask->mod_mask); +#endif + spi_dec_plat_ungrab_key (controller, + grab_mask->key_val, + grab_mask->mod_mask); + + do_remove = TRUE; + } + else if (grab_mask->pending_add || re_issue_grab) + { + +#ifdef SPI_DEBUG + fprintf (stderr, "grab %d with mask %x\n", grab_mask->key_val, grab_mask->mod_mask); +#endif + update_failed = spi_dec_plat_grab_key (controller, + grab_mask->key_val, + grab_mask->mod_mask); + if (update_failed) { + while (grab_mask->ref_count > 0) --grab_mask->ref_count; + do_remove = TRUE; + } + } + + grab_mask->pending_add = FALSE; + grab_mask->pending_remove = FALSE; + + if (do_remove) + { + g_assert (grab_mask->ref_count <= 0); + + controller->keygrabs_list = g_list_delete_link ( + controller->keygrabs_list, l); + + spi_grab_mask_free (grab_mask); + } + + } + + return ! update_failed; +} + +/* + * Implemented GObject::finalize + */ +static void +spi_device_event_controller_object_finalize (GObject *object) +{ + SpiDEController *controller; + GObjectClass *parent_class = G_OBJECT_CLASS(spi_device_event_controller_parent_class); + SpiDEControllerClass *klass; + + controller = SPI_DEVICE_EVENT_CONTROLLER (object); + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (controller); +#ifdef SPI_DEBUG + fprintf(stderr, "spi_device_event_controller_object_finalize called\n"); +#endif + if (klass->plat.finalize) + klass->plat.finalize (controller); + + parent_class->finalize (object); +} + +/* + * DBus Accessibility::DEController::RegisterKeystrokeListener + * method implementation + */ +static DBusMessage * +impl_register_keystroke_listener (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DEControllerKeyListener *dec_listener; + DBusMessageIter iter, iter_array; + const char *path; + GSList *keys = NULL; + dbus_int32_t mask, type; + Accessibility_EventListenerMode *mode; + dbus_bool_t ret; + DBusMessage *reply = NULL; + char *keystring; + + if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu(bbb)") != 0) + return invalid_arguments_error (message); + + dbus_message_iter_init(message, &iter); + dbus_message_iter_get_basic(&iter, &path); + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &iter_array); + while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID) + { + Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition)); + if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID)) + { + break; + } + kd->keystring = g_strdup (keystring); + keys = g_slist_append(keys, kd); + } + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &mask); + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &type); + dbus_message_iter_next(&iter); + mode = (Accessibility_EventListenerMode *)g_malloc(sizeof(Accessibility_EventListenerMode)); + if (mode) + { + spi_dbus_message_iter_get_struct(&iter, DBUS_TYPE_BOOLEAN, &mode->synchronous, DBUS_TYPE_BOOLEAN, &mode->preemptive, DBUS_TYPE_BOOLEAN, &mode->global, DBUS_TYPE_INVALID); + } +#ifdef SPI_DEBUG + fprintf (stderr, "registering keystroke listener %s:%s with maskVal %lu\n", + dbus_message_get_sender(message), path, (unsigned long) mask); +#endif + dec_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, mode); + g_free (mode); + ret = spi_controller_register_device_listener ( + controller, (DEControllerListener *) dec_listener); + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID); + } + return reply; +} + +/* + * DBus Accessibility::DEController::RegisterDeviceEventListener + * method implementation + */ +static DBusMessage * +impl_register_device_event_listener (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DEControllerListener *dec_listener; + const char *path; + dbus_int32_t event_types; + dbus_bool_t ret; + DBusMessage *reply = NULL; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID)) + { + return invalid_arguments_error (message); + } + dec_listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types); + ret = spi_controller_register_device_listener ( + controller, (DEControllerListener *) dec_listener); + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID); + } + return reply; +} + +typedef struct { + DBusConnection *bus; + DEControllerListener *listener; +} RemoveListenerClosure; + +static SpiReEntrantContinue +remove_listener_cb (GList * const *list, + gpointer user_data) +{ + DEControllerListener *listener = (*list)->data; + RemoveListenerClosure *ctx = user_data; + + if (!strcmp(ctx->listener->bus_name, listener->bus_name) && + !strcmp(ctx->listener->path, listener->path)) + { + spi_re_entrant_list_delete_link (list); + spi_dbus_remove_disconnect_match (ctx->bus, listener->bus_name); + spi_dec_listener_free (listener); + } + + return SPI_RE_ENTRANT_CONTINUE; +} + +static SpiReEntrantContinue +copy_key_listener_cb (GList * const *list, + gpointer user_data) +{ + DEControllerKeyListener *key_listener = (*list)->data; + RemoveListenerClosure *ctx = user_data; + + if (!strcmp(ctx->listener->bus_name, key_listener->listener.bus_name) && + !strcmp(ctx->listener->path, key_listener->listener.path)) + { + /* TODO: FIXME aggregate keys in case the listener is registered twice */ + DEControllerKeyListener *ctx_key_listener = + (DEControllerKeyListener *) ctx->listener; + keylist_free (ctx_key_listener->keys); + ctx_key_listener->keys = keylist_clone(key_listener->keys); + } + + return SPI_RE_ENTRANT_CONTINUE; +} + +static void +spi_controller_deregister_device_listener (SpiDEController *controller, + DEControllerListener *listener) +{ + RemoveListenerClosure ctx; + + ctx.bus = controller->bus; + ctx.listener = listener; + + notify_mouse_listener (controller, listener, FALSE); + + spi_re_entrant_list_foreach (&controller->mouse_listeners, + remove_listener_cb, &ctx); + if (!controller->mouse_listeners) + have_mouse_listener = FALSE; +} + +static void +spi_deregister_controller_key_listener (SpiDEController *controller, + DEControllerKeyListener *key_listener) +{ + RemoveListenerClosure ctx; + + ctx.bus = controller->bus; + ctx.listener = (DEControllerListener *) spi_key_listener_clone (key_listener); + + notify_keystroke_listener (controller, key_listener, FALSE); + + /* special case, copy keyset from existing controller list entry */ + if (g_slist_length(key_listener->keys) == 0) + { + spi_re_entrant_list_foreach (&controller->key_listeners, + copy_key_listener_cb, &ctx); + } + + spi_controller_deregister_global_keygrabs (controller, key_listener); + + spi_re_entrant_list_foreach (&controller->key_listeners, + remove_listener_cb, &ctx); + + spi_key_listener_clone_free ((DEControllerKeyListener *) ctx.listener); +} + +void +spi_remove_device_listeners (SpiDEController *controller, const char *bus_name) +{ + GList *l, *tmp; + + for (l = controller->mouse_listeners; l; l = tmp) + { + DEControllerListener *listener = l->data; + tmp = l->next; + if (!strcmp (listener->bus_name, bus_name)) + { + spi_controller_deregister_device_listener (controller, listener); + tmp = controller->mouse_listeners; + } + } + for (l = controller->key_listeners; l; l = tmp) + { + DEControllerKeyListener *key_listener = l->data; + tmp = l->next; + if (!strcmp (key_listener->listener.bus_name, bus_name)) + { + /* TODO: untangle the below line(s) */ + spi_deregister_controller_key_listener (controller, key_listener); + tmp = controller->key_listeners; + } + } +} + +/* + * DBus Accessibility::DEController::DeregisterKeystrokeListener + * method implementation + */ +static DBusMessage * +impl_deregister_keystroke_listener (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DEControllerKeyListener *key_listener; + DBusMessageIter iter, iter_array; + const char *path; + GSList *keys = NULL; + dbus_int32_t mask, type; + DBusMessage *reply = NULL; + + dbus_message_iter_init(message, &iter); + if (strcmp (dbus_message_get_signature (message), "oa(iisi)uu") != 0) + { + g_warning ("Received DeregisterKeystrokeListener with strange signature '%s'", dbus_message_get_signature (message)); + return invalid_arguments_error (message); + } + + dbus_message_iter_get_basic(&iter, &path); + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &iter_array); + while (dbus_message_iter_get_arg_type(&iter_array) != DBUS_TYPE_INVALID) + { + Accessibility_KeyDefinition *kd = (Accessibility_KeyDefinition *)g_malloc(sizeof(Accessibility_KeyDefinition)); + char *keystring; + + if (!spi_dbus_message_iter_get_struct(&iter_array, DBUS_TYPE_INT32, &kd->keycode, DBUS_TYPE_INT32, &kd->keysym, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_INVALID)) + { + break; + } + kd->keystring = g_strdup (keystring); + keys = g_slist_append(keys, kd); + } + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &mask); + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &type); + dbus_message_iter_next(&iter); + key_listener = spi_dec_key_listener_new (dbus_message_get_sender(message), path, keys, mask, type, NULL); +#ifdef SPI_DEREGISTER_DEBUG + fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n", + (void *) l, (unsigned long) mask->value); +#endif + + spi_deregister_controller_key_listener (controller, key_listener); + + spi_dec_listener_free ((DEControllerListener *) key_listener); + reply = dbus_message_new_method_return (message); + return reply; +} + +/* + * DBus Accessibility::DEController::DeregisterDeviceEventListener + * method implementation + */ +static DBusMessage * +impl_deregister_device_event_listener (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DEControllerListener *listener; + const char *path; + dbus_int32_t event_types; + DBusMessage *reply = NULL; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UINT32, &event_types, DBUS_TYPE_INVALID)) + { + return invalid_arguments_error (message); + } + listener = spi_dec_listener_new (dbus_message_get_sender(message), path, event_types); + spi_controller_deregister_device_listener ( + controller, listener); + reply = dbus_message_new_method_return (message); + return reply; +} + +static DBusMessage * +impl_get_keystroke_listeners (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DBusMessageIter iter, iter_array; + DBusMessage *reply = dbus_message_new_method_return (message); + GList *l; + + if (!reply) + return NULL; + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, + "(souua(iisi)u(bbb))", &iter_array); + for (l = controller->key_listeners; l; l = l->next) + { + append_keystroke_listener (&iter_array, l->data); + } + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +static DBusMessage * +impl_get_device_event_listeners (DBusConnection *bus, + DBusMessage *message, + void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + DBusMessageIter iter, iter_array; + GList *l; + DBusMessage *reply = dbus_message_new_method_return (message); + + if (!reply) + return NULL; + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, + "(sou)", &iter_array); + for (l = controller->key_listeners; l; l = l->next) + { + append_mouse_listener (&iter_array, l->data); + } + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +static unsigned +get_modifier_state (SpiDEController *controller) +{ + return mouse_mask_state; +} + +gboolean +spi_dec_synth_keysym (SpiDEController *controller, long keysym) +{ + long key_synth_code; + unsigned int modifiers, synth_mods, lock_mods; + + key_synth_code = spi_dec_plat_get_keycode (controller, keysym, NULL, TRUE, &synth_mods); + + if ((key_synth_code == 0) || (synth_mods == 0xFF)) return FALSE; + + /* TODO: set the modifiers accordingly! */ + modifiers = get_modifier_state (controller); + /* side-effect; we may unset mousebutton modifiers here! */ + + lock_mods = 0; + if (synth_mods != modifiers) { + lock_mods = synth_mods & ~modifiers; + spi_dec_plat_lock_modifiers (controller, lock_mods); + } + spi_dec_plat_synth_keycode_press (controller, key_synth_code); + spi_dec_plat_synth_keycode_release (controller, key_synth_code); + + if (synth_mods != modifiers) + spi_dec_plat_unlock_modifiers (controller, lock_mods); + return TRUE; +} + + + +/* + * DBus Accessibility::DEController::RegisterKeystrokeListener + * method implementation + */ +static DBusMessage * +impl_generate_keyboard_event (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + dbus_int32_t keycode; + char *keystring; + dbus_uint32_t synth_type; + DBusMessage *reply = NULL; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &keycode, DBUS_TYPE_STRING, &keystring, DBUS_TYPE_UINT32, &synth_type, DBUS_TYPE_INVALID)) + { + return invalid_arguments_error (message); + } + +#ifdef SPI_DEBUG + fprintf (stderr, "synthesizing keystroke %ld, type %d\n", + (long) keycode, (int) synth_type); +#endif + /* TODO: hide/wrap/remove X dependency */ + + /* + * TODO: when initializing, query for XTest extension before using, + * and fall back to XSendEvent() if XTest is not available. + */ + + switch (synth_type) + { + case Accessibility_KEY_PRESS: + spi_dec_plat_synth_keycode_press (controller, keycode); + break; + case Accessibility_KEY_PRESSRELEASE: + spi_dec_plat_synth_keycode_press (controller, keycode); + case Accessibility_KEY_RELEASE: + spi_dec_plat_synth_keycode_release (controller, keycode); + break; + case Accessibility_KEY_SYM: +#ifdef SPI_XKB_DEBUG + fprintf (stderr, "KeySym synthesis\n"); +#endif + /* + * note: we are using long for 'keycode' + * in our arg list; it can contain either + * a keycode or a keysym. + */ + spi_dec_synth_keysym (controller, keycode); + break; + case Accessibility_KEY_STRING: + if (!spi_dec_plat_synth_keystring (controller, synth_type, keycode, keystring)) + fprintf (stderr, "Keystring synthesis failure, string=%s\n", + keystring); + break; + } + reply = dbus_message_new_method_return (message); + return reply; +} + +/* Accessibility::DEController::GenerateMouseEvent */ +static DBusMessage * +impl_generate_mouse_event (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + dbus_int32_t x; + dbus_int32_t y; + char *eventName; + DBusMessage *reply = NULL; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_STRING, &eventName, DBUS_TYPE_INVALID)) + { + return invalid_arguments_error (message); + } + +#ifdef SPI_DEBUG + fprintf (stderr, "generating mouse %s event at %ld, %ld\n", + eventName, (long int) x, (long int) y); +#endif + spi_dec_plat_generate_mouse_event (saved_controller, x, y, eventName); + reply = dbus_message_new_method_return (message); + return reply; +} + +/* Accessibility::DEController::NotifyListenersSync */ +static DBusMessage * +impl_notify_listeners_sync (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + Accessibility_DeviceEvent event; + dbus_bool_t ret; + DBusMessage *reply = NULL; + + if (!spi_dbus_demarshal_deviceEvent(message, &event)) + { + return invalid_arguments_error (message); + } +#ifdef SPI_DEBUG + g_print ("notifylistening listeners synchronously: controller %p, event id %d\n", + controller, (int) event.id); +#endif + ret = spi_controller_notify_keylisteners (controller, + (Accessibility_DeviceEvent *) + &event, FALSE) ? + TRUE : FALSE; + reply = dbus_message_new_method_return (message); + if (reply) + { + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &ret, DBUS_TYPE_INVALID); + } + return reply; +} + +static DBusMessage * +impl_notify_listeners_async (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER(user_data); + Accessibility_DeviceEvent event; + DBusMessage *reply = NULL; + + if (!spi_dbus_demarshal_deviceEvent(message, &event)) + { + return invalid_arguments_error (message); + } +#ifdef SPI_DEBUG + g_print ("notifylistening listeners asynchronously: controller %p, event id %d\n", + controller, (int) event.id); +#endif + spi_controller_notify_keylisteners (controller, (Accessibility_DeviceEvent *) + &event, FALSE); + reply = dbus_message_new_method_return (message); + return reply; +} + +static void +spi_device_event_controller_class_init (SpiDEControllerClass *klass) +{ + GObjectClass * object_class = (GObjectClass *) klass; + + spi_device_event_controller_parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = spi_device_event_controller_object_finalize; + +#ifdef HAVE_X11 + if (g_getenv ("DISPLAY")) + spi_dec_setup_x11 (klass); + else +#endif + g_type_class_add_private (object_class, sizeof (long)); /* dummy */ +} + +static void +spi_device_event_controller_init (SpiDEController *device_event_controller) +{ + SpiDEControllerClass *klass; + klass = SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS (device_event_controller); + + /* TODO: shouldn't be gpointer below */ + device_event_controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_event_controller, + SPI_DEVICE_EVENT_CONTROLLER_TYPE, + gpointer); + device_event_controller->message_queue = g_queue_new (); + saved_controller = device_event_controller; + + if (klass->plat.init) + klass->plat.init (device_event_controller); +} + + +/*---------------------------------------------------------------------------*/ + +static const char *introspection_header = +"\n"; + +static const char *introspection_node_element = +"\n"; + +static const char *introspection_footer = +""; + +static DBusMessage * +impl_Introspect (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + GString *output; + gchar *final; + + const gchar *pathstr = SPI_DBUS_PATH_DEC; + + DBusMessage *reply; + + output = g_string_new(introspection_header); + + g_string_append_printf(output, introspection_node_element, pathstr); + + g_string_append (output, spi_org_a11y_atspi_DeviceEventController); + + g_string_append(output, introspection_footer); + final = g_string_free(output, FALSE); + + reply = dbus_message_new_method_return (message); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID); + + g_free(final); + return reply; +} + +/*---------------------------------------------------------------------------*/ + +static void +handle_dec_method_from_idle (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + DBusMessage *reply = NULL; + + if (!strcmp (iface, SPI_DBUS_INTERFACE_DEC)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "RegisterKeystrokeListener")) + reply = impl_register_keystroke_listener (bus, message, user_data); + else if (!strcmp (member, "RegisterDeviceEventListener")) + reply = impl_register_device_event_listener (bus, message, user_data); + else if (!strcmp (member, "DeregisterKeystrokeListener")) + reply = impl_deregister_keystroke_listener (bus, message, user_data); + else if (!strcmp (member, "DeregisterDeviceEventListener")) + reply = impl_deregister_device_event_listener (bus, message, user_data); + else if (!strcmp (member, "GetKeystrokeListeners")) + reply = impl_get_keystroke_listeners (bus, message, user_data); + else if (!strcmp (member, "GetDeviceEventListeners")) + reply = impl_get_device_event_listeners (bus, message, user_data); + else if (!strcmp (member, "GenerateKeyboardEvent")) + reply = impl_generate_keyboard_event (bus, message, user_data); + else if (!strcmp (member, "GenerateMouseEvent")) + reply = impl_generate_mouse_event (bus, message, user_data); + else if (!strcmp (member, "NotifyListenersSync")) + reply = impl_notify_listeners_sync (bus, message, user_data); + else if (!strcmp (member, "NotifyListenersAsync")) + reply = impl_notify_listeners_async (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "Introspect")) + reply = impl_Introspect (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (result == DBUS_HANDLER_RESULT_HANDLED) + { + if (!reply) + { + reply = dbus_message_new_method_return (message); + } + + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } +} + +static gboolean +message_queue_dispatch (gpointer data) +{ + saved_controller->message_queue_idle = 0; + while (!g_queue_is_empty (saved_controller->message_queue)) + { + DBusMessage *message = g_queue_pop_head (saved_controller->message_queue); + data = g_queue_pop_head (saved_controller->message_queue); + handle_dec_method_from_idle (saved_controller->bus, message, data); + dbus_message_unref (message); + } + return FALSE; +} + +static DBusHandlerResult +handle_dec_method (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + dbus_message_ref (message); + g_queue_push_tail (saved_controller->message_queue, message); + g_queue_push_tail (saved_controller->message_queue, user_data); + if (!saved_controller->message_queue_idle) { + saved_controller->message_queue_idle = g_idle_add (message_queue_dispatch, NULL); + g_source_set_name_by_id (saved_controller->message_queue_idle, "[at-spi2-core] message_queue_dispatch"); + } + return DBUS_HANDLER_RESULT_HANDLED; +} + +static DBusObjectPathVTable dec_vtable = +{ + NULL, + &handle_dec_method, + NULL, NULL, NULL, NULL +}; + +SpiDEController * +spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus) +{ + SpiDEController *dec = g_object_new (SPI_DEVICE_EVENT_CONTROLLER_TYPE, NULL); + + dec->registry = g_object_ref (reg); + reg->dec = g_object_ref (dec); + dec->bus = bus; + + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_DEC, &dec_vtable, dec); + + return dec; +} + +void +spi_device_event_controller_start_poll_mouse (SpiRegistry *registry) +{ + if (!have_mouse_event_listener) + { + have_mouse_event_listener = TRUE; + if (!have_mouse_listener) { + guint id; + id = g_timeout_add (100, spi_dec_poll_mouse_idle, registry->dec); + g_source_set_name_by_id (id, "[at-spi2-core] spi_dec_poll_mouse_idle"); + } + } +} + +void +spi_device_event_controller_stop_poll_mouse (void) +{ + have_mouse_event_listener = FALSE; +} diff --git a/registryd/deviceeventcontroller.h b/registryd/deviceeventcontroller.h new file mode 100644 index 0000000..0c6eee4 --- /dev/null +++ b/registryd/deviceeventcontroller.h @@ -0,0 +1,179 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_DEVICE_EVENT_CONTROLLER_H_ +#define SPI_DEVICE_EVENT_CONTROLLER_H_ + +#ifdef HAVE_X11 +#include +#endif +#include + +typedef struct _SpiDEController SpiDEController; + +#include "registry.h" +#include "de-types.h" + +G_BEGIN_DECLS + +#define SPI_DEVICE_EVENT_CONTROLLER_TYPE (spi_device_event_controller_get_type ()) +#define SPI_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEController)) +#define SPI_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEControllerClass)) +#define SPI_IS_DEVICE_EVENT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPI_DEVICE_EVENT_CONTROLLER_TYPE)) +#define SPI_IS_DEVICE_EVENT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_DEVICE_EVENT_CONTROLLER_TYPE)) +#define SPI_DEVICE_EVENT_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPI_DEVICE_EVENT_CONTROLLER_TYPE, SpiDEControllerClass)) + +struct _SpiDEController { + GObject parent; + DBusConnection *bus; + SpiRegistry *registry; + GList *key_listeners; + GList *mouse_listeners; + GList *keygrabs_list; + GQueue *message_queue; + guint message_queue_idle; + gpointer priv; +}; + +typedef enum { + SPI_DEVICE_TYPE_KBD, + SPI_DEVICE_TYPE_MOUSE, + SPI_DEVICE_TYPE_LAST_DEFINED +} SpiDeviceTypeCategory; + +typedef struct { + char *bus_name; + char *path; + SpiDeviceTypeCategory type; + gulong types; +} DEControllerListener; + +typedef struct { + DEControllerListener listener; + + GSList *keys; + Accessibility_ControllerEventMask mask; + Accessibility_EventListenerMode *mode; +} DEControllerKeyListener; + +typedef struct +{ + gint (*get_keycode) (SpiDEController *controller, + gint keysym, + gchar *key_str, + gboolean fix, + guint *modmask); + + guint (*mouse_check) (SpiDEController *controller, + gint *x, + gint *y, + gboolean *moved); + + gboolean (*register_global_keygrabs) (SpiDEController *controller, + DEControllerKeyListener *key_listener); + + void (*deregister_global_keygrabs) (SpiDEController *controller, + DEControllerKeyListener *key_listener); + + gboolean (*synth_keycode_press) (SpiDEController *controller, + guint keycode); + + gboolean (*synth_keycode_release) (SpiDEController *controller, + guint keycode); + + gboolean (*lock_modifiers) (SpiDEController *controller, + unsigned modifiers); + + gboolean (*unlock_modifiers) (SpiDEController *controller, + unsigned modifiers); + + gboolean (*synth_keystring) (SpiDEController *controller, + guint synth_type, + gint keycode, + const char *keystring); + + gboolean (*grab_key) (SpiDEController *controller, + guint key_val, + Accessibility_ControllerEventMask mod_mask); + + void (*ungrab_key) (SpiDEController *controller, + guint key_val, + Accessibility_ControllerEventMask mod_mask); + + void (*emit_modifier_event) (SpiDEController *controller, + guint prev_mask, + guint current_mask); + + void (*generate_mouse_event) (SpiDEController *controller, + gint x, + gint y, + const char *eventName); + + void (*init) (SpiDEController *controller); + void (*finalize) (SpiDEController *controller); +} SpiDEControllerPlat; + +typedef struct { + GObjectClass parent_class; + SpiDEControllerPlat plat; +} SpiDEControllerClass; + +GType spi_device_event_controller_get_type (void); +SpiDEController *spi_device_event_controller_new (SpiRegistry *registry, + DBusConnection *bus); + +gboolean spi_clear_error_state (void); + +void spi_device_event_controller_start_poll_mouse (SpiRegistry *registry); +void spi_device_event_controller_stop_poll_mouse (void); + +void spi_remove_device_listeners (SpiDEController *controller, const char *bus_name); + +SpiDEController *spi_registry_dec_new (SpiRegistry *reg, DBusConnection *bus); + +gboolean +spi_controller_notify_mouselisteners (SpiDEController *controller, + const Accessibility_DeviceEvent *event); + +gboolean +spi_controller_notify_keylisteners (SpiDEController *controller, + Accessibility_DeviceEvent *key_event, + dbus_bool_t is_system_global); + +gboolean spi_controller_update_key_grabs (SpiDEController *controller, + Accessibility_DeviceEvent *recv); + +gboolean spi_dec_synth_keysym (SpiDEController *controller, long keysym); + +void spi_dec_dbus_emit(SpiDEController *controller, const char *interface, const char *name, const char *minor, int a1, int a2); + +#ifdef HAVE_X11 +void spi_dec_setup_x11 (SpiDEControllerClass *klass); +#endif + +long ucs2keysym (long ucs); +long keysym2ucs(long keysym); + +G_END_DECLS + +#endif /* DEVICEEVENTCONTROLLER_H_ */ diff --git a/registryd/display.c b/registryd/display.c new file mode 100644 index 0000000..2ba781c --- /dev/null +++ b/registryd/display.c @@ -0,0 +1,90 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Nokia. + * + * 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. + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "display.h" + +static Display *default_display = NULL; + +Display *spi_set_display (const char *display_name) +{ + /* + * TODO - Should we ever do anything different might need to + * close previous display. + */ + default_display = XOpenDisplay (display_name); + if (!default_display) + { + g_warning ("AT-SPI: Cannot open default display"); + exit (1); + } + return default_display; +} + +Display *spi_get_display () +{ + if (!default_display) + spi_set_display (NULL); + + return default_display; +} + +Window spi_get_root_window () +{ + if (!default_display) + spi_set_display (NULL); + + return DefaultRootWindow (default_display); +} + +static int (*old_x_error_handler) (Display *, XErrorEvent *); +static int x_error_code; + +static int spi_x_error_handler (Display *display, XErrorEvent *error) +{ + if (error->error_code) + x_error_code = error->error_code; + else + x_error_code = 0; + + return 0; +} + +void spi_x_error_trap (void) +{ + old_x_error_handler = XSetErrorHandler (spi_x_error_handler); +} + +int spi_x_error_release (void) +{ + XSetErrorHandler (old_x_error_handler); + return x_error_code; +} diff --git a/registryd/display.h b/registryd/display.h new file mode 100644 index 0000000..2238a55 --- /dev/null +++ b/registryd/display.h @@ -0,0 +1,36 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Nokia. + * + * 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 SPI_DISPLAY_H_ +#define SPI_DISPLAY_H_ + +#include + +Display *spi_set_display (const char *display_name); +Display *spi_get_display (); + +Window spi_get_root_window (); + +void spi_x_error_trap (void); +int spi_x_error_release (void); + +#endif /* SPI_DISPLAY_H_ */ diff --git a/registryd/event-source.c b/registryd/event-source.c new file mode 100644 index 0000000..9ad3ec5 --- /dev/null +++ b/registryd/event-source.c @@ -0,0 +1,175 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Nokia. + * + * 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. + */ + +#include + +#include "event-source.h" + +typedef struct _DisplaySource +{ + GSource source; + + Display *display; + GPollFD event_poll_fd; +} DisplaySource; + +/*---------------------------------------------------------------------------*/ + +static void (*_spi_default_filter) (XEvent*, void*) = NULL; +static void* _spi_default_filter_data = NULL; + +/*---------------------------------------------------------------------------*/ + +static gboolean +event_prepare (GSource *source, gint *timeout) +{ + Display *display = ((DisplaySource *)source)->display; + gboolean retval; + + *timeout = -1; + retval = XPending (display); + + return retval; +} + +static gboolean +event_check (GSource *source) +{ + DisplaySource *display_source = (DisplaySource*)source; + gboolean retval; + + if (display_source->event_poll_fd.revents & G_IO_IN) + retval = XPending (display_source->display); + else + retval = FALSE; + + return retval; +} + +static gboolean +event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) +{ + Display *display = ((DisplaySource*)source)->display; + XEvent xevent; + + /* TODO - Should this be "if (XPending (display))"? + * The effect of this might be to run other main loop functions + * before dispatching the next XEvent. + */ + while (XPending (display)) + { + XNextEvent (display, &xevent); + + switch (xevent.type) + { + case KeyPress: + case KeyRelease: + break; + default: + if (XFilterEvent (&xevent, None)) + continue; + } + + if (_spi_default_filter) + { + _spi_default_filter (&xevent, _spi_default_filter_data); + } + } + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ + +static GSourceFuncs event_funcs = { + event_prepare, + event_check, + event_dispatch, + NULL +}; + +static GSource * +display_source_new (Display *display) +{ + GSource *source = g_source_new (&event_funcs, sizeof (DisplaySource)); + DisplaySource *display_source = (DisplaySource *) source; + g_source_set_name (source, "[at-spi2-core] display_source_funcs"); + + display_source->display = display; + + return source; +} + +/*---------------------------------------------------------------------------*/ + +static DisplaySource *spi_display_source = NULL; + +void +spi_events_init (Display *display) +{ + GSource *source; + + int connection_number = ConnectionNumber (display); + + source = display_source_new (display); + spi_display_source = (DisplaySource*) source; + + g_source_set_priority (source, G_PRIORITY_DEFAULT); + + spi_display_source->event_poll_fd.fd = connection_number; + spi_display_source->event_poll_fd.events = G_IO_IN; + + g_source_add_poll (source, &spi_display_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); +} + +void +spi_events_uninit () +{ + if (spi_display_source) + { + g_source_destroy ((GSource *) spi_display_source); + g_source_unref ((GSource *) spi_display_source); + spi_display_source = NULL; + } +} + +void +spi_set_events (long event_mask) +{ + long xevent_mask = StructureNotifyMask | PropertyChangeMask; + xevent_mask |= event_mask; + + XSelectInput (spi_display_source->display, + DefaultRootWindow (spi_display_source->display), + xevent_mask); +} + +void +spi_set_filter (void (*filter) (XEvent*, void*), void* data) +{ + _spi_default_filter = filter; + _spi_default_filter_data = data; +} + +/*END------------------------------------------------------------------------*/ diff --git a/registryd/event-source.h b/registryd/event-source.h new file mode 100644 index 0000000..55ab663 --- /dev/null +++ b/registryd/event-source.h @@ -0,0 +1,33 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009 Nokia. + * + * 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 SPI_EVENT_SOURCE_H_ +#define SPI_EVENT_SOURCE_H_ + +#include + +void spi_events_init (Display *display); +void spi_events_uninit (); +void spi_set_events (long event_mask); +void spi_set_filter (void (*filter) (XEvent*, void*), void* data); + +#endif /* SPI_EVENT_SOURCE_H_ */ diff --git a/registryd/introspection.c b/registryd/introspection.c new file mode 100644 index 0000000..5b694ad --- /dev/null +++ b/registryd/introspection.c @@ -0,0 +1,860 @@ + +/* + * This file has been auto-generated from the introspection data available + * in the at-spi2-core repository. The D-Bus procol is defined in this + * repository, which can be found at: + * + * http://download.gnome.org/sources/at-spi2-core/0.1/ + * + * DO NOT EDIT. + */ + + +const char *spi_org_a11y_atspi_Accessible = +"" +"" +" " +"" +" " +"" +" " +" " +" " +"" +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Action = +"" +"" +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Application = +"" +"" +" " +"" +" " +"" +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Collection = +"" +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Component = +"" +"" +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Document = +"" +"" +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Hypertext = +"" +"" +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Hyperlink = +"" +"" +" " +"" +" " +"" +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Image = +"" +"" +" " +"" +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Selection = +"" +"" +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Table = +"" +"" +" " +"" +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +"" +" " +"" +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Text = +"" +"" +" " +"" +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_EditableText = +"" +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Cache = +"" +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Value = +"" +"" +" " +"" +" " +"" +" " +"" +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_Registry = +"" +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +""; + +const char *spi_org_a11y_atspi_DeviceEventController = +"" +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +" " +"" +"" +""; + +const char *spi_org_a11y_atspi_DeviceEventListener = +"" +"" +" " +" " +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +" " +" " +" " +"" +"" +""; + diff --git a/registryd/introspection.h b/registryd/introspection.h new file mode 100644 index 0000000..5c28333 --- /dev/null +++ b/registryd/introspection.h @@ -0,0 +1,53 @@ + +/* + * This file has been auto-generated from the introspection data available + * in the at-spi2-core repository. The D-Bus procol is defined in this + * repository, which can be found at: + * + * http://download.gnome.org/sources/at-spi2-core/0.1/ + * + * DO NOT EDIT. + */ + +#ifndef SPI_INTROSPECTION_DATA_H_ +#define SPI_INTROSPECTION_DATA_H_ + + +extern const char *spi_org_a11y_atspi_Accessible; + +extern const char *spi_org_a11y_atspi_Action; + +extern const char *spi_org_a11y_atspi_Application; + +extern const char *spi_org_a11y_atspi_Collection; + +extern const char *spi_org_a11y_atspi_Component; + +extern const char *spi_org_a11y_atspi_Document; + +extern const char *spi_org_a11y_atspi_Hypertext; + +extern const char *spi_org_a11y_atspi_Hyperlink; + +extern const char *spi_org_a11y_atspi_Image; + +extern const char *spi_org_a11y_atspi_Selection; + +extern const char *spi_org_a11y_atspi_Table; + +extern const char *spi_org_a11y_atspi_Text; + +extern const char *spi_org_a11y_atspi_EditableText; + +extern const char *spi_org_a11y_atspi_Cache; + +extern const char *spi_org_a11y_atspi_Value; + +extern const char *spi_org_a11y_atspi_Registry; + +extern const char *spi_org_a11y_atspi_DeviceEventController; + +extern const char *spi_org_a11y_atspi_DeviceEventListener; + + +#endif /* SPI_INTROSPECTION_DATA_H_ */ diff --git a/registryd/keymasks.h b/registryd/keymasks.h new file mode 100644 index 0000000..4e838b8 --- /dev/null +++ b/registryd/keymasks.h @@ -0,0 +1,53 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_KEYMASKS_H_ +#define SPI_KEYMASKS_H_ + +#include + +G_BEGIN_DECLS + +typedef unsigned long SpiKeyMaskType; + +/* Values taken from Xlib.h */ +#define SPI_KEYMASK_ALT (1<<3) /* Mod1Mask */ +#define SPI_KEYMASK_MOD1 (1<<3) /* Mod1Mask */ +#define SPI_KEYMASK_MOD2 (1<<4) /* Mod2Mask */ +#define SPI_KEYMASK_MOD3 (1<<5) /* Mod3Mask */ +#define SPI_KEYMASK_MOD4 (1<<6) /* Mod4Mask */ +#define SPI_KEYMASK_MOD5 (1<<7) /* Mod5Mask */ +#define SPI_KEYMASK_BUTTON1 (1L<<8) /* Button1Mask */ +#define SPI_KEYMASK_BUTTON2 (1L<<9) /* Button2Mask */ +#define SPI_KEYMASK_BUTTON3 (1L<<10) /* Button3Mask */ +#define SPI_KEYMASK_BUTTON4 (1L<<11) /* Button4Mask */ +#define SPI_KEYMASK_BUTTON5 (1L<<12) /* Button5Mask */ +#define SPI_KEYMASK_CONTROL (1<<2) /* ControlMask */ +#define SPI_KEYMASK_SHIFT (1<<0) /* ShiftMask */ +#define SPI_KEYMASK_SHIFTLOCK (1<<1) /* LockMask */ +#define SPI_KEYMASK_NUMLOCK (1<<14) +#define SPI_KEYMASK_UNMODIFIED 0 + +G_END_DECLS + +#endif /* SPI_KEYMASKS_H_ */ diff --git a/registryd/meson.build b/registryd/meson.build new file mode 100644 index 0000000..eb8236e --- /dev/null +++ b/registryd/meson.build @@ -0,0 +1,45 @@ +atspi_introspection_path = '' + +registryd_sources = [ + 'de-marshaller.c', + 'registry-main.c', + 'registry.c', + 'introspection.c', + 'deviceeventcontroller.c', + 'reentrant-list.c', +] + +registryd_deps = [ + gio_dep, + libdbus_dep, + atspi_dep, + dl_dep, +] + +x11_option = get_option('enable-x11') +if x11_option != 'no' + if x11_dep.found() + registryd_sources += [ + 'deviceeventcontroller-x11.c', + 'display.c', + 'event-source.c', + 'ucs2keysym.c', + ] + + registryd_deps += x11_deps + endif +endif + +executable('at-spi2-registryd', registryd_sources, + dependencies: registryd_deps, + install: true, + install_dir: atspi_libexecdir) + +libexec_conf = configuration_data() +libexec_conf.set('libexecdir', atspi_libexecdir) + +configure_file(input: 'org.a11y.atspi.Registry.service.in', + output: 'org.a11y.atspi.Registry.service', + configuration: libexec_conf, + install: true, + install_dir: join_paths(atspi_datadir, 'dbus-1/accessibility-services')) diff --git a/registryd/org.a11y.atspi.Registry.service.in b/registryd/org.a11y.atspi.Registry.service.in new file mode 100644 index 0000000..de93790 --- /dev/null +++ b/registryd/org.a11y.atspi.Registry.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.a11y.atspi.Registry +Exec=@libexecdir@/at-spi2-registryd --use-gnome-session diff --git a/registryd/paths.h b/registryd/paths.h new file mode 100644 index 0000000..918df67 --- /dev/null +++ b/registryd/paths.h @@ -0,0 +1,53 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_PATHS_H_ +#define SPI_PATHS_H_ + +#define SPI_DBUS_NAME_PREFIX "org.a11y.atspi." +#define SPI_DBUS_PATH_PREFIX "/org/a11y/atspi/" +#define SPI_DBUS_INTERFACE_PREFIX "org.a11y.atspi." + +#define SPI_DBUS_PATH_NULL SPI_DBUS_PATH_PREFIX "null" +#define SPI_DBUS_PATH_ROOT SPI_DBUS_PATH_PREFIX "accessible/root" + +#define SPI_DBUS_NAME_REGISTRY SPI_DBUS_NAME_PREFIX "Registry" +#define SPI_DBUS_INTERFACE_REGISTRY SPI_DBUS_INTERFACE_PREFIX "Registry" +#define SPI_DBUS_PATH_REGISTRY SPI_DBUS_PATH_PREFIX "registry" + +#define SPI_DBUS_PATH_DEC SPI_DBUS_PATH_PREFIX "registry/deviceeventcontroller" +#define SPI_DBUS_INTERFACE_DEC SPI_DBUS_INTERFACE_PREFIX "DeviceEventController" +#define SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER SPI_DBUS_INTERFACE_PREFIX "DeviceEventListener" + +#define SPI_DBUS_PATH_CACHE SPI_DBUS_PATH_PREFIX "cache" +#define SPI_DBUS_INTERFACE_CACHE SPI_DBUS_INTERFACE_PREFIX "Cache" + +#define SPI_DBUS_INTERFACE_ACCESSIBLE SPI_DBUS_INTERFACE_PREFIX "Accessible" +#define SPI_DBUS_INTERFACE_APPLICATION SPI_DBUS_INTERFACE_PREFIX "Application" +#define SPI_DBUS_INTERFACE_COMPONENT SPI_DBUS_INTERFACE_PREFIX "Component" +#define SPI_DBUS_INTERFACE_EVENT_KEYBOARD SPI_DBUS_INTERFACE_PREFIX "Keyboard" +#define SPI_DBUS_INTERFACE_EVENT_MOUSE SPI_DBUS_INTERFACE_PREFIX "Event.Mouse" +#define SPI_DBUS_INTERFACE_EVENT_OBJECT SPI_DBUS_INTERFACE_PREFIX "Event.Object" +#define SPI_DBUS_INTERFACE_SOCKET SPI_DBUS_INTERFACE_PREFIX "Socket" + +#endif /* SPI_PATHS_H_ */ diff --git a/registryd/reentrant-list.c b/registryd/reentrant-list.c new file mode 100644 index 0000000..29bdfca --- /dev/null +++ b/registryd/reentrant-list.c @@ -0,0 +1,105 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include +#include + +#include "reentrant-list.h" + +typedef struct { + GList **list; + GList *iterator; +} Iteration; + +static GSList *working_list = NULL; /* of Iteration */ + +/* + * deletes an element from the list - in a re-entrant + * safe fashion; advances the element pointer to the next + * element. + */ +void +spi_re_entrant_list_delete_link (GList * const *element_ptr) +{ + GSList *l; + GList *next; + GList *element; + gboolean first_item; + GList *dummy; /* suppress warning */ + + g_return_if_fail (element_ptr != NULL); + + element = *element_ptr; + g_return_if_fail (element != NULL); + + next = element->next; + first_item = (element->prev == NULL); + + dummy = g_list_remove_link (NULL, element); + + for (l = working_list; l; l = l->next) + { + Iteration *i = l->data; + + if (i->iterator == element) + { + i->iterator = next; + } + + if (first_item && *(i->list) == element) + { + *(i->list) = next; + } + } + + g_list_free_1 (element); +} + +void +spi_re_entrant_list_foreach (GList **list, + SpiReEntrantFn func, + gpointer user_data) +{ + Iteration i; + + if (!list || !*list) + { + return; + } + + i.list = list; + i.iterator = *list; + + working_list = g_slist_prepend (working_list, &i); + + while (i.iterator) { + GList *l = i.iterator; + + func (&i.iterator, user_data); + + if (i.iterator == l) + i.iterator = i.iterator->next; + } + + working_list = g_slist_remove (working_list, &i); +} diff --git a/registryd/reentrant-list.h b/registryd/reentrant-list.h new file mode 100644 index 0000000..901561b --- /dev/null +++ b/registryd/reentrant-list.h @@ -0,0 +1,46 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 REENTRANT_LIST_H_ +#define REENTRANT_LIST_H_ + +#include + +G_BEGIN_DECLS + +typedef enum { + SPI_RE_ENTRANT_CONTINUE = 0, + SPI_RE_ENTRANT_TERMINATE +} SpiReEntrantContinue; + +typedef SpiReEntrantContinue (*SpiReEntrantFn) (GList * const *list, + gpointer user_data); + +void spi_re_entrant_list_delete_link (GList * const *element_ptr); +void spi_re_entrant_list_foreach (GList **list, + SpiReEntrantFn func, + gpointer user_data); + +G_END_DECLS + +#endif /* REENTRANT_LIST_H_ */ diff --git a/registryd/registry-main.c b/registryd/registry-main.c new file mode 100644 index 0000000..d8b5dc5 --- /dev/null +++ b/registryd/registry-main.c @@ -0,0 +1,268 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "paths.h" +#include "registry.h" +#include "deviceeventcontroller.h" +#include "atspi/atspi.h" + +static GMainLoop *mainloop; +static gchar *dbus_name = NULL; +static gboolean use_gnome_session = FALSE; + +static GOptionEntry optentries[] = +{ + {"dbus-name", 0, 0, G_OPTION_ARG_STRING, &dbus_name, "Well-known name to register with D-Bus", NULL}, + {"use-gnome-session", 0, 0, G_OPTION_ARG_NONE, &use_gnome_session, "Should register with gnome session manager", NULL}, + {NULL} +}; + +static GDBusProxy *sm_proxy = NULL; +static char *client_id = NULL; +static GDBusProxy *client_proxy = NULL; + +#define SM_DBUS_NAME "org.gnome.SessionManager" +#define SM_DBUS_PATH "/org/gnome/SessionManager" +#define SM_DBUS_INTERFACE "org.gnome.SessionManager" + +#define SM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate" + +static gboolean register_client (void); + +static void +on_session_signal (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + if (g_strcmp0 (signal_name, "SessionOver") == 0) { + g_main_loop_quit (mainloop); + } else if (g_strcmp0 (signal_name, "SessionRunning") == 0) { + if (!register_client ()) + g_warning ("Unable to register client with session manager"); + } +} + +static gboolean +session_manager_connect (void) +{ + GVariant *res; + gboolean is_running; + + sm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, NULL, + SM_DBUS_NAME, + SM_DBUS_PATH, + SM_DBUS_INTERFACE, NULL, NULL); + + res = g_dbus_proxy_call_sync (sm_proxy, + "IsSessionRunning", NULL, + 0, 1000, NULL, NULL); + + if (res) { + g_variant_get (res, "(b)", &is_running); + g_variant_unref (res); + if (is_running) { + if (!register_client ()) + g_warning ("Unable to register client with session manager"); + } + } + + g_signal_connect (G_OBJECT (sm_proxy), "g-signal", + G_CALLBACK (on_session_signal), NULL); + + return (sm_proxy != NULL); +} + +static gboolean +end_session_response (gboolean is_okay, const gchar *reason) +{ + GVariant *ret; + GError *error = NULL; + + if (!reason) + reason = ""; + + ret = g_dbus_proxy_call_sync (client_proxy, "EndSessionResponse", + g_variant_new ("(bs)", is_okay, reason), + 0, 1000, NULL, &error); + + if (!ret) { + g_warning ("Failed to send session response %s", error->message); + g_error_free (error); + return FALSE; + } + else + g_variant_unref (ret); + + return TRUE; +} + +static void +client_proxy_signal_cb (GDBusProxy *proxy, + gchar *sender_name, + gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + if (g_strcmp0 (signal_name, "QueryEndSession") == 0) { + g_debug ("Got QueryEndSession signal"); + end_session_response (TRUE, NULL); + } else if (g_strcmp0 (signal_name, "EndSession") == 0) { + g_debug ("Got EndSession signal"); + end_session_response (TRUE, NULL); + g_main_loop_quit (mainloop); + } else if (g_strcmp0 (signal_name, "Stop") == 0) { + g_debug ("Got Stop signal"); + g_main_loop_quit (mainloop); + } +} + +static gboolean +register_client (void) +{ + GError *error; + GVariant *res; + const char *startup_id; + const char *app_id; + + if (client_proxy) + return TRUE; + + startup_id = g_getenv ("DESKTOP_AUTOSTART_ID"); + if (!startup_id) + startup_id = ""; + app_id = "at-spi-registryd.desktop"; + + error = NULL; + res = g_dbus_proxy_call_sync (sm_proxy, + "RegisterClient", + g_variant_new ("(ss)", app_id, + startup_id), + 0, 1000, NULL, &error); + if (! res) { + const char *message = (error && error->message ? error->message + : "no error"); + g_warning ("Failed to register client: %s", message); + if (error) + g_error_free (error); + return FALSE; + } + g_variant_get (res, "(o)", &client_id); + g_variant_unref (res); + + client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, 0, NULL, + SM_DBUS_NAME, + client_id, + SM_CLIENT_DBUS_INTERFACE, + NULL, NULL); + + g_signal_connect (client_proxy, "g-signal", + G_CALLBACK (client_proxy_signal_cb), NULL); + + g_unsetenv ("DESKTOP_AUTOSTART_ID"); + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ + +typedef GObject *(*gconf_client_get_default_t) (); +typedef gboolean (*gconf_client_get_bool_t)(GObject *, const char *, void *); + +int +main (int argc, char **argv) +{ + SpiRegistry *registry; + SpiDEController *dec; + + DBusConnection *bus = NULL; + + GOptionContext *opt; + + GError *err = NULL; + int ret; + + /*Parse command options*/ + opt = g_option_context_new(NULL); + g_option_context_add_main_entries(opt, optentries, NULL); + + if (!g_option_context_parse(opt, &argc, &argv, &err)) + { + g_error("Option parsing failed: %s\n", err->message); + g_clear_error (&err); + } + + if (dbus_name == NULL) + dbus_name = SPI_DBUS_NAME_REGISTRY; + + bus = atspi_get_a11y_bus (); + if (!bus) + { + return 0; + } + + mainloop = g_main_loop_new (NULL, FALSE); + atspi_dbus_connection_setup_with_g_main(bus, NULL); + + ret = dbus_bus_request_name(bus, dbus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL); + if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) + { + exit (0); /* most likely already running */ + } + else + { + g_print ("SpiRegistry daemon is running with well-known name - %s\n", dbus_name); + } + + registry = spi_registry_new (bus); + dec = spi_registry_dec_new (registry, bus); + + if (use_gnome_session) + { + if (!session_manager_connect ()) + g_warning ("Unable to connect to session manager"); + } + + g_main_loop_run (mainloop); + + dbus_connection_close (bus); + dbus_connection_unref (bus); + g_object_unref (dec); + g_object_unref (registry); + + return 0; +} diff --git a/registryd/registry.c b/registryd/registry.c new file mode 100644 index 0000000..cbf0c1b --- /dev/null +++ b/registryd/registry.c @@ -0,0 +1,1444 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008, 2010 Codethink Ltd. + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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. + */ + +#include +#include +#include + +#include "paths.h" +#include "registry.h" +#include "introspection.h" + +typedef struct event_data event_data; +struct event_data +{ + gchar *bus_name; + gchar **data; + GSList *properties; +}; + +static void +children_added_listener (DBusConnection * bus, + gint index, + const gchar * name, + const gchar * path); + +static void +children_removed_listener (DBusConnection * bus, + gint index, + const gchar * name, + const gchar * path); + +/*---------------------------------------------------------------------------*/ + +typedef struct _SpiReference +{ + gchar *name; + gchar *path; +} SpiReference; + +static SpiReference * +spi_reference_new (const gchar *name, const gchar *path) +{ + SpiReference *ref; + + ref = g_new0 (SpiReference, 1); + ref->name = g_strdup (name); + ref->path = g_strdup (path); + + return ref; +} + +static void +spi_reference_free (SpiReference *ref) +{ + g_free (ref->name); + g_free (ref->path); + g_free (ref); +} + +/*---------------------------------------------------------------------------*/ + +G_DEFINE_TYPE(SpiRegistry, spi_registry, G_TYPE_OBJECT) + +static void +spi_registry_class_init (SpiRegistryClass *klass) +{ + spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT); +} + +static void +spi_registry_init (SpiRegistry *registry) +{ + registry->apps = g_ptr_array_new_with_free_func ((GDestroyNotify) spi_reference_free); +} + +/*---------------------------------------------------------------------------*/ + +static dbus_bool_t +return_v_string (DBusMessageIter * iter, const gchar * str) +{ + DBusMessageIter variant; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "s", + &variant)) + return FALSE; + + dbus_message_iter_append_basic (&variant, DBUS_TYPE_STRING, &str); + dbus_message_iter_close_container (iter, &variant); + return TRUE; +} + +static dbus_bool_t +append_reference (DBusMessageIter * iter, const char * name, const char * path) +{ + DBusMessageIter iter_struct; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct)) + return FALSE; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (iter, &iter_struct); + return TRUE; +} + +/*---------------------------------------------------------------------------*/ + +static gboolean +compare_reference (SpiReference *one, SpiReference *two) +{ + if (g_strcmp0 (one->name, two->name) == 0 && + g_strcmp0 (one->path, two->path) == 0) + return TRUE; + else + return FALSE; +} + +static gboolean +find_index_of_reference (GPtrArray *arr, const gchar *name, const gchar * path, guint *index) +{ + SpiReference *ref; + gboolean found = FALSE; + guint i = 0; + + ref = spi_reference_new (name, path); + + for (i = 0; i < arr->len; i++) + { + if (compare_reference (ref, g_ptr_array_index (arr, i))) + { + found = TRUE; + break; + } + } + + spi_reference_free (ref); + + *index = i; + return found; +} + +static void +add_application (SpiRegistry *reg, DBusConnection *bus, const gchar *name, const gchar *path) +{ + g_ptr_array_add (reg->apps, spi_reference_new (name, path)); + children_added_listener (bus, reg->apps->len - 1, name, path); +} + +static void +set_id (SpiRegistry *reg, DBusConnection *bus, const gchar *name, const gchar *path) +{ + DBusMessage *message; + DBusMessageIter iter, iter_variant; + const char *iface_application = "org.a11y.atspi.Application"; + const char *id = "Id"; + + message = dbus_message_new_method_call (name, path, + DBUS_INTERFACE_PROPERTIES, "Set"); + if (!message) + return; + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &iface_application); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id); + dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant); + dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, ®->id); + /* TODO: This will cause problems if we cycle through 2^31 ids */ + reg->id++; + dbus_message_iter_close_container (&iter, &iter_variant); + dbus_connection_send (bus, message, NULL); + dbus_message_unref (message); +} + +static void +remove_application (SpiRegistry *reg, DBusConnection *bus, guint index) +{ + SpiReference *ref = g_ptr_array_index (reg->apps, index); + + spi_remove_device_listeners (reg->dec, ref->name); + children_removed_listener (bus, index, ref->name, ref->path); + g_ptr_array_remove_index (reg->apps, index); +} + +static gboolean +event_is_subtype (gchar **needle, gchar **haystack) +{ + while (*haystack && **haystack) + { + if (g_strcmp0 (*needle, *haystack)) + return FALSE; + needle++; + haystack++; + } + return TRUE; +} + +static gboolean +needs_mouse_poll (char **event) +{ + if (g_strcmp0 (event [0], "Mouse") != 0) + return FALSE; + if (!event [1] || !event [1][0]) + return TRUE; + return (g_strcmp0 (event [1], "Abs") == 0); +} + +static void +remove_events (SpiRegistry *registry, const char *bus_name, const char *event) +{ + gchar **remove_data; + GList *list; + gboolean mouse_found = FALSE; + DBusMessage *signal; + + remove_data = g_strsplit (event, ":", 3); + if (!remove_data) + { + return; + } + + for (list = registry->events; list;) + { + event_data *evdata = list->data; + list = list->next; + if (!g_strcmp0 (evdata->bus_name, bus_name) && + event_is_subtype (evdata->data, remove_data)) + { + g_strfreev (evdata->data); + g_free (evdata->bus_name); + g_slist_free_full (evdata->properties, g_free); + g_free (evdata); + registry->events = g_list_remove (registry->events, evdata); + } + else + { + if (needs_mouse_poll (evdata->data)) + mouse_found = TRUE; + } + } + + if (!mouse_found) + spi_device_event_controller_stop_poll_mouse (); + + g_strfreev (remove_data); + + signal = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY, + SPI_DBUS_INTERFACE_REGISTRY, + "EventListenerDeregistered"); + dbus_message_append_args (signal, DBUS_TYPE_STRING, &bus_name, + DBUS_TYPE_STRING, &event, DBUS_TYPE_INVALID); + dbus_connection_send (registry->bus, signal, NULL); + dbus_message_unref (signal); +} + +static void +handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + char *name, *old, *new; + SpiRegistry *reg = SPI_REGISTRY (user_data); + + if (dbus_message_get_args (message, NULL, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID)) + { + if (*old != '\0' && *new == '\0') + { + /* Remove all children with the application name the same as the disconnected application. */ + guint i; + for (i = 0; i < reg->apps->len; i++) + { + SpiReference *ref = g_ptr_array_index (reg->apps, i); + if (!g_strcmp0 (old, ref->name)) + { + remove_application (reg, bus, i); + i--; + } + } + + remove_events (reg, old, ""); + } + } +} + +/* + * Converts names of the form "active-descendant-changed" to + *" ActiveDescendantChanged" + */ +static gchar * +ensure_proper_format (const char *name) +{ + gchar *ret = (gchar *) g_malloc (strlen (name) * 2 + 2); + gchar *p = ret; + gboolean need_upper = TRUE; + + if (!ret) + return NULL; + while (*name) + { + if (need_upper) + { + *p++ = toupper (*name); + need_upper = FALSE; + } + else if (*name == '-') + need_upper = TRUE; + else if (*name == ':') + { + need_upper = TRUE; + *p++ = *name; + } + else + *p++ = *name; + name++; + } + *p = '\0'; + return ret; +} + +static DBusHandlerResult +signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + guint res = DBUS_HANDLER_RESULT_HANDLED; + const gint type = dbus_message_get_type (message); + const char *iface = dbus_message_get_interface (message); + const char *member = dbus_message_get_member (message); + + if (type != DBUS_MESSAGE_TYPE_SIGNAL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && + !g_strcmp0(member, "NameOwnerChanged")) + handle_disconnection (bus, message, user_data); + else + res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + return res; +} + +/* org.at_spi.Socket interface */ +/*---------------------------------------------------------------------------*/ + +static DBusMessage* +impl_Embed (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + DBusMessageIter iter, iter_struct; + const gchar *app_name, *obj_path; + + DBusMessage *reply = NULL; + DBusMessageIter reply_iter; + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_struct); + if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_STRING)) + goto error; + dbus_message_iter_get_basic (&iter_struct, &app_name); + if (!app_name) + app_name = dbus_message_get_sender (message); + if (!dbus_message_iter_next (&iter_struct)) + goto error; + if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_OBJECT_PATH)) + goto error; + dbus_message_iter_get_basic (&iter_struct, &obj_path); + + add_application(reg, bus, app_name, obj_path); + + set_id (reg, bus, app_name, obj_path); + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &reply_iter); + append_reference (&reply_iter, + dbus_bus_get_unique_name (bus), + SPI_DBUS_PATH_ROOT); + + return reply; +error: + return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments"); +} + +static DBusMessage* +impl_Unembed (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + DBusMessageIter iter, iter_struct; + gchar *app_name, *obj_path; + guint index; + + dbus_message_iter_init (message, &iter); + dbus_message_iter_recurse (&iter, &iter_struct); + if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_STRING)) + goto error; + dbus_message_iter_get_basic (&iter_struct, &app_name); + if (!dbus_message_iter_next (&iter_struct)) + goto error; + if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_OBJECT_PATH)) + goto error; + dbus_message_iter_get_basic (&iter_struct, &obj_path); + + if (find_index_of_reference (reg->apps, app_name, obj_path, &index)) + remove_application(reg, bus, index); + + return NULL; +error: + return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments"); +} + +/* org.at_spi.Component interface */ +/*---------------------------------------------------------------------------*/ + +static DBusMessage * +impl_Contains (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + dbus_bool_t retval = FALSE; + DBusMessage *reply; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetAccessibleAtPoint (DBusConnection * bus, DBusMessage * message, + void *user_data) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + append_reference (&iter, + dbus_bus_get_unique_name (bus), + SPI_DBUS_PATH_NULL); + + return reply; +} + +static DBusMessage * +impl_GetExtents (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + dbus_int32_t x = 0, y = 0, width = 1024, height = 768; + DBusMessage *reply; + DBusMessageIter iter, iter_struct; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &x); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &y); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &width); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &height); + dbus_message_iter_close_container (&iter, &iter_struct); + return reply; +} + +static DBusMessage * +impl_GetPosition (DBusConnection * bus, DBusMessage * message, + void *user_data) +{ + DBusMessage *reply; + dbus_int32_t x = 0, y = 0; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, + &y, DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetSize (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + /* TODO - Get the screen size */ + DBusMessage *reply; + dbus_int32_t width = 1024, height = 768; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &width, + DBUS_TYPE_INT32, &height, DBUS_TYPE_INVALID); + return reply; +} + +#define LAYER_WIDGET 3; + +static DBusMessage * +impl_GetLayer (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + dbus_uint32_t rv = LAYER_WIDGET; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetMDIZOrder (DBusConnection * bus, DBusMessage * message, + void *user_data) +{ + DBusMessage *reply; + dbus_int16_t rv = 0; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_INT16, &rv, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GrabFocus (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + dbus_bool_t retval = FALSE; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetAlpha (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + double rv = 1.0; + DBusMessage *reply; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_DOUBLE, &rv, + DBUS_TYPE_INVALID); + return reply; +} + +/* org.at_spi.Accessible interface */ +/*---------------------------------------------------------------------------*/ + +static dbus_bool_t +impl_get_Name (DBusMessageIter * iter, void *user_data) +{ + const gchar *name = "main"; + return return_v_string (iter, name); +} + +static dbus_bool_t +impl_get_Description (DBusMessageIter * iter, void *user_data) +{ + const gchar *description = ""; + return return_v_string (iter, description); +} + +static dbus_bool_t +impl_get_Parent (DBusMessageIter * iter, void *user_data) +{ + const gchar *name = ""; + DBusMessageIter iter_variant; + + dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)", + &iter_variant); + append_reference (&iter_variant, + name, + SPI_DBUS_PATH_NULL); + dbus_message_iter_close_container (iter, &iter_variant); + return TRUE; +} + +static dbus_bool_t +impl_get_ChildCount (DBusMessageIter * iter, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + dbus_int32_t rv = reg->apps->len; + dbus_bool_t result; + DBusMessageIter iter_variant; + + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "i", + &iter_variant)) + return FALSE; + result = dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &rv); + dbus_message_iter_close_container (iter, &iter_variant); + return result; +} + +static dbus_bool_t +impl_get_ToolkitName (DBusMessageIter * iter, void *user_data) +{ + return return_v_string (iter, "at-spi-registry"); +} + +static dbus_bool_t +impl_get_ToolkitVersion (DBusMessageIter * iter, void *user_data) +{ + return return_v_string (iter, "2.0"); +} + +static DBusMessage * +impl_GetChildAtIndex (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + SpiReference *ref; + dbus_int32_t i; + + dbus_error_init (&error); + if (!dbus_message_get_args + (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID)) + { + return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments"); + } + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + + if (i < 0 || i >= reg->apps->len) + append_reference (&iter, SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_NULL); + else + { + ref = g_ptr_array_index (reg->apps, i); + append_reference (&iter, ref->name, ref->path); + } + + return reply; +} + +static DBusMessage * +impl_GetChildren (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter, iter_array; + SpiRegistry *reg = SPI_REGISTRY (user_data); + int i; + + reply = dbus_message_new_method_return (message); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array); + for (i=0; i < reg->apps->len; i++) + { + SpiReference *current = g_ptr_array_index (reg->apps, i); + append_reference (&iter_array, current->name, current->path); + } + dbus_message_iter_close_container(&iter, &iter_array); + return reply; +} + +static DBusMessage * +impl_GetIndexInParent (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + dbus_uint32_t rv = 0; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv, DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetRelationSet (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array); + dbus_message_iter_close_container (&iter, &iter_array); + + return reply; +} + +static DBusMessage * +impl_GetRole (DBusConnection * bus, DBusMessage * message, void * user_data) +{ + DBusMessage *reply; + dbus_uint32_t rv = 14; /* TODO: Get DESKTOP_FRAME from somewhere */ + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetRoleName (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + const char *role_name = "desktop frame"; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetLocalizedRoleName (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + /* TODO - Localize this */ + DBusMessage *reply; + const char *role_name = "desktop frame"; + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name, + DBUS_TYPE_INVALID); + return reply; +} + +static DBusMessage * +impl_GetState (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter, iter_array; + + dbus_uint32_t states[2] = {0, 0}; + guint count; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array); + for (count = 0; count < 2; count++) + { + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32, + &states[count]); + } + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +static DBusMessage * +impl_GetAttributes (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter, array; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", &array); + dbus_message_iter_close_container (&iter, &array); + + return reply; +} + +static DBusMessage * +impl_GetApplication (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + append_reference (&iter, + dbus_bus_get_unique_name (bus), + SPI_DBUS_PATH_NULL); + + return reply; +} + +static DBusMessage * +impl_GetInterfaces (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + + const char *acc = SPI_DBUS_INTERFACE_ACCESSIBLE; + const char *com = SPI_DBUS_INTERFACE_COMPONENT; + + reply = dbus_message_new_method_return (message); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", + &iter_array); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &acc); + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &com); + dbus_message_iter_close_container (&iter, &iter_array); + + return reply; +} + +static DBusMessage * +impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + + reply = dbus_message_new_method_return (message); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, + "((so)(so)(so)a(so)assusau)", &iter_array); + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +/* I would rather these two be signals, but I'm not sure that dbus-python + * supports emitting signals except for a service, so implementing as both + * a method call and signal for now. + */ +static DBusMessage * +impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *registry = SPI_REGISTRY (user_data); + const char *orig_name; + gchar *name; + event_data *evdata; + gchar **data; + DBusMessage *signal; + const char *sender = dbus_message_get_sender (message); + DBusMessageIter iter, iter_array; + const char *signature = dbus_message_get_signature (message); + + if (strcmp (signature, "sas") != 0 && + strcmp (signature, "s") != 0) + { + g_warning ("got RegisterEvent with invalid signature '%s'", signature); + return NULL; + } + + dbus_message_iter_init (message, &iter); + dbus_message_iter_get_basic (&iter, &orig_name); + dbus_message_iter_next (&iter); + name = ensure_proper_format (orig_name); + + evdata = g_new0 (event_data, 1); + data = g_strsplit (name, ":", 3); + evdata->bus_name = g_strdup (sender); + evdata->data = data; + + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY) + { + dbus_message_iter_recurse (&iter, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + const char *property; + dbus_message_iter_get_basic (&iter_array, &property); + evdata->properties = g_slist_append (evdata->properties, + g_strdup (property)); + dbus_message_iter_next (&iter_array); + } + } + registry->events = g_list_append (registry->events, evdata); + + if (needs_mouse_poll (evdata->data)) + { + spi_device_event_controller_start_poll_mouse (registry); + } + + signal = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY, + SPI_DBUS_INTERFACE_REGISTRY, + "EventListenerRegistered"); + if (signal) + { + GSList *ls = evdata->properties; + dbus_message_iter_init_append (signal, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &name); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array); + while (ls) + { + dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &ls->data); + ls = g_slist_next (ls); + } + dbus_message_iter_close_container (&iter, &iter_array); + dbus_connection_send (bus, signal, NULL); + dbus_message_unref (signal); + } + + g_free (name); + return dbus_message_new_method_return (message); +} + +static DBusMessage * +impl_deregister_event (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *registry = SPI_REGISTRY (user_data); + const char *orig_name; + gchar *name; + const char *sender = dbus_message_get_sender (message); + + if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &orig_name, + DBUS_TYPE_INVALID)) + return NULL; + name = ensure_proper_format (orig_name); + + remove_events (registry, sender, name); + + g_free (name); + return dbus_message_new_method_return (message); +} + +static DBusMessage * +impl_get_registered_events (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *registry = SPI_REGISTRY (user_data); + event_data *evdata; + DBusMessage *reply; + DBusMessageIter iter, iter_struct, iter_array; + GList *list; + + reply = dbus_message_new_method_return (message); + if (!reply) + return NULL; + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &iter_array); + for (list = registry->events; list; list = list->next) + { + gchar *str; + evdata = list->data; + str = g_strconcat (evdata->data [0], + ":", (evdata->data [1]? evdata->data [1]: ""), + ":", (evdata->data [1] && evdata->data [2]? evdata->data [2]: ""), NULL); + dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &evdata->bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &str); + dbus_message_iter_close_container (&iter_array, &iter_struct); + g_free (str); + } + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +/*---------------------------------------------------------------------------*/ + +static void +emit_Available (DBusConnection * bus) +{ + DBusMessage *sig; + DBusMessageIter iter; + + sig = dbus_message_new_signal(SPI_DBUS_PATH_ROOT, SPI_DBUS_INTERFACE_SOCKET, "Available"); + + dbus_message_iter_init_append(sig, &iter); + append_reference (&iter, SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_ROOT); + + dbus_connection_send(bus, sig, NULL); + dbus_message_unref(sig); +} + +/*---------------------------------------------------------------------------*/ + +static const char *introspection_header = +"\n"; + +static const char *introspection_node_element = +"\n"; + +static const char *introspection_footer = +""; + +static DBusMessage * +impl_Introspect_root (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + GString *output; + gchar *final; + + const gchar *pathstr = SPI_DBUS_PATH_ROOT; + + DBusMessage *reply; + + output = g_string_new(introspection_header); + + g_string_append_printf(output, introspection_node_element, pathstr); + + g_string_append (output, spi_org_a11y_atspi_Accessible); + g_string_append (output, spi_org_a11y_atspi_Component); + + g_string_append(output, introspection_footer); + final = g_string_free(output, FALSE); + + reply = dbus_message_new_method_return (message); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID); + + g_free(final); + return reply; +} + +static DBusMessage * +impl_Introspect_registry (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + GString *output; + gchar *final; + + const gchar *pathstr = SPI_DBUS_PATH_REGISTRY; + + DBusMessage *reply; + + output = g_string_new(introspection_header); + + g_string_append_printf(output, introspection_node_element, pathstr); + + g_string_append (output, spi_org_a11y_atspi_Registry); + + g_string_append(output, introspection_footer); + final = g_string_free(output, FALSE); + + reply = dbus_message_new_method_return (message); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID); + + g_free(final); + return reply; +} + +/*---------------------------------------------------------------------------*/ + +/* + * Emits an AT-SPI event. + * AT-SPI events names are split into three parts: + * class:major:minor + * This is mapped onto D-Bus events as: + * D-Bus Interface:Signal Name:Detail argument + * + * Marshals a basic type into the 'any_data' attribute of + * the AT-SPI event. + */ +static void +emit_event (DBusConnection *bus, + const char *klass, + const char *major, + const char *minor, + dbus_int32_t detail1, + dbus_int32_t detail2, + const char *name, + const char *path) +{ + DBusMessage *sig; + DBusMessageIter iter, iter_variant; + + sig = dbus_message_new_signal(SPI_DBUS_PATH_ROOT, klass, major); + + dbus_message_iter_init_append(sig, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2); + + dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(so)", + &iter_variant); + append_reference (&iter_variant, name, path); + dbus_message_iter_close_container (&iter, &iter_variant); + + append_reference (&iter, + dbus_bus_get_unique_name (bus), + SPI_DBUS_PATH_ROOT); + + dbus_connection_send(bus, sig, NULL); + dbus_message_unref(sig); +} + +/*---------------------------------------------------------------------------*/ + +/* + * Children changed signal converter and forwarder. + * + * Klass (Interface) org.a11y.atspi.Event.Object + * Major is the signal name. + * Minor is 'add' or 'remove' + * detail1 is the index. + * detail2 is 0. + * any_data is the child reference. + */ + +static void +children_added_listener (DBusConnection * bus, + gint index, + const gchar * name, + const gchar * path) +{ + emit_event (bus, SPI_DBUS_INTERFACE_EVENT_OBJECT, "ChildrenChanged", "add", index, 0, + name, path); +} + +static void +children_removed_listener (DBusConnection * bus, + gint index, + const gchar * name, + const gchar * path) +{ + emit_event (bus, SPI_DBUS_INTERFACE_EVENT_OBJECT, "ChildrenChanged", "remove", index, 0, + name, path); +} + +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +handle_method_root (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + + DBusMessage *reply = NULL; + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!strcmp (iface, "org.freedesktop.DBus.Properties")) + { + if (!strcmp (member, "Get")) + { + const gchar *prop_iface; + const gchar *prop_member; + DBusError error; + + dbus_error_init (&error); + if (dbus_message_get_args (message, + &error, + DBUS_TYPE_STRING, + &prop_iface, + DBUS_TYPE_STRING, + &prop_member, + DBUS_TYPE_INVALID)) + { + DBusMessageIter iter; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + + + if (!strcmp (prop_iface, SPI_DBUS_INTERFACE_ACCESSIBLE)) + { + if (!strcmp (prop_member, "Name")) + impl_get_Name (&iter, user_data); + else if (!strcmp (prop_member, "Description")) + impl_get_Description (&iter, user_data); + else if (!strcmp (prop_member, "Parent")) + impl_get_Parent (&iter, user_data); + else if (!strcmp (prop_member, "ChildCount")) + impl_get_ChildCount (&iter, user_data); + else + { + dbus_message_unref (reply); + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable"); + } + } + else if (!strcmp (prop_iface, SPI_DBUS_INTERFACE_APPLICATION)) + { + if (!strcmp (prop_member, "ToolkitName")) + impl_get_ToolkitName (&iter, user_data); + else if (!strcmp (prop_member, "ToolkitVersion")) + impl_get_ToolkitVersion (&iter, user_data); + else + { + dbus_message_unref (reply); + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable"); + } + } + else + { + dbus_message_unref (reply); + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable"); + } + } + else + { + reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message); + } + result = DBUS_HANDLER_RESULT_HANDLED; + } + else if (!strcmp (member, "GetAll")) + { + result = DBUS_HANDLER_RESULT_HANDLED; + } + } + + if (!strcmp (iface, SPI_DBUS_INTERFACE_ACCESSIBLE)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "GetChildAtIndex")) + reply = impl_GetChildAtIndex (bus, message, user_data); + else if (!strcmp (member, "GetChildren")) + reply = impl_GetChildren (bus, message, user_data); + else if (!strcmp (member, "GetIndexInParent")) + reply = impl_GetIndexInParent (bus, message, user_data); + else if (!strcmp (member, "GetRelationSet")) + reply = impl_GetRelationSet (bus, message, user_data); + else if (!strcmp (member, "GetRole")) + reply = impl_GetRole (bus, message, user_data); + else if (!strcmp (member, "GetRoleName")) + reply = impl_GetRoleName (bus, message, user_data); + else if (!strcmp (member, "GetLocalizedRoleName")) + reply = impl_GetLocalizedRoleName (bus, message, user_data); + else if (!strcmp (member, "GetState")) + reply = impl_GetState (bus, message, user_data); + else if (!strcmp (member, "GetAttributes")) + reply = impl_GetAttributes (bus, message, user_data); + else if (!strcmp (member, "GetApplication")) + reply = impl_GetApplication (bus, message, user_data); + else if (!strcmp (member, "GetInterfaces")) + reply = impl_GetInterfaces (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (iface, SPI_DBUS_INTERFACE_COMPONENT)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "Contains")) + reply = impl_Contains (bus, message, user_data); + else if (!strcmp (member, "GetAccessibleAtPoint")) + reply = impl_GetAccessibleAtPoint (bus, message, user_data); + else if (!strcmp (member, "GetExtents")) + reply = impl_GetExtents (bus, message, user_data); + else if (!strcmp (member, "GetPosition")) + reply = impl_GetPosition (bus, message, user_data); + else if (!strcmp (member, "GetSize")) + reply = impl_GetSize (bus, message, user_data); + else if (!strcmp (member, "GetLayer")) + reply = impl_GetLayer (bus, message, user_data); + else if (!strcmp (member, "GetMDIZOrder")) + reply = impl_GetMDIZOrder (bus, message, user_data); + else if (!strcmp (member, "GrabFocus")) + reply = impl_GrabFocus (bus, message, user_data); + else if (!strcmp (member, "GetAlpha")) + reply = impl_GetAlpha (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (iface, SPI_DBUS_INTERFACE_SOCKET)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "Embed")) + reply = impl_Embed (bus, message, user_data); + else if (!strcmp (member, "Unembed")) + reply = impl_Unembed (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "Introspect")) + reply = impl_Introspect_root (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (result == DBUS_HANDLER_RESULT_HANDLED) + { + if (!reply) + { + reply = dbus_message_new_method_return (message); + } + + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } +#if 0 + else + { + g_print ("Registry | Unhandled message : %s|%s\n", iface, member); + } +#endif + + return result; +} + +static DBusHandlerResult +handle_method_cache (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + + DBusMessage *reply = NULL; + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!strcmp (iface, SPI_DBUS_INTERFACE_CACHE)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "GetItems")) + reply = impl_GetItems (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (result == DBUS_HANDLER_RESULT_HANDLED) + { + if (!reply) + { + reply = dbus_message_new_method_return (message); + } + + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } + return result; +} + +static DBusHandlerResult +handle_method_registry (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + const gchar *iface = dbus_message_get_interface (message); + const gchar *member = dbus_message_get_member (message); + const gint type = dbus_message_get_type (message); + + DBusMessage *reply = NULL; + + /* Check for basic reasons not to handle */ + if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || + member == NULL || + iface == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!strcmp (iface, SPI_DBUS_INTERFACE_REGISTRY)) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp(member, "RegisterEvent")) + reply = impl_register_event (bus, message, user_data); + else if (!strcmp(member, "DeregisterEvent")) + reply = impl_deregister_event (bus, message, user_data); + else if (!strcmp(member, "GetRegisteredEvents")) + reply = impl_get_registered_events (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) + { + result = DBUS_HANDLER_RESULT_HANDLED; + if (!strcmp (member, "Introspect")) + reply = impl_Introspect_registry (bus, message, user_data); + else + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (result == DBUS_HANDLER_RESULT_HANDLED) + { + if (!reply) + { + reply = dbus_message_new_method_return (message); + } + + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } +#if 0 + else + { + g_print ("Registry | Unhandled message : %s|%s\n", iface, member); + } +#endif + + return result; +} + +/*---------------------------------------------------------------------------*/ + +static DBusObjectPathVTable root_vtable = +{ + NULL, + &handle_method_root, + NULL, NULL, NULL, NULL +}; + +static DBusObjectPathVTable registry_vtable = +{ + NULL, + &handle_method_registry, + NULL, NULL, NULL, NULL +}; + +static DBusObjectPathVTable cache_vtable = +{ + NULL, + &handle_method_cache, + NULL, NULL, NULL, NULL +}; + +static gchar *app_sig_match_name_owner = + "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'"; + +SpiRegistry * +spi_registry_new (DBusConnection *bus) +{ + SpiRegistry *reg = g_object_new (SPI_REGISTRY_TYPE, NULL); + + reg->bus = bus; + + dbus_bus_add_match (bus, app_sig_match_name_owner, NULL); + dbus_connection_add_filter (bus, signal_filter, reg, NULL); + + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_ROOT, &root_vtable, reg); + + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_CACHE, &cache_vtable, reg); + + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_REGISTRY, ®istry_vtable, reg); + + emit_Available (bus); + + reg->events = NULL; + + return reg; +} + +/*END------------------------------------------------------------------------*/ diff --git a/registryd/registry.h b/registryd/registry.h new file mode 100644 index 0000000..16dd0d9 --- /dev/null +++ b/registryd/registry.h @@ -0,0 +1,64 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, 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 SPI_REGISTRY_H_ +#define SPI_REGISTRY_H_ + +#include +#include + +#include + +typedef struct _SpiRegistry SpiRegistry; +typedef struct _SpiRegistryClass SpiRegistryClass; + +#include "deviceeventcontroller.h" + +G_BEGIN_DECLS + +#define SPI_REGISTRY_TYPE (spi_registry_get_type ()) +#define SPI_REGISTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_REGISTRY_TYPE, SpiRegistry)) +#define SPI_REGISTRY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_REGISTRY_TYPE, SpiRegistryClass)) +#define SPI_IS_REGISTRY(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_REGISTRY_TYPE)) +#define SPI_IS_REGISTRY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_REGISTRY_TYPE)) + +struct _SpiRegistry { + GObject parent; + SpiDEController *dec; + GPtrArray *apps; + dbus_int32_t id; + + DBusConnection *bus; + GList *events; +}; + +struct _SpiRegistryClass { + GObjectClass parent_class; +}; + +GType spi_registry_get_type (void); +SpiRegistry *spi_registry_new (DBusConnection *bus); + +G_END_DECLS + +#endif /* SPI_REGISTRY_H_ */ diff --git a/registryd/testregistry.py b/registryd/testregistry.py new file mode 100755 index 0000000..db85e74 --- /dev/null +++ b/registryd/testregistry.py @@ -0,0 +1,59 @@ +#!/usr/bin/python + +import sys +import dbus +import dbus.service +import gobject + +from dbus.mainloop.glib import DBusGMainLoop + +DBusGMainLoop(set_as_default=True) + +class IdleStateM (object): + def __init__(self, bus, loop): + self._bus = bus + self._loop = loop + self._func = self.setup + + def idle_handler(self): + self._func = self._func() + if self._func == None: + self._func = self.teardown + return True + + def setup(self): + self.obj = self._bus.get_object("org.a11y.atspi.Registry", + "/org/a11y/atspi/accessible/root", + introspect=False) + self.itf = dbus.Interface(self.obj, dbus_interface="org.a11y.atspi.Accessible") + return self.register_apps + + def register_apps(self): + #self.itf.registerApplication(":R456", ignore_reply=True) + #self.itf.registerApplication(":R123", ignore_reply=True) + return self.print_applications + + def print_applications(self): + apps = self.itf.GetChildren() + print apps + return self.teardown + + def teardown(self): + self._loop.quit() + +def main(argv): + bus = dbus.SessionBus() + obj = bus.get_object("org.a11y.Bus", + "/org/a11y/bus", + introspect=False) + itf = dbus.Interface(obj, dbus_interface="org.a11y.Bus") + address = itf.GetAddress() + + bus = dbus.bus.BusConnection(str(address)) + loop = gobject.MainLoop() + stateM = IdleStateM(bus, loop) + gobject.idle_add(stateM.idle_handler) + loop.run() + +if __name__=="__main__": + sys.exit(main(sys.argv)) diff --git a/registryd/ucs2keysym.c b/registryd/ucs2keysym.c new file mode 100644 index 0000000..b4967be --- /dev/null +++ b/registryd/ucs2keysym.c @@ -0,0 +1,855 @@ +/* Modified from the public domain program keysym2ucs.c, + * as documented below. + * + * This module converts ISO 10646 + * (UCS, Unicode) values into X Keysym values. + * + * The array keysymtab[] contains pairs of X11 keysym values for graphical + * characters and the corresponding Unicode value. The function + * keysym2ucs() maps a Unicode value onto a keysym using a binary search, + * therefore keysymtab[] must remain SORTED by ucs2 value. + * + * We allow to represent any UCS character in the range U-00000000 to + * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. + * This admittedly does not cover the entire 31-bit space of UCS, but + * it does cover all of the characters up to U-10FFFF, which can be + * represented by UTF-16, and more, and it is very unlikely that higher + * UCS codes will ever be assigned by ISO. So to get Unicode character + * U+ABCD you can directly use keysym 0x0100abcd. + * + * NOTE: The comments in the table below contain the actual character + * encoded in UTF-8, so for viewing and editing best use an editor in + * UTF-8 mode. + * + * Author: Markus G. Kuhn , + * University of Cambridge, April 2001 + * + * Special thanks to Richard Verhoeven for preparing + * an initial draft of the mapping table. + * + * This software is in the public domain. Share and enjoy! + * + */ + +#include +#include "deviceeventcontroller.h" /* for prototype */ + +struct codepair { + unsigned short keysym; + unsigned short ucs; +} keysymtab[] = { + { 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */ + { 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ + { 0x0bc6, 0x005f }, /* underbar _ LOW LINE */ + { 0x0bc0, 0x00af }, /* overbar ¯ MACRON */ + + { 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ + { 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ + { 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ + { 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ + { 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ + { 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ + { 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ + { 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ + { 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ + { 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ + { 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ + { 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ + { 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ + { 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ + { 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ + { 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ + { 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ + { 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ + { 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ + { 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ + { 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ + { 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ + { 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ + { 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ + { 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ + { 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ + { 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ + { 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ + { 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ + { 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ + { 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ + { 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ + { 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ + { 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ + { 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ + { 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ + { 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ + { 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ + { 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ + { 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ + { 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ + { 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ + { 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ + { 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ + { 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ + { 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ + { 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ + { 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ + { 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ + { 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ + { 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ + { 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ + { 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ + { 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ + { 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ + { 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ + { 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ + { 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ + { 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ + { 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ + { 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ + { 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ + { 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ + { 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ + { 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ + { 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ + { 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ + { 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ + { 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ + { 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ + { 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ + { 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ + { 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ + { 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ + { 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ + { 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ + { 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ + { 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ + { 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ + { 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ + { 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ + { 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ + { 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ + { 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ + { 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ + { 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ + { 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ + { 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ + { 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ + { 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ + { 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ + { 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ + { 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ + { 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ + { 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ + { 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ + { 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ + { 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ + { 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ + { 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ + { 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ + { 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ + { 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ + { 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ + { 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ + { 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ + { 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ + { 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ + { 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ + { 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ + { 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ + { 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ + { 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ + + { 0x01b7, 0x02c7 }, /* caron ˇ CARON */ + { 0x01a2, 0x02d8 }, /* breve ˘ BREVE */ + { 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ + { 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */ + { 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ + + { 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ + { 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ + { 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ + { 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ + { 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ + { 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ + { 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ + { 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ + { 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ + { 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ + { 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ + { 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ + { 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ + { 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ + { 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ + { 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ + { 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ + { 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ + { 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ + { 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ + { 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ + { 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ + { 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ + { 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ + { 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ + { 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ + { 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ + { 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ + { 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ + { 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ + { 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ + { 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ + { 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ + { 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ + { 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ + { 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ + { 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ + { 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ + { 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ + { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ + { 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ + { 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ + { 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ + { 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ + { 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ + { 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ + { 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ + { 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ + { 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ + { 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ + { 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ + { 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ + { 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ + { 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ + { 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ + { 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ + { 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ + { 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ + { 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ + { 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ + { 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ + { 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ + { 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ + { 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ + { 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ + { 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ + { 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ + { 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ + { 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ + { 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ + + { 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ + { 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ + { 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ + { 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ + { 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ + { 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ + { 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ + { 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ + { 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ + { 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ + { 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ + { 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ + { 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ + { 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ + { 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ + { 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ + { 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ + { 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ + { 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ + { 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ + { 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ + { 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ + { 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ + { 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ + { 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ + { 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ + { 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ + { 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ + { 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ + { 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ + { 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ + { 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ + { 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ + { 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ + { 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ + { 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ + { 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ + { 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ + { 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ + { 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ + { 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ + { 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ + { 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ + { 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ + { 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ + { 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ + { 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ + { 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ + { 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ + { 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ + { 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ + { 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ + { 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ + { 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ + { 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ + { 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ + { 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ + { 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ + { 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ + { 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ + { 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ + { 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ + { 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ + { 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ + { 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ + { 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ + { 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ + { 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ + { 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ + { 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ + { 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ + { 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ + { 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ + { 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ + { 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ + { 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ + { 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ + { 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ + { 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ + { 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ + { 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ + { 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ + { 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ + { 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ + { 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ + { 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ + { 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ + { 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ + { 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ + { 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ + { 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ + + { 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ + { 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ + { 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ + { 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ + { 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ + { 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ + { 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ + { 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ + { 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ + { 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ + { 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ + { 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ + { 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ + { 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ + { 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ + { 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ + { 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ + { 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ + { 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ + { 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ + { 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ + { 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ + { 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ + { 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ + { 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ + { 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ + { 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ + + { 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ + { 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ + { 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ + { 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ + { 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ + { 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ + { 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ + { 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ + { 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ + { 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ + { 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ + { 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ + { 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ + { 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ + { 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ + { 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ + { 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ + { 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ + { 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ + { 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ + { 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ + { 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ + { 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ + { 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ + { 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ + { 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ + { 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ + { 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ + { 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ + { 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ + { 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ + { 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ + { 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ + { 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ + { 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ + { 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ + { 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ + { 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ + { 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ + { 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ + { 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ + { 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ + { 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ + { 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ + { 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ + { 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ + { 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ + { 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ + + { 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ + { 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ + { 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ + { 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ + { 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ + { 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ + { 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ + { 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ + { 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ + { 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ + { 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ + { 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ + { 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ + { 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ + { 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ + { 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ + { 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ + { 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ + { 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ + { 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ + { 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ + { 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ + { 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ + { 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ + { 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ + { 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ + { 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ + { 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ + { 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ + { 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ + { 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ + { 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ + { 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ + { 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ + { 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ + { 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ + { 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ + { 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ + { 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ + { 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ + { 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ + { 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ + { 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ + { 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ + { 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ + { 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ + { 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ + { 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ + { 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ + { 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ + { 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ + { 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ + { 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ + { 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ + { 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ + { 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ + { 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ + { 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ + { 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ + { 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ + { 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ + { 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ + { 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ + { 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ + { 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ + { 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ + { 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ + { 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ + { 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ + { 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ + { 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ + { 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ + { 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ + { 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ + { 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ + { 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ + { 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ + { 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ + { 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ + { 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ + { 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ + { 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ + { 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ + + { 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ + { 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ + { 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ + { 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ + { 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ + { 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ + { 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ + { 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ + { 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ + { 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ + { 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ + { 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ + { 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ + { 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ + { 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ + { 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ + { 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ + { 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ + { 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ + { 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ + { 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ + { 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ + { 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ + { 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ + { 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ + { 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ + { 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ + { 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ + { 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ + { 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ + + + { 0x0aa2, 0x2002 }, /* enspace   EN SPACE */ + { 0x0aa1, 0x2003 }, /* emspace   EM SPACE */ + { 0x0aa3, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ + { 0x0aa4, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ + { 0x0aa5, 0x2007 }, /* digitspace   FIGURE SPACE */ + { 0x0aa6, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ + { 0x0aa7, 0x2009 }, /* thinspace   THIN SPACE */ + { 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */ + { 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */ + { 0x0aaa, 0x2013 }, /* endash – EN DASH */ + { 0x0aa9, 0x2014 }, /* emdash — EM DASH */ + { 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ + { 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ + { 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ + { 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ + { 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ + { 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ + { 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ + { 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ + { 0x0af1, 0x2020 }, /* dagger † DAGGER */ + { 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ + { 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */ + { 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ + { 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ + { 0x0ad6, 0x2032 }, /* minutes ′ PRIME */ + { 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */ + { 0x0afc, 0x2038 }, /* caret ‸ CARET */ + { 0x047e, 0x203e }, /* overline ‾ OVERLINE */ + { 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ + { 0x13a4, 0x20ac }, /* Euro € EURO SIGN */ + + { 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */ + { 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */ + { 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ + { 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ + { 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ + { 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ + { 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ + { 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ + { 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ + { 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ + { 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ + { 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ + { 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ + { 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ + { 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ + { 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ + { 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ + { 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ + { 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ + { 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ + { 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ + { 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ + { 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ + { 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ + { 0x08c5, 0x2207 }, /* nabla ∇ NABLA */ + { 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */ + { 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */ + { 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */ + { 0x08c2, 0x221e }, /* infinity ∞ INFINITY */ + { 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */ + { 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */ + { 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */ + { 0x08dd, 0x222a }, /* union ∪ UNION */ + { 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */ + { 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */ + { 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */ + { 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ + { 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ + { 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */ + { 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ + { 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ + { 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */ + { 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */ + { 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */ + { 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */ + { 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */ + { 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */ + { 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */ + { 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */ + { 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ + { 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ + { 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ + { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */ + { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */ + { 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */ + { 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */ + { 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */ + { 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */ + { 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */ + { 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */ + { 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */ + { 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */ + { 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */ + { 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */ + { 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */ + { 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */ + { 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ + { 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ + { 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ + { 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ + { 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ + { 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ + { 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ + { 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ + { 0x09e8, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ + { 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ + + { 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ + { 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ + { 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ + { 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ + { 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ + { 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ + { 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ + { 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ + { 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ + { 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ + { 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ + { 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ + { 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ + { 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ + { 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ + { 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ + { 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ + { 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ + { 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ + { 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ + { 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ + { 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ + { 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ + { 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ + { 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ + { 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ + { 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ + { 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ + { 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ + { 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ + { 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ + { 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ + { 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ + { 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ + { 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */ + { 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */ + { 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */ + { 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ + + { 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ + { 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ + { 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ + { 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ + { 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ + { 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ + { 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ + { 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ + { 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ + { 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ + { 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ + { 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ + { 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ + { 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ + { 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ + { 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ + { 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ + { 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ + { 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ + { 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ + { 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ + { 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ + { 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ + { 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ + { 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ + { 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ + { 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ + { 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ + { 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ + { 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ + { 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ + { 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ + { 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ + { 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ + { 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ + { 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ + { 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ + { 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ + { 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ + { 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ + { 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ + { 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ + { 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ + { 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ + { 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ + { 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ + { 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ + { 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ + { 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ + { 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ + { 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ + { 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ + { 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ + { 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ + { 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ + { 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ + { 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ + { 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ + { 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ + { 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ + { 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ + { 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ + { 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ + + { 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ + { 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ + { 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ + { 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ + { 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ + { 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ + { 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ + { 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ + { 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ + { 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ + { 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ + { 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ + { 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ + { 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ + { 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ + { 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ + { 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ + { 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ + { 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ + { 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ + { 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ + { 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ + { 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ + { 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ + { 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ + { 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ + { 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ + { 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ + { 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ + { 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ + { 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ + { 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ + { 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ + { 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ + { 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ + { 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ + { 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ + { 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ + { 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ + { 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ + { 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ + { 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ + { 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ + { 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ + { 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ + { 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ + { 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ + { 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ + { 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ + { 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ + { 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ + { 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ + { 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ + { 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ + { 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ + { 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ + { 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ + { 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ + { 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ + { 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ + }; + +long ucs2keysym (long ucs) +{ + int min = 0; + int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; + int mid; + + /* first check for Latin-1 characters (1:1 mapping) */ + if ((ucs >= 0x0020 && ucs <= 0x007e) || + (ucs >= 0x00a0 && ucs <= 0x00ff)) + return ucs; + + /* binary search in table */ + while (max >= min) { + mid = (min + max) / 2; + if (keysymtab[mid].ucs < ucs) + min = mid + 1; + else if (keysymtab[mid].ucs > ucs) + max = mid - 1; + else { + /* found it */ + return keysymtab[mid].keysym; + } + } + + /* no matching keysym value found, return UCS2 with bit set */ + return ucs | 0x01000000; +} + +long keysym2ucs(long keysym) +{ + int min = 0; + int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; + int mid; + + /* first check for Latin-1 characters (1:1 mapping) */ + if ((keysym >= 0x0020 && keysym <= 0x007e) || + (keysym >= 0x00a0 && keysym <= 0x00ff)) + return (long) keysym; + + /* also check for directly encoded 24-bit UCS characters */ + if ((keysym & 0xff000000) == 0x01000000) + return keysym & 0x00ffffff; + + /* binary search in table */ + while (max >= min) { + mid = (min + max) / 2; + if (keysymtab[mid].keysym < keysym) + min = mid + 1; + else if (keysymtab[mid].keysym > keysym) + max = mid - 1; + else { + /* found it */ + return keysymtab[mid].ucs; + } + } + + /* no matching Unicode value found */ + return -1; +} diff --git a/test/memory.c b/test/memory.c new file mode 100644 index 0000000..df5e0a1 --- /dev/null +++ b/test/memory.c @@ -0,0 +1,84 @@ +#include "atspi/atspi.h" +#include +#include +#include + +pid_t child_pid; +AtspiEventListener *listener; + +void +basic (AtspiAccessible *obj) +{ + gchar *str; + gint count; + gint i; + AtspiAccessible *accessible; + GError *error = NULL; + + str = atspi_accessible_get_name (obj, &error); + if (str) + g_free (str); + accessible = atspi_accessible_get_parent (obj, NULL); + if (accessible) + g_object_unref (accessible); + count = atspi_accessible_get_child_count (obj, &error); + for (i = 0; i < count; i++) + { + accessible = atspi_accessible_get_child_at_index (obj, i, &error); + if (accessible) + g_object_unref (accessible); + } +} + +static gboolean +end (void *data) +{ + atspi_event_quit (); + atspi_exit (); + exit (0); +} + +static gboolean +kill_child (void *data) +{ + kill (child_pid, SIGTERM); + return FALSE; +} + +void +on_event (AtspiEvent *event, void *data) +{ + if (atspi_accessible_get_role (event->source, NULL) == ATSPI_ROLE_DESKTOP_FRAME) + { + if (strstr (event->type, "add")) + { + AtspiAccessible *desktop = atspi_get_desktop (0); + guint id; + basic (desktop); + g_object_unref (desktop); + id = g_timeout_add (3000, kill_child, NULL); + g_source_set_name_by_id (id, "[at-spi2-core] kill_child"); + } + else + { + guint id; + id = g_idle_add (end, NULL); + g_source_set_name_by_id (id, "[at-spi2-core] end"); + } + } + g_boxed_free (ATSPI_TYPE_EVENT, event); +} + +int +main() +{ + atspi_init (); + + listener = atspi_event_listener_new (on_event, NULL, NULL); + atspi_event_listener_register (listener, "object:children-changed", NULL); + child_pid = fork (); + if (!child_pid) + execlp ("gedit", "gedit", NULL); + atspi_event_main (); + return 0; +} diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000..1fb35a8 --- /dev/null +++ b/test/meson.build @@ -0,0 +1,4 @@ +test('memory', + executable('memory', 'memory.c', + include_directories: root_inc, + dependencies: [ atspi_dep ])) diff --git a/xml/Accessibility.xml b/xml/Accessibility.xml new file mode 100644 index 0000000..a454aeb --- /dev/null +++ b/xml/Accessibility.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Accessible.xml b/xml/Accessible.xml new file mode 100644 index 0000000..9240882 --- /dev/null +++ b/xml/Accessible.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Action.xml b/xml/Action.xml new file mode 100644 index 0000000..0f5aa85 --- /dev/null +++ b/xml/Action.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Application.xml b/xml/Application.xml new file mode 100644 index 0000000..04a2e70 --- /dev/null +++ b/xml/Application.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Cache.xml b/xml/Cache.xml new file mode 100644 index 0000000..e693b54 --- /dev/null +++ b/xml/Cache.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Collection.xml b/xml/Collection.xml new file mode 100644 index 0000000..7b39776 --- /dev/null +++ b/xml/Collection.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Component.xml b/xml/Component.xml new file mode 100644 index 0000000..c67dde9 --- /dev/null +++ b/xml/Component.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/DeviceEventController.xml b/xml/DeviceEventController.xml new file mode 100644 index 0000000..0af9aac --- /dev/null +++ b/xml/DeviceEventController.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/DeviceEventListener.xml b/xml/DeviceEventListener.xml new file mode 100644 index 0000000..a6dd3b6 --- /dev/null +++ b/xml/DeviceEventListener.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/xml/Document.xml b/xml/Document.xml new file mode 100644 index 0000000..d12a306 --- /dev/null +++ b/xml/Document.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/EditableText.xml b/xml/EditableText.xml new file mode 100644 index 0000000..09f62f5 --- /dev/null +++ b/xml/EditableText.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Event.xml b/xml/Event.xml new file mode 100644 index 0000000..fac67de --- /dev/null +++ b/xml/Event.xml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Hyperlink.xml b/xml/Hyperlink.xml new file mode 100644 index 0000000..75f8099 --- /dev/null +++ b/xml/Hyperlink.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Hypertext.xml b/xml/Hypertext.xml new file mode 100644 index 0000000..18a3b34 --- /dev/null +++ b/xml/Hypertext.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Image.xml b/xml/Image.xml new file mode 100644 index 0000000..43536ee --- /dev/null +++ b/xml/Image.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Registry.xml b/xml/Registry.xml new file mode 100644 index 0000000..a3ab93c --- /dev/null +++ b/xml/Registry.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Selection.xml b/xml/Selection.xml new file mode 100644 index 0000000..2e19187 --- /dev/null +++ b/xml/Selection.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Socket.xml b/xml/Socket.xml new file mode 100644 index 0000000..5f9367e --- /dev/null +++ b/xml/Socket.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Table.xml b/xml/Table.xml new file mode 100644 index 0000000..181acaa --- /dev/null +++ b/xml/Table.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/TableCell.xml b/xml/TableCell.xml new file mode 100644 index 0000000..c60a074 --- /dev/null +++ b/xml/TableCell.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Text.xml b/xml/Text.xml new file mode 100644 index 0000000..320ee5e --- /dev/null +++ b/xml/Text.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/Value.xml b/xml/Value.xml new file mode 100644 index 0000000..ccd6c7a --- /dev/null +++ b/xml/Value.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/xml/create-introspection.sh b/xml/create-introspection.sh new file mode 100755 index 0000000..81d60e4 --- /dev/null +++ b/xml/create-introspection.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +xsltproc --xinclude remove-annotations.xsl Accessibility.xml >Processed.xml +python versioned-introspection.py diff --git a/xml/remove-annotations.xsl b/xml/remove-annotations.xsl new file mode 100644 index 0000000..5d25d0e --- /dev/null +++ b/xml/remove-annotations.xsl @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/xml/versioned-introspection.py b/xml/versioned-introspection.py new file mode 100644 index 0000000..3922f66 --- /dev/null +++ b/xml/versioned-introspection.py @@ -0,0 +1,91 @@ + +import sys +from xml.etree import ElementTree + +CTEMPLATE = \ +""" +/* + * This file has been auto-generated from the introspection data available + * in the at-spi2-core repository. The D-Bus procol is defined in this + * repository, which can be found at: + * + * http://download.gnome.org/sources/at-spi2-core/0.1/ + * + * DO NOT EDIT. + */ + +%s +""" + +HTEMPLATE = \ +""" +/* + * This file has been auto-generated from the introspection data available + * in the at-spi2-core repository. The D-Bus procol is defined in this + * repository, which can be found at: + * + * http://download.gnome.org/sources/at-spi2-core/0.1/ + * + * DO NOT EDIT. + */ + +#ifndef SPI_INTROSPECTION_DATA_H_ +#define SPI_INTROSPECTION_DATA_H_ + +%s + +#endif /* SPI_INTROSPECTION_DATA_H_ */ +""" + +DECTEMPLATE = \ +""" +extern const char *%s; +""" + +DEFTEMPLATE = \ +""" +const char *%s = +%s; +""" + +VERSION = "0.1.7" + +def convert_name (name): + return "spi_" + name.replace (".", "_") + +def convert_contents (contents): + contents = contents.replace ("\"", "\\\"") + literals = ["\"%s\"" % (line) for line in contents.split ("\n")] + return "\n".join (literals) + +def main (argv): + #Open the XML file and process includes. + tree = ElementTree.parse ("Processed.xml") + root = tree.getroot () + + #Open the output files. + cfile = open ("introspection.c", "w") + hfile = open ("introspection.h", "w") + + ccontents = "" + hcontents = "" + + for itf in root.findall ("node/interface"): + #Get and convert the name of the interface. + name = convert_name (itf.attrib["name"]) + + #Create the introspection string with version information. + itf.attrib["version"] = VERSION + contents = convert_contents (ElementTree.tostring (itf)) + + hcontents += DECTEMPLATE % (name) + ccontents += DEFTEMPLATE % (name, contents) + + cfile.write (CTEMPLATE % (ccontents)) + hfile.write (HTEMPLATE % (hcontents)) + + cfile.close () + hfile.close () + +if __name__ == "__main__": + sys.exit(main(sys.argv))