libxklavier-5.4/000077500000000000000000000000001213561201300136705ustar00rootroot00000000000000libxklavier-5.4/.gitignore000066400000000000000000000010441213561201300156570ustar00rootroot00000000000000Doxyfile Makefile Makefile.in aclocal.m4 config.cache config.guess config.h config.h.in config.log config.status config.sub configure gtk-doc.make libtool libxklavier.deps libxklavier.prj libxklavier.pws libxklavier.spec libxklavier.vapi ltmain.sh stamp-h stamp-h.in autom4te-2.53.cache stamp-h1 libxklavier.pc autom4te.cache .tm_project.cache stamp-h2 COPYING INSTALL depcomp install-sh missing mkinstalldirs libxklavier-*.tar.* .anjuta .anjuta_sym_db.db .tm_project2.cache m4/* !m4/introspection.m4 !m4/vapigen.m4 *.bak *~ ABOUT-NLS po build-aux libxklavier-5.4/AUTHORS000066400000000000000000000000571213561201300147420ustar00rootroot00000000000000Sergey V. Udaltsov (svu@users.sourceforge.net) libxklavier-5.4/COPYING.LIB000066400000000000000000000612731213561201300153410ustar00rootroot00000000000000 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 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! libxklavier-5.4/CREDITS000066400000000000000000000001051213561201300147040ustar00rootroot00000000000000Ivan Pascal Andriy Rysin libxklavier-5.4/ChangeLog000066400000000000000000000001001213561201300154310ustar00rootroot00000000000000This file is not maintained anymore. Use git log, git blame etc libxklavier-5.4/ChangeLog.cvs000066400000000000000000000747201213561201300162460ustar00rootroot000000000000002011-02-12 svu * libxklavier/xkl_config_item.h, libxklavier/xkl_config_registry.h: more gtk-doc comments * doc/reference/libxklavier-sections.txt: fixed gtk-doc meta 2011-01-29 svu * libxklavier/xklavier_xkb.c: checking that XInput is >=2, otherwise DevicePresence may be missing. https://bugzilla.gnome.org/show_bug.cgi?id=583709 * libxklavier/xklavier_config.c: added variants to the search function * tests/test_config.c: Improved printing * configure.in: bumped the package version and soname 2011-01-28 svu * libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c, libxklavier/xklavier_private.h, tests/test_config.c: Adding the function to perform the search by pattern. Current implementation searches only layouts - variants are to be added 2011-01-03 svu * libxklavier/xklavier_evt.c, libxklavier/xklavier_private.h: fixed one race condition, https://bugzilla.gnome.org/show_bug.cgi?id=638332 2010-09-13 svu * configure.in: accessing X11 api using pkg-config 2010-01-11 svu * libxklavier/xkl_engine.h, libxklavier/xklavier.c, libxklavier/xklavier_private.h: introducing counters for start/stop listen operations: in one process (actually g-s-d) start and stop can be called several times, with different masks. The API is incompatibly changed! * configure.in: preparing 5.0 with new API * libxklavier/xklavier.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_evt_xmm.c, libxklavier/xklavier_private.h, libxklavier/xklavier_util.c, libxklavier/xklavier_xmm.c: removing listener mask field, it is enough to use counters 2009-10-12 svu * libxklavier/xklavier_toplevel.c: using transient property for smart handling of the popup windows (for the per-window layout scenario). Nice idea by Paul Sokolovsky 2009-09-30 svu * libxklavier/xklavier_evt.c: ignore BadDrawable error, https://bugs.edge.launchpad.net/ubuntu/+source/libxklavier/+bug/404924 * libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_xkb.c: save xinput error code and event type * libxklavier/xklavier_evt.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_private.h, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_xkb.c, libxklavier/xklavier_xmm.c: introduced engine-specific error handling (for ignoring xinput errors) 2009-08-29 svu * libxklavier/xklavier_evt.c: sometimes focus_in arrives when the previously focused window is already destroyed. That causes BadMatch and all kinds of trouble. The code should handle that case correctly. 2009-08-17 svu * libxklavier/xklavier_xkb.c: fixed a bug with XIE check, http://bugzilla.gnome.org/show_bug.cgi?id=583709 2009-07-20 svu * tests/Makefile.am: a bit of cleanup, thanks Samuli Suominen 2009-07-02 svu * libxklavier/xkl_engine.h: small fix for flag enum, https://bugs.freedesktop.org/show_bug.cgi?id=21578 2009-06-28 svu * libxklavier/xkl_engine.h, reference/tmpl/*: fix small gtk-doc issues * NEWS: preparing 4.0 2009-05-06 Sayamindu Dasgupta https://bugs.freedesktop.org/show_bug.cgi?id=21578 - Make use of glib-mkenums * libxklavier/Makefile.am: Use glib-mkenums * libxklavier/xklavier.c (xkl_engine_class_init): Do not use g_flags_register_static for XklEngineFeatures here. * libxklavier/xklavier.h: Include xkl-enum-types.h 2009-06-24 svu * libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c: avoiding duplicated config items (in main and extras) 2009-06-23 svu * configure.in, libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_config_xmm.c, libxklavier/xklavier_private.h, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_private_xmm.h, tests/test_config.c: use exotic materials optionally. Breaking API/ABI (incrementing version_info) * tests/test_monitor.c: eliminating unneeded code 2009-06-19 svu * libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c, libxklavier/xklavier_private.h: use xml files with exotic layouts 2009-06-02 svu * libxklavier/xklavier_config_iso.c: changed g_snprintf to more semantically correct g_strlcpy, just to eliminate the warning. * libxklavier/xklavier_props.c: fixed potential crash, reassigning the pointer after realloc (credits go to Canonical) 2009-05-28 svu * libxklavier/xklavier_config.c: fixed handling of translated XML entities < / > / &. http://bugs.freedesktop.org/show_bug.cgi?id=21924 2009-05-14 svu * autogen.sh, Makefile.am: fixing the build process (thanks to Marc-André Lureau) 2009-04-23 Federico Mena Quintero https://bugs.freedesktop.org/show_bug.cgi?id=21365 - Make sure libxklavier's X error handler still runs, even if the XKB extension is not present. * libxklavier/xklavier_evt.c (xkl_process_error): Fix the prototype to match XErrorHandler, so that we don't have to use casts when using XSetErrorHandler(). * libxklavier/xklavier_xkb.c (xkl_xkb_init): In case XKB is not present, do not reset the X error handler here... * libxklavier/xklavier.c (xkl_engine_constructor): ... but do it here instead in case neither the XKB nor xmodmap modules can be initialized. This way if either succeeds, libxklavier will have its own X error handler present, which is needed to filter out "harmless" errors like BadWindow for disappearing windows. 2009-04-06 svu * libxklavier/Makefile.am, tests/Makefile.am: adding -lX11 to .la file, http://bugs.freedesktop.org/show_bug.cgi?id=20243 2009-03-18 svu * Makefile.am, gtk-doc.make: unneeded external file should not be in dist/CVS * configure.in, NEWS: preparing 3.9 2009-03-10 svu * libxklavier/xklavier_evt.c: The X11 error processing is more robust in relation to the missing engine (during the initialization) 2009-03-09 svu * libxklavier/xklavier_config_xkb.c: no need to display loads of warnings from xkbcomp, http://bugs.freedesktop.org/show_bug.cgi?id=20526 2009-02-21 svu * libxklavier/Makefile.am, tests/Makefile.am: reordering CFLAGS, http://bugs.freedesktop.org/show_bug.cgi?id=20244 2009-01-21 svu * configure.in: eliminate bashisms, http://bugs.freedesktop.org/show_bug.cgi?id=19645 2008-12-14 svu * libxklavier/Makefile.am, tests/Makefile.am: small cygwin fixes, http://bugs.freedesktop.org/show_bug.cgi?id=19030 2008-11-26 Rob Bradford * libxklavier/Makefile.am: * tests/Makefile.am: Remove "-I$(includedir)" from the build system. It is superfluous and break cross-compilation. http://bugs.freedesktop.org/show_bug.cgi?id=17738 2008-11-26 svu * libxklavier/xklavier_config.c: fixed memleak, http://bugs.freedesktop.org/show_bug.cgi?id=17651 2008-11-24 svu * NEWS: preparing 3.8 2008-11-17 svu * configure.in: bumping versions (package and dll interface) 2008-11-16 svu * configure.in, libxklavier/Makefile.am: updating the build process, adding XInput dependency * libxklavier/xkl_engine.h, libxklavier/xklavier.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_xkb.c, libxklavier/xklavier_private_xkb.h: using XInput for device discovery 2008-09-28 svu * libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_xkb.c: introducing device_id (for a moment - the core one, hardcoded) 2008-09-05 svu * NEWS, configure.in: preparing 3.7 2008-09-03 svu * libxklavier/xklavier_config.c: enforcing UTF-8 output of gettext, http://bugzilla.gnome.org/show_bug.cgi?id=529773 2008-06-17 svu * configure.in: fixing glib version requirement, http://bugs.freedesktop.org/show_bug.cgi?id=16207 2008-06-09 svu * libxklavier/xklavier_config_iso.c: take languages from variants into account 2008-04-27 svu * libxklavier/xkl_config_item.h, libxklavier/xkl_config_registry.h, doc/reference: a bit of cleanup for gtkdoc * NEWS: preparing 3.6 * libxklavier/xklavier_config_iso.c, libxklavier/xklavier_config.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_util.c, libxklavier/xklavier_xmm.c: C99 fixes 2008-04-26 svu * libxklavier/xklavier_config_iso.c: another lost xpath, better handling of lowercase 2008-04-25 svu * libxklavier/xklavier_config_iso.c: lost xpath * tests/test_config.c: a bit of polish 2008-04-23 svu * libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c, libxklavier/xklavier_private.h, tests/test_config.c: finished ISO browsing functionality 2008-04-21 svu * configure.in, libxklavier/Makefile.am, libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_iso.c, libxklavier/xklavier_private.h, tests/test_config.c: adding country/language iteration functions, introducing dependency on iso-codes 2008-04-15 svu * libxklavier/xkl_config_item.h, libxklavier/xklavier_config.c, tests/test_config.c: processing the language lists 2008-04-14 svu * configure.in, libxklavier/xkl_config_item.h, libxklavier/xklavier_config.c, tests/test_config.c: processing the country lists 2008-03-10 svu * NEWS: preparing 3.5 2008-03-01 svu * libxklavier/xklavier_util.c, libxklavier/xklavier_toplevel.c: properly managing PointerRoot, another attempt to fix http://bugzilla.gnome.org/show_bug.cgi?id=516318 2008-02-28 svu * libxklavier/xklavier_util.c: fix by Jens for Xnest issue, http://bugzilla.gnome.org/show_bug.cgi?id=516318 * Makefile.am, configure.in, xfree86.xml, libxklavier/xklavier_config.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_config_xmm.c, libxklavier/xklavier_private.h: getting rid of xfree86.xml, end of support for XFree 4.2, generalizing some registry loading code 2008-02-01 svu * tests/test_monitor.c: C99 fix, by Jens 2008-01-30 svu * NEWS: preparing 3.4 2007-10-06 svu * libxklavier/Makefile.am, libxklavier/xklavier_config.c, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_private.h, xkl_config_registry.h, xklavier_private.h: now, only gettext is doing string translation. No more hackish code in that area. 2007-10-03 svu * libxklavier/xklavier_config.c: using xkeyboard-config domain for translation, dealing with lowfat base.xml 2007-09-29 svu * tests/test_monitor.c: tracking the config 2007-09-04 svu * configure.in: indicate gtkdoc enabling * Makefile.am: make distcheck works * NEWS: preparing 3.3 2007-05-20 svu * libxklavier/xklavier.c, libxklavier/xklavier_private.h, libxklavier/xklavier_xkb.c, libxklavier/xklavier_xmm.c, tests/test_monitor.c: added missing indicator names function (thanks to Andriy Rysin for spotting) 2007-05-16 svu * configure.in: incrementing the version 2007-05-13 svu * libxklavier/xkl_config_item.h, libxklavier/xklavier_config.c, tests/test_config.c: processing "vendor" element, if specified 2007-03-22 svu * configure.in: make build process a bit smarter (in relation to xkbcomp), preparing 3.2 2007-03-19 svu * libxklavier/xklavier_toplevel.c: fixing the default group processing. Closing http://bugzilla.gnome.org/show_bug.cgi?id=414269 2007-02-23 svu * libxklavier/xklavier.c: workaround for xlib ambiguous behavior. http://bugzilla.gnome.org/show_bug.cgi?id=392853 2007-02-11 svu * configure.in: process empty x_libraries correctly, fixing http://bugzilla.gnome.org/show_bug.cgi?id=343762 2006-11-03 svu * libxklavier/xklavier_config.c: more accurate dealing with empty nodeset, hopefully fixing http://bugzilla.gnome.org/show_bug.cgi?id=370038 2006-10-16 svu * configure.in, NEWS: preparing release 3.1 2006-10-15 svu * libxklavier/xklavier.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_evt_xmm.c, libxklavier/xklavier_private.h: more correct processing of the root window property defining the configuration. Apps listening for XKLL_TRACK_KEYBOARD_STATE should be notified as well. * libxklavier/xklavier_props.c: fixing splitting variant out of layout, like in "ru(winkeys)" 2006-10-07 svu * *.h,*.c: added copyright statements, as requested by debian folks 2006-08-30 svu * configure.in, NEWS: preparing release 3.0 2006-08-03 svu * libxklavier/xklavier_config.c: Loading with custom SAX handler (inherited from the existing default DOM builder). Now, loaded XML takes only 500K (for us locale). Hurray! 2006-08-02 svu * libxklavier/xklavier_config.c: improving the XML parsing options, saving at least 1M of heap. 2006-07-30 svu * libxklavier/xkl_config_registry.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_private.h, tests/test_config.c: simplifying description charset conversion, adding custom charset (as Andriy requested) 2006-07-30 svu * configure.in, libxklavier/Makefile.am: fixing autoconf stuff for modular X 2006-07-30 svu * libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_private_xkb.h: patching mismatch between declarations and functions. Fixing http://bugzilla.gnome.org/show_bug.cgi?id=349275 2006-07-29 svu * xkeyboard_config.c: sanity patch, fixing http://bugzilla.gnome.org/show_bug.cgi?id=346980 2006-07-01 svu * autogen.sh, configure.in, gtk-doc.make: Make life better for people building without gtkdoc. 2006-07-01 svu * libxklavier.pc.in: added missing Cflags, Libs 2006-06-30 svu * libxklavier/xklavier.c, libxklavier/xklavier_config_xmm.c, libxklavier/Makefile.am, configure.in: Small fix for xmodmap, configure script gives more info about the configuration, at the end. 2006-06-04 svu * libxklavier/xklavier_props.c: fixed default options handling, the gchar** array changed from NULL to g_new0( char*, 1) 2006-05-20 svu * configure.in, libxklavier/Makefile.am, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_xkb.c: xkb_headers -> libxkbfile, linking to xkbfile is also optional. Thanks to Thomas Vander Stichele 2006-04-30 svu * autogen.sh: fail on autoconf/automake errors, thanks to Thomas Stichele 2006-04-22 svu * libxklavier/*.c: * tests/*.c: fixing gcc 2.95 compilation, thanks to Jens Granseuer 2006-04-18 svu * NEWS: preparing 2.91 2006-04-12 svu * libxklavier/xklavier_config.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_evt_xmm.c, libxklavier/xklavier_private.h, libxklavier/xklavier_props.c: syncing with 2.x fixes 2006-03-12 svu * everything: branching 2.x series, merging GLIBing branch to HEAD 2006-03-12 svu * everything: branching 2.x series, merging GLIBing branch to HEAD 2006-03-12 svu * everything: branching 2.x series, merging GLIBing branch to HEAD 2006-03-12 svu * everything: branching 2.x series, merging GLIBing branch to HEAD 2006-02-14 svu * libxklavier/xklavier.c, libxklavier/xklavier_evt.c: hopefully fixing the crash on SetTransparent 2006-01-16 svu * libxklavier/xklavier_config.c: handling XML comments 2005-12-26 svu * configure.in, libxklavier/xklavier_config_xkb.c: adding XKB_BIN_BASE, closing https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=174361 2005-12-10 svu * NEWS: update for 2.1 2005-12-03 svu * libxklavier/xklavier_config_xkb.c: wait -> waitpid, fixed http://bugzilla.gnome.org/show_bug.cgi?id=322955 2005-09-22 svu * libxklavier/xklavier_config_xkb.c: don't remove tmp files on debug level >= 500 2005-05-29 svu * libxklavier/xklavier.c, libxklavier/xklavier.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_private.h, libxklavier/xklavier_private_xmm.h, libxklavier/xklavier_props.c, libxklavier/xklavier_util.c, libxklavier/xklavier_xkb.c, libxklavier/xklavier_xmm.c, tests/test_config.c: patches for gcc4. Thanks to kmaraas 2005-03-11 svu * libxklavier/xklavier_xkb.c: fixed memory leak, precachedXkb. Thanks to kmaraas 2005-02-25 svu * NEWS: update for 2.0 2005-02-24 svu * libxklavier/xklavier_props.c: small warning eliminated 2005-01-07 svu * libxklavier: a lot of optimizations (and some small fixes) 2004-12-30 svu * libxklavier/xklavier_config_xkb.c: some memory leak nailed * libxklavier/xklavier.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_private.h, libxklavier/xklavier_xmm.c: internal polish, secondary layouts are managed through the root window property. * configure.in, NEWS: preparing 1.14 2004-12-27 svu * libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_private_xkb.h: A bit of restructuring in all XkbComponentNames-related functions. Introducing some ... ugh, 'protected' functions. 2004-12-09 21:30 svu * libxklavier/xklavier_xkb.c, libxklavier/xklavier_xmm.c: intoducing XKL_*_DISABLE envvars - for testing and related stuff. It is just handy to have them. 2004-12-08 23:30 svu * libxklavier/xklavier_util.c, libxklavier/xklavier_config_xkb.c: Fixing memory leaks. 2004-12-08 18:30 svu * configure.in, NEWS: Preparing 1.13 2004-12-07 01:30 svu * libxklavier, tests: introducing XklGetMaxNumGroups. Another new call in API. 2004-12-07 00:20 svu * configure.in: using ac_x_includes to make configure work better. Improved backend checking and diagnostics. * autogen.sh: updating the version of tools 2004-12-02 21:47 svu * configure.in: xmodmap support is built by default 2004-12-02 21:20 svu * libxklavier/xklavier_xkb.c: Fix for compiling without headers 2004-12-02 00:21 svu * libxklavier/xklavier_xkb.c: Build patch by Andrei Yurkevich 2004-11-28 16:00 svu * NEWS: Preparing 1.12 2004-11-27 16:00 svu * libxklavier: Some fixes in xmodmap. First version, working somehow 2004-11-25 23:00 svu * libxklavier, tests: MASSIVE commit. First version with somewhat working xmodmap support. Broken API 2004-11-04 19:00 svu * libxklavier/Makefile.am, libxklavier/xklavier.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_config_xmm.c, libxklavier/xklavier_evt_xmm.c, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_private_xmm.h, libxklavier/xklavier_xmm.c: going xmodmappy 2004-11-04 19:00 svu * libxklavier/xklavier_config_i18n.c, tests/Makefile.am, tests/test_config.c, tests/test_monitor.c: 64-bit compatibility patch from James Henstridge. -Wall -Werror for tests. 2004-11-02 22:55 svu * libxklavier/Makefile.am, libxklavier/xklavier.c, libxklavier/xklavier.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_evt_xkb.c, libxklavier/xklavier_private.h, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_props.c, libxklavier/xklavier_xkb.c: virtualizing everything (?) which involves XKB directly. The VTable is introduced. So, now another VTable (xmodmap) can be created, hopefully... * configure.in: preparing 1.11 2004-10-31 21:00 svu * libxklavier/xklavier_config_xkb.c: Fixing the xkbcomp command line. Ubercool! 2004-10-24 03:54 svu * libxklavier/xklavier_config.h, libxklavier/xklavier_evt.c, libxklavier/xklavier_util.c: fixing handling of the transparent windows. Fixes some problems with metacity and Window List-based switching (reported by Alexander Ovcharenko). 2004-10-16 23:18 svu * NEWS: preparing 1.10 2004-10-11 23:38 svu * libxklavier/: xklavier_config.c, xklavier_config_xkb.c, xklavier_private.h, xklavier_xkb.c: Introducing the envvar XKL_DEBUG - I am sick of calling XklSetDebug manually 2004-10-10 23:38 svu * libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_xkb.c, tests/test_config.c, tests/test_monitor.c: The revolution is on. The whole description is not compiled on the client side - nothing on the server side 2004-10-04 22:51 svu * ChangeLog, configure.in, libxklavier/xklavier_config.h, libxklavier/xklavier_config_xkb.c, tests/.cvsignore, tests/test_config.c: Cleaning up some functions. BREAKING the API/ABI. Hope people will not start chasing me with axes... 2004-10-04 19:31 svu * configure.in: 1.10 but not 1.1 2004-10-02 01:32 svu * NEWS, RELEASE_NOTES_1_01, RELEASE_NOTES_1_02, configure.in: a bit of cleanup 2004-10-01 23:04 svu * NEWS: mentioning tests in the NEWS 2004-10-01 22:55 svu * ChangeLog, NEWS, configure.in: preparing 1.04 2004-10-01 21:51 svu * ChangeLog, Makefile.am, configure.in, libxklavier/xklavier_config.c, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_props.c, tests/.cvsignore, tests/Makefile.am, tests/test_config.c, tests/test_monitor.c: Syncing with HEAD. Major leaks nailed. Default ruleset introduced (well, it does not help much) 2004-09-30 02:17 svu * tests/test_config.c: now, test_config can set debug level as well 2004-09-30 02:15 svu * libxklavier/xklavier_config_xkb.c: dumping low-level components before calling XkbGetKeyboardByName 2004-09-26 03:57 svu * tests/: test_config.c, test_monitor.c: monitor is working somehow, more when needed 2004-09-25 02:40 svu * libxklavier/xklavier_config_xkb.c: bit of code polish 2004-09-25 02:25 svu * tests/: .cvsignore, Makefile.am, test_config.c, test_monitor.c: printing the usage, adding the monitor app 2004-09-25 01:57 svu * libxklavier/: xklavier_config.c, xklavier_config_xkb.c: found and fixed some leaks. hurray 2004-09-25 00:43 svu * tests/Makefile.am: added -lX11 2004-09-24 01:18 svu * tests/test_config.c: command line options give use some flexibility in testing 2004-09-23 23:29 svu * tests/test_config.c: a bit deeper 2004-09-23 01:09 svu * Makefile.am, configure.in, tests/.cvsignore, tests/Makefile.am, tests/test_config.c: starting the tests writing - I just had to do it, so at least now... 2004-09-23 00:08 svu * libxklavier/: xklavier_config_xkb.c, xklavier_props.c: Thanks to kmaraas for pointing me to the leak. I hope this will fix it 2004-09-18 00:47 svu * ChangeLog: Just to make people happy. Though it makes me unhappy enough 2004-09-18 00:42 svu * configure.in, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_props.c: The default value for the root window property is introduced. I help it will help to the poor people with broken XKB - just a little... 2004-08-09 23:24 svu * libxklavier/: xklavier_config_xkb.c, xklavier_evt.c, xklavier_private.h, xklavier_util.c: syncing with b_1_00 2004-08-09 23:06 svu * libxklavier/xklavier_evt.c: fixing 126200 2004-07-26 20:05 svu * libxklavier/xklavier_config_xkb.c: fixing non-compilation error on non-xkb systems, reported by Albert Chin-A-Young 2004-06-26 02:26 svu * RELEASE_NOTES_1_03: preparing 1.03 2004-06-13 13:26 svu * libxklavier/: xklavier_evt.c, xklavier_private.h, xklavier_util.c: a bit improved debugging 2004-06-09 01:58 svu * libxklavier/: xklavier_evt.c, xklavier_private.h, xklavier_util.c: forward-porting of the bugfixes from b_1_00 branch 2004-06-08 02:44 svu * libxklavier/xklavier_evt.c: some improvement in the last fix - really update the current state only when LockGroup is planned 2004-06-08 02:20 svu * libxklavier/: xklavier_evt.c, xklavier_private.h, xklavier_util.c: Some little restructuring, more debugging - AND BIG FIX for global mode - we should not read current state from the window focus switched to. 2004-05-27 23:41 svu * libxklavier/: xklavier.c: VERY VERY BAD BUG. ETERNAL SHAME ON ME 2004-04-30 01:02 svu * configure.in, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_evt.c: syncing with b_1_0 2004-04-30 00:55 svu * configure.in, libxklavier/xklavier_config_xkb.c: hopefully now libxklavier better detects multiple layouts support 2004-04-29 22:21 svu * libxklavier/xklavier_evt.c: more correct handling of transparent windows in the global switching mode 2004-04-19 21:04 svu * RELEASE_NOTES_1_02, configure.in, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_private.h, libxklavier/xklavier_props.c: syncing with b_1_00 - do not want to get jhbuild problems any more 2004-04-19 20:41 svu * libxklavier/xklavier_config_xkb.c: compilation fix for non-xkb arches 2004-04-13 22:33 svu * RELEASE_NOTES_1_02: preparing one more release - without redundant configure flag 2004-04-13 22:21 svu * libxklavier/: xklavier_config_xkb.c, xklavier_private.h, xklavier_props.c: no memory leaks necessary - just static data 2004-04-12 22:08 svu * configure.in, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_props.c: it seems we got runtime rules detection working 2004-04-12 18:35 svu * configure.in: better help message 2004-04-12 18:11 svu * configure.in: better help message 2004-04-09 23:09 svu * RELEASE_NOTES_1_01, configure.in, libxklavier/xklavier_config_xkb.c: synching with HEAD 2004-04-09 21:15 svu * RELEASE_NOTES_1_01: preparing urgent release 2004-04-09 21:11 svu * configure.in, libxklavier/xklavier_config_xkb.c: I suppose now libxklavier should be able to live in xorg world - the name of the rules files is customizable at build-time 2004-03-16 22:53 svu * RELEASE_NOTES_1_00, configure.in: preparing 1.00 2004-03-16 22:37 svu * libxklavier/xklavier_xkb.c: Cleaner patch for the improper display - along with some debug print, by Jody 2004-03-04 22:58 svu * libxklavier/xklavier_evt.c: All events can just come through transparently 2004-03-04 22:55 svu * libxklavier/xklavier_config.h: out-of-date param comment removed 2004-03-04 22:54 svu * libxklavier/xklavier_xkb.c: fix for Solaris by Niall - though I still do not understand how dpy can be NULL 2004-03-04 00:56 svu * libxklavier/xklavier.c: Some Solaris compilation patch (thanks to Glynn Foster) - overall better than it was, unsigned should not be just -1 2004-01-26 09:32 svu * RELEASE_NOTES_0_97: preparing 0.97 2004-01-22 08:57 svu * libxklavier/xklavier.h: fixed preprocessor varargs for solaris compiler 2004-01-21 09:14 svu * configure.in, libxklavier/xklavier_config.c, libxklavier/xklavier_config.h, libxklavier/xklavier_config_xkb.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_private_xkb.h, libxklavier/xklavier_xkb.c: The public API does not depend on XKB symbols any more. The API/ABI are broken 2004-01-20 08:56 svu * libxklavier/: Makefile.am, xklavier.h, xklavier_config.h, xklavier_config_xkb.c, xklavier_dump.c, xklavier_evt.c, xklavier_private.h, xklavier_private_xkb.h, xklavier_props.c, xklavier_xkb.c: Trying to make libxklavier buildable without xkb headers, first round 2004-01-20 08:55 svu * configure.in: detecting xkb headers 2004-01-19 09:06 svu * configure.in, libxklavier/Makefile.am: trying to be smart about iconv 2004-01-12 00:14 svu * libxklavier/xklavier_props.c: Some a=a checking stuff makes life a bit faster. But it happens rarely 2004-01-11 00:51 svu * libxklavier/: xklavier_config.h, xklavier_props.c: One extra function to compare configurations 2004-01-11 00:50 svu * libxklavier/xklavier.c: 0 debugging initially. Otherwise the startup of libxklavier applications does not look nice 2004-01-01 21:48 svu * doc/html/Makefile.am: GALAXYo made me fix installation without doxygen 2003-12-31 00:59 svu * libxklavier/: xklavier.c, xklavier_props.c, xklavier_xkb.c: some staff taken from xkb-dependent C file 2003-12-31 00:58 svu * configure.in: The proper share library versioning is important. The new interface (8) compatible with old one (age 1) 2003-12-30 23:40 svu * libxklavier/: Makefile.am, xklavier.c, xklavier_config.c, xklavier_config.h, xklavier_config_xkb.c, xklavier_dump.c, xklavier_evt.c, xklavier_private.h, xklavier_private_xkb.h, xklavier_props.c, xklavier_util.c, xklavier_xkb.c: first step in separating all xkb-related things 2003-12-20 03:30 svu * RELEASE_NOTES_0_96: little polish 2003-12-20 02:44 svu * RELEASE_NOTES_0_96: preparing 0.96 2003-12-19 22:26 svu * libxklavier/Makefile.am: AM_CFLAGS used instead of CFLAGS 2003-12-19 09:40 svu * xfree86.xml: I GOT SICK OF PEOPLE BUILDING THINGS FROM CVS 2003-12-19 09:37 svu * libxklavier/xklavier_config.c: fixes for Solaris and other OSes which does not have strndup, thanks to George Sageev 2003-11-17 23:32 svu * libxklavier/: xklavier_config.c, xklavier_evt.c: a bit of cleanup 2003-11-10 23:45 svu * doc/html/Makefile.am: empty lines cause problems 2003-11-10 23:44 svu * autogen.sh: autogen should enable doxygen - maintainer mode, you know 2003-11-04 23:44 svu * libxklavier/: Makefile.am, xklavier.c, xklavier_evt.c, xklavier_util.c: small fixen 2003-11-04 23:44 svu * configure.in, libxklavier.spec.in, doc/html/Makefile.am: doxygen disabled by default - and docs are included in tarball 2003-10-31 02:47 svu * configure.in, libxklavier/Makefile.am: now really looking for X includes. Thanks to Mike Castle 2003-10-20 21:23 svu * libxklavier.spec.in: stupid me - not devel but base package should include xfree86.xml 2003-10-20 21:19 svu * RELEASE_NOTES_0_95: nearly 0.95 2003-10-20 21:16 svu * .cvsignore, Makefile.am, libxklavier.spec.in, libxklavier/Makefile.am, libxklavier/xklavier_config.c: xfree86.xml fallback implemented - as requested by Jody 2003-10-19 03:21 svu * libxklavier.pc.in: Thanks to Jody, the include path is straightened out 2003-09-20 00:36 svu * .cvsignore, AUTHORS, COPYING.LIB, CREDITS, Doxyfile.in, Makefile.am, NEWS, README, RELEASE_NOTES_0_3, RELEASE_NOTES_0_4, RELEASE_NOTES_0_5, RELEASE_NOTES_0_6, RELEASE_NOTES_0_7, RELEASE_NOTES_0_8, RELEASE_NOTES_0_90, autogen.sh, configure.in, libxklavier.pc.in, libxklavier.spec.in, doc/.cvsignore, doc/Makefile.am, doc/html/.cvsignore, doc/html/Makefile.am, libxklavier/.cvsignore, libxklavier/Makefile.am, libxklavier/xklavier.c, libxklavier/xklavier.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config.h, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_private.h, libxklavier/xklavier_props.c, libxklavier/xklavier_util.c: Initial revision 2003-09-20 00:36 svu * .cvsignore, AUTHORS, COPYING.LIB, CREDITS, Doxyfile.in, Makefile.am, NEWS, README, RELEASE_NOTES_0_3, RELEASE_NOTES_0_4, RELEASE_NOTES_0_5, RELEASE_NOTES_0_6, RELEASE_NOTES_0_7, RELEASE_NOTES_0_8, RELEASE_NOTES_0_90, autogen.sh, configure.in, libxklavier.pc.in, libxklavier.spec.in, doc/.cvsignore, doc/Makefile.am, doc/html/.cvsignore, doc/html/Makefile.am, libxklavier/.cvsignore, libxklavier/Makefile.am, libxklavier/xklavier.c, libxklavier/xklavier.h, libxklavier/xklavier_config.c, libxklavier/xklavier_config.h, libxklavier/xklavier_config_i18n.c, libxklavier/xklavier_dump.c, libxklavier/xklavier_evt.c, libxklavier/xklavier_private.h, libxklavier/xklavier_props.c, libxklavier/xklavier_util.c: start libxklavier-5.4/Makefile.am000066400000000000000000000006141213561201300157250ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SUBDIRS = libxklavier doc tests EXTRA_DIST = libxklavier.spec libxklavier.spec.in \ autogen.sh \ CREDITS libxklavier.pc.in \ m4/introspection.m4 \ $(config_xml_DATA) DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc --enable-introspection pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libxklavier.pc libxklavier-5.4/NEWS000066400000000000000000000052621213561201300143740ustar00rootroot000000000000005.4 A couple of introspection fixes 5.3 A number of introspection and build fixes 5.2.1 Fixed GIR params for introspection (broken build) 5.2 Optional introspection introduced Some minor fixes (runtime and build-time) 5.1 Expanding APIs for GNOME 3 needs (bumped soname): - converting ISO codes to translatable names (it was private, now public) - search by pattern Using to X11 API throgh pkg-config One race condition eliminated XInput2 version checking: looking for support of DevicePresence 5.0 Ability to have different types of listeners in the same process (necessary for the latest unstable version of GNOME). 4.0 Support for "extras" in xkeyboard-config, small bugfixes and build fixes 3.8 Added "new device" signal - for plugged keyboard (no need in the "device removed yet" 3.9 Several small bugs fixed, including memleak and crash under NX 3.8 Added "new device" signal - for plugged keyboard (no need in the "device removed yet" 3.7 A couple of essential bugfixes. Now all translated strings are in UTF-8 (even in 8-bit locales). 3.6 Added API for countries and languages 3.5 Got rid of the fallback xml file (some code cleanup). Fixed a couple of bugs (one crasher) 3.4 Updated translation scheme, based on xkeyboard-config 1.2 3.3 Processing "vendor" elements, bugfix. 3.2 Some bugfixes. 3.1 Straghten the licensing terms. Some bugfixes. 3.0 Some fixes in 2.91. Huge memory optimization 2.91 Absolutely new API based on glib. 2.2 Bugfixes. XML processing improved. Better compatibility with modular X.org filesystem layout 2.1 Bugfixes. GCC 4.x compatibility patches. 2.0 New stable release (for GNOME 2.10). Minor changes since 1.14: some optimization and cleanup. 1.14 Memory leaks nailed. Some minor restructuring. Bugfixing. A couple of XKL_*_DISABLE envvars introduced. 1.13 Some build process cleanup and fixes. One more "virtual function" introduced. 1.12 First version with real xmodmap support. Sure, bugs are possible. I did it again - broke API. Really hope no API changes in 1.1x series any more. 1.11 A lot of internal changes. VTable introduced (so now at some point there can be implemented xmodmap backend). Some bugs were fixed. 1.10 Some internal reorganization in the xklavier-config department. API/ABI are broken. All this stuff is going to be used in GNOME 2.9x. The environment variable XKL_DEBUG introduced in order to control the debug info more handy. Minor portability bug was fixed. 1.04 Some memory leaks were nailed (thanks to kmaraas and valgrind). Default ruleset for partially non-compliant servers introduced (though it still long way to go for AccelleratedX support). A couple of small tests introduced. Hopefully the last release in 1.0x series. libxklavier-5.4/README000066400000000000000000000001131213561201300145430ustar00rootroot00000000000000libxklavier - utility library to make XKB stuff easier Sergey V. Udaltsov libxklavier-5.4/autogen.sh000077500000000000000000000013671213561201300157000ustar00rootroot00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. test -n "$srcdir" || srcdir=`dirname "$0"` test -n "$srcdir" || srcdir=. olddir=`pwd` cd "$srcdir" GTKDOCIZE=`which gtkdocize` if test -z $GTKDOCIZE; then echo "*** No gtkdocize found, please install the gtk-doc package ***" exit 1 fi INTLTOOLIZE=`which intltoolize` if test -z $INTLTOOLIZE; then echo "*** No intltoolize found, please install the intltool package ***" exit 1 fi AUTORECONF=`which autoreconf` if test -z $AUTORECONF; then echo "*** No autoreconf found, please install it ***" exit 1 fi mkdir -p m4 gtkdocize autoreconf --force --install --verbose || exit $? cd "$olddir" test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" libxklavier-5.4/configure.ac000066400000000000000000000150651213561201300161650ustar00rootroot00000000000000AC_PREREQ([2.63]) AC_INIT([libxklavier], [5.4], [http://bugs.freedesktop.org/enter_bug.cgi?product=libxklavier], [libxklavier]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([libxklavier/xklavier.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([1.10 dist-bzip2 -Wno-portability]) AM_MAINTAINER_MODE([enable]) # Support silent build rules, requires at least automake-1.11. Disable # by either passing --disable-silent-rules to configure or passing V=1 # to make m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) dnl for DLL dnl http://sources.redhat.com/autobook/autobook/autobook_91.html VERSION_INFO=20:0:4 AC_SUBST(VERSION_INFO) # Check for programs AC_PROG_CC AM_ICONV # Initialize libtool LT_PREREQ([2.2]) LT_INIT # Gettext stuff, needed by AM_ICONV AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.17]) # Introspection GOBJECT_INTROSPECTION_CHECK([1.30.0]) # Vala VAPIGEN_CHECK([0.18.0.110]) m4_ifset([GTK_DOC_CHECK], [ GTK_DOC_CHECK(1.0) ], [ AM_CONDITIONAL(ENABLE_GTK_DOC, false) AM_CONDITIONAL(GTK_DOC_USE_LIBTOOL, false) ]) AC_DEFUN([jm_LANGINFO_CODESET], [ AC_CHECK_HEADERS(langinfo.h) AC_CHECK_FUNCS(nl_langinfo) AC_CACHE_CHECK([for nl_langinfo and CODESET], jm_cv_langinfo_codeset, [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[char* cs = nl_langinfo(CODESET);]])], [jm_cv_langinfo_codeset=yes], [jm_cv_langinfo_codeset=no]) ]) if test $jm_cv_langinfo_codeset = yes; then AC_DEFINE(HAVE_LANGINFO_CODESET, 1, [Define if you have and nl_langinfo(CODESET).]) fi ]) dnl jm_LANGINFO_CODESET AC_CHECK_FUNCS(setlocale) PKG_CHECK_MODULES(X, \ x11) AC_SUBST(X_LIBS) AC_SUBST(X_CFLAGS) AC_ARG_WITH( xkb_base, [ --with-xkb-base=DIR XKB base path (by default it is /usr/share/X11/xkb)], xkb_base="$withval", xorgdata=`$PKG_CONFIG --variable=datarootdir xorg-server` if test -z "$xorgdata" ; then xkb_base="/usr/share/X11/xkb" else xkb_base="$xorgdata/X11/xkb" fi ) AC_DEFINE_UNQUOTED(XKB_BASE,"${xkb_base}",Base for XKB configuration) AC_PATH_PROG(XKBCOMP, xkbcomp, ,$PATH:/usr/X11R6/bin:/usr/bin/X11) AC_ARG_WITH( xkb_bin_base, [ --with-xkb-bin-base=DIR XKB executables base path], xkb_bin_base="$withval", if test -z "$XKBCOMP" ; then xkb_bin_base="${xkb_base}" else xkb_bin_base="`dirname $XKBCOMP`" fi ) AC_DEFINE_UNQUOTED(XKB_BIN_BASE,"${xkb_bin_base}",Base for XKB executables) AC_ARG_WITH( xkb_default_ruleset, [ --with-xkb-default-ruleset=RULES XKB default set of rules (by default it is base)], xkb_default_ruleset="$withval", xkb_default_ruleset="base" ) AC_DEFINE_UNQUOTED(XKB_DEFAULT_RULESET,"${xkb_default_ruleset}",Default XKB set of rules) AC_ARG_WITH( xmodmap_default_ruleset, [ --with-xmodmap-default-ruleset=RULES Xmodmap default set of rules (by default it is base)], xmodmap_default_ruleset="$withval", xmodmap_default_ruleset="base" ) AC_DEFINE_UNQUOTED(XMODMAP_DEFAULT_RULESET,"${xmodmap_default_ruleset}",Default Xmodmap set of rules) AC_ARG_WITH( xmodmap_base, [ --with-xmodmap-base=DIR xmodmap base path (by default it is /usr/share/xmodmap)], xmodmap_base="$withval", xmodmap_base="/usr/share/xmodmap" ) AC_DEFINE_UNQUOTED(XMODMAP_BASE,"${xmodmap_base}",Base for xmodmap configuration) ac_xkblib_include="\ #include #include #include " AC_CHECK_HEADER([X11/extensions/XKBrules.h], [libxkbfile_present=yes],[],$ac_xkblib_include) AM_CONDITIONAL(LIBXKBFILE_PRESENT, test "$libxkbfile_present" = "yes") AC_SUBST(libxkbfile_present) AC_ARG_ENABLE(xkb-support, [ --enable-xkb-support Enable XKB support], , enable_xkb_support=yes) AM_CONDITIONAL(ENABLE_XKB_SUPPORT, test "$enable_xkb_support" = "yes") AC_ARG_ENABLE(xmodmap-support, [ --enable-xmodmap-support Enable xmodmap support], , enable_xmodmap_support=yes) AM_CONDITIONAL(ENABLE_XMODMAP_SUPPORT, test "$enable_xmodmap_support" = "yes") AC_MSG_CHECKING(whether at least one libxklavier backend is enabled) if test \( "$enable_xkb_support" = "yes" -a \ "$libxkbfile_present" = "yes" \) -o \ "$enable_xmodmap_support" = "yes" ; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_ERROR([no libxklavier backends configured]) fi dnl Checks for libraries. PKG_CHECK_MODULES(XML, \ libxml-2.0 >= 2.0.0) AC_SUBST(XML_LIBS) AC_SUBST(XML_CFLAGS) PKG_CHECK_MODULES(GLIB, \ glib-2.0 >= 2.16.0 gobject-2.0 >= 2.16.0) AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_CFLAGS) PKG_CHECK_MODULES(XINPUT, xi >= 1.1.3, [AC_DEFINE(HAVE_XINPUT, 1, [Define if xinput dev lib is available]) have_xinput=yes], [have_xinput=no]) AC_SUBST(XINPUT_LIBS) AC_SUBST(XINPUT_CFLAGS) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) dnl ----------------------------------------------------------- dnl ISO codes dnl ----------------------------------------------------------- AC_MSG_CHECKING([whether iso-codes exists]) if $PKG_CONFIG iso-codes > /dev/null ; then AC_MSG_RESULT([yes]) iso_codes_prefix=`$PKG_CONFIG --variable=prefix iso-codes` iso_codes_pkgconfig=iso-codes have_iso_codes=yes else AC_MSG_RESULT([no]) AC_MSG_ERROR([You must have iso-codes.]) fi AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["$iso_codes_prefix"],[ISO codes prefix]) AC_CONFIG_FILES([ Makefile libxklavier/Makefile libxklavier.spec doc/Makefile doc/reference/Makefile tests/Makefile libxklavier.pc ]) AC_OUTPUT echo '**********************************************************' echo ' Libxklavier is configured with the following backends:' if test "$enable_xkb_support" = "yes" ; then if test "$libxkbfile_present" = "yes" ; then echo " XKB, libxkbfile is present" echo " default ruleset: $xkb_default_ruleset" echo " base: $xkb_base" echo " xkbcomp is used from: $xkb_bin_base" echo " xinput available: $have_xinput" else echo " XKB, libxkbfile is NOT present" fi fi if test "$enable_xmodmap_support" = "yes" ; then echo " xmodmap, default ruleset: $xmodmap_default_ruleset" echo " base: $xmodmap_base" fi if test "$enable_gtk_doc" = "yes" ; then echo " gtk-doc enabled" else echo " gtk-doc disabled" fi echo '**********************************************************' libxklavier-5.4/doc/000077500000000000000000000000001213561201300144355ustar00rootroot00000000000000libxklavier-5.4/doc/Makefile.am000066400000000000000000000000221213561201300164630ustar00rootroot00000000000000SUBDIRS=reference libxklavier-5.4/doc/reference/000077500000000000000000000000001213561201300163735ustar00rootroot00000000000000libxklavier-5.4/doc/reference/.gitignore000066400000000000000000000001001213561201300203520ustar00rootroot00000000000000*.txt html xml .libs Makefile Makefile.in libxklavier.* *.stamp libxklavier-5.4/doc/reference/Makefile.am000066400000000000000000000053651213561201300204400ustar00rootroot00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libxklavier # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=../../libxklavier # 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-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= CFILE_GLOB= # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES=xklavier_private.h xklavier_private_xkb.h xklavier_private_xmm.h xkl_engine_marshal.h # 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. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GLIB_CFLAGS) GTKDOC_LIBS=$(GLIB_LIBS) -L$(top_builddir)/libxklavier -lxklavier # 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 += libxklavier-5.4/doc/reference/libxklavier-docs.sgml000066400000000000000000000012361213561201300225230ustar00rootroot00000000000000 Libxklavier Reference Manual Libxklavier Objects Libxklavier Utilities libxklavier-5.4/doc/reference/libxklavier-sections.txt000066400000000000000000000165011213561201300233000ustar00rootroot00000000000000
xkl_engine XklEnginePrivate XklEngineStateChange XklEngineFeatures XklState XklEngine XklEngine xkl_engine_get_instance xkl_engine_get_backend_name xkl_engine_get_features xkl_engine_get_max_num_groups XklEngineListenModes xkl_engine_start_listen xkl_engine_stop_listen xkl_engine_pause_listen xkl_engine_resume_listen xkl_engine_grab_key xkl_engine_ungrab_key xkl_engine_filter_events xkl_engine_allow_one_switch_to_secondary_group xkl_engine_get_current_window xkl_engine_get_current_state xkl_engine_get_window_title xkl_engine_get_state xkl_engine_delete_state xkl_engine_save_state xkl_engine_set_window_transparent xkl_engine_is_window_transparent xkl_engine_is_window_from_same_toplevel_window xkl_engine_get_num_groups xkl_engine_get_groups_names xkl_engine_get_indicators_names xkl_engine_get_next_group xkl_engine_get_prev_group xkl_engine_get_current_window_group xkl_engine_lock_group xkl_engine_set_group_per_toplevel_window xkl_engine_is_group_per_toplevel_window xkl_engine_set_indicators_handling xkl_engine_get_indicators_handling xkl_engine_set_secondary_groups_mask xkl_engine_get_secondary_groups_mask xkl_engine_set_default_group xkl_engine_get_default_group xkl_engine_features_get_type xkl_engine_listen_modes_get_type xkl_engine_state_change_get_type XKL_ENGINE XKL_IS_ENGINE XKL_TYPE_ENGINE xkl_engine_get_type XKL_ENGINE_CLASS XKL_IS_ENGINE_CLASS XKL_ENGINE_GET_CLASS XKL_TYPE_ENGINE_FEATURES XKL_TYPE_ENGINE_LISTEN_MODES XKL_TYPE_ENGINE_STATE_CHANGE
xkl_config_item XklConfigItem XKL_MAX_CI_NAME_LENGTH XKL_MAX_CI_SHORT_DESC_LENGTH XKL_MAX_CI_DESC_LENGTH XCI_PROP_ALLOW_MULTIPLE_SELECTION XCI_PROP_VENDOR XCI_PROP_COUNTRY_LIST XCI_PROP_LANGUAGE_LIST XCI_PROP_EXTRA_ITEM XklConfigItem xkl_config_item_new xkl_get_country_name xkl_get_language_name XKL_CONFIG_ITEM XKL_IS_CONFIG_ITEM XKL_TYPE_CONFIG_ITEM xkl_config_item_get_type XKL_CONFIG_ITEM_CLASS XKL_IS_CONFIG_ITEM_CLASS XKL_CONFIG_ITEM_GET_CLASS
xkl_config_rec XklConfigRec XklConfigRec xkl_config_rec_new xkl_config_rec_activate xkl_config_rec_get_from_server xkl_config_rec_get_from_backup xkl_config_rec_write_to_file xkl_config_rec_get_from_root_window_property xkl_config_rec_set_to_root_window_property xkl_engine_backup_names_prop xkl_restore_names_prop xkl_config_rec_reset xkl_config_rec_equals XKL_CONFIG_REC XKL_IS_CONFIG_REC XKL_TYPE_CONFIG_REC xkl_config_rec_get_type XKL_CONFIG_REC_CLASS XKL_IS_CONFIG_REC_CLASS XKL_CONFIG_REC_GET_CLASS
xkl_config_registry XklConfigRegistry XklConfigRegistryPrivate XklConfigRegistry xkl_config_registry_load XklConfigItemProcessFunc XklTwoConfigItemsProcessFunc xkl_config_registry_foreach_model xkl_config_registry_foreach_layout xkl_config_registry_foreach_layout_variant xkl_config_registry_foreach_option_group xkl_config_registry_foreach_option xkl_config_registry_find_model xkl_config_registry_find_layout xkl_config_registry_find_variant xkl_config_registry_find_option_group xkl_config_registry_find_option xkl_config_registry_foreach_country xkl_config_registry_foreach_country_variant xkl_config_registry_foreach_language xkl_config_registry_foreach_language_variant xkl_config_registry_search_by_pattern XKL_CONFIG_REGISTRY XKL_IS_CONFIG_REGISTRY XKL_TYPE_CONFIG_REGISTRY xkl_config_registry_get_type XKL_CONFIG_REGISTRY_CLASS XKL_IS_CONFIG_REGISTRY_CLASS XKL_CONFIG_REGISTRY_GET_CLASS
xklavier_private_xkb ForPhysIndicators XklXkb xkl_engine_dump_xkb_desc xkl_xkb_multiple_layouts_supported xkl_xkb_event_get_name xkl_xkb_config_native_prepare xkl_xkb_config_native_cleanup xkl_xkb_set_indicator xkl_xkb_activate_config_rec xkl_xkb_init_config_registry xkl_xkb_load_config_registry xkl_xkb_write_config_rec_to_file xkl_xkb_process_x_event xkl_xkb_free_all_info xkl_xkb_get_groups_names xkl_xkb_get_max_num_groups xkl_xkb_get_num_groups xkl_xkb_get_server_state xkl_xkb_if_cached_info_equals_actual xkl_xkb_load_all_info xkl_xkb_lock_group xkl_xkb_pause_listen xkl_xkb_resume_listen xkl_xkb_set_indicators xkl_xkb_term
xklavier_private XklEnginePrivate xkl_get_the_engine XklConfigRegistryPrivate xkl_engine_ensure_vtable_inited xkl_engine_process_focus_in_evt xkl_engine_process_focus_out_evt xkl_engine_process_property_evt xkl_engine_process_create_window_evt xkl_process_error xkl_engine_process_state_modification xkl_engine_get_registered_parent xkl_engine_reset_all_info xkl_engine_load_window_tree xkl_engine_load_subtree xkl_engine_if_window_has_wm_state xkl_engine_add_toplevel_window xkl_engine_find_toplevel_window_bottom_to_top xkl_engine_find_toplevel_window xkl_engine_is_toplevel_window_transparent xkl_engine_set_toplevel_window_transparent xkl_engine_get_toplevel_window_state xkl_engine_remove_toplevel_window_state xkl_engine_save_toplevel_window_state xkl_engine_select_input_merging xkl_get_debug_window_title xkl_engine_query_tree xkl_engine_try_call_state_func xkl_engine_get_ruleset_name xkl_config_rec_get_full_from_server xkl_strings_concat_comma_separated xkl_strings_split_comma_separated xkl_config_rec_merge_layouts xkl_config_rec_merge_variants xkl_config_rec_merge_options xkl_config_rec_split_layouts xkl_config_rec_split_variants xkl_config_rec_split_options xkl_config_rec_dump xkl_event_get_name xkl_engine_update_current_state xkl_xkb_init xkl_xmm_init xkl_engine_is_one_switch_to_secondary_group_allowed xkl_engine_one_switch_to_secondary_group_performed xkl_config_registry_load_from_file xkl_config_registry_free xkl_locale_from_utf8 xkl_config_registry_load_helper XKLAVIER_STATE_PROP_LENGTH XKB_RF_NAMES_PROP_MAXLEN WINID_FORMAT xkl_engine_priv xkl_engine_backend xkl_engine_get_display xkl_engine_vcall xkl_config_registry_is_initialized xkl_config_registry_priv xkl_config_registry_get_engine XKBCR_MODEL_PATH XKBCR_LAYOUT_PATH XKBCR_VARIANT_PATH XKBCR_GROUP_PATH XKBCR_OPTION_PATH XML_TAG_DESCR XML_TAG_SHORT_DESCR XML_TAG_VENDOR XML_TAG_COUNTRY_LIST XML_TAG_LANGUAGE_LIST XML_TAG_ISO3166ID XML_TAG_ISO639ID xkl_config_registry_foreach_in_xpath_with_param xkl_config_registry_foreach_in_xpath xkl_read_config_item xkl_debug_level xkl_last_error_message
xklavier xkl_get_last_error XklLogAppender xkl_default_log_appender xkl_set_log_appender xkl_set_debug_level xkl_debug
xklavier_private_xmm XmmShortcut MAX_SHORTCUTS_PER_OPTION XmmSwitchOption XklXmm xkl_xmm_grab_ignoring_indicators xkl_xmm_ungrab_ignoring_indicators xkl_xmm_shortcuts_grab xkl_xmm_shortcuts_ungrab xkl_xmm_shortcut_get_current_option_name xkl_xmm_shortcut_get_current xkl_xmm_actualize_group xkl_xmm_find_switch_option xkl_xmm_init_switch_options xkl_xmm_term_switch_options xkl_xmm_activate_config_rec xkl_xmm_init_config_registry xkl_xmm_load_config_registry xkl_xmm_process_x_event xkl_xmm_free_all_info xkl_xmm_get_groups_names xkl_xmm_get_max_num_groups xkl_xmm_get_num_groups xkl_xmm_lock_group xkl_xmm_get_server_state xkl_xmm_if_cached_info_equals_actual xkl_xmm_load_all_info xkl_xmm_listen_pause xkl_xmm_listen_resume xkl_xmm_set_indicators xkl_xmm_term
xkl_engine_marshal xkl_engine_VOID__VOID xkl_engine_INT__LONG_LONG xkl_engine_VOID__FLAGS_INT_BOOLEAN
libxklavier-5.4/doc/reference/libxklavier.types000066400000000000000000000001421213561201300217720ustar00rootroot00000000000000xkl_engine_get_type xkl_config_item_get_type xkl_config_rec_get_type xkl_config_registry_get_type libxklavier-5.4/doc/reference/tmpl/000077500000000000000000000000001213561201300173475ustar00rootroot00000000000000libxklavier-5.4/doc/reference/tmpl/.gitignore000066400000000000000000000000221213561201300213310ustar00rootroot00000000000000*.sgml *.sgml.bak libxklavier-5.4/libxklavier.anjuta000066400000000000000000000026461213561201300174200ustar00rootroot00000000000000 libxklavier-5.4/libxklavier.pc.in000066400000000000000000000004001213561201300171270ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libxklavier Description: libxklavier library Requires.private: gobject-2.0 glib-2.0 libxml-2.0 Version: @VERSION@ Libs: -L${libdir} -lxklavier Cflags: -I${includedir} libxklavier-5.4/libxklavier.spec.in000066400000000000000000000026321213561201300174700ustar00rootroot00000000000000Name: libxklavier Summary: libXklavier library Version: @VERSION@ Release: 1 License: LGPL Group: Development/Libraries Url: http://gswitchit.sourceforge.net/ BuildRequires: gtk-doc Source: http://gswitchit.sourceforge.net/%{name}-%{version}.tar.gz Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root %description This library allows you simplify XKB-related development. %package devel Summary: Libraries, includes, etc to develop libxklavier applications Group: Development/Libraries Requires: %{name} = %{version} %description devel Libraries, include files, etc you can use to develop libxklavier applications. %prep %setup -q %build CONFIG_FLAGS="--prefix=%{_prefix} --libdir=%{_libdir} \ --includedir=%{_includedir} --bindir=%{_bindir}" if [ ! -f configure ]; then CFLAGS="$RPM_OPT_FLAGS" ./autogen.sh $CONFIG_FLAGS fi CFLAGS="$RPM_OPT_FLAGS" ./configure $CONFIG_FLAGS make %install rm -rf $RPM_BUILD_ROOT DESTDIR="$RPM_BUILD_ROOT" make install strip $RPM_BUILD_ROOT%{_libdir}/*.so* strip $RPM_BUILD_ROOT%{_libdir}/*.a %clean rm -rf %{buildroot} rm -rf $RPM_BUILD_DIR/%{name}-%{version} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-, root, root) %doc AUTHORS ChangeLog NEWS README COPYING.LIB %{_libdir}/lib*.so* %{_datadir}/libxklavier %files devel %defattr(-, root, root) %{_libdir}/pkgconfig/*.pc %{_libdir}/*a %{_includedir}/* %{_datadir}/gtk-doc/html/libxklavier libxklavier-5.4/libxklavier/000077500000000000000000000000001213561201300162045ustar00rootroot00000000000000libxklavier-5.4/libxklavier/.gitignore000066400000000000000000000001401213561201300201670ustar00rootroot00000000000000*.o *.lo *.la Makefile Makefile.in .deps .libs *xkl-enum-types.* Xkl-1.0.* xkl_engine_marshal.* libxklavier-5.4/libxklavier/.indent.pro000066400000000000000000000000151213561201300202610ustar00rootroot00000000000000-kr -i8 -psl libxklavier-5.4/libxklavier/Makefile.am000066400000000000000000000116551213561201300202500ustar00rootroot00000000000000if LIBXKBFILE_PRESENT LIBXKBFILE_PRESENT_CFLAG = -DLIBXKBFILE_PRESENT=1 LIBXKBFILE_PRESENT_LDFLAGS = -lxkbfile endif if ENABLE_XKB_SUPPORT ENABLE_XKB_SUPPORT_CFLAG = -DENABLE_XKB_SUPPORT=1 else ENABLE_XKB_SUPPORT_CFLAG = -DDISABLE_XKB_SUPPORT=1 endif if ENABLE_XMODMAP_SUPPORT ENABLE_XMODMAP_SUPPORT_CFLAG = -DENABLE_XMODMAP_SUPPORT=1 else ENABLE_XMODMAP_SUPPORT_CFLAG = -DDISABLE_XMODMAP_SUPPORT=1 endif AM_CFLAGS=-Wall -DDATA_DIR=\"$(datadir)/$(PACKAGE)\" \ -I. -I$(top_srcdir) $(X_CFLAGS) \ $(XML_CFLAGS) $(GLIB_CFLAGS) $(XINPUT_CFLAGS) \ $(LIBXKBFILE_PRESENT_CFLAG) \ $(ENABLE_XKB_SUPPORT_CFLAG) \ $(ENABLE_XMODMAP_SUPPORT_CFLAG) lib_LTLIBRARIES = libxklavier.la noinst_HEADERS = xklavier_private.h xklavier_private_xkb.h xklavier_private_xmm.h xklavier_headers = xkl_engine.h xkl_config_item.h xkl_config_registry.h \ xkl_config_rec.h xkl_engine_marshal.h xklavier.h BUILT_SOURCES = $(xklavier_built_headers) $(xklavier_built_cfiles) xklavier_built_headers = xkl-enum-types.h xklavier_built_cfiles = xkl-enum-types.c xklavierincdir = $(includedir)/libxklavier xklavierinc_HEADERS = $(xklavier_headers) $(xklavier_built_headers) libxklavier_la_SOURCES = $(xklavier_built_cfiles) xklavier.c xklavier_evt.c xklavier_config.c xklavier_config_iso.c \ xklavier_xkb.c xklavier_evt_xkb.c xklavier_config_xkb.c xklavier_toplevel.c \ xklavier_xmm.c xklavier_xmm_opts.c xklavier_evt_xmm.c xklavier_config_xmm.c \ xklavier_util.c xklavier_props.c xklavier_dump.c xkl_engine_marshal.c \ $(noinst_HEADERS) $(xklavierinc_HEADERS) libxklavier_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined -export-symbols $(srcdir)/libxklavier.public libxklavier_la_LIBADD = \ $(XML_LIBS) $(GLIB_LIBS) $(XINPUT_LIBS) \ $(LIBXKBFILE_PRESENT_LDFLAGS) \ $(X_LIBS) -lX11 $(LIBICONV) EXTRA_DIST=marshal.list libxklavier.public GLIB_GENMARSHAL = `$(PKG_CONFIG) --variable=glib_genmarshal glib-2.0` xkl_engine_marshal.h: marshal.list $(GLIB_GENMARSHAL) --prefix=xkl_engine $(srcdir)/marshal.list --header > xkl_engine_marshal.h xkl_engine_marshal.c: xkl_engine_marshal.h $(GLIB_GENMARSHAL) --prefix=xkl_engine $(srcdir)/marshal.list --body > xkl_engine_marshal.c xkl-enum-types.h: stamp-xkl-enum-types.h @true stamp-xkl-enum-types.h: $(xklavier_headers) (cd $(srcdir) \ && glib-mkenums \ --fhead "#ifndef __XKL_ENUM_TYPES_H__\n#define __XKL_ENUM_TYPES_H__\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void);\n#define XKL_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "#endif /* __XKL_ENUM_TYPES_H__ */" \ $(xklavier_headers)) > new-xkl-enum-types.h \ && (cmp -s new-xkl-enum-types.h xkl-enum-types.h || cp new-xkl-enum-types.h xkl-enum-types.h) \ && rm -f new-xkl-enum-types.h \ && echo timestamp > $(@F) xkl-enum-types.c: $(xklavier_headers) xkl-enum-types.h (cd $(srcdir) \ && glib-mkenums \ --fhead "#include " \ --fprod "\n/* enumerations from \"@filename@\" */" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(xklavier_headers)) > new-xkl-enum-types.c \ && cp new-xkl-enum-types.c $(@F) \ && rm -f new-xkl-enum-types.c DISTCLEANFILES=$(xklavier_built_headers) \ $(xklavier_built_cfiles) \ stamp-xkl-enum-types.h \ xkl_engine_marshal.c \ xkl_engine_marshal.h CLEANFILES= # build intospection typelib -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) if HAVE_INTROSPECTION # avoid introspecting private headers introspection_sources = $(xklavier_headers) $(xklavier_built_headers) $(filter %.c, $(libxklavier_la_SOURCES)) Xkl-1.0.gir: libxklavier.la Xkl_1_0_gir_INCLUDES = GObject-2.0 xlib-2.0 Xkl_1_0_gir_CFLAGS = -I$(top_srcdir) -I$(top_builddir) $(INCLUDES) $(X_CFLAGS) $(XML_CFLAGS) $(GLIB_CFLAGS) $(XINPUT_CFLAGS) Xkl_1_0_gir_LIBS = libxklavier.la Xkl_1_0_gir_FILES = $(xklavier_headers) $(introspection_sources) Xkl_1_0_gir_EXPORT_PACKAGES = libxklavier Xkl_1_0_gir_SCANNERFLAGS = --c-include="libxklavier/xklavier.h" INTROSPECTION_GIRS += Xkl-1.0.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) typelibdir = $(libdir)/girepository-1.0 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelib_DATA) if ENABLE_VAPIGEN -include $(VAPIGEN_MAKEFILE) libxklavier.vapi: Xkl-1.0.gir libxklavier.deps VAPIGEN_VAPIS = libxklavier.vapi libxklavier_vapi_DEPS = x11 libxklavier_vapi_FILES = Xkl-1.0.gir libxklavier.deps: $(AM_V_GEN) for pkg in $(libxklavier_vapi_DEPS); do \ echo $$pkg >> $@; \ done vapidir = $(datadir)/vala/vapi vapi_DATA = $(VAPIGEN_VAPIS) $(VAPIGEN_VAPIS:.vapi=.deps) endif endif libxklavier-5.4/libxklavier/libxklavier.public000066400000000000000000000054231213561201300217240ustar00rootroot00000000000000xkl_config_item_get_type xkl_config_item_new xkl_config_item_get_description xkl_config_item_set_description xkl_config_item_get_name xkl_config_item_set_name xkl_config_item_get_short_description xkl_config_item_set_short_description xkl_config_rec_activate xkl_config_rec_dump xkl_config_rec_equals xkl_config_rec_get_from_backup xkl_config_rec_get_from_root_window_property xkl_config_rec_get_from_server xkl_config_rec_get_type xkl_config_rec_new xkl_config_rec_reset xkl_config_rec_set_layouts xkl_config_rec_set_options xkl_config_rec_set_to_root_window_property xkl_config_rec_set_variants xkl_config_rec_set_model xkl_config_rec_write_to_file xkl_config_registry_find_layout xkl_config_registry_find_model xkl_config_registry_find_option xkl_config_registry_find_option_group xkl_config_registry_find_variant xkl_config_registry_foreach_country xkl_config_registry_foreach_country_variant xkl_config_registry_foreach_language xkl_config_registry_foreach_language_variant xkl_config_registry_foreach_layout xkl_config_registry_foreach_layout_variant xkl_config_registry_foreach_model xkl_config_registry_foreach_option xkl_config_registry_foreach_option_group xkl_config_registry_get_instance xkl_config_registry_get_type xkl_config_registry_load xkl_config_registry_search_by_pattern _xkl_debug xkl_default_log_appender xkl_engine_allow_one_switch_to_secondary_group xkl_engine_backup_names_prop xkl_engine_delete_state xkl_engine_features_get_type xkl_engine_filter_events xkl_engine_get_backend_name xkl_engine_get_current_state xkl_engine_get_current_window xkl_engine_get_current_window_group xkl_engine_get_default_group xkl_engine_get_features xkl_engine_get_groups_names xkl_engine_get_indicators_handling xkl_engine_get_indicators_names xkl_engine_get_instance xkl_engine_get_max_num_groups xkl_engine_get_next_group xkl_engine_get_num_groups xkl_engine_get_prev_group xkl_engine_get_secondary_groups_mask xkl_engine_get_state xkl_engine_get_type xkl_engine_get_window_title xkl_engine_grab_key xkl_engine_INT__LONG_LONG xkl_engine_is_group_per_toplevel_window xkl_engine_is_window_from_same_toplevel_window xkl_engine_is_window_transparent xkl_engine_listen_modes_get_type xkl_engine_lock_group xkl_engine_pause_listen xkl_engine_resume_listen xkl_engine_save_state xkl_engine_set_default_group xkl_engine_set_group_per_toplevel_window xkl_engine_set_indicators_handling xkl_engine_set_secondary_groups_mask xkl_engine_set_window_transparent xkl_engine_start_listen xkl_engine_state_change_get_type xkl_engine_stop_listen xkl_engine_ungrab_key xkl_engine_VOID__FLAGS_INT_BOOLEAN xkl_engine_VOID__ENUM_INT_BOOLEAN xkl_get_country_name xkl_get_language_name xkl_get_last_error xkl_restore_names_prop xkl_set_debug_level xkl_set_log_appender xkl_state_get_type xkl_xkb_config_native_cleanup xkl_xkb_config_native_prepare libxklavier-5.4/libxklavier/marshal.list000066400000000000000000000000561213561201300205310ustar00rootroot00000000000000VOID:VOID INT:LONG,LONG VOID:ENUM,INT,BOOLEAN libxklavier-5.4/libxklavier/xkl_config_item.h000066400000000000000000000156161213561201300215270ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKL_CONFIG_ITEM_H__ #define __XKL_CONFIG_ITEM_H__ #include /* * Maximum name length, including '\'0' character */ #define XKL_MAX_CI_NAME_LENGTH 32 /* * Maximum short description length, including '\\0' character * (this length is in bytes, so for UTF-8 encoding in * XML file the actual maximum length can be smaller) */ #define XKL_MAX_CI_SHORT_DESC_LENGTH 10 /* * Maximum description length, including '\\0' character * (this length is in bytes, so for UTF-8 encoding in * XML file the actual maximum length can be smaller) */ #define XKL_MAX_CI_DESC_LENGTH 192 #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef struct _XklConfigItem XklConfigItem; typedef struct _XklConfigItemClass XklConfigItemClass; #define XKL_TYPE_CONFIG_ITEM (xkl_config_item_get_type ()) #define XKL_CONFIG_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XKL_TYPE_CONFIG_ITEM, XklConfigItem)) #define XKL_CONFIG_ITEM_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), XKL_CONFIG_ITEM, XklConfigItemClass)) #define XKL_IS_CONFIG_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XKL_TYPE_CONFIG_ITEM)) #define XKL_IS_CONFIG_ITEM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), XKL_TYPE_CONFIG_ITEM)) #define XKL_CONFIG_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XKL_TYPE_CONFIG_ITEM, XklConfigItemClass)) /** * _XklConfigItem: * @parent: The superclass object * @name: The configuration item name. Corresponds to XML element "name". * @short_description: The configuration item short description. Corresponds to XML element "shortDescription". * @description: The configuration item description. Corresponds to XML element "description". * * The configuration item. Corresponds to XML element "configItem". */ struct _XklConfigItem { GObject parent; gchar name[XKL_MAX_CI_NAME_LENGTH]; gchar short_description[XKL_MAX_CI_DESC_LENGTH]; gchar description[XKL_MAX_CI_DESC_LENGTH]; }; /** * XCI_PROP_ALLOW_MULTIPLE_SELECTION: * Extra property for the XklConfigItem, defining whether the group allows multiple selection */ #define XCI_PROP_ALLOW_MULTIPLE_SELECTION "allowMultipleSelection" /** * XCI_PROP_VENDOR: * Extra property for the XklConfigItem, defining the vendor (used for models) */ #define XCI_PROP_VENDOR "vendor" /** * XCI_PROP_COUNTRY_LIST: * Extra property for the XklConfigItem, defining the list of countries (used for layouts/variants) */ #define XCI_PROP_COUNTRY_LIST "countryList" /** * XCI_PROP_LANGUAGE_LIST: * Extra property for the XklConfigItem, defining the list of languages (used for layouts/variants) */ #define XCI_PROP_LANGUAGE_LIST "languageList" /** * XCI_PROP_EXTRA_ITEM: * Extra property for the XklConfigItem, defining whether that item is exotic(extra) */ #define XCI_PROP_EXTRA_ITEM "extraItem" /** * _XklConfigItemClass: * @parent_class: The superclass * The XklConfigItem class, derived from GObject */ struct _XklConfigItemClass { GObjectClass parent_class; }; /** * xkl_config_item_get_type: * * Get type info for XklConfigItem * * Returns: GType for XklConfigItem */ extern GType xkl_config_item_get_type(void); /** * xkl_config_item_new: * * Create new XklConfigItem * * Returns: new instance */ extern XklConfigItem *xkl_config_item_new(void); /** * xkl_config_item_get_name: * @item: the XklConfigItem object * * Returns: The @name field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern const gchar * xkl_config_item_get_name(XklConfigItem * item); /** * xkl_config_item_set_name: * @item: the XklConfigItem object to be changed * @name: (transfer none) (allow-none): Name (max. 32 characters); can be NULL. * * Change the @name field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern void xkl_config_item_set_name(XklConfigItem * item, const gchar * name); /** * xkl_config_item_get_short_description: * @item: the XklConfigItem object * * Returns: The @short_description field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern const gchar * xkl_config_item_get_short_description(XklConfigItem * item); /** * xkl_config_item_set_short_description: * @item: the XklConfigItem object to be changed * @short_description: (transfer none) (allow-none): Short Description (max. 10 * characters); can be NULL. * * Change the @short_description field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern void xkl_config_item_set_short_description(XklConfigItem * item, const gchar * short_description); /** * xkl_config_item_get_description: * @item: the XklConfigItem object * * Returns: The @description field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern const gchar * xkl_config_item_get_description(XklConfigItem * item); /** * xkl_config_item_set_description: * @item: the XklConfigItem object to be changed * @description: (transfer none) (allow-none): Description (max. 192 * characters); can be NULL. * * Change the @description field of a XklConfigItem. This is mostly useful for * language bindings, in C you can manipulate the member directly. */ extern void xkl_config_item_set_description(XklConfigItem * item, const gchar * description); /** * xkl_get_country_name: * @code: ISO 3166 Alpha 2 code: 2 chars, uppercase (US, RU, FR, ...) * * Get localized country name, from ISO code * * Returns: localized country name (USA, Russia, France, ... translated) */ extern const gchar * xkl_get_country_name(const gchar * code); /** * xkl_get_language_name: * @code: ISO 639 2B or 2T code: 3 chars, lowercase (eng, rus, fra, ...) * * Get localized language name, from ISO code * * Returns: localized country name (English, Russiam, French, ... translated) */ extern const gchar * xkl_get_language_name(const gchar * code); #ifdef __cplusplus } #endif /* __cplusplus */ #endif libxklavier-5.4/libxklavier/xkl_config_rec.h000066400000000000000000000173321213561201300213370ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKL_CONFIG_REC_H__ #define __XKL_CONFIG_REC_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** * XklConfigRec: * @layouts: (array zero-terminated=1): * @variants: (array zero-terminated=1): * @options: (array zero-terminated=1): */ typedef struct _XklConfigRec XklConfigRec; typedef struct _XklConfigRecClass XklConfigRecClass; #define XKL_TYPE_CONFIG_REC (xkl_config_rec_get_type ()) #define XKL_CONFIG_REC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XKL_TYPE_CONFIG_REC, XklConfigRec)) #define XKL_CONFIG_REC_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), XKL_CONFIG_REC, XklConfigRecClass)) #define XKL_IS_CONFIG_REC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XKL_TYPE_CONFIG_REC)) #define XKL_IS_CONFIG_REC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), XKL_TYPE_CONFIG_REC)) #define XKL_CONFIG_REC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XKL_TYPE_CONFIG_REC, XklConfigRecClass)) /* * Basic configuration params */ struct _XklConfigRec { /* * The superclass object */ GObject parent; /* * The keyboard model */ gchar *model; /* * The array of keyboard layouts */ gchar **layouts; /* * The array of keyboard layout variants (if any) */ gchar **variants; /* * The array of keyboard layout options */ gchar **options; }; /* * The XklConfigRec class, derived from GObject */ struct _XklConfigRecClass { /* * The superclass */ GObjectClass parent_class; }; /** * xkl_config_rec_get_type: * * Get type info for XConfigRec * * Returns: GType for XConfigRec */ extern GType xkl_config_rec_get_type(void); /** * xkl_config_rec_new: * * Create new XklConfigRec * * Returns: new instance */ extern XklConfigRec *xkl_config_rec_new(void); /** * xkl_config_rec_activate: * @data: valid XKB configuration * @engine: the engine * * Activates some XKB configuration * description. Can be NULL * * Returns: TRUE on success */ extern gboolean xkl_config_rec_activate(const XklConfigRec * data, XklEngine * engine); /** * xkl_config_rec_get_from_server: * @data: buffer for XKB configuration * @engine: the engine * * Loads the current XKB configuration (from X server) * * Returns: TRUE on success */ extern gboolean xkl_config_rec_get_from_server(XklConfigRec * data, XklEngine * engine); /** * xkl_config_rec_get_from_backup: * @data: buffer for XKB configuration * @engine: the engine * * Loads the current XKB configuration (from backup) * * Returns: TRUE on success */ extern gboolean xkl_config_rec_get_from_backup(XklConfigRec * data, XklEngine * engine); /** * xkl_config_rec_write_to_file: * @file_name: name of the file to create * @data: valid XKB configuration * description. Can be NULL * @binary: flag indicating whether the output file should be binary * @engine: the engine * * Writes some XKB configuration into XKM/XKB/... file * * Returns: TRUE on success */ extern gboolean xkl_config_rec_write_to_file(XklEngine * engine, const gchar * file_name, const XklConfigRec * data, const gboolean binary); /** * xkl_config_rec_get_from_root_window_property: * @rules_atom_name: atom name of the root window property to read * @rules_file_out: pointer to hold the file name * @config_out: buffer to hold the result * @engine: the engine * * Gets the XKB configuration from any root window property * * Returns: TRUE on success */ extern gboolean xkl_config_rec_get_from_root_window_property(XklConfigRec * config_out, Atom rules_atom_name, gchar ** rules_file_out, XklEngine * engine); /** * xkl_config_rec_set_to_root_window_property: * @rules_atom_name: atom name of the root window property to write * @rules_file: rules file name * @config: configuration to save * @engine: the engine * * Saves the XKB configuration into any root window property * * Returns: TRUE on success */ extern gboolean xkl_config_rec_set_to_root_window_property(const XklConfigRec * config, Atom rules_atom_name, gchar * rules_file, XklEngine * engine); /** * xkl_engine_backup_names_prop: * @engine: the engine * * Backups current XKB configuration into some property - * if this property is not defined yet. * * Returns: TRUE on success */ extern gboolean xkl_engine_backup_names_prop(XklEngine * engine); /** * xkl_restore_names_prop: * @engine: the engine * * Restores XKB from the property saved by xkl_backup_names_prop * * Returns: TRUE on success */ extern gboolean xkl_restore_names_prop(XklEngine * engine); /** * xkl_config_rec_reset: * @data: record to reset * * Resets the record (equal to Destroy and Init) */ extern void xkl_config_rec_reset(XklConfigRec * data); /** * xkl_config_rec_equals: * @data1: record to compare * @data2: another record * * Compares two records * * Returns: TRUE if records are same */ extern gboolean xkl_config_rec_equals(XklConfigRec * data1, XklConfigRec * data2); /** * xkl_config_rec_set_layouts: * @data: record to change * @new_layouts: (array zero-terminated=1) (transfer none): zero terminated * list of new layout names. * * Sets a new layout list. * * Frees the previous layout list. This is primarily useful for bindings, in C * you can manipulate the @layouts record member directly. */ extern void xkl_config_rec_set_layouts(XklConfigRec * data, const gchar ** new_layouts); /** * xkl_config_rec_set_variants: * @data: record to change * @new_variants: (transfer none) (array zero-terminated=1): zero terminated * list of new variant names. * * Sets a new variant list. * * Frees the previous variant list. This is primarily useful for bindings, in C * you can manipulate the @variants record member directly. */ extern void xkl_config_rec_set_variants(XklConfigRec * data, const gchar ** new_variants); /** * xkl_config_rec_set_options: * @data: record to change * @new_options: (transfer none) (array zero-terminated=1): zero terminated * list of new option names. * * Sets a new option list. * * Frees the previous option list. This is primarily useful for bindings, in C * you can manipulate the @options record member directly. */ extern void xkl_config_rec_set_options(XklConfigRec * data, const gchar ** new_options); /** * xkl_config_rec_set_model: * @data: record to change * @new_model: (transfer none): new keyboard name. * * Sets a new model. * * Frees the previous model. This is primarily useful for bindings, in C * you can manipulate the @model record member directly. */ extern void xkl_config_rec_set_model(XklConfigRec * data, const gchar * new_model); #ifdef __cplusplus } #endif /* __cplusplus */ #endif libxklavier-5.4/libxklavier/xkl_config_registry.h000066400000000000000000000301411213561201300224270ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKL_CONFIG_REGISTRY_H__ #define __XKL_CONFIG_REGISTRY_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef struct _XklConfigRegistry XklConfigRegistry; typedef struct _XklConfigRegistryPrivate XklConfigRegistryPrivate; typedef struct _XklConfigRegistryClass XklConfigRegistryClass; #define XKL_TYPE_CONFIG_REGISTRY (xkl_config_registry_get_type ()) #define XKL_CONFIG_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XKL_TYPE_CONFIG_REGISTRY, XklConfigRegistry)) #define XKL_CONFIG_REGISTRY_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), XKL_TYPE_CONFIG_REGISTRY, XklConfigRegistryClass)) #define XKL_IS_CONFIG_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XKL_TYPE_CONFIG_REGISTRY)) #define XKL_IS_CONFIG_REGISTRY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), XKL_TYPE_CONFIG_REGISTRY)) #define XKL_CONFIG_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XKL_TYPE_CONFIG_REGISTRY, XklConfigRegistryClass)) /** * _XklConfigRegistry: * @parent: The superclass object * * The configuration manager. Corresponds to XML element "configItem". */ struct _XklConfigRegistry { GObject parent; /*< private >*/ XklConfigRegistryPrivate *priv; }; /** * _XklConfigRegistryClass: * @parent_class: The superclass * * The XklConfigRegistry class, derived from GObject */ struct _XklConfigRegistryClass { GObjectClass parent_class; }; /** * xkl_config_registry_get_type: * * Get type info for XklConfigRegistry * * Returns: GType for XklConfigRegistry */ extern GType xkl_config_registry_get_type(void); /** * xkl_config_registry_get_instance: * @engine: the engine to use for accessing X in all the operations * (like accessing root window properties etc) * * Create new XklConfig * * Returns: (transfer none): new instance */ extern XklConfigRegistry * xkl_config_registry_get_instance(XklEngine * engine); /** * xkl_config_registry_load: * @config: the config registry * @if_extras_needed: whether exotic materials (layouts, options) * should be loaded as well * * Loads XML configuration registry. The name is taken from X server * (for XKB/libxkbfile, from the root window property) * * Returns: TRUE on success */ extern gboolean xkl_config_registry_load(XklConfigRegistry * config, gboolean if_extras_needed); /** * XklConfigItemProcessFunc: * @config: the config registry * @item: the item from registry * @data: anything which can be stored into the pointer * * Callback type used for enumerating keyboard models, layouts, variants, options */ typedef void (*XklConfigItemProcessFunc) (XklConfigRegistry * config, const XklConfigItem * item, gpointer data); /** * XklTwoConfigItemsProcessFunc: * @config: the config registry * @item: the item from registry * @subitem: the item from registry * @data: anything which can be stored into the pointer * * Callback type used for enumerating layouts/variants for countries/languages */ typedef void (*XklTwoConfigItemsProcessFunc) (XklConfigRegistry * config, const XklConfigItem * item, const XklConfigItem * subitem, gpointer data); /* provide the old names for backwards compatibility */ typedef XklConfigItemProcessFunc ConfigItemProcessFunc; typedef XklTwoConfigItemsProcessFunc TwoConfigItemsProcessFunc; /** * xkl_config_registry_foreach_model: * @config: the config registry * @func: (scope call): callback to call for every model * @data: anything which can be stored into the pointer * * Enumerates keyboard models from the XML configuration registry */ extern void xkl_config_registry_foreach_model(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_layout: * @config: the config registry * @func: (scope call): callback to call for every layout * @data: anything which can be stored into the pointer * * Enumerates keyboard layouts from the XML configuration registry */ extern void xkl_config_registry_foreach_layout(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_layout_variant: * @config: the config registry * @layout_name: layout name for which variants will be listed * @func: (scope call): callback to call for every layout variant * @data: anything which can be stored into the pointer * * Enumerates keyboard layout variants from the XML configuration registry */ extern void xkl_config_registry_foreach_layout_variant(XklConfigRegistry * config, const gchar * layout_name, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_option_group: * @config: the config registry * @func: (scope call): callback to call for every option group * @data: anything which can be stored into the pointer * * Enumerates keyboard option groups from the XML configuration registry */ extern void xkl_config_registry_foreach_option_group(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_option: * @config: the config registry * @option_group_name: option group name for which variants * will be listed * @func: (scope call): callback to call for every option * @data: anything which can be stored into the pointer * * Enumerates keyboard options from the XML configuration registry */ extern void xkl_config_registry_foreach_option(XklConfigRegistry * config, const gchar * option_group_name, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_find_model: * @config: the config registry * @item: pointer to a XklConfigItem containing the name of the * keyboard model. On successfull return, the descriptions are filled. * * Loads a keyboard model information from the XML configuration registry. * * Returns: TRUE if appropriate element was found and loaded */ extern gboolean xkl_config_registry_find_model(XklConfigRegistry * config, XklConfigItem * item); /** * xkl_config_registry_find_layout: * @config: the config registry * @item: pointer to a XklConfigItem containing the name of the * keyboard layout. On successfull return, the descriptions are filled. * * Loads a keyboard layout information from the XML configuration registry. * * Returns: TRUE if appropriate element was found and loaded */ extern gboolean xkl_config_registry_find_layout(XklConfigRegistry * config, XklConfigItem * item); /** * xkl_config_registry_find_variant: * @config: the config registry * @layout_name: name of the parent layout * @item: pointer to a XklConfigItem containing the name of the * keyboard layout variant. On successfull return, the descriptions are filled. * * Loads a keyboard layout variant information from the XML configuration * registry. * * Returns: TRUE if appropriate element was found and loaded */ extern gboolean xkl_config_registry_find_variant(XklConfigRegistry * config, const char *layout_name, XklConfigItem * item); /** * xkl_config_registry_find_option_group: * @config: the config registry * @item: pointer to a XklConfigItem containing the name of the * keyboard option group. On successfull return, the descriptions are filled. * * Loads a keyboard option group information from the XML configuration * registry. * * Returns: TRUE if appropriate element was found and loaded */ extern gboolean xkl_config_registry_find_option_group(XklConfigRegistry * config, XklConfigItem * item); /** * xkl_config_registry_find_option: * @config: the config registry * @option_group_name: name of the option group * @item: pointer to a XklConfigItem containing the name of the * keyboard option. On successfull return, the descriptions are filled. * * Loads a keyboard option information from the XML configuration * registry. * * Returns: TRUE if appropriate element was found and loaded */ extern gboolean xkl_config_registry_find_option(XklConfigRegistry * config, const gchar * option_group_name, XklConfigItem * item); /** * xkl_config_registry_foreach_country: * @config: the config registry * @func: (scope call): callback to call for every ISO 3166 country code * @data: anything which can be stored into the pointer * * Enumerates countries for which layouts are available, * from the XML configuration registry */ extern void xkl_config_registry_foreach_country(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_country_variant: * @config: the config registry * @country_code: country ISO code for which variants will be listed * @func: (scope call): callback to call for every country variant * @data: anything which can be stored into the pointer * * Enumerates keyboard layout variants for the country, * from the XML configuration registry */ extern void xkl_config_registry_foreach_country_variant(XklConfigRegistry * config, const gchar * country_code, XklTwoConfigItemsProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_language: * @config: the config registry * @func: (scope call): callback to call for every ISO 639-2 country code * @data: anything which can be stored into the pointer * * Enumerates languages for which layouts are available, * from the XML configuration registry */ extern void xkl_config_registry_foreach_language(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data); /** * xkl_config_registry_foreach_language_variant: * @config: the config registry * @language_code: language ISO code for which variants will be listed * @func: (scope call): callback to call for every country variant * @data: anything which can be stored into the pointer * * Enumerates keyboard layout variants for the language, * from the XML configuration registry */ extern void xkl_config_registry_foreach_language_variant(XklConfigRegistry * config, const gchar * language_code, XklTwoConfigItemsProcessFunc func, gpointer data); /** * xkl_config_registry_search_by_pattern: * @config: the config registry * @pattern: pattern to search for (NULL means "all") * @func: (scope call): callback to call for every matching layout/variant * @data: anything which can be stored into the pointer * * Enumerates keyboard layout/variants that match the pattern. * The layout/variant is considered as matching if one of the following * is true: * 1. Country description (from the country list or name) contains pattern as substring * 2. Language description (from the language list or name) contains pattern as substring */ extern void xkl_config_registry_search_by_pattern(XklConfigRegistry * config, const gchar * pattern, XklTwoConfigItemsProcessFunc func, gpointer data); #ifdef __cplusplus } #endif /* __cplusplus */ #endif libxklavier-5.4/libxklavier/xkl_engine.h000066400000000000000000000356101213561201300205050ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKL_ENGINE_H__ #define __XKL_ENGINE_H__ #include #include #ifdef __cplusplus extern "C" { #endif typedef struct _XklEngine XklEngine; typedef struct _XklEnginePrivate XklEnginePrivate; typedef struct _XklEngineClass XklEngineClass; typedef struct _XklState XklState; #define XKL_TYPE_ENGINE (xkl_engine_get_type ()) #define XKL_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XKL_TYPE_ENGINE, XklEngine)) #define XKL_ENGINE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), XKL_TYPE_ENGINE, XklEngineClass)) #define XKL_IS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XKL_TYPE_ENGINE)) #define XKL_IS_ENGINE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), XKL_TYPE_ENGINE)) #define XKL_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XKL_TYPE_ENGINE, XklEngineClass)) /** * XklEngineStateChange: * @GROUP_CHANGED: Group was changed * @INDICATORS_CHANGED: Indicators were changed * * The type of the keyboard state change */ typedef enum { GROUP_CHANGED, INDICATORS_CHANGED } XklEngineStateChange; /** * XklEngineFeatures: * @XKLF_CAN_TOGGLE_INDICATORS: Backend allows to toggls indicators on/off * @XKLF_CAN_OUTPUT_CONFIG_AS_ASCII: Backend allows writing ASCII representation of the configuration * @XKLF_CAN_OUTPUT_CONFIG_AS_BINARY: Backend allows writing binary representation of the configuration * @XKLF_MULTIPLE_LAYOUTS_SUPPORTED: Backend supports multiple layouts * @XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT: Backend requires manual configuration, some daemon should do * xkl_start_listen(engine,XKLL_MANAGE_LAYOUTS); * @XKLF_DEVICE_DISCOVERY: Backend supports device discovery, can notify * * A set of flags used to indicate the capabilities of the active backend * */ typedef enum { /*< flags >*/ XKLF_CAN_TOGGLE_INDICATORS = 1 << 0, XKLF_CAN_OUTPUT_CONFIG_AS_ASCII = 1 << 1, XKLF_CAN_OUTPUT_CONFIG_AS_BINARY = 1 << 2, XKLF_MULTIPLE_LAYOUTS_SUPPORTED = 1 << 3, XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT = 1 << 4, XKLF_DEVICE_DISCOVERY = 1 << 5 } XklEngineFeatures; /** * _XklState: * @group: selected group * @indicators: set of active indicators * * XKB state. Can be global or per-window */ struct _XklState { gint32 group; guint32 indicators; }; #define XKL_TYPE_STATE (xkl_state_get_type()) GType xkl_state_get_type (void) G_GNUC_CONST; /** * _XklEngine: * @parent: The superclass object * * The main Xklavier engine class */ struct _XklEngine { GObject parent; /*< private >*/ XklEnginePrivate *priv; }; /** * _XklEngineClass: * @parent_class: The superclass * * The XklEngine class, derived from GObject */ struct _XklEngineClass { GObjectClass parent_class; /** * XklEngine::config-notify: * @engine: the object on which the signal is emitted * * Used for notifying application of the XKB configuration change. */ void (*config_notify) (XklEngine * engine); /** * XklEngine::new_window_notify: * @engine: the object on which the signal is emitted * @win: new window * @parent: new window's parent * * Used for notifying application of new window creation (actually, * registration). * * Returns: the initial group id for the window (-1 to use the default value) */ gint(*new_window_notify) (XklEngine * engine, Window win, Window parent); /** * XklEngine::state_notify: * @engine: the object on which the signal is emitted * @change_type: mask of changes * @group: new group * @restore: whether this state is restored from * saved state of set as new. * * Used for notifying application of the window state change. */ void (*state_notify) (XklEngine * engine, XklEngineStateChange change_type, gint group, gboolean restore); /** * XklEngine::new_device_notify: * @engine: the object on which the signal is emitted * * Used for notifying application of the new keyboard attached */ void (*new_device_notify) (XklEngine * engine); }; /** * xkl_engine_get_type: * * Get type info for XklEngine * * Returns: GType for XklEngine */ extern GType xkl_engine_get_type(void); /** * xkl_engine_get_instance: * @display: the X display used by the application * * Get the instance of the XklEngine. Within a process, there is always once instance. * * Returns: (transfer none): the singleton instance */ extern XklEngine *xkl_engine_get_instance(Display * display); /** * xkl_engine_get_backend_name: * @engine: the engine * * What kind of backend is used * * Returns: some string id of the backend */ extern const gchar *xkl_engine_get_backend_name(XklEngine * engine); /** * xkl_engine_get_features: * @engine: the engine * * Provides information regarding available backend features * (combination of XKLF_* constants) * * Returns: ORed XKLF_* constants */ extern guint xkl_engine_get_features(XklEngine * engine); /** * xkl_engine_get_max_num_groups: * @engine: the engine * * Provides the information on maximum number of simultaneously supported * groups (layouts) * * Returns: maximum number of the groups in configuration, * 0 if no restrictions. */ extern guint xkl_engine_get_max_num_groups(XklEngine * engine); /** * XklEngineListenModes: * @XKLL_MANAGE_WINDOW_STATES: The listener process should handle the per-window states * and all the related activity * @XKLL_TRACK_KEYBOARD_STATE: Just track the state and pass it to the application above. * @XKLL_MANAGE_LAYOUTS: The listener process should help backend to maintain the configuration * (manually switch layouts etc). * * The listener action modes: */ typedef enum { XKLL_MANAGE_WINDOW_STATES = 0x01, XKLL_TRACK_KEYBOARD_STATE = 0x02, XKLL_MANAGE_LAYOUTS = 0x04, } XklEngineListenModes; /** * xkl_engine_start_listen: * @engine: the engine * @flags: any combination of XKLL_* constants * * Starts listening for XKB-related events * * Returns: 0 */ extern gint xkl_engine_start_listen(XklEngine * engine, guint flags); /** * xkl_engine_stop_listen: * @engine: the engine * @flags: any combination of XKLL_* constants * * Stops listening for XKB-related events * Returns: 0 */ extern gint xkl_engine_stop_listen(XklEngine * engine, guint flags); /** * xkl_engine_pause_listen: * @engine: the engine * * Temporary pauses listening for XKB-related events * * Returns: 0 */ extern gint xkl_engine_pause_listen(XklEngine * engine); /** * xkl_engine_resume_listen: * @engine: the engine * * Resumes listening for XKB-related events * * Returns: 0 */ extern gint xkl_engine_resume_listen(XklEngine * engine); /** * xkl_engine_grab_key: * @engine: the engine * @keycode: keycode * @modifiers: bitmask of modifiers * * Grabs some key * * Returns: TRUE on success */ extern gboolean xkl_engine_grab_key(XklEngine * engine, gint keycode, guint modifiers); /** * xkl_engine_ungrab_key: * @engine: the engine * @keycode: keycode * @modifiers: bitmask of modifiers * * Ungrabs some key * * Returns: TRUE on success */ extern gboolean xkl_engine_ungrab_key(XklEngine * engine, gint keycode, guint modifiers); /** * xkl_engine_filter_events: * @engine: the engine * @evt: (skip): delivered X event * * Processes X events. Should be included into the main event cycle of an * application. One of the most important functions. * * Returns: 0 if the event it processed - 1 otherwise */ extern gint xkl_engine_filter_events(XklEngine * engine, XEvent * evt); /** * xkl_engine_allow_one_switch_to_secondary_group: * @engine: the engine * * Allows to switch (once) to the secondary group * */ extern void xkl_engine_allow_one_switch_to_secondary_group(XklEngine * engine); /** * xkl_engine_get_current_window: * @engine: the engine * * Returns: currently focused window */ extern Window xkl_engine_get_current_window(XklEngine * engine); /** * xkl_engine_get_current_state: * @engine: the engine * * Returns: (transfer none): current state of the keyboard. * Returned value is a statically allocated buffer, should not be freed. */ extern XklState *xkl_engine_get_current_state(XklEngine * engine); /** * xkl_engine_get_window_title: * @engine: the engine * @win: X window * * Returns: the window title of some window or NULL. * If not NULL, it should be freed with XFree */ extern gchar *xkl_engine_get_window_title(XklEngine * engine, Window win); /** * xkl_engine_get_state: * @engine: the engine * @win: window to query * @state_out: structure to store the state * * Finds the state for a given window (for its "App window"). * * Returns: TRUE on success, otherwise FALSE * (the error message can be obtained using xkl_GetLastError). */ extern gboolean xkl_engine_get_state(XklEngine * engine, Window win, XklState * state_out); /** * xkl_engine_delete_state: * @engine: the engine * @win: target window * * Drops the state of a given window (of its "App window"). */ extern void xkl_engine_delete_state(XklEngine * engine, Window win); /** * xkl_engine_save_state: * @engine: the engine * @win: target window * @state: new state of the window * * Stores ths state for a given window */ extern void xkl_engine_save_state(XklEngine * engine, Window win, XklState * state); /** * xkl_engine_set_window_transparent: * @engine: the engine * @win: window do set the flag for. * @transparent: if true, the windows is transparent. * * Sets the "transparent" flag. It means focus switching onto * this window will never change the state. */ extern void xkl_engine_set_window_transparent(XklEngine * engine, Window win, gboolean transparent); /** * xkl_engine_is_window_transparent: * @engine: the engine * @win: window to get the transparent flag from. * * Returns: TRUE if the window is "transparent" */ extern gboolean xkl_engine_is_window_transparent(XklEngine * engine, Window win); /** * xkl_engine_is_window_from_same_toplevel_window: * @engine: the engine * @win1: first window * @win2: second window * * Checks whether 2 windows have the same topmost window * * Returns: TRUE is windows are in the same application */ extern gboolean xkl_engine_is_window_from_same_toplevel_window(XklEngine * engine, Window win1, Window win2); /** * xkl_engine_get_num_groups: * @engine: the engine * * Returns: the total number of groups in the current configuration * (keyboard) */ extern guint xkl_engine_get_num_groups(XklEngine * engine); /** * xkl_engine_get_groups_names: * @engine: the engine * * Returns: (transfer none): the array of group names for the current XKB * configuration (keyboard). * This array is static, should not be freed */ extern const gchar **xkl_engine_get_groups_names(XklEngine * engine); /** * xkl_engine_get_indicators_names: * @engine: the engine * * Returns: (transfer none): the array of indicator names for the current XKB * configuration (keyboard). * This array is static, should not be freed */ extern const gchar **xkl_engine_get_indicators_names(XklEngine * engine); /** * xkl_engine_get_next_group: * @engine: the engine * * Calculates next group id. Does not change the state of anything. * * Returns: next group id */ extern gint xkl_engine_get_next_group(XklEngine * engine); /** * xkl_engine_get_prev_group: * @engine: the engine * * Calculates prev group id. Does not change the state of anything. * * Returns: prev group id */ extern gint xkl_engine_get_prev_group(XklEngine * engine); /** * xkl_engine_get_current_window_group: * @engine: the engine * * Returns: saved group id of the current window. */ extern gint xkl_engine_get_current_window_group(XklEngine * engine); /** * xkl_engine_lock_group: * @engine: the engine * @group: group number for locking * * Locks the group. Can be used after xkl_GetXXXGroup functions */ extern void xkl_engine_lock_group(XklEngine * engine, gint group); /** * xkl_engine_set_group_per_toplevel_window: * @engine: the engine * @is_global: new parameter value * * Sets the configuration parameter: group per application */ extern void xkl_engine_set_group_per_toplevel_window(XklEngine * engine, gboolean is_global); /** * xkl_engine_is_group_per_toplevel_window: * @engine: the engine * * Returns: the value of the parameter: group per application */ extern gboolean xkl_engine_is_group_per_toplevel_window(XklEngine * engine); /** * xkl_engine_set_indicators_handling: * @engine: the engine * @whether_handle: new parameter value * * Sets the configuration parameter: perform indicators handling */ extern void xkl_engine_set_indicators_handling(XklEngine * engine, gboolean whether_handle); /** * xkl_engine_get_indicators_handling: * @engine: the engine * * Returns: the value of the parameter: perform indicator handling */ extern gboolean xkl_engine_get_indicators_handling(XklEngine * engine); /** * xkl_engine_set_secondary_groups_mask: * @engine: the engine * @mask: new group mask * * Sets the secondary groups (one bit per group). * Secondary groups require explicit "allowance" for switching */ extern void xkl_engine_set_secondary_groups_mask(XklEngine * engine, guint mask); /** * xkl_engine_get_secondary_groups_mask: * @engine: the engine * * Returns: the secondary group mask */ extern guint xkl_engine_get_secondary_groups_mask(XklEngine * engine); /** * xkl_engine_set_default_group: * @engine: the engine * @group: default group * * Configures the default group set on window creation. * If -1, no default group is used */ extern void xkl_engine_set_default_group(XklEngine * engine, gint group); /** * xkl_engine_get_default_group: * @engine: the engine * * Returns the default group set on window creation * If -1, no default group is used * * Returns: the default group */ extern gint xkl_engine_get_default_group(XklEngine * engine); #ifdef __cplusplus } #endif /* __cplusplus */ #endif libxklavier-5.4/libxklavier/xklavier.c000066400000000000000000000562601213561201300202060ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" #include "xkl_engine_marshal.h" static GObjectClass *parent_class = NULL; static XklEngine *the_engine = NULL; gint xkl_debug_level = 0; static XklLogAppender log_appender = xkl_default_log_appender; const gchar *xkl_last_error_message; enum { PROP_0, PROP_DISPLAY, PROP_BACKEND_NAME, PROP_FEATURES, PROP_MAX_NUM_GROUPS, PROP_NUM_GROUPS, PROP_DEFAULT_GROUP, PROP_SECONDARY_GROUPS_MASK, PROP_INDICATORS_HANDLING, }; void xkl_engine_set_indicators_handling(XklEngine * engine, gboolean whether_handle) { xkl_engine_priv(engine, handle_indicators) = whether_handle; } gboolean xkl_engine_get_indicators_handling(XklEngine * engine) { return xkl_engine_priv(engine, handle_indicators); } void xkl_set_debug_level(int level) { xkl_debug_level = level; } void xkl_engine_set_group_per_toplevel_window(XklEngine * engine, gboolean is_set) { xkl_engine_priv(engine, group_per_toplevel_window) = is_set; } gboolean xkl_engine_is_group_per_toplevel_window(XklEngine * engine) { return xkl_engine_priv(engine, group_per_toplevel_window); } static void xkl_engine_set_switch_to_secondary_group(XklEngine * engine, gboolean val) { gulong propval = (gulong) val == TRUE; Display *dpy = xkl_engine_get_display(engine); XChangeProperty(dpy, xkl_engine_priv(engine, root_window), xkl_engine_priv(engine, atoms)[XKLAVIER_ALLOW_SECONDARY], XA_INTEGER, 32, PropModeReplace, (unsigned char *) &propval, 1); XSync(dpy, False); } void xkl_engine_allow_one_switch_to_secondary_group(XklEngine * engine) { xkl_debug(150, "Setting allow_one_switch_to_secondary_group flag\n"); xkl_engine_set_switch_to_secondary_group(engine, TRUE); } gboolean xkl_engine_is_one_switch_to_secondary_group_allowed(XklEngine * engine) { gboolean rv = FALSE; unsigned char *propval = NULL; Atom actual_type; int actual_format; unsigned long bytes_remaining; unsigned long actual_items; int result; result = XGetWindowProperty(xkl_engine_get_display(engine), xkl_engine_priv(engine, root_window), xkl_engine_priv(engine, atoms) [XKLAVIER_ALLOW_SECONDARY], 0L, 1L, False, XA_INTEGER, &actual_type, &actual_format, &actual_items, &bytes_remaining, &propval); if (Success == result) { if (actual_format == 32 && actual_items == 1) { rv = (gboolean) * (Bool *) propval; } XFree(propval); } return rv; } void xkl_engine_one_switch_to_secondary_group_performed(XklEngine * engine) { xkl_debug(150, "Resetting allow_one_switch_to_secondary_group flag\n"); xkl_engine_set_switch_to_secondary_group(engine, FALSE); } void xkl_engine_set_default_group(XklEngine * engine, gint group) { xkl_engine_priv(engine, default_group) = group; } gint xkl_engine_get_default_group(XklEngine * engine) { return xkl_engine_priv(engine, default_group); } void xkl_engine_set_secondary_groups_mask(XklEngine * engine, guint mask) { xkl_engine_priv(engine, secondary_groups_mask) = mask; } guint xkl_engine_get_secondary_groups_mask(XklEngine * engine) { return xkl_engine_priv(engine, secondary_groups_mask); } void xkl_set_log_appender(XklLogAppender func) { log_appender = func; } gint xkl_engine_start_listen(XklEngine * engine, guint what) { int i; guchar *cntr = xkl_engine_priv(engine, listener_type_counters); for (i = 0; i < XKLL_NUMBER_OF_LISTEN_MODES; i++, cntr++) if (what & (1 << i)) (*cntr)++; if (! (xkl_engine_priv(engine, features) & XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT) && (what & XKLL_MANAGE_LAYOUTS)) xkl_debug(0, "The backend does not require manual layout management - " "but it is provided by the application\n"); xkl_engine_resume_listen(engine); xkl_engine_load_window_tree(engine); XFlush(xkl_engine_get_display(engine)); return 0; } gint xkl_engine_stop_listen(XklEngine * engine, guint what) { int i; gboolean no_flags_remains = TRUE; guchar *cntr = xkl_engine_priv(engine, listener_type_counters); for (i = 0; i < XKLL_NUMBER_OF_LISTEN_MODES; i++, cntr++) { int mask = 1 << i; if (what & mask) (*cntr)--; if (*cntr) no_flags_remains = FALSE; } if (no_flags_remains) xkl_engine_pause_listen(engine); return 0; } XklEngine * xkl_engine_get_instance(Display * display) { if (the_engine != NULL) { g_object_ref(G_OBJECT(the_engine)); return the_engine; } if (!display) { xkl_debug(10, "xkl_init : display is NULL ?\n"); return NULL; } the_engine = XKL_ENGINE(g_object_new (xkl_engine_get_type(), "display", display, NULL)); return the_engine; } gboolean xkl_engine_grab_key(XklEngine * engine, gint keycode, guint modifiers) { gboolean ret_code; gchar *keyname; Display *dpy = xkl_engine_get_display(engine); if (xkl_debug_level >= 100) { keyname = XKeysymToString(XKeycodeToKeysym(dpy, keycode, 0)); xkl_debug(100, "Listen to the key %d/(%s)/%d\n", keycode, keyname, modifiers); } if (0 == keycode) return FALSE; xkl_engine_priv(engine, last_error_code) = Success; ret_code = XGrabKey(dpy, keycode, modifiers, xkl_engine_priv(engine, root_window), TRUE, GrabModeAsync, GrabModeAsync); XSync(dpy, False); xkl_debug(100, "XGrabKey recode %d/error %d\n", ret_code, xkl_engine_priv(engine, last_error_code)); ret_code = (xkl_engine_priv(engine, last_error_code) == Success); if (!ret_code) xkl_last_error_message = "Could not grab the key"; return ret_code; } gboolean xkl_engine_ungrab_key(XklEngine * engine, gint keycode, guint modifiers) { if (0 == keycode) return FALSE; return Success == XUngrabKey(xkl_engine_get_display(engine), keycode, 0, xkl_engine_priv(engine, root_window)); } gint xkl_engine_get_next_group(XklEngine * engine) { gint n = xkl_engine_get_num_groups(engine); return (xkl_engine_priv(engine, curr_state).group + 1) % n; } gint xkl_engine_get_prev_group(XklEngine * engine) { gint n = xkl_engine_get_num_groups(engine); return (xkl_engine_priv(engine, curr_state).group + n - 1) % n; } gint xkl_engine_get_current_window_group(XklEngine * engine) { XklState state; if (xkl_engine_priv(engine, curr_toplvl_win) == (Window) NULL) { xkl_debug(150, "cannot restore without current client\n"); } else if (xkl_engine_get_toplevel_window_state (engine, xkl_engine_priv(engine, curr_toplvl_win), &state)) { return state.group; } else xkl_debug(150, "Unbelievable: current client " WINID_FORMAT ", '%s' has no group\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win))); return 0; } void xkl_engine_set_window_transparent(XklEngine * engine, Window win, gboolean transparent) { Window toplevel_win; xkl_debug(150, "setting transparent flag %d for " WINID_FORMAT "\n", transparent, win); if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) { xkl_debug(150, "No toplevel window!\n"); /* toplevel_win = win; */ return; } xkl_engine_set_toplevel_window_transparent(engine, toplevel_win, transparent); } gboolean xkl_engine_is_window_transparent(XklEngine * engine, Window win) { Window toplevel_win; if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) return FALSE; return xkl_engine_is_toplevel_window_transparent(engine, toplevel_win); } /* * Loads the tree recursively. */ gboolean xkl_engine_load_window_tree(XklEngine * engine) { Window focused; int revert; gboolean retval = TRUE, have_toplevel_win; if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) retval = xkl_engine_load_subtree(engine, xkl_engine_priv(engine, root_window), 0, &xkl_engine_priv(engine, curr_state)); XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert); xkl_debug(160, "initially focused: " WINID_FORMAT ", '%s'\n", focused, xkl_get_debug_window_title(engine, focused)); have_toplevel_win = xkl_engine_find_toplevel_window(engine, focused, &xkl_engine_priv(engine, curr_toplvl_win)); if (have_toplevel_win) { XklState old_state; old_state = xkl_engine_priv (engine, curr_state); gboolean have_state = xkl_engine_get_toplevel_window_state(engine, xkl_engine_priv (engine, curr_toplvl_win), &xkl_engine_priv (engine, curr_state)); xkl_debug(160, "initial toplevel: " WINID_FORMAT ", '%s' %s state %d/%X\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win)), (have_state ? "with" : "without"), (have_state ? xkl_engine_priv(engine, curr_state).group : -1), (have_state ? xkl_engine_priv(engine, curr_state).indicators : -1)); if (old_state.group != xkl_engine_priv (engine, curr_state).group) { xkl_engine_lock_group (engine, xkl_engine_priv (engine, curr_state).group); } } else { xkl_debug(160, "Could not find initial app. " "Probably, focus belongs to some WM service window. " "Will try to survive:)"); } return retval; } void _xkl_debug(const gchar file[], const gchar function[], gint level, const gchar format[], ...) { va_list lst; if (level > xkl_debug_level) return; va_start(lst, format); if (log_appender != NULL) (*log_appender) (file, function, level, format, lst); va_end(lst); } void xkl_default_log_appender(const gchar file[], const gchar function[], gint level, const gchar format[], va_list args) { time_t now = time(NULL); fprintf(stdout, "[%08ld,%03d,%s:%s/] \t", (long) now, level, file, function); vfprintf(stdout, format, args); } /* * Just selects some events from the window. */ void xkl_engine_select_input(XklEngine * engine, Window win, gulong mask) { if (xkl_engine_priv(engine, root_window) == win) xkl_debug(160, "Someone is looking for %lx on root window ***\n", mask); XSelectInput(xkl_engine_get_display(engine), win, mask); } void xkl_engine_select_input_merging(XklEngine * engine, Window win, gulong mask) { XWindowAttributes attrs; gulong oldmask = 0L, newmask; memset(&attrs, 0, sizeof(attrs)); if (XGetWindowAttributes (xkl_engine_get_display(engine), win, &attrs)) oldmask = attrs.your_event_mask; newmask = oldmask | mask; if (newmask != oldmask) xkl_engine_select_input(engine, win, newmask); } void xkl_engine_try_call_state_func(XklEngine * engine, XklEngineStateChange change_type, XklState * old_state) { gint group = xkl_engine_priv(engine, curr_state).group; gboolean restore = old_state->group == group; xkl_debug(150, "change_type: %d, group: %d, secondary_group_mask: %X, allowsecondary: %d\n", change_type, group, xkl_engine_priv(engine, secondary_groups_mask), xkl_engine_is_one_switch_to_secondary_group_allowed (engine)); if (change_type == GROUP_CHANGED) { if (!restore) { if ((xkl_engine_priv(engine, secondary_groups_mask) & (1 << group)) != 0 && !xkl_engine_is_one_switch_to_secondary_group_allowed (engine)) { xkl_debug(150, "secondary -> go next\n"); group = xkl_engine_get_next_group(engine); xkl_engine_lock_group(engine, group); return; /* we do not need to revalidate */ } } xkl_engine_one_switch_to_secondary_group_performed(engine); } g_signal_emit_by_name(engine, "X-state-changed", change_type, xkl_engine_priv(engine, curr_state).group, restore); } void xkl_engine_ensure_vtable_inited(XklEngine * engine) { char *p; if (xkl_engine_priv(engine, backend_id) == NULL) { xkl_debug(0, "ERROR: XKL VTable is NOT initialized.\n"); /* force the crash! */ p = NULL; *p = '\0'; } } const gchar * xkl_engine_get_backend_name(XklEngine * engine) { return xkl_engine_priv(engine, backend_id); } guint xkl_engine_get_features(XklEngine * engine) { return xkl_engine_priv(engine, features); } void xkl_engine_reset_all_info(XklEngine * engine, gboolean force, const gchar reason[]) { xkl_debug(150, "Resetting all the cached info, reason: [%s]\n", reason); xkl_engine_ensure_vtable_inited(engine); if (force || !xkl_engine_vcall(engine, if_cached_info_equals_actual) (engine)) { xkl_engine_vcall(engine, free_all_info) (engine); xkl_engine_vcall(engine, load_all_info) (engine); } else xkl_debug(100, "NOT Resetting the cache: same configuration\n"); } /* * Calling through vtable */ const gchar ** xkl_engine_get_groups_names(XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, get_groups_names) (engine); } const gchar ** xkl_engine_get_indicators_names(XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, get_indicators_names) (engine); } guint xkl_engine_get_num_groups(XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, get_num_groups) (engine); } void xkl_engine_lock_group(XklEngine * engine, int group) { xkl_engine_ensure_vtable_inited(engine); xkl_engine_vcall(engine, lock_group) (engine, group); } gint xkl_engine_pause_listen(XklEngine * engine) { xkl_debug(150, "Pause listening\n"); xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, pause_listen) (engine); } gint xkl_engine_resume_listen(XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); guchar *listener_type_counters = xkl_engine_priv(engine, listener_type_counters); xkl_debug(150, "Resume listening, listenerType: (%s%s%s)\n", (listener_type_counters [XKLL_MANAGE_WINDOW_STATES_OFFSET]) ? "XKLL_MANAGE_WINDOW_STATES " : "", (listener_type_counters [XKLL_TRACK_KEYBOARD_STATE_OFFSET]) ? "XKLL_TRACK_KEYBOARD_STATE " : "", (listener_type_counters[XKLL_MANAGE_LAYOUTS_OFFSET]) ? "XKLL_MANAGE_LAYOUTS " : ""); if (xkl_engine_vcall(engine, resume_listen) (engine)) return 1; xkl_engine_select_input_merging(engine, xkl_engine_priv(engine, root_window), SubstructureNotifyMask | PropertyChangeMask); xkl_engine_vcall(engine, get_server_state) (engine, &xkl_engine_priv(engine, curr_state)); return 0; } guint xkl_engine_get_max_num_groups(XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, get_max_num_groups) (engine); } XklEngine * xkl_get_the_engine() { return the_engine; } G_DEFINE_TYPE(XklEngine, xkl_engine, G_TYPE_OBJECT) static GObject * xkl_engine_constructor(GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { GObject *obj; XklEngine *engine; Display *display; int scr; gint rv; { /* Invoke parent constructor. */ g_type_class_peek(XKL_TYPE_ENGINE); obj = parent_class->constructor(type, n_construct_properties, construct_properties); } engine = XKL_ENGINE(obj); display = (Display *) g_value_peek_pointer(construct_properties[0].value); xkl_engine_priv(engine, display) = display; xkl_engine_priv(engine, default_error_handler) = XSetErrorHandler(xkl_process_error); scr = DefaultScreen(display); xkl_engine_priv(engine, root_window) = RootWindow(display, scr); xkl_engine_priv(engine, skip_one_restore) = FALSE; xkl_engine_priv(engine, default_group) = -1; xkl_engine_priv(engine, secondary_groups_mask) = 0L; xkl_engine_priv(engine, prev_toplvl_win) = 0; xkl_engine_priv(engine, atoms)[WM_NAME] = XInternAtom(display, "WM_NAME", False); xkl_engine_priv(engine, atoms)[WM_STATE] = XInternAtom(display, "WM_STATE", False); xkl_engine_priv(engine, atoms)[XKLAVIER_STATE] = XInternAtom(display, "XKLAVIER_STATE", False); xkl_engine_priv(engine, atoms)[XKLAVIER_TRANSPARENT] = XInternAtom(display, "XKLAVIER_TRANSPARENT", False); xkl_engine_priv(engine, atoms)[XKLAVIER_ALLOW_SECONDARY] = XInternAtom(display, "XKLAVIER_ALLOW_SECONDARY", False); xkl_engine_one_switch_to_secondary_group_performed(engine); rv = -1; xkl_debug(150, "Trying all backends:\n"); #ifdef ENABLE_XKB_SUPPORT xkl_debug(150, "Trying XKB backend\n"); rv = xkl_xkb_init(engine); #endif #ifdef ENABLE_XMODMAP_SUPPORT if (rv != 0) { xkl_debug(150, "Trying xmodmap backend\n"); rv = xkl_xmm_init(engine); } #endif if (rv == 0) { xkl_debug(150, "Actual backend: %s\n", xkl_engine_get_backend_name(engine)); } else { xkl_debug(0, "All backends failed, last result: %d\n", rv); XSetErrorHandler(xkl_engine_priv (engine, default_error_handler)); xkl_engine_priv(engine, display) = NULL; g_object_unref(G_OBJECT(engine)); return NULL; } xkl_engine_ensure_vtable_inited(engine); if (!xkl_engine_vcall(engine, load_all_info) (engine)) { g_object_unref(G_OBJECT(engine)); return NULL; } return obj; } static void xkl_engine_init(XklEngine * engine) { engine->priv = g_new0(XklEnginePrivate, 1); } static void xkl_engine_set_property(GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { } static void xkl_engine_get_property(GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { XklEngine *engine = XKL_ENGINE(object); switch (property_id) { case PROP_DISPLAY: g_value_set_pointer(value, xkl_engine_get_display(engine)); break; case PROP_BACKEND_NAME: g_value_set_string(value, xkl_engine_priv(engine, backend_id)); break; case PROP_FEATURES: g_value_set_flags(value, xkl_engine_priv(engine, features)); break; case PROP_MAX_NUM_GROUPS: g_value_set_uint(value, xkl_engine_vcall(engine, get_max_num_groups) (engine)); break; case PROP_NUM_GROUPS: g_value_set_uint(value, xkl_engine_vcall(engine, get_num_groups) (engine)); break; case PROP_DEFAULT_GROUP: g_value_set_uint(value, xkl_engine_priv(engine, default_group)); break; case PROP_SECONDARY_GROUPS_MASK: g_value_set_uint(value, xkl_engine_priv(engine, secondary_groups_mask)); break; case PROP_INDICATORS_HANDLING: g_value_set_boolean(value, xkl_engine_priv(engine, handle_indicators)); break; } } static void xkl_engine_finalize(GObject * obj) { XklEngine *engine = (XklEngine *) obj; gpointer backend; XSetErrorHandler((XErrorHandler) xkl_engine_priv(engine, default_error_handler)); xkl_engine_ensure_vtable_inited(engine); xkl_engine_vcall(engine, free_all_info) (engine); xkl_engine_vcall(engine, finalize) (engine); backend = xkl_engine_priv(engine, backend); if (backend != NULL) g_free(backend); g_free(engine->priv); G_OBJECT_CLASS(parent_class)->finalize(obj); } static void xkl_engine_class_init(XklEngineClass * klass) { GObjectClass *object_class; GParamSpec *display_param_spec; GParamSpec *backend_name_param_spec; GParamSpec *features_param_spec; GParamSpec *max_num_groups_param_spec; GParamSpec *num_groups_param_spec; GParamSpec *default_group_param_spec; GParamSpec *secondary_groups_mask_param_spec; GParamSpec *indicators_handling_param_spec; const gchar *sdl; object_class = (GObjectClass *) klass; parent_class = g_type_class_peek_parent(object_class); object_class->constructor = xkl_engine_constructor; object_class->finalize = xkl_engine_finalize; object_class->set_property = xkl_engine_set_property; object_class->get_property = xkl_engine_get_property; display_param_spec = g_param_spec_pointer("display", "Display", "X Display pointer", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); backend_name_param_spec = g_param_spec_string("backendName", "backendName", "Backend name", NULL, G_PARAM_READABLE); features_param_spec = g_param_spec_flags("features", "Features", "Backend features", XKL_TYPE_ENGINE_FEATURES, 0, G_PARAM_READABLE); max_num_groups_param_spec = g_param_spec_uint("max-num-groups", "maxNumGroups", "Max number of groups", 0, 0x100, 0, G_PARAM_READABLE); num_groups_param_spec = g_param_spec_uint("num-groups", "numGroups", "Current number of groups", 0, 0x100, 0, G_PARAM_READABLE); default_group_param_spec = g_param_spec_uint("default-group", "defaultGroup", "Default group", 0, 0x100, 0, G_PARAM_READABLE); secondary_groups_mask_param_spec = g_param_spec_uint("secondary-groups-mask", "secondaryGroupsMask", "Secondary groups mask", 0, 0x100, 0, G_PARAM_READABLE); indicators_handling_param_spec = g_param_spec_boolean("indicators-handling", "indicatorsHandling", "Whether engine should handle indicators", FALSE, G_PARAM_READABLE); g_object_class_install_property(object_class, PROP_DISPLAY, display_param_spec); g_object_class_install_property(object_class, PROP_BACKEND_NAME, backend_name_param_spec); g_object_class_install_property(object_class, PROP_FEATURES, features_param_spec); g_object_class_install_property(object_class, PROP_MAX_NUM_GROUPS, max_num_groups_param_spec); g_object_class_install_property(object_class, PROP_NUM_GROUPS, num_groups_param_spec); g_object_class_install_property(object_class, PROP_DEFAULT_GROUP, default_group_param_spec); g_object_class_install_property(object_class, PROP_SECONDARY_GROUPS_MASK, secondary_groups_mask_param_spec); g_object_class_install_property(object_class, PROP_INDICATORS_HANDLING, indicators_handling_param_spec); g_signal_new("X-config-changed", XKL_TYPE_ENGINE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass, config_notify), NULL, NULL, xkl_engine_VOID__VOID, G_TYPE_NONE, 0); g_signal_new("X-new-device", XKL_TYPE_ENGINE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass, new_device_notify), NULL, NULL, xkl_engine_VOID__VOID, G_TYPE_NONE, 0); g_signal_new("new-toplevel-window", XKL_TYPE_ENGINE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass, new_window_notify), NULL, NULL, xkl_engine_INT__LONG_LONG, G_TYPE_INT, 2, G_TYPE_LONG, G_TYPE_LONG); g_signal_new("X-state-changed", XKL_TYPE_ENGINE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(XklEngineClass, state_notify), NULL, NULL, xkl_engine_VOID__ENUM_INT_BOOLEAN, G_TYPE_NONE, 3, XKL_TYPE_ENGINE_STATE_CHANGE, G_TYPE_INT, G_TYPE_BOOLEAN); /* static stuff initialized */ sdl = g_getenv("XKL_DEBUG"); if (sdl != NULL) { xkl_set_debug_level(atoi(sdl)); } } libxklavier-5.4/libxklavier/xklavier.h000066400000000000000000000075001213561201300202040ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKLAVIER_H__ #define __XKLAVIER_H__ #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * xkl_get_last_error: * * Returns: the text message (statically allocated) of the last error */ extern const gchar *xkl_get_last_error(void); /** * _xkl_debug: * @file: the name of the source file. * Preprocessor symbol__FILE__ should be used here * @function: name of the function * Preprocessor symbol__func__ should be used here * @level: level of the message * @format: is a format (like in printf) * * Output (optionally) some debug info */ extern void _xkl_debug(const gchar file[], const gchar function[], gint level, const gchar format[], ...); /** * XklLogAppender: * @file: name of the source file. * Preprocessor symbol__FILE__ should be used here * @function: name of the function * Preprocessor symbol__func__ should be used here * @level: level of the message * @format: format (like in printf) * @args: list of parameters * * Custom log output method for _xkl_debug. This appender is NOT called if the * level of the message is greater than currently set debug level. */ typedef void (*XklLogAppender) (const gchar file[], const gchar function[], gint level, const gchar format[], va_list args); /** * xkl_default_log_appender: * @file: name of the source file. * Preprocessor symbol__FILE__ should be used here * @function: name of the function * Preprocessor symbol__func__ should be used here * @level: level of the message * @format: format (like in printf) * @args: list of parameters * * Default log output method. Sends everything to stdout. */ extern void xkl_default_log_appender(const gchar file[], const gchar function[], gint level, const gchar format[], va_list args); /** * xkl_set_log_appender: * @fun: new log appender * * Installs the custom log appender.function */ extern void xkl_set_log_appender(XklLogAppender fun); /** * xkl_set_debug_level: * @level: new debug level * * Sets maximum debug level. * Message of the level more than the one set here - will be ignored */ extern void xkl_set_debug_level(gint level); #ifdef G_HAVE_ISO_VARARGS /** * xkl_debug: * @level: level of the message * * Output (optionally) some debug info */ #define xkl_debug( level, ... ) \ _xkl_debug( __FILE__, __func__, level, __VA_ARGS__ ) #elif defined(G_HAVE_GNUC_VARARGS) /** * xkl_debug: * @level: level of the message * @format: format (like in printf) * * Output (optionally) some debug info */ #define xkl_debug( level, format, args... ) \ _xkl_debug( __FILE__, __func__, level, format, ## args ) #else #define xkl_debug( level, ... ) \ _xkl_debug( __FILE__, __func__, level, __VA_ARGS__ ) #endif #ifdef __cplusplus } #endif /* __cplusplus */ #endif libxklavier-5.4/libxklavier/xklavier_config.c000066400000000000000000000746751213561201300215450ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "config.h" #include "xklavier_private.h" static GObjectClass *parent_class = NULL; static xmlXPathCompExprPtr models_xpath; static xmlXPathCompExprPtr layouts_xpath; static xmlXPathCompExprPtr option_groups_xpath; static GRegex **xml_encode_regexen = NULL; static GRegex **xml_decode_regexen = NULL; static const char *xml_decode_regexen_str[] = { "<", ">", "&" }; static const char *xml_encode_regexen_str[] = { "<", ">", "&" }; /* gettext domain for translations */ #define XKB_DOMAIN "xkeyboard-config" enum { PROP_0, PROP_ENGINE }; typedef struct { gchar **patterns; XklTwoConfigItemsProcessFunc func; gpointer data; gboolean country_matched; gboolean language_matched; const XklConfigItem *layout_item; } SearchParamType; static gboolean xkl_xml_find_config_item_child(xmlNodePtr iptr, xmlNodePtr * ptr) { /* * Walking through the 1st level children of iptr * looking for the configItem */ if (iptr->type != XML_ELEMENT_NODE) return FALSE; *ptr = iptr->children; while (*ptr != NULL) { switch ((*ptr)->type) { case XML_ELEMENT_NODE: return !g_ascii_strcasecmp ((char *) (*ptr)->name, "configItem"); case XML_TEXT_NODE: case XML_COMMENT_NODE: (*ptr) = (*ptr)->next; continue; default: return FALSE; } break; } return FALSE; } static xmlNodePtr xkl_find_element(xmlNodePtr ptr, const gchar * tag_name) { xmlNodePtr found_element = NULL; /* Look through all siblings, trying to find a node with proper name */ while (ptr != NULL) { char *node_name = (char *) ptr->name; if (ptr->type != XML_TEXT_NODE) { if (!g_ascii_strcasecmp(node_name, tag_name)) { found_element = ptr; break; } } ptr = ptr->next; } return found_element; } static gboolean xkl_item_populate_optional_array(XklConfigItem * item, xmlNodePtr ptr, const gchar list_tag[], const gchar element_tag[], const gchar property_name[]) { xmlNodePtr top_list_element = xkl_find_element(ptr, list_tag), element_ptr; gint n_elements, idx; gchar **elements = NULL; if (top_list_element == NULL || top_list_element->children == NULL) return FALSE; n_elements = 0; /* First, count countries */ element_ptr = top_list_element->children; while (NULL != (element_ptr = xkl_find_element(element_ptr, element_tag))) { n_elements++; element_ptr = element_ptr->next; } if (n_elements == 0) return FALSE; elements = g_new0(gchar *, n_elements + 1); /* Then, actually, populate the list */ element_ptr = top_list_element->children; for (idx = 0; NULL != (element_ptr = xkl_find_element(element_ptr, element_tag)); element_ptr = element_ptr->next, idx++) { elements[idx] = g_strdup((const char *) element_ptr-> children->content); } g_object_set_data_full(G_OBJECT(item), property_name, elements, (GDestroyNotify) g_strfreev); return TRUE; } #include "libxml/parserInternals.h" gboolean xkl_read_config_item(XklConfigRegistry * config, gint doc_index, xmlNodePtr iptr, XklConfigItem * item) { xmlNodePtr name_element, ptr; xmlNodePtr desc_element = NULL, short_desc_element = NULL, vendor_element = NULL; gchar *vendor = NULL, *translated = NULL, *escaped = NULL, *unescaped = NULL; gint i; *item->name = 0; *item->short_description = 0; *item->description = 0; g_object_set_data(G_OBJECT(item), XCI_PROP_VENDOR, NULL); g_object_set_data(G_OBJECT(item), XCI_PROP_COUNTRY_LIST, NULL); g_object_set_data(G_OBJECT(item), XCI_PROP_LANGUAGE_LIST, NULL); if (!xkl_xml_find_config_item_child(iptr, &ptr)) return FALSE; if (doc_index > 0) g_object_set_data(G_OBJECT(item), XCI_PROP_EXTRA_ITEM, GINT_TO_POINTER(TRUE)); ptr = ptr->children; if (ptr->type == XML_TEXT_NODE) ptr = ptr->next; name_element = ptr; ptr = ptr->next; short_desc_element = xkl_find_element(ptr, XML_TAG_SHORT_DESCR); desc_element = xkl_find_element(ptr, XML_TAG_DESCR); vendor_element = xkl_find_element(ptr, XML_TAG_VENDOR); if (name_element != NULL && name_element->children != NULL) strncat(item->name, (char *) name_element->children->content, XKL_MAX_CI_NAME_LENGTH - 1); if (short_desc_element != NULL && short_desc_element->children != NULL) { strncat(item->short_description, dgettext(XKB_DOMAIN, (const char *) short_desc_element->children->content), XKL_MAX_CI_SHORT_DESC_LENGTH - 1); } if (desc_element != NULL && desc_element->children != NULL) { /* Convert all xml-related characters to XML form, otherwise dgettext won't find the translation * The conversion is not using libxml2, because there are no handy functions in API */ translated = g_strdup((gchar *) desc_element->children->content); for (i = sizeof(xml_encode_regexen_str) / sizeof(xml_encode_regexen_str[0]); --i >= 0;) { escaped = g_regex_replace(xml_encode_regexen[i], translated, -1, 0, xml_decode_regexen_str[i], 0, NULL); g_free(translated); translated = escaped; } escaped = translated; /* Do the translation! */ translated = g_strdup(dgettext(XKB_DOMAIN, (const char *) escaped)); g_free(escaped); /* Convert all XML entities back to normal form */ for (i = sizeof(xml_decode_regexen_str) / sizeof(xml_decode_regexen_str[0]); --i >= 0;) { unescaped = g_regex_replace(xml_decode_regexen[i], translated, -1, 0, xml_encode_regexen_str[i], 0, NULL); g_free(translated); translated = unescaped; } strncat(item->description, translated, XKL_MAX_CI_DESC_LENGTH - 1); g_free(translated); } if (vendor_element != NULL && vendor_element->children != NULL) { vendor = g_strdup((const char *) vendor_element->children-> content); g_object_set_data_full(G_OBJECT(item), XCI_PROP_VENDOR, vendor, g_free); } xkl_item_populate_optional_array(item, ptr, XML_TAG_COUNTRY_LIST, XML_TAG_ISO3166ID, XCI_PROP_COUNTRY_LIST); xkl_item_populate_optional_array(item, ptr, XML_TAG_LANGUAGE_LIST, XML_TAG_ISO639ID, XCI_PROP_LANGUAGE_LIST); return TRUE; } static void xkl_config_registry_foreach_in_nodeset(XklConfigRegistry * config, GSList ** processed_ids, gint doc_index, xmlNodeSetPtr nodes, XklConfigItemProcessFunc func, gpointer data) { gint i; if (nodes != NULL) { xmlNodePtr *pnode = nodes->nodeTab; XklConfigItem *ci = xkl_config_item_new(); for (i = nodes->nodeNr; --i >= 0;) { if (xkl_read_config_item (config, doc_index, *pnode, ci)) { if (g_slist_find_custom (*processed_ids, ci->name, (GCompareFunc) g_ascii_strcasecmp) == NULL) { func(config, ci, data); *processed_ids = g_slist_append(*processed_ids, g_strdup (ci->name)); } } pnode++; } g_object_unref(G_OBJECT(ci)); } } void xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, xmlXPathCompExprPtr xpath_comp_expr, XklConfigItemProcessFunc func, gpointer data) { xmlXPathObjectPtr xpath_obj; gint di; GSList *processed_ids = NULL; if (!xkl_config_registry_is_initialized(config)) return; for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathCompiledEval(xpath_comp_expr, xmlctxt); if (xpath_obj == NULL) continue; xkl_config_registry_foreach_in_nodeset(config, &processed_ids, di, xpath_obj-> nodesetval, func, data); xmlXPathFreeObject(xpath_obj); } g_slist_foreach(processed_ids, (GFunc) g_free, NULL); g_slist_free(processed_ids); } void xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry * config, const gchar * format, const gchar * value, XklConfigItemProcessFunc func, gpointer data) { char xpath_expr[1024]; xmlXPathObjectPtr xpath_obj; gint di; GSList *processed_ids = NULL; if (!xkl_config_registry_is_initialized(config)) return; g_snprintf(xpath_expr, sizeof xpath_expr, format, value); for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathEval((unsigned char *) xpath_expr, xmlctxt); if (xpath_obj == NULL) continue; xkl_config_registry_foreach_in_nodeset(config, &processed_ids, di, xpath_obj-> nodesetval, func, data); xmlXPathFreeObject(xpath_obj); } g_slist_foreach(processed_ids, (GFunc) g_free, NULL); g_slist_free(processed_ids); } static gboolean xkl_config_registry_find_object(XklConfigRegistry * config, const gchar * format, const gchar * arg1, XklConfigItem * pitem /* in/out */ , xmlNodePtr * pnode /* out */ ) { xmlXPathObjectPtr xpath_obj; xmlNodeSetPtr nodes; gboolean rv = FALSE; gchar xpath_expr[1024]; gint di; if (!xkl_config_registry_is_initialized(config)) return FALSE; g_snprintf(xpath_expr, sizeof xpath_expr, format, arg1, pitem->name); for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathEval((unsigned char *) xpath_expr, xmlctxt); if (xpath_obj == NULL) continue; nodes = xpath_obj->nodesetval; if (nodes != NULL && nodes->nodeTab != NULL && nodes->nodeNr > 0) { rv = xkl_read_config_item(config, di, nodes->nodeTab[0], pitem); if (pnode != NULL) { *pnode = *nodes->nodeTab; } } xmlXPathFreeObject(xpath_obj); } return rv; } gchar * xkl_config_rec_merge_layouts(const XklConfigRec * data) { return xkl_strings_concat_comma_separated(data->layouts); } gchar * xkl_config_rec_merge_variants(const XklConfigRec * data) { return xkl_strings_concat_comma_separated(data->variants); } gchar * xkl_config_rec_merge_options(const XklConfigRec * data) { return xkl_strings_concat_comma_separated(data->options); } gchar * xkl_strings_concat_comma_separated(gchar ** array) { if (array) { return g_strjoinv(",", array); } else { return g_strdup(""); } } void xkl_config_rec_split_layouts(XklConfigRec * data, const gchar * merged) { xkl_strings_split_comma_separated(&data->layouts, merged); } void xkl_config_rec_split_variants(XklConfigRec * data, const gchar * merged) { xkl_strings_split_comma_separated(&data->variants, merged); } void xkl_config_rec_split_options(XklConfigRec * data, const gchar * merged) { xkl_strings_split_comma_separated(&data->options, merged); } void xkl_strings_split_comma_separated(gchar *** array, const gchar * merged) { *array = g_strsplit(merged, ",", 0); } gchar * xkl_engine_get_ruleset_name(XklEngine * engine, const gchar default_ruleset[]) { static gchar rules_set_name[1024] = ""; if (!rules_set_name[0]) { /* first call */ gchar *rf = NULL; if (!xkl_config_rec_get_from_root_window_property (NULL, xkl_engine_priv(engine, base_config_atom), &rf, engine) || (rf == NULL)) { g_strlcpy(rules_set_name, default_ruleset, sizeof rules_set_name); xkl_debug(100, "Using default rules set: [%s]\n", rules_set_name); return rules_set_name; } g_strlcpy(rules_set_name, rf, sizeof rules_set_name); g_free(rf); } xkl_debug(100, "Rules set: [%s]\n", rules_set_name); return rules_set_name; } XklConfigRegistry * xkl_config_registry_get_instance(XklEngine * engine) { XklConfigRegistry *config; if (!engine) { xkl_debug(10, "xkl_config_registry_get_instance : engine is NULL ?\n"); return NULL; } config = XKL_CONFIG_REGISTRY(g_object_new (xkl_config_registry_get_type(), "engine", engine, NULL)); return config; } /* We process descriptions as "leaf" elements - this is ok for base.xml*/ gboolean xkl_config_registry_load_from_file(XklConfigRegistry * config, const gchar * file_name, gint docidx) { xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); xmlDocPtr doc; xkl_debug(100, "Loading XML registry from file %s\n", file_name); xmlSAX2InitDefaultSAXHandler(ctxt->sax, TRUE); doc = xkl_config_registry_priv(config, docs[docidx]) = xmlCtxtReadFile(ctxt, file_name, NULL, XML_PARSE_NOBLANKS); xmlFreeParserCtxt(ctxt); if (doc == NULL) { xkl_config_registry_priv(config, xpath_contexts[docidx]) = NULL; xkl_last_error_message = "Could not parse primary XKB configuration registry"; return FALSE; } xkl_config_registry_priv(config, xpath_contexts[docidx]) = xmlXPathNewContext(doc); return TRUE; } gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, const char default_ruleset[], const char base_dir[], gboolean if_extras_needed) { struct stat stat_buf; gchar file_name[MAXPATHLEN] = ""; XklEngine *engine = xkl_config_registry_get_engine(config); gchar *rf = xkl_engine_get_ruleset_name(engine, default_ruleset); if (rf == NULL || rf[0] == '\0') return FALSE; g_snprintf(file_name, sizeof file_name, "%s/%s.xml", base_dir, rf); if (stat(file_name, &stat_buf) != 0) { xkl_debug(0, "Missing registry file %s\n", file_name); xkl_last_error_message = "Missing registry file"; return FALSE; } if (!xkl_config_registry_load_from_file(config, file_name, 0)) return FALSE; if (!if_extras_needed) return TRUE; g_snprintf(file_name, sizeof file_name, "%s/%s.extras.xml", base_dir, rf); /* no extras - ok, no problem */ if (stat(file_name, &stat_buf) != 0) return TRUE; return xkl_config_registry_load_from_file(config, file_name, 1); } void xkl_config_registry_free(XklConfigRegistry * config) { if (xkl_config_registry_is_initialized(config)) { gint di; for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xmlXPathFreeContext(xmlctxt); xmlFreeDoc(xkl_config_registry_priv (config, docs[di])); xkl_config_registry_priv(config, xpath_contexts[di]) = NULL; xkl_config_registry_priv(config, docs[di]) = NULL; } } } void xkl_config_registry_foreach_model(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data) { xkl_config_registry_foreach_in_xpath(config, models_xpath, func, data); } void xkl_config_registry_foreach_layout(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data) { xkl_config_registry_foreach_in_xpath(config, layouts_xpath, func, data); } void xkl_config_registry_foreach_layout_variant(XklConfigRegistry * config, const gchar * layout_name, XklConfigItemProcessFunc func, gpointer data) { xkl_config_registry_foreach_in_xpath_with_param(config, XKBCR_VARIANT_PATH "[../../configItem/name = '%s']", layout_name, func, data); } void xkl_config_registry_foreach_option_group(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data) { xmlXPathObjectPtr xpath_obj; gint di, j; GSList *processed_ids = NULL; if (!xkl_config_registry_is_initialized(config)) return; for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlNodeSetPtr nodes; xmlNodePtr *pnode; XklConfigItem *ci; xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathCompiledEval(option_groups_xpath, xmlctxt); if (xpath_obj == NULL) continue; nodes = xpath_obj->nodesetval; pnode = nodes->nodeTab; ci = xkl_config_item_new(); for (j = nodes->nodeNr; --j >= 0;) { if (xkl_read_config_item(config, di, *pnode, ci)) { if (g_slist_find_custom (processed_ids, ci->name, (GCompareFunc) g_ascii_strcasecmp) == NULL) { gboolean allow_multisel = TRUE; xmlChar *sallow_multisel = xmlGetProp(*pnode, (unsigned char *) XCI_PROP_ALLOW_MULTIPLE_SELECTION); if (sallow_multisel != NULL) { allow_multisel = !g_ascii_strcasecmp ("true", (char *) sallow_multisel); xmlFree(sallow_multisel); g_object_set_data(G_OBJECT (ci), XCI_PROP_ALLOW_MULTIPLE_SELECTION, GINT_TO_POINTER (allow_multisel)); } func(config, ci, data); processed_ids = g_slist_append(processed_ids, g_strdup (ci->name)); } } pnode++; } g_object_unref(G_OBJECT(ci)); xmlXPathFreeObject(xpath_obj); } g_slist_foreach(processed_ids, (GFunc) g_free, NULL); g_slist_free(processed_ids); } void xkl_config_registry_foreach_option(XklConfigRegistry * config, const gchar * option_group_name, XklConfigItemProcessFunc func, gpointer data) { xkl_config_registry_foreach_in_xpath_with_param(config, XKBCR_OPTION_PATH "[../configItem/name = '%s']", option_group_name, func, data); } static gboolean search_all(const gchar * haystack, gchar ** needles) { /* match anything */ if (!needles || !*needles) return TRUE; gchar *uchs = g_utf8_strup(haystack, -1); do { if (g_strstr_len(uchs, -1, *needles) == NULL) { g_free(uchs); return FALSE; } needles++; } while (*needles); g_free(uchs); return TRUE; } static gboolean if_country_matches_pattern(const XklConfigItem * item, gchar ** patterns, const gboolean check_name) { const gchar *country_desc; if (check_name) { gchar *upper_name = g_ascii_strup(item->name, -1); country_desc = xkl_get_country_name(upper_name); g_free(upper_name); xkl_debug(200, "Checking layout country: [%s]\n", country_desc); if ((country_desc != NULL) && search_all(country_desc, patterns)) return TRUE; } gchar **countries = g_object_get_data(G_OBJECT(item), XCI_PROP_COUNTRY_LIST); for (; countries && *countries; countries++) { country_desc = xkl_get_country_name(*countries); xkl_debug(200, "Checking country: [%s][%s]\n", *countries, country_desc); if ((country_desc != NULL) && search_all(country_desc, patterns)) { return TRUE; } } return FALSE; } static gboolean if_language_matches_pattern(const XklConfigItem * item, gchar ** patterns, const gboolean check_name) { const gchar *language_desc; if (check_name) { language_desc = xkl_get_language_name(item->name); xkl_debug(200, "Checking layout language: [%s]\n", language_desc); if ((language_desc != NULL) && search_all(language_desc, patterns)) return TRUE; } gchar **languages = g_object_get_data(G_OBJECT(item), XCI_PROP_LANGUAGE_LIST); for (; languages && *languages; languages++) { language_desc = xkl_get_language_name(*languages); xkl_debug(200, "Checking language: [%s][%s]\n", *languages, language_desc); if ((language_desc != NULL) && search_all(language_desc, patterns)) { return TRUE; } } return FALSE; } static void xkl_config_registry_search_by_pattern_in_variant(XklConfigRegistry * config, const XklConfigItem * item, SearchParamType * search_param) { gboolean variant_matched = FALSE; gchar *full_desc = g_strdup_printf("%s - %s", search_param-> layout_item->description, item->description); xkl_debug(200, "Variant to check: [%s][%s]\n", item->name, item->description); if (search_all(full_desc, search_param->patterns)) variant_matched = TRUE; g_free(full_desc); if (!variant_matched) { gchar **countries = g_object_get_data(G_OBJECT(item), XCI_PROP_COUNTRY_LIST); if (countries && g_strv_length(countries) > 0) { if (if_country_matches_pattern (item, search_param->patterns, FALSE)) variant_matched = TRUE; } else { if (search_param->country_matched) variant_matched = TRUE; } } if (!variant_matched) { gchar **languages = g_object_get_data(G_OBJECT(item), XCI_PROP_LANGUAGE_LIST); if (languages && g_strv_length(languages) > 0) { if (if_language_matches_pattern (item, search_param->patterns, FALSE)) variant_matched = TRUE; } else { if (search_param->language_matched) variant_matched = TRUE; } } if (variant_matched) (search_param->func) (config, search_param->layout_item, item, search_param->data); } static void xkl_config_registry_search_by_pattern_in_layout(XklConfigRegistry * config, const XklConfigItem * item, SearchParamType * search_param) { gchar *upper_name = g_ascii_strup(item->name, -1); xkl_debug(200, "Layout to check: [%s][%s]\n", item->name, item->description); search_param->country_matched = search_param->language_matched = FALSE; if (if_country_matches_pattern(item, search_param->patterns, TRUE)) search_param->country_matched = TRUE; else if (if_language_matches_pattern (item, search_param->patterns, TRUE)) search_param->language_matched = TRUE; else if (search_all(item->description, search_param->patterns)) search_param->language_matched = TRUE; if (search_param->country_matched || search_param->language_matched) (search_param->func) (config, item, NULL, search_param->data); search_param->layout_item = item; xkl_config_registry_foreach_layout_variant(config, item->name, (XklConfigItemProcessFunc) xkl_config_registry_search_by_pattern_in_variant, search_param); g_free(upper_name); } void xkl_config_registry_search_by_pattern(XklConfigRegistry * config, const gchar * pattern, XklTwoConfigItemsProcessFunc func, gpointer data) { xkl_debug(200, "Searching by pattern: [%s]\n", pattern); gchar *upattern = pattern ? g_utf8_strup(pattern, -1) : NULL; gchar **patterns = pattern ? g_strsplit(upattern, " ", -1) : NULL; SearchParamType search_param = { patterns, func, data }; xkl_config_registry_foreach_layout(config, (XklConfigItemProcessFunc) xkl_config_registry_search_by_pattern_in_layout, &search_param); g_strfreev(patterns); g_free(upattern); } gboolean xkl_config_registry_find_model(XklConfigRegistry * config, XklConfigItem * pitem /* in/out */ ) { return xkl_config_registry_find_object(config, XKBCR_MODEL_PATH "[configItem/name = '%s%s']", "", pitem, NULL); } gboolean xkl_config_registry_find_layout(XklConfigRegistry * config, XklConfigItem * pitem /* in/out */ ) { return xkl_config_registry_find_object(config, XKBCR_LAYOUT_PATH "[configItem/name = '%s%s']", "", pitem, NULL); } gboolean xkl_config_registry_find_variant(XklConfigRegistry * config, const char *layout_name, XklConfigItem * pitem /* in/out */ ) { return xkl_config_registry_find_object(config, XKBCR_VARIANT_PATH "[../../configItem/name = '%s' and configItem/name = '%s']", layout_name, pitem, NULL); } gboolean xkl_config_registry_find_option_group(XklConfigRegistry * config, XklConfigItem * pitem /* in/out */ ) { xmlNodePtr node = NULL; gboolean rv = xkl_config_registry_find_object(config, XKBCR_GROUP_PATH "[configItem/name = '%s%s']", "", pitem, &node); if (rv) { xmlChar *val = xmlGetProp(node, (unsigned char *) XCI_PROP_ALLOW_MULTIPLE_SELECTION); if (val != NULL) { gboolean allow_multisel = !g_ascii_strcasecmp("true", (char *) val); g_object_set_data(G_OBJECT(pitem), XCI_PROP_ALLOW_MULTIPLE_SELECTION, GINT_TO_POINTER(allow_multisel)); xmlFree(val); } } return rv; } gboolean xkl_config_registry_find_option(XklConfigRegistry * config, const char *option_group_name, XklConfigItem * pitem /* in/out */ ) { return xkl_config_registry_find_object(config, XKBCR_OPTION_PATH "[../configItem/name = '%s' and configItem/name = '%s']", option_group_name, pitem, NULL); } /* * Calling through vtable */ gboolean xkl_config_rec_activate(const XklConfigRec * data, XklEngine * engine) { xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, activate_config_rec) (engine, data); } gboolean xkl_config_registry_load(XklConfigRegistry * config, gboolean if_extras_needed) { XklEngine *engine; xkl_config_registry_free(config); engine = xkl_config_registry_get_engine(config); xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, load_config_registry) (config, if_extras_needed); } gboolean xkl_config_rec_write_to_file(XklEngine * engine, const gchar * file_name, const XklConfigRec * data, const gboolean binary) { if ((!binary && !(xkl_engine_priv(engine, features) & XKLF_CAN_OUTPUT_CONFIG_AS_ASCII)) || (binary && !(xkl_engine_priv(engine, features) & XKLF_CAN_OUTPUT_CONFIG_AS_BINARY))) { xkl_last_error_message = "Function not supported at backend"; return FALSE; } xkl_engine_ensure_vtable_inited(engine); return xkl_engine_vcall(engine, write_config_rec_to_file) (engine, file_name, data, binary); } void xkl_config_rec_dump(FILE * file, XklConfigRec * data) { int j; fprintf(file, " model: [%s]\n", data->model); fprintf(file, " layouts:\n"); #define OUTPUT_ARRZ(arrz) \ { \ gchar **p = data->arrz; \ fprintf( file, " " #arrz ":\n" ); \ if ( p != NULL ) \ for( j = 0; *p != NULL; ) \ fprintf( file, " %d: [%s]\n", j++, *p++ ); \ } OUTPUT_ARRZ(layouts); OUTPUT_ARRZ(variants); OUTPUT_ARRZ(options); } G_DEFINE_TYPE(XklConfigRegistry, xkl_config_registry, G_TYPE_OBJECT) static GObject * xkl_config_registry_constructor(GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) { GObject *obj; XklConfigRegistry *config; XklEngine *engine; { /* Invoke parent constructor. */ g_type_class_peek(XKL_TYPE_CONFIG_REGISTRY); obj = parent_class->constructor(type, n_construct_properties, construct_properties); } config = XKL_CONFIG_REGISTRY(obj); engine = XKL_ENGINE(g_value_peek_pointer (construct_properties[0].value)); xkl_config_registry_get_engine(config) = engine; xkl_engine_ensure_vtable_inited(engine); xkl_engine_vcall(engine, init_config_registry) (config); return obj; } static void xkl_config_registry_init(XklConfigRegistry * config) { config->priv = g_new0(XklConfigRegistryPrivate, 1); } static void xkl_config_registry_set_property(GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { } static void xkl_config_registry_get_property(GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { XklConfigRegistry *config = XKL_CONFIG_REGISTRY(object); switch (property_id) { case PROP_ENGINE: g_value_set_pointer(value, xkl_config_registry_get_engine (config)); break; } } static void xkl_config_registry_finalize(GObject * obj) { XklConfigRegistry *config = (XklConfigRegistry *) obj; xkl_config_registry_free(config); g_free(config->priv); G_OBJECT_CLASS(parent_class)->finalize(obj); } /* * This function is actually NEVER called. * It is 'extern' just to avoid the compilation warnings * TODO: add class cleanup */ extern void xkl_config_registry_class_term(XklConfigRegistryClass * klass) { gint i; if (models_xpath != NULL) { xmlXPathFreeCompExpr(models_xpath); models_xpath = NULL; } if (layouts_xpath != NULL) { xmlXPathFreeCompExpr(layouts_xpath); layouts_xpath = NULL; } if (option_groups_xpath != NULL) { xmlXPathFreeCompExpr(option_groups_xpath); option_groups_xpath = NULL; } if (xml_encode_regexen != NULL) { for (i = sizeof(xml_encode_regexen_str) / sizeof(xml_encode_regexen_str[0]); --i >= 0;) { g_regex_unref(xml_encode_regexen[i]); } g_free(xml_encode_regexen); xml_encode_regexen = NULL; } if (xml_decode_regexen != NULL) { for (i = sizeof(xml_decode_regexen_str) / sizeof(xml_decode_regexen_str[0]); --i >= 0;) { g_regex_unref(xml_decode_regexen[i]); } g_free(xml_decode_regexen); xml_decode_regexen = NULL; } } static void xkl_config_registry_class_init(XklConfigRegistryClass * klass) { GObjectClass *object_class; GParamSpec *engine_param_spec; gint i; object_class = (GObjectClass *) klass; parent_class = g_type_class_peek_parent(object_class); object_class->constructor = xkl_config_registry_constructor; object_class->finalize = xkl_config_registry_finalize; object_class->set_property = xkl_config_registry_set_property; object_class->get_property = xkl_config_registry_get_property; bind_textdomain_codeset(XKB_DOMAIN, "UTF-8"); engine_param_spec = g_param_spec_object("engine", "Engine", "XklEngine", XKL_TYPE_ENGINE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); g_object_class_install_property(object_class, PROP_ENGINE, engine_param_spec); /* static stuff initialized */ xmlXPathInit(); models_xpath = xmlXPathCompile((unsigned char *) XKBCR_MODEL_PATH); layouts_xpath = xmlXPathCompile((unsigned char *) XKBCR_LAYOUT_PATH); option_groups_xpath = xmlXPathCompile((unsigned char *) XKBCR_GROUP_PATH); xml_encode_regexen = g_new0(GRegex *, sizeof(xml_encode_regexen_str) / sizeof(xml_encode_regexen_str[0])); xml_decode_regexen = g_new0(GRegex *, sizeof(xml_decode_regexen_str) / sizeof(xml_decode_regexen_str[0])); for (i = sizeof(xml_encode_regexen_str) / sizeof(xml_encode_regexen_str[0]); --i >= 0;) { xml_encode_regexen[i] = g_regex_new(xml_encode_regexen_str[i], 0, 0, NULL); xml_decode_regexen[i] = g_regex_new(xml_decode_regexen_str[i], 0, 0, NULL); } } libxklavier-5.4/libxklavier/xklavier_config_iso.c000066400000000000000000000310011213561201300223670ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "config.h" #include "xklavier_private.h" #define ISO_CODES_DATADIR ISO_CODES_PREFIX "/share/xml/iso-codes" #define ISO_CODES_LOCALESDIR ISO_CODES_PREFIX "/share/locale" static GHashTable *country_code_names = NULL; static GHashTable *lang_code_names = NULL; typedef struct { const gchar *domain; const gchar **attr_names; } LookupParams; typedef struct { GHashTable *code_names; const gchar *tag_name; LookupParams *params; } CodeBuildStruct; static const char *countryLookupNames[] = { "alpha_2_code", NULL }; static const char *languageLookupNames[] = { "iso_639_2B_code", "iso_639_2T_code", NULL }; static LookupParams countryLookup = { "iso_3166", countryLookupNames }; static LookupParams languageLookup = { "iso_639", languageLookupNames }; static void iso_codes_parse_start_tag(GMarkupParseContext * ctx, const gchar * element_name, const gchar ** attr_names, const gchar ** attr_values, gpointer user_data, GError ** error) { const gchar *name; const gchar **san = attr_names, **sav = attr_values; CodeBuildStruct *cbs = (CodeBuildStruct *) user_data; /* Is this the tag we are looking for? */ if (!g_str_equal(element_name, cbs->tag_name) || attr_names == NULL || attr_values == NULL) { return; } name = NULL; /* What would be the value? */ while (*attr_names && *attr_values) { if (g_str_equal(*attr_names, "name")) { name = *attr_values; break; } attr_names++; attr_values++; } if (!name) { return; } attr_names = san; attr_values = sav; /* Walk again the attributes */ while (*attr_names && *attr_values) { const gchar **attr = cbs->params->attr_names; /* Look through all the attributess we are interested in */ while (*attr) { if (g_str_equal(*attr_names, *attr)) { if (**attr_values) { g_hash_table_insert (cbs->code_names, g_strdup(*attr_values), g_strdup(name)); } } attr++; } attr_names++; attr_values++; } } static GHashTable * iso_code_names_init(LookupParams * params) { GError *err = NULL; gchar *buf, *filename, *tag_name; gsize buf_len; CodeBuildStruct cbs; GHashTable *ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); tag_name = g_strdup_printf("%s_entry", params->domain); cbs.code_names = ht; cbs.tag_name = tag_name; cbs.params = params; bindtextdomain(params->domain, ISO_CODES_LOCALESDIR); bind_textdomain_codeset(params->domain, "UTF-8"); filename = g_strdup_printf("%s/%s.xml", ISO_CODES_DATADIR, params->domain); if (g_file_get_contents(filename, &buf, &buf_len, &err)) { GMarkupParseContext *ctx; GMarkupParser parser = { iso_codes_parse_start_tag, NULL, NULL, NULL, NULL }; ctx = g_markup_parse_context_new(&parser, 0, &cbs, NULL); if (!g_markup_parse_context_parse(ctx, buf, buf_len, &err)) { g_warning("Failed to parse '%s/%s.xml': %s", ISO_CODES_DATADIR, params->domain, err->message); g_error_free(err); } g_markup_parse_context_free(ctx); g_free(buf); } else { g_warning("Failed to load '%s/%s.xml': %s", ISO_CODES_DATADIR, params->domain, err->message); g_error_free(err); } g_free(filename); g_free(tag_name); return ht; } typedef const gchar *(*DescriptionGetterFunc) (const gchar * code); const gchar * xkl_get_language_name(const gchar * code) { const gchar *name; if (!lang_code_names) { lang_code_names = iso_code_names_init(&languageLookup); } name = g_hash_table_lookup(lang_code_names, code); if (!name) { return NULL; } return dgettext("iso_639", name); } const gchar * xkl_get_country_name(const gchar * code) { const gchar *name; if (!country_code_names) { country_code_names = iso_code_names_init(&countryLookup); } name = g_hash_table_lookup(country_code_names, code); if (!name) { return NULL; } return dgettext("iso_3166", name); } static void xkl_config_registry_foreach_iso_code(XklConfigRegistry * config, XklConfigItemProcessFunc func, const gchar * xpath_exprs[], DescriptionGetterFunc dgf, gboolean to_upper, gpointer data) { GHashTable *code_pairs; GHashTableIter iter; xmlXPathObjectPtr xpath_obj; const gchar **xpath_expr; gpointer key, value; XklConfigItem *ci; gint di; if (!xkl_config_registry_is_initialized(config)) return; code_pairs = g_hash_table_new(g_str_hash, g_str_equal); for (xpath_expr = xpath_exprs; *xpath_expr; xpath_expr++) { for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { gint ni; xmlNodePtr *node; xmlNodeSetPtr nodes; xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathEval((unsigned char *) *xpath_expr, xmlctxt); if (xpath_obj == NULL) continue; nodes = xpath_obj->nodesetval; if (nodes == NULL) { xmlXPathFreeObject(xpath_obj); continue; } node = nodes->nodeTab; for (ni = nodes->nodeNr; --ni >= 0;) { gchar *iso_code = (gchar *) (*node)->children->content; const gchar *description; iso_code = to_upper ? g_ascii_strup(iso_code, -1) : g_strdup(iso_code); description = dgf(iso_code); /* If there is a mapping to some ISO description - consider it as ISO code (well, it is just an assumption) */ if (description) g_hash_table_insert (code_pairs, g_strdup (iso_code), g_strdup(description)); g_free(iso_code); node++; } xmlXPathFreeObject(xpath_obj); } } g_hash_table_iter_init(&iter, code_pairs); ci = xkl_config_item_new(); while (g_hash_table_iter_next(&iter, &key, &value)) { g_strlcpy(ci->name, (const gchar *) key, sizeof(ci->name)); g_strlcpy(ci->description, (const gchar *) value, sizeof(ci->description)); func(config, ci, data); } g_object_unref(G_OBJECT(ci)); g_hash_table_unref(code_pairs); } void xkl_config_registry_foreach_country(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data) { const gchar *xpath_exprs[] = { XKBCR_LAYOUT_PATH "/configItem/countryList/iso3166Id", XKBCR_LAYOUT_PATH "/configItem/name", NULL }; xkl_config_registry_foreach_iso_code(config, func, xpath_exprs, xkl_get_country_name, TRUE, data); } void xkl_config_registry_foreach_language(XklConfigRegistry * config, XklConfigItemProcessFunc func, gpointer data) { const gchar *xpath_exprs[] = { XKBCR_LAYOUT_PATH "/configItem/languageList/iso639Id", XKBCR_VARIANT_PATH "/configItem/languageList/iso639Id", NULL }; xkl_config_registry_foreach_iso_code(config, func, xpath_exprs, xkl_get_language_name, FALSE, data); } void xkl_config_registry_foreach_iso_variant(XklConfigRegistry * config, const gchar * iso_code, XklTwoConfigItemsProcessFunc func, gpointer data, const gchar * layout_xpath_exprs[], const gboolean should_code_be_lowered1[], const gchar * variant_xpath_exprs[], const gboolean should_code_be_lowered2[]) { xmlXPathObjectPtr xpath_obj; xmlNodeSetPtr nodes; const gchar **xpath_expr; const gboolean *is_low_id = should_code_be_lowered1; gchar *low_iso_code; if (!xkl_config_registry_is_initialized(config)) return; low_iso_code = g_ascii_strdown(iso_code, -1); for (xpath_expr = layout_xpath_exprs; *xpath_expr; xpath_expr++, is_low_id++) { const gchar *aic = *is_low_id ? low_iso_code : iso_code; gchar *xpe = g_strdup_printf(*xpath_expr, aic); gint di; GSList *processed_ids = NULL; for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathEval((unsigned char *) xpe, xmlctxt); if (xpath_obj == NULL) continue; nodes = xpath_obj->nodesetval; if (nodes != NULL) { gint ni; xmlNodePtr *node = nodes->nodeTab; XklConfigItem *ci = xkl_config_item_new(); for (ni = nodes->nodeNr; --ni >= 0;) { if (xkl_read_config_item (config, di, *node, ci)) { if (g_slist_find_custom (processed_ids, ci->name, (GCompareFunc) g_ascii_strcasecmp) == NULL) { func(config, ci, NULL, data); processed_ids = g_slist_append (processed_ids, g_strdup (ci->name)); } } node++; } g_object_unref(G_OBJECT(ci)); } xmlXPathFreeObject(xpath_obj); } g_free(xpe); } is_low_id = should_code_be_lowered2; for (xpath_expr = variant_xpath_exprs; *xpath_expr; xpath_expr++, is_low_id++) { const gchar *aic = *is_low_id ? low_iso_code : iso_code; gchar *xpe = g_strdup_printf(*xpath_expr, aic); gint di; for (di = 0; di < XKL_NUMBER_OF_REGISTRY_DOCS; di++) { xmlXPathContextPtr xmlctxt = xkl_config_registry_priv(config, xpath_contexts[di]); if (xmlctxt == NULL) continue; xpath_obj = xmlXPathEval((unsigned char *) xpe, xmlctxt); if (xpath_obj == NULL) continue; nodes = xpath_obj->nodesetval; if (nodes != NULL) { gint ni; xmlNodePtr *node = nodes->nodeTab; XklConfigItem *ci = xkl_config_item_new(); XklConfigItem *pci = xkl_config_item_new(); for (ni = nodes->nodeNr; --ni >= 0;) { if (xkl_read_config_item (config, di, *node, ci) && xkl_read_config_item (config, di, (*node)->parent->parent, pci)) func(config, pci, ci, data); node++; } g_object_unref(G_OBJECT(pci)); g_object_unref(G_OBJECT(ci)); } xmlXPathFreeObject(xpath_obj); } g_free(xpe); } g_free(low_iso_code); } void xkl_config_registry_foreach_country_variant(XklConfigRegistry * config, const gchar * country_code, XklTwoConfigItemsProcessFunc func, gpointer data) { const gchar *layout_xpath_exprs[] = { XKBCR_LAYOUT_PATH "[configItem/name = '%s']", XKBCR_LAYOUT_PATH "[configItem/countryList/iso3166Id = '%s']", NULL }; const gboolean should_code_be_lowered1[] = { TRUE, FALSE }; const gchar *variant_xpath_exprs[] = { XKBCR_VARIANT_PATH "[configItem/countryList/iso3166Id = '%s']", XKBCR_VARIANT_PATH "[../../configItem/name = '%s' and not(configItem/countryList/iso3166Id)]", XKBCR_VARIANT_PATH "[../../configItem/countryList/iso3166Id = '%s' and not(configItem/countryList/iso3166Id)]", NULL }; const gboolean should_code_be_lowered2[] = { FALSE, TRUE, FALSE }; xkl_config_registry_foreach_iso_variant(config, country_code, func, data, layout_xpath_exprs, should_code_be_lowered1, variant_xpath_exprs, should_code_be_lowered2); } void xkl_config_registry_foreach_language_variant(XklConfigRegistry * config, const gchar * language_code, XklTwoConfigItemsProcessFunc func, gpointer data) { const gchar *layout_xpath_exprs[] = { XKBCR_LAYOUT_PATH "[configItem/languageList/iso639Id = '%s']", NULL }; const gboolean should_code_be_lowered1[] = { FALSE }; const gchar *variant_xpath_exprs[] = { XKBCR_VARIANT_PATH "[configItem/languageList/iso639Id = '%s']", XKBCR_VARIANT_PATH "[../../configItem/languageList/iso639Id = '%s' and not(configItem/languageList/iso639Id)]", NULL }; const gboolean should_code_be_lowered2[] = { FALSE, FALSE }; xkl_config_registry_foreach_iso_variant(config, language_code, func, data, layout_xpath_exprs, should_code_be_lowered1, variant_xpath_exprs, should_code_be_lowered2); } libxklavier-5.4/libxklavier/xklavier_config_xkb.c000066400000000000000000000362611213561201300223760ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #include #include "config.h" #include "xklavier_private.h" #include "xklavier_private_xkb.h" #ifdef LIBXKBFILE_PRESENT #include #include #endif #define XKBCOMP ( XKB_BIN_BASE "/xkbcomp" ) #define XK_XKB_KEYS #include #ifdef LIBXKBFILE_PRESENT static XkbRF_RulesPtr xkl_rules; static XkbRF_RulesPtr xkl_rules_set_load(XklEngine * engine) { XkbRF_RulesPtr rules_set = NULL; char file_name[MAXPATHLEN] = ""; char *rf = xkl_engine_get_ruleset_name(engine, XKB_DEFAULT_RULESET); char *locale = NULL; if (rf == NULL) { xkl_last_error_message = "Could not find the XKB rules set"; return NULL; } locale = setlocale(LC_ALL, NULL); g_snprintf(file_name, sizeof file_name, XKB_BASE "/rules/%s", rf); xkl_debug(160, "Loading rules from [%s]\n", file_name); rules_set = XkbRF_Load(file_name, locale, True, True); if (rules_set == NULL) { xkl_last_error_message = "Could not load rules"; return NULL; } return rules_set; } static void xkl_rules_set_free(void) { if (xkl_rules) XkbRF_Free(xkl_rules, True); xkl_rules = NULL; } #endif void xkl_xkb_init_config_registry(XklConfigRegistry * config) { #ifdef LIBXKBFILE_PRESENT XkbInitAtoms(NULL); #endif } gboolean xkl_xkb_load_config_registry(XklConfigRegistry * config, gboolean if_extras_needed) { return xkl_config_registry_load_helper(config, XKB_DEFAULT_RULESET, XKB_BASE "/rules", if_extras_needed); } #ifdef LIBXKBFILE_PRESENT gboolean xkl_xkb_config_native_prepare(XklEngine * engine, const XklConfigRec * data, XkbComponentNamesPtr component_names_ptr) { XkbRF_VarDefsRec xkl_var_defs; gboolean got_components; memset(&xkl_var_defs, 0, sizeof(xkl_var_defs)); xkl_rules = xkl_rules_set_load(engine); if (!xkl_rules) { return FALSE; } xkl_var_defs.model = (char *) data->model; if (data->layouts != NULL) xkl_var_defs.layout = xkl_config_rec_merge_layouts(data); if (data->variants != NULL) xkl_var_defs.variant = xkl_config_rec_merge_variants(data); if (data->options != NULL) xkl_var_defs.options = xkl_config_rec_merge_options(data); got_components = XkbRF_GetComponents(xkl_rules, &xkl_var_defs, component_names_ptr); g_free(xkl_var_defs.layout); g_free(xkl_var_defs.variant); g_free(xkl_var_defs.options); if (!got_components) { xkl_last_error_message = "Could not translate rules into components"; /* Just cleanup the stuff in case of failure */ xkl_xkb_config_native_cleanup(engine, component_names_ptr); return FALSE; } if (xkl_debug_level >= 200) { xkl_debug(200, "keymap: %s\n", component_names_ptr->keymap); xkl_debug(200, "keycodes: %s\n", component_names_ptr->keycodes); xkl_debug(200, "compat: %s\n", component_names_ptr->compat); xkl_debug(200, "types: %s\n", component_names_ptr->types); xkl_debug(200, "symbols: %s\n", component_names_ptr->symbols); xkl_debug(200, "geometry: %s\n", component_names_ptr->geometry); } return TRUE; } void xkl_xkb_config_native_cleanup(XklEngine * engine, XkbComponentNamesPtr component_names_ptr) { xkl_rules_set_free(); g_free(component_names_ptr->keymap); g_free(component_names_ptr->keycodes); g_free(component_names_ptr->compat); g_free(component_names_ptr->types); g_free(component_names_ptr->symbols); g_free(component_names_ptr->geometry); } static gchar * xkl_config_get_current_group_description(XklEngine * engine) { XklState state; xkl_xkb_get_server_state(engine, &state); int group = state.group; if ((group < 0) || (group >= xkl_engine_backend(engine, XklXkb, cached_desc)->ctrls->num_groups)) return NULL; return g_strdup(xkl_engine_backend(engine, XklXkb, group_names) [group]); } static void xkl_config_set_group_by_description(XklEngine * engine, gchar * descr) { int group, n_groups; gchar **group_names; if (descr == NULL) return; // perhaps could be made mode lightweight? xkl_engine_reset_all_info(engine, FALSE, "Direct reload on activation"); n_groups = xkl_engine_backend(engine, XklXkb, cached_desc)->ctrls->num_groups; group_names = xkl_engine_backend(engine, XklXkb, group_names); for (group = 0; group < n_groups; group++, group_names++) { if (!g_ascii_strcasecmp(descr, *group_names)) { xkl_debug(150, "Found the group with the same description, %d: [%s]\n", group, *group_names); xkl_engine_lock_group(engine, group); break; } } g_free(descr); } static XkbDescPtr xkl_config_get_keyboard(XklEngine * engine, XkbComponentNamesPtr component_names_ptr, gboolean activate) { XkbDescPtr xkb = NULL; char xkm_fn[L_tmpnam]; char xkb_fn[L_tmpnam]; FILE *tmpxkm; XkbFileInfo result; int xkmloadres; Display *display = xkl_engine_get_display(engine); gchar *preactivation_group_description = activate ? xkl_config_get_current_group_description(engine) : NULL; if (tmpnam(xkm_fn) != NULL && tmpnam(xkb_fn) != NULL) { pid_t cpid, pid; int status = 0; FILE *tmpxkb; xkl_debug(150, "tmp XKB/XKM file names: [%s]/[%s]\n", xkb_fn, xkm_fn); if ((tmpxkb = fopen(xkb_fn, "w")) != NULL) { fprintf(tmpxkb, "xkb_keymap {\n"); fprintf(tmpxkb, " xkb_keycodes { include \"%s\" };\n", component_names_ptr->keycodes); fprintf(tmpxkb, " xkb_types { include \"%s\" };\n", component_names_ptr->types); fprintf(tmpxkb, " xkb_compat { include \"%s\" };\n", component_names_ptr->compat); fprintf(tmpxkb, " xkb_symbols { include \"%s\" };\n", component_names_ptr->symbols); fprintf(tmpxkb, " xkb_geometry { include \"%s\" };\n", component_names_ptr->geometry); fprintf(tmpxkb, "};\n"); fclose(tmpxkb); xkl_debug(150, "xkb_keymap {\n" " xkb_keycodes { include \"%s\" };\n" " xkb_types { include \"%s\" };\n" " xkb_compat { include \"%s\" };\n" " xkb_symbols { include \"%s\" };\n" " xkb_geometry { include \"%s\" };\n};\n", component_names_ptr->keycodes, component_names_ptr->types, component_names_ptr->compat, component_names_ptr->symbols, component_names_ptr->geometry); XSync(display, False); /* From this point, ALL errors should be intercepted only by libxklavier */ xkl_engine_priv(engine, critical_section) = TRUE; cpid = fork(); switch (cpid) { case -1: xkl_debug(0, "Could not fork: %d\n", errno); break; case 0: /* child */ xkl_debug(160, "Executing %s\n", XKBCOMP); xkl_debug(160, "%s %s %s %s %s %s %s %s\n", XKBCOMP, XKBCOMP, "-w0", "-I", "-I" XKB_BASE, "-xkm", xkb_fn, xkm_fn); execl(XKBCOMP, XKBCOMP, "-w0", "-I", "-I" XKB_BASE, "-xkm", xkb_fn, xkm_fn, NULL); xkl_debug(0, "Could not exec %s: %d\n", XKBCOMP, errno); exit(1); default: /* parent */ pid = waitpid(cpid, &status, 0); xkl_debug(150, "Return status of %d (well, started %d): %d\n", pid, cpid, status); memset((char *) &result, 0, sizeof(result)); result.xkb = XkbAllocKeyboard(); if (Success == XkbChangeKbdDisplay(display, &result)) { xkl_debug(150, "Hacked the kbddesc - set the display...\n"); if ((tmpxkm = fopen(xkm_fn, "r")) != NULL) { xkmloadres = XkmReadFile(tmpxkm, XkmKeymapLegal, XkmKeymapLegal, &result); xkl_debug(150, "Loaded %s output as XKM file, got %d (comparing to %d)\n", XKBCOMP, (int) xkmloadres, (int) XkmKeymapLegal); if ((int) xkmloadres != (int) XkmKeymapLegal) { xkl_debug(150, "Loaded legal keymap\n"); if (activate) { xkl_debug (150, "Activating it...\n"); if (XkbWriteToServer(&result)) { xkl_debug (150, "Updating the keyboard...\n"); xkb = result.xkb; } else { xkl_debug (0, "Could not write keyboard description to the server\n"); } } else /* no activate, just load */ xkb = result.xkb; } else { /* could not load properly */ xkl_debug(0, "Could not load %s output as XKM file, got %d (asked %d)\n", XKBCOMP, (int) xkmloadres, (int) XkmKeymapLegal); } fclose(tmpxkm); xkl_debug(160, "Unlinking the temporary xkm file %s\n", xkm_fn); if (xkl_debug_level < 500) { /* don't remove on high debug levels! */ if (remove(xkm_fn) == -1) xkl_debug (0, "Could not unlink the temporary xkm file %s: %d\n", xkm_fn, errno); } else xkl_debug(500, "Well, not really - the debug level is too high: %d\n", xkl_debug_level); } else { /* could not open the file */ xkl_debug(0, "Could not open the temporary xkm file %s\n", xkm_fn); } } else { /* could not assign to display */ xkl_debug(0, "Could not change the keyboard description to display\n"); } if (xkb == NULL) XkbFreeKeyboard(result.xkb, XkbAllComponentsMask, True); break; } XSync(display, False); /* Return to normal X error processing */ xkl_engine_priv(engine, critical_section) = FALSE; if (activate) xkl_config_set_group_by_description(engine, preactivation_group_description); xkl_debug(160, "Unlinking the temporary xkb file %s\n", xkb_fn); if (xkl_debug_level < 500) { /* don't remove on high debug levels! */ if (remove(xkb_fn) == -1) xkl_debug(0, "Could not unlink the temporary xkb file %s: %d\n", xkb_fn, errno); } else xkl_debug(500, "Well, not really - the debug level is too high: %d\n", xkl_debug_level); } else { /* could not open input tmp file */ xkl_debug(0, "Could not open tmp XKB file [%s]: %d\n", xkb_fn, errno); } } else { xkl_debug(0, "Could not get tmp names\n"); } return xkb; } #else /* no XKB headers */ gboolean xkl_xkb_config_native_prepare(XklEngine * engine, const XklConfigRec * data, gpointer componentNamesPtr) { return FALSE; } void xkl_xkb_config_native_cleanup(XklEngine * engine, gpointer component_names_ptr) { } #endif /* check only client side support */ gboolean xkl_xkb_multiple_layouts_supported(XklEngine * engine) { enum { NON_SUPPORTED, SUPPORTED, UNCHECKED }; static int support_state = UNCHECKED; if (support_state == UNCHECKED) { XklConfigRec *data = xkl_config_rec_new(); #ifdef LIBXKBFILE_PRESENT XkbComponentNamesRec component_names; memset(&component_names, 0, sizeof(component_names)); #endif data->model = g_strdup("pc105"); data->layouts = g_strsplit_set("us:de", ":", -1); data->variants = g_strsplit_set(":", ":", -1); data->options = NULL; xkl_debug(100, "!!! Checking multiple layouts support\n"); support_state = NON_SUPPORTED; #ifdef LIBXKBFILE_PRESENT if (xkl_xkb_config_native_prepare (engine, data, &component_names)) { xkl_debug(100, "!!! Multiple layouts ARE supported\n"); support_state = SUPPORTED; xkl_xkb_config_native_cleanup(engine, &component_names); } else { xkl_debug(100, "!!! Multiple layouts ARE NOT supported\n"); } #endif g_object_unref(G_OBJECT(data)); } return support_state == SUPPORTED; } gboolean xkl_xkb_activate_config_rec(XklEngine * engine, const XklConfigRec * data) { gboolean rv = FALSE; #if 0 { int i; xkl_debug(150, "New model: [%s]\n", data->model); xkl_debug(150, "New layouts: %p\n", data->layouts); for (i = 0; i < g_strv_length(data->layouts); i++) xkl_debug(150, "New layout[%d]: [%s]\n", i, data->layouts[i]); xkl_debug(150, "New variants: %p\n", data->variants); for (i = 0; i < g_strv_length(data->variants); i++) xkl_debug(150, "New variant[%d]: [%s]\n", i, data->variants[i]); xkl_debug(150, "New options: %p\n", data->options); for (i = 0; i < g_strv_length(data->options); i++) xkl_debug(150, "New option[%d]: [%s]\n", i, data->options[i]); } #endif #ifdef LIBXKBFILE_PRESENT XkbComponentNamesRec component_names; memset(&component_names, 0, sizeof(component_names)); if (xkl_xkb_config_native_prepare(engine, data, &component_names)) { XkbDescPtr xkb; xkb = xkl_config_get_keyboard(engine, &component_names, TRUE); if (xkb != NULL) { if (xkl_config_rec_set_to_root_window_property (data, xkl_engine_priv(engine, base_config_atom), xkl_engine_get_ruleset_name(engine, XKB_DEFAULT_RULESET), engine)) /* We do not need to check the result of _XklGetRulesSetName - because PrepareBeforeKbd did it for us */ rv = TRUE; else xkl_last_error_message = "Could not set names property"; XkbFreeKeyboard(xkb, XkbAllComponentsMask, True); } else { xkl_last_error_message = "Could not load keyboard description"; } xkl_xkb_config_native_cleanup(engine, &component_names); } #endif return rv; } gboolean xkl_xkb_write_config_rec_to_file(XklEngine * engine, const char *file_name, const XklConfigRec * data, const gboolean binary) { gboolean rv = FALSE; #ifdef LIBXKBFILE_PRESENT XkbComponentNamesRec component_names; FILE *output = fopen(file_name, "w"); XkbFileInfo dump_info; if (output == NULL) { xkl_last_error_message = "Could not open the XKB file"; return FALSE; } memset(&component_names, 0, sizeof(component_names)); if (xkl_xkb_config_native_prepare(engine, data, &component_names)) { XkbDescPtr xkb; xkb = xkl_config_get_keyboard(engine, &component_names, FALSE); if (xkb != NULL) { dump_info.defined = 0; dump_info.xkb = xkb; dump_info.type = XkmKeymapFile; if (binary) rv = XkbWriteXKMFile(output, &dump_info); else rv = XkbWriteXKBFile(output, &dump_info, True, NULL, NULL); XkbFreeKeyboard(xkb, XkbGBN_AllComponentsMask, True); } else xkl_last_error_message = "Could not load keyboard description"; xkl_xkb_config_native_cleanup(engine, &component_names); } fclose(output); #endif return rv; } libxklavier-5.4/libxklavier/xklavier_config_xmm.c000066400000000000000000000034641213561201300224120ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #include #include "config.h" #include "xklavier_private.h" #include "xklavier_private_xmm.h" #define XK_XKB_KEYS #include void xkl_xmm_init_config_registry(XklConfigRegistry * config) { } gboolean xkl_xmm_load_config_registry(XklConfigRegistry * config, gboolean if_extras_needed) { return xkl_config_registry_load_helper(config, XMODMAP_DEFAULT_RULESET, XMODMAP_BASE, if_extras_needed); } gboolean xkl_xmm_activate_config_rec(XklEngine * engine, const XklConfigRec * data) { gboolean rv; rv = xkl_config_rec_set_to_root_window_property(data, xkl_engine_priv (engine, base_config_atom), xkl_engine_backend (engine, XklXmm, current_rules), engine); if (rv) xkl_xmm_lock_group(engine, 0); return rv; } libxklavier-5.4/libxklavier/xklavier_dump.c000066400000000000000000000205601213561201300212250ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" #include "xklavier_private_xkb.h" #ifdef LIBXKBFILE_PRESENT #if 0 static void _XkbModsRecDump(FILE * fs, XkbModsRec * mods) { fprintf(fs, "flags: 0x%X\n", mods->mask); fprintf(fs, "real_mods: 0x%X\n", mods->real_mods); fprintf(fs, "vmods: 0x%X\n", mods->vmods); } static void _XkbControlsDump(FILE * fs, XkbControlsPtr ctrls) { gint i; gchar buf[1024]; fprintf(fs, "mk_dflt_btn: %d\n", ctrls->mk_dflt_btn); fprintf(fs, "num_groups: %d\n", ctrls->num_groups); fprintf(fs, "groups_wrap: %d\n", ctrls->groups_wrap); fprintf(fs, "internal: \n"); _XkbModsRecDump(fs, &ctrls->internal); fprintf(fs, "ignore_lock: \n"); _XkbModsRecDump(fs, &ctrls->ignore_lock); fprintf(fs, "enabled_ctrls: 0x%X\n", ctrls->enabled_ctrls); fprintf(fs, "repeat_delay: %d\n", ctrls->repeat_delay); fprintf(fs, "repeat_interval: %d\n", ctrls->repeat_interval); fprintf(fs, "slow_keys_delay: %d\n", ctrls->slow_keys_delay); fprintf(fs, "debounce_delay: %d\n", ctrls->debounce_delay); fprintf(fs, "mk_delay: %d\n", ctrls->mk_delay); fprintf(fs, "mk_interval: %d\n", ctrls->mk_interval); fprintf(fs, "mk_time_to_max: %d\n", ctrls->mk_time_to_max); fprintf(fs, "mk_max_speed: %d\n", ctrls->mk_max_speed); fprintf(fs, "mk_curve: %d\n", ctrls->mk_curve); fprintf(fs, "ax_options: %d\n", ctrls->ax_options); fprintf(fs, "ax_timeout: %d\n", ctrls->ax_timeout); fprintf(fs, "axt_opts_mask: 0x%X\n", ctrls->axt_opts_mask); fprintf(fs, "axt_opts_values: 0x%X\n", ctrls->axt_opts_values); fprintf(fs, "axt_ctrls_mask: 0x%X\n", ctrls->axt_ctrls_mask); fprintf(fs, "axt_ctrls_values: 0x%X\n", ctrls->axt_ctrls_values); fprintf(fs, "axt_ctrls_values: 0x%X\n", ctrls->axt_ctrls_values); fprintf(fs, "per_key_repeat:\n"); buf[0] = 0; for (i = 0; i < XkbPerKeyBitArraySize; i++) { gchar b[5]; snprintf(b, sizeof(b), "%d ", ctrls->per_key_repeat[i]); strcat(buf, b); } fprintf(fs, " %s\n", buf); } #endif static const gchar *action_type_names[] = { "XkbSA_NoAction", "XkbSA_SetMods", "XkbSA_LatchMods", "XkbSA_LockMods", "XkbSA_SetGroup", "XkbSA_LatchGroup", "XkbSA_LockGroup", "XkbSA_MovePtr", "XkbSA_PtrBtn", "XkbSA_LockPtrBtn", "XkbSA_SetPtrDflt", "XkbSA_ISOLock", "XkbSA_Terminate", "XkbSA_SwitchScreen", "XkbSA_SetControls", "XkbSA_LockControls", "XkbSA_ActionMessage", "XkbSA_RedirectKey", "XkbSA_DeviceBtn", "XkbSA_LockDeviceBtn", "XkbSA_DeviceValuator" }; static void xkb_action_dump(FILE * fs, gint level, XkbAction * act) { XkbGroupAction *ga; fprintf(fs, "%*stype: %d(%s)\n", level, "", act->type, action_type_names[act->type]); switch (act->type) { case XkbSA_SetGroup: case XkbSA_LatchGroup: case XkbSA_LockGroup: ga = (XkbGroupAction *) act; fprintf(fs, "%*sXkbGroupAction: \n", level, ""); fprintf(fs, "%*sflags: %d\n", level, "", ga->flags); fprintf(fs, "%*sgroup_XXX: %d\n", level, "", ga->group_XXX); break; } } static void xkb_behavior_dump(FILE * fs, gint level, XkbBehavior * b) { fprintf(fs, "%*stype: %d\n", level, "", b->type); fprintf(fs, "%*sdata: %d\n", level, "", b->data); } static void xkb_server_map_dump(FILE * fs, gint level, XkbServerMapPtr server, XkbDescPtr kbd) { gint i; XkbAction *pa = server->acts; XkbBehavior *pb = server->behaviors; fprintf(fs, "%*snum_acts: %d\n", level, "", server->num_acts); fprintf(fs, "%*ssize_acts: %d\n", level, "", server->size_acts); if (server->acts != NULL) { for (i = 0; i < server->num_acts; i++) { fprintf(fs, "%*sacts[%d]:\n", level, "", i); xkb_action_dump(fs, level + 2, pa++); } } else fprintf(fs, "%*sNO acts\n", level, ""); if (server->key_acts != NULL) { for (i = 0; i <= kbd->max_key_code; i++) { fprintf(fs, "%*skey_acts[%d]: offset %d, total %d\n", level, "", i, server->key_acts[i], XkbKeyNumSyms(kbd, i)); } } else fprintf(fs, "%*sNO key_acts\n", level, ""); for (i = 0; i < XkbNumVirtualMods; i++) { fprintf(fs, "%*svmod[%d]: %X\n", level, "", i, server->vmods[i]); } if (server->behaviors != NULL) { for (i = 0; i <= kbd->max_key_code; i++) { fprintf(fs, "%*sbehaviors[%d]:\n", level, "", i); xkb_behavior_dump(fs, level + 2, pb++); } } else fprintf(fs, "%*sNO behaviors\n", level, ""); if (server->explicit != NULL) { for (i = 0; i <= kbd->max_key_code; i++) { fprintf(fs, "%*sexplicit[%d]: %d\n", level, "", i, server->explicit[i]); } } else fprintf(fs, "%*sNO explicit\n", level, ""); if (server->vmodmap != NULL) { for (i = 0; i <= kbd->max_key_code; i++) { fprintf(fs, "%*svmodmap[%d]: %d\n", level, "", i, server->vmodmap[i]); } } else fprintf(fs, "%*sNO vmodmap\n", level, ""); } static void xkb_key_type_dump(FILE * fs, gint level, XkbKeyTypePtr type, XklEngine * engine) { gchar *z = type->name == None ? NULL : XGetAtomName(xkl_engine_get_display(engine), type->name); fprintf(fs, "%*sname: 0x%X(%s)\n", level, "", (gint) type->name, z); if (z != NULL) XFree(z); } static void xkb_sym_map_dump(FILE * fs, gint level, XkbSymMapPtr ksm) { gint i; fprintf(fs, "%*skt_index: ", level, ""); for (i = 0; i < XkbNumKbdGroups; i++) { fprintf(fs, "%d ", ksm->kt_index[i]); } fprintf(fs, "\n%*sgroup_info: %d\n", level, "", ksm->group_info); fprintf(fs, "%*swidth: %d\n", level, "", ksm->width); fprintf(fs, "%*soffset: %d\n", level, "", ksm->offset); } static void xkb_client_map_dump(FILE * fs, gint level, XkbClientMapPtr map, XkbDescPtr kbd, XklEngine * engine) { gint i; fprintf(fs, "%*ssize_types: %d\n", level, "", map->size_types); fprintf(fs, "%*snum_types: %d\n", level, "", map->num_types); if (map->types != NULL) { XkbKeyTypePtr type = map->types; for (i = 0; i < map->num_types; i++) { fprintf(fs, "%*stypes[%d]:\n", level, "", i); xkb_key_type_dump(fs, level + 2, type++, engine); } } else fprintf(fs, "%*sNO types\n", level, ""); fprintf(fs, "%*ssize_syms: %d\n", level, "", map->size_syms); fprintf(fs, "%*snum_syms: %d\n", level, "", map->num_syms); if (map->syms != NULL) { for (i = 0; i < map->num_syms; i++) fprintf(fs, "%*ssyms[%d]:0x%lX(%s)\n", level, "", i, map->syms[i], XKeysymToString(map->syms[i])); } else fprintf(fs, "%*sNO syms\n", level, ""); if (map->key_sym_map != NULL) { XkbSymMapPtr ksm = map->key_sym_map; for (i = 0; i <= kbd->max_key_code; i++) { fprintf(fs, "%*skey_sym_map[%d]:\n", level, "", i); xkb_sym_map_dump(fs, level + 2, ksm++); } } else fprintf(fs, "%*sNO key_sym_map\n", level, ""); } static void xkb_desc_dump(FILE * fs, gint level, XkbDescPtr kbd, XklEngine * engine) { fprintf(fs, "%*sflags: 0x%X\n", level, "", kbd->flags); fprintf(fs, "%*sdevice_spec: %d\n", level, "", kbd->device_spec); fprintf(fs, "%*smin_key_code: %d\n", level, "", kbd->min_key_code); fprintf(fs, "%*smax_key_code: %d\n", level, "", kbd->max_key_code); #if 0 if (kbd->ctrls != NULL) { fprintf(fs, "ctrls:\n"); _XkbControlsDump(fs, kbd->ctrls); } else fprintf(fs, "NO server\n"); #endif if (kbd->server != NULL) { fprintf(fs, "%*sserver:\n", level, ""); xkb_server_map_dump(fs, level + 2, kbd->server, kbd); } else fprintf(fs, "%*sNO server\n", level, ""); if (kbd->map != NULL) { fprintf(fs, "%*smap:\n", level, ""); xkb_client_map_dump(fs, level + 2, kbd->map, kbd, engine); } else fprintf(fs, "%*sNO map\n", level, ""); fprintf(fs, "XKB libraries not present\n"); } void xkl_engine_dump_xkb_desc(XklEngine * engine, const gchar * file_name, XkbDescPtr kbd) { FILE *fs = fopen(file_name, "w+"); if (fs != NULL) { xkb_desc_dump(fs, 0, kbd == NULL ? xkl_engine_backend(engine, XklXkb, cached_desc) : kbd, engine); fclose(fs); } } #endif libxklavier-5.4/libxklavier/xklavier_evt.c000066400000000000000000000470051213561201300210610ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" gint xkl_engine_filter_events(XklEngine * engine, XEvent * xev) { XAnyEvent *pe = (XAnyEvent *) xev; xkl_debug(400, "**> Filtering event %d of type %d from window %d\n", pe->serial, pe->type, pe->window); xkl_engine_ensure_vtable_inited(engine); if (!xkl_engine_vcall(engine, process_x_event) (engine, xev)) switch (xev->type) { /* core events */ case FocusIn: xkl_engine_process_focus_in_evt(engine, &xev->xfocus); break; case FocusOut: xkl_engine_process_focus_out_evt(engine, &xev->xfocus); break; case PropertyNotify: xkl_engine_process_property_evt(engine, &xev->xproperty); break; case CreateNotify: xkl_engine_process_create_window_evt(engine, &xev->xcreatewindow); break; case DestroyNotify: xkl_debug(150, "Window " WINID_FORMAT " destroyed\n", xev->xdestroywindow.window); break; case UnmapNotify: xkl_debug(200, "Window " WINID_FORMAT " unmapped\n", xev->xunmap.window); break; case MapNotify: case GravityNotify: xkl_debug(200, "%s\n", xkl_event_get_name(xev->type)); break; /* Ignore these events */ case ReparentNotify: xkl_debug(200, "Window " WINID_FORMAT " reparented to " WINID_FORMAT "\n", xev->xreparent.window, xev->xreparent.parent); break; /* Ignore these events */ case MappingNotify: xkl_debug(200, "%s\n", xkl_event_get_name(xev->type)); xkl_engine_reset_all_info(engine, FALSE, "X event: MappingNotify"); break; default: { xkl_debug(200, "Unknown event %d [%s]\n", xev->type, xkl_event_get_name(xev->type)); return 1; } } xkl_debug(400, "Filtered event %d of type %d from window %d **>\n", pe->serial, pe->type, pe->window); return 1; } /* * FocusIn handler */ void xkl_engine_process_focus_in_evt(XklEngine * engine, XFocusChangeEvent * fev) { Window win; Window prev_toplevel_win = xkl_engine_priv(engine, curr_toplvl_win); Window toplevel_win; XklState selected_window_state; if (! (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES))) return; win = fev->window; switch (fev->mode) { case NotifyNormal: case NotifyWhileGrabbed: break; default: xkl_debug(160, "Window " WINID_FORMAT " has got focus during special action %d\n", win, fev->mode); return; } xkl_debug(150, "Window " WINID_FORMAT ", '%s' has got focus\n", win, xkl_get_debug_window_title(engine, win)); if (!xkl_engine_find_toplevel_window(engine, win, &toplevel_win)) { return; } xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' has got focus\n", toplevel_win, xkl_get_debug_window_title(engine, toplevel_win)); if (xkl_engine_get_toplevel_window_state (engine, toplevel_win, &selected_window_state)) { if (prev_toplevel_win != toplevel_win) { gboolean new_win_transparent; Window parent = (Window) NULL, root = (Window) NULL, *children = NULL; guint nchildren = 0; /* * If previous focused window exists - handle transparency and state * (optional) */ if (xkl_engine_query_tree (engine, prev_toplevel_win, &root, &parent, &children, &nchildren) == Success) { XklState tmp_state; gboolean old_win_transparent = xkl_engine_is_toplevel_window_transparent (engine, prev_toplevel_win); if (children != NULL) XFree(children); if (old_win_transparent) xkl_debug(150, "Leaving transparent window\n"); /* * Reload the current state from the current window. * Do not do it for transparent window - we keep the state from * the _previous_ window. */ if (!old_win_transparent && xkl_engine_get_toplevel_window_state (engine, prev_toplevel_win, &tmp_state)) { xkl_engine_update_current_state (engine, tmp_state.group, tmp_state.indicators, "Loading current (previous) state from the current (previous) window"); } } else xkl_debug(150, "Current (previous) window " WINID_FORMAT " does not exist any more, so transparency/state are not analyzed\n", prev_toplevel_win); xkl_engine_priv(engine, curr_toplvl_win) = toplevel_win; xkl_debug(150, "CurClient:changed to " WINID_FORMAT ", '%s'\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win))); new_win_transparent = xkl_engine_is_toplevel_window_transparent (engine, toplevel_win); if (new_win_transparent) xkl_debug(150, "Entering transparent window\n"); if (xkl_engine_is_group_per_toplevel_window(engine) == !new_win_transparent) { /* We skip restoration only if we return to the same app window */ gboolean do_skip = FALSE; if (xkl_engine_priv (engine, skip_one_restore)) { xkl_engine_priv(engine, skip_one_restore) = FALSE; if (toplevel_win == xkl_engine_priv(engine, prev_toplvl_win)) do_skip = TRUE; } if (do_skip) { xkl_debug(150, "Skipping one restore as requested - instead, " "saving the current group into the window state\n"); xkl_engine_save_toplevel_window_state (engine, toplevel_win, &xkl_engine_priv(engine, curr_state)); } else { if (xkl_engine_priv (engine, curr_state).group != selected_window_state.group) { xkl_debug(150, "Restoring the group from %d to %d after gaining focus\n", xkl_engine_priv (engine, curr_state).group, selected_window_state.group); /* * For fast mouse movements - the state is probably not updated yet * (because of the group change notification being late). * so we'll enforce the update. But this should only happen in GPA mode */ xkl_engine_update_current_state (engine, selected_window_state.group, selected_window_state.indicators, "Enforcing fast update of the current state"); xkl_engine_lock_group (engine, selected_window_state.group); xkl_engine_priv(engine, skip_one_save) = TRUE; } else { xkl_debug(150, "Both old and new focused window " "have group %d so no point restoring it\n", selected_window_state.group); xkl_engine_one_switch_to_secondary_group_performed (engine); } } if ((xkl_engine_priv(engine, features) & XKLF_CAN_TOGGLE_INDICATORS) && xkl_engine_get_indicators_handling (engine)) { xkl_debug(150, "Restoring the indicators from %X to %X after gaining focus\n", xkl_engine_priv(engine, curr_state).indicators, selected_window_state.indicators); xkl_engine_ensure_vtable_inited (engine); xkl_engine_vcall(engine, set_indicators) (engine, &selected_window_state); } else xkl_debug(150, "Not restoring the indicators %X after gaining focus: indicator handling is not enabled\n", xkl_engine_priv(engine, curr_state).indicators); } else xkl_debug(150, "Not restoring the group %d after gaining focus: global layout (xor transparent window)\n", xkl_engine_priv(engine, curr_state).group); } else xkl_debug(150, "Same app window - just do nothing\n"); } else { xkl_debug(150, "But it does not have xklavier_state\n"); if (xkl_engine_if_window_has_wm_state(engine, win)) { xkl_debug(150, "But it does have wm_state so we'll add it\n"); xkl_engine_priv(engine, curr_toplvl_win) = toplevel_win; xkl_debug(150, "CurClient:changed to " WINID_FORMAT ", '%s'\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win))); xkl_engine_add_toplevel_window(engine, xkl_engine_priv (engine, curr_toplvl_win), (Window) NULL, FALSE, &xkl_engine_priv (engine, curr_state)); } else xkl_debug(150, "And it does have wm_state either\n"); } } /* * FocusOut handler */ void xkl_engine_process_focus_out_evt(XklEngine * engine, XFocusChangeEvent * fev) { if (! (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES))) return; if (fev->mode != NotifyNormal) { xkl_debug(200, "Window " WINID_FORMAT " has lost focus during special action %d\n", fev->window, fev->mode); return; } xkl_debug(160, "Window " WINID_FORMAT ", '%s' has lost focus\n", fev->window, xkl_get_debug_window_title(engine, fev->window)); if (xkl_engine_is_toplevel_window_transparent(engine, fev->window)) { xkl_debug(150, "Leaving transparent window!\n"); /* * If we are leaving the transparent window - we skip the restore operation. * This is useful for secondary groups switching from the transparent control * window. */ xkl_engine_priv(engine, skip_one_restore) = TRUE; } else { Window p; if (xkl_engine_find_toplevel_window (engine, fev->window, &p)) xkl_engine_priv(engine, prev_toplvl_win) = p; } } /* * PropertyChange handler * Interested in : * + for XKLL_MANAGE_WINDOW_STATES * - WM_STATE property for all windows * - Configuration property of the root window * + for XKLL_TRACK_KEYBOARD_STATE * - Configuration property of the root window */ void xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * pev) { if (400 <= xkl_debug_level) { char *atom_name = XGetAtomName(xkl_engine_get_display(engine), pev->atom); if (atom_name != NULL) { xkl_debug(400, "The property '%s' changed for " WINID_FORMAT "\n", atom_name, pev->window); XFree(atom_name); } else { xkl_debug(200, "Some magic property changed for " WINID_FORMAT "\n", pev->window); } } if (pev->atom == xkl_engine_priv(engine, atoms)[WM_STATE]) { if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES)) { gboolean has_xkl_state = xkl_engine_get_state(engine, pev->window, NULL); if (pev->state == PropertyNewValue) { xkl_debug(160, "New value of WM_STATE on window " WINID_FORMAT "\n", pev->window); if (!has_xkl_state) { /* Is this event the first or not? */ xkl_engine_add_toplevel_window (engine, pev->window, (Window) NULL, FALSE, &xkl_engine_priv(engine, curr_state)); } } else { /* ev->xproperty.state == PropertyDelete, either client or WM can remove it, ICCCM 4.1.3.1 */ xkl_debug(160, "Something (%d) happened to WM_STATE of window 0x%x\n", pev->state, pev->window); xkl_engine_select_input_merging(engine, pev->window, PropertyChangeMask); if (has_xkl_state) { xkl_engine_delete_state(engine, pev->window); } } } /* XKLL_MANAGE_WINDOW_STATES */ } else if (pev->atom == xkl_engine_priv(engine, base_config_atom) && pev->window == xkl_engine_priv(engine, root_window)) { if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES) | xkl_engine_is_listening_for(engine, XKLL_TRACK_KEYBOARD_STATE)) { if (pev->state == PropertyNewValue) { /* If root window got new *_NAMES_PROP_ATOM - it most probably means new keyboard config is loaded by somebody */ xkl_engine_reset_all_info (engine, TRUE, "New value of *_NAMES_PROP_ATOM on root window"); } } /* XKLL_MANAGE_WINDOW_STATES | XKLL_TRACK_KEYBOARD_STATE */ } } /* * CreateNotify handler. Just interested in properties and focus events... */ void xkl_engine_process_create_window_evt(XklEngine * engine, XCreateWindowEvent * cev) { if (!xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES)) return; xkl_debug(200, "Under-root window " WINID_FORMAT "/%s (%d,%d,%d x %d) is created\n", cev->window, xkl_get_debug_window_title(engine, cev->window), cev->x, cev->y, cev->width, cev->height); if (!cev->override_redirect) { /* ICCCM 4.1.6: override-redirect is NOT private to * client (and must not be changed - am I right?) * We really need only PropertyChangeMask on this window but even in the case of * local server we can lose PropertyNotify events (the trip time for this CreateNotify * event + SelectInput request is not zero) and we definitely will (my system DO) * lose FocusIn/Out events after the following call of PropertyNotifyHandler. * So I just decided to purify this extra FocusChangeMask in the FocusIn/OutHandler. */ xkl_engine_select_input_merging(engine, cev->window, PropertyChangeMask | FocusChangeMask); if (xkl_engine_if_window_has_wm_state(engine, cev->window)) { xkl_debug(200, "Just created window already has WM_STATE - so I'll add it"); xkl_engine_add_toplevel_window(engine, cev->window, (Window) NULL, FALSE, &xkl_engine_priv (engine, curr_state)); } } } /* * Just error handler - sometimes we get BadWindow error for already gone * windows, so we'll just ignore * This handler can be called in the middle of the engine initialization - * so it is not fair to assume that the engine is available */ int xkl_process_error(Display * dpy, XErrorEvent * evt) { char buf[128] = ""; XklEngine *engine = xkl_get_the_engine(); if (engine != NULL) xkl_engine_priv(engine, last_error_code) = evt->error_code; switch (evt->error_code) { case BadAccess: case BadDrawable: case BadWindow: case BadMatch: { XGetErrorText(evt->display, evt->error_code, buf, sizeof(buf)); /* in most cases this means we are late:) */ xkl_debug(200, "ERROR: %p, " WINID_FORMAT ", %d [%s], " "X11 request: %d, minor code: %d\n", dpy, (unsigned long) evt->resourceid, (int) evt->error_code, buf, (int) evt->request_code, (int) evt->minor_code); break; } default: if (engine != NULL && xkl_engine_priv(engine, process_x_error)) { if (xkl_engine_priv(engine, process_x_error) (engine, evt)) { xkl_debug(200, "X ERROR processed by the engine: %p, " WINID_FORMAT ", %d [%s], " "X11 request: %d, minor code: %d\n", dpy, (unsigned long) evt->resourceid, (int) evt->error_code, buf, (int) evt->request_code, (int) evt->minor_code); break; } } xkl_debug(200, "Unexpected by libxklavier X ERROR: %p, " WINID_FORMAT ", %d [%s], " "X11 request: %d, minor code: %d\n", dpy, (unsigned long) evt->resourceid, (int) evt->error_code, buf, (int) evt->request_code, (int) evt->minor_code); if (engine != NULL) if (!xkl_engine_priv(engine, critical_section)) (*xkl_engine_priv (engine, default_error_handler)) (dpy, evt); } /* X ignores this return value anyway */ return 0; } /* * Some common functionality for Xkb handler */ void xkl_engine_process_state_modification(XklEngine * engine, XklEngineStateChange change_type, gint grp, guint inds, gboolean set_inds) { Window focused, focused_toplevel; XklState old_state; gint revert; gboolean have_old_state = TRUE; gboolean set_group = change_type == GROUP_CHANGED; if (xkl_engine_priv(engine, skip_one_save)) { xkl_debug(160, "Skipping one callback"); xkl_engine_priv(engine, skip_one_save) = FALSE; return; } XGetInputFocus(xkl_engine_get_display(engine), &focused, &revert); if ((focused == None) || (focused == PointerRoot)) { xkl_debug(160, "Something with focus: " WINID_FORMAT "\n", focused); return; } /* * Only if we manage states - otherwise xkl_engine_priv(engine,curr_toplvl_win) does not make sense */ if (!xkl_engine_find_toplevel_window (engine, focused, &focused_toplevel) && xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) focused_toplevel = xkl_engine_priv(engine, curr_toplvl_win); /* what else can I do */ xkl_debug(150, "Focused window: " WINID_FORMAT ", '%s'\n", focused_toplevel, xkl_get_debug_window_title(engine, focused_toplevel)); if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) { xkl_debug(150, "CurClient: " WINID_FORMAT ", '%s'\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win))); if (focused_toplevel != xkl_engine_priv(engine, curr_toplvl_win)) { /* * If not state - we got the new window */ if (!xkl_engine_get_toplevel_window_state (engine, focused_toplevel, &old_state)) { xkl_engine_update_current_state(engine, grp, inds, "Updating the state from new focused window"); if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES)) xkl_engine_add_toplevel_window (engine, focused_toplevel, (Window) NULL, FALSE, &xkl_engine_priv(engine, curr_state)); } /* * There is state - just get the state from the window */ else { grp = old_state.group; inds = old_state.indicators; } xkl_engine_priv(engine, curr_toplvl_win) = focused_toplevel; xkl_debug(160, "CurClient:changed to " WINID_FORMAT ", '%s'\n", xkl_engine_priv(engine, curr_toplvl_win), xkl_get_debug_window_title(engine, xkl_engine_priv (engine, curr_toplvl_win))); } /* If the window already has this this state - we are just restoring it! (see the second parameter of stateCallback */ have_old_state = xkl_engine_get_toplevel_window_state(engine, xkl_engine_priv (engine, curr_toplvl_win), &old_state); } else { /* just tracking the stuff, no smart things */ xkl_debug(160, "Just updating the current state in the tracking mode\n"); memcpy(&old_state, &xkl_engine_priv(engine, curr_state), sizeof(XklState)); } if (set_group || have_old_state) { xkl_engine_update_current_state(engine, set_group ? grp : old_state.group, set_inds ? inds : old_state.indicators, "Restoring the state from the window"); } if (have_old_state) xkl_engine_try_call_state_func(engine, change_type, &old_state); if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES)) xkl_engine_save_toplevel_window_state(engine, xkl_engine_priv (engine, curr_toplvl_win), &xkl_engine_priv (engine, curr_state)); } libxklavier-5.4/libxklavier/xklavier_evt_xkb.c000066400000000000000000000122351213561201300217220ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" #include "xklavier_private_xkb.h" #ifdef HAVE_XINPUT #include "config.h" #include "X11/extensions/XInput.h" static gint xkl_xinput_process_x_event(XklEngine * engine, XEvent * xev) { XDevicePresenceNotifyEvent *dpne = (XDevicePresenceNotifyEvent *) xev; xkl_debug(200, "XInput event detected: %d\n", dpne->devchange); if (dpne->devchange == DeviceEnabled) { xkl_debug(150, "Device enabled: %d\n", dpne->deviceid); g_signal_emit_by_name(engine, "X-new-device"); } return 1; } #endif /* * XKB event handler */ gint xkl_xkb_process_x_event(XklEngine * engine, XEvent * xev) { #ifdef LIBXKBFILE_PRESENT gint i; guint bit; guint inds; XkbEvent *kev = (XkbEvent *) xev; if (! (xkl_engine_is_listening_for(engine, XKLL_MANAGE_WINDOW_STATES) | xkl_engine_is_listening_for(engine, XKLL_TRACK_KEYBOARD_STATE))) return 0; #ifdef HAVE_XINPUT /* Special case XInput event */ if (xev->type == xkl_engine_backend(engine, XklXkb, xi_event_type)) return xkl_xinput_process_x_event(engine, xev); #endif if (xev->type != xkl_engine_backend(engine, XklXkb, event_type)) return 0; xkl_debug(150, "Xkb event detected\n"); switch (kev->any.xkb_type) { /* * Group is changed! */ case XkbStateNotify: #define GROUP_CHANGE_MASK \ ( XkbGroupStateMask | XkbGroupBaseMask | XkbGroupLatchMask | XkbGroupLockMask ) xkl_debug(150, "XkbStateNotify detected, changes: %X/(mask %X), new group %d\n", kev->state.changed, GROUP_CHANGE_MASK, kev->state.locked_group); if (kev->state.changed & GROUP_CHANGE_MASK) xkl_engine_process_state_modification(engine, GROUP_CHANGED, kev-> state.locked_group, 0, FALSE); else { /* ...not interested... */ xkl_debug(200, "This type of state notification is not regarding groups\n"); if (kev->state.locked_group != xkl_engine_priv(engine, curr_state).group) xkl_debug(0, "ATTENTION! Currently cached group %d is not equal to the current group from the event: %d\n!", xkl_engine_priv(engine, curr_state).group, kev->state.locked_group); } break; /* * Indicators are changed! */ case XkbIndicatorStateNotify: xkl_debug(150, "XkbIndicatorStateNotify\n"); inds = xkl_engine_priv(engine, curr_state).indicators; ForPhysIndicators(i, bit) if (kev->indicators.changed & bit) { if (kev->indicators.state & bit) inds |= bit; else inds &= ~bit; } xkl_engine_process_state_modification(engine, INDICATORS_CHANGED, 0, inds, TRUE); break; /* * The configuration is changed! */ case XkbIndicatorMapNotify: case XkbControlsNotify: case XkbNamesNotify: #if 0 /* not really fair - but still better than flooding... */ XklDebug(200, "warning: configuration event %s is not actually processed\n", _XklXkbGetXkbEventName(kev->any.xkb_type)); break; #endif case XkbNewKeyboardNotify: xkl_debug(150, "%s\n", xkl_xkb_event_get_name(kev->any.xkb_type)); xkl_engine_reset_all_info(engine, FALSE, "XKB event: XkbNewKeyboardNotify"); break; /* * ...Not interested... */ default: xkl_debug(150, "Unknown XKB event %d [%s]\n", kev->any.xkb_type, xkl_xkb_event_get_name(kev->any.xkb_type)); return 0; } return 1; #else return 0; #endif } /* * XKB error handler */ gint xkl_xkb_process_x_error(XklEngine * engine, XErrorEvent * xerev) { #ifdef HAVE_XINPUT /* Ignore XInput errors */ if (xerev->error_code >= xkl_engine_backend(engine, XklXkb, xi_error_code) && xerev->error_code <= (xkl_engine_backend(engine, XklXkb, xi_error_code) + XI_BadClass)) return 1; #endif return 0; } void xkl_xkb_set_indicators(XklEngine * engine, const XklState * window_state) { #ifdef LIBXKBFILE_PRESENT int i; unsigned bit; XkbDescPtr cached = xkl_engine_backend(engine, XklXkb, cached_desc); ForPhysIndicators(i, bit) if (cached->names->indicators[i] != None) { gboolean status; status = xkl_xkb_set_indicator(engine, i, (window_state->indicators & bit) != 0); xkl_debug(150, "Set indicator \"%s\"/%d to %d: %d\n", xkl_engine_backend(engine, XklXkb, indicator_names)[i], cached->names->indicators[i], window_state->indicators & bit, status); } #endif } libxklavier-5.4/libxklavier/xklavier_evt_xmm.c000066400000000000000000000131061213561201300217350ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" #include "xklavier_private_xmm.h" static gint xkl_xmm_process_keypress_event(XklEngine * engine, XKeyPressedEvent * kpe) { if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS)) { gint current_shortcut = 0; const XmmSwitchOption *sop; xkl_debug(200, "Processing the KeyPress event\n"); sop = xkl_xmm_find_switch_option(engine, kpe->keycode, kpe->state, ¤t_shortcut); if (sop != NULL) { XklState state; xkl_debug(150, "It is THE shortcut\n"); xkl_xmm_get_server_state(engine, &state); if (state.group != -1) { gint new_group = (state.group + sop->shortcut_steps[current_shortcut]) % g_strv_length(xkl_engine_backend (engine, XklXmm, current_config).layouts); xkl_debug(150, "Setting new xmm group %d\n", new_group); xkl_xmm_lock_group(engine, new_group); return 1; } } } return 0; } static gint xkl_xmm_process_property_event(XklEngine * engine, XPropertyEvent * kpe) { Atom state_atom = xkl_engine_backend(engine, XklXmm, state_atom); xkl_debug(200, "Processing the PropertyNotify event: %d/%d\n", kpe->atom, state_atom); /* * Group is changed! */ if (kpe->atom == state_atom) { XklState state; xkl_xmm_get_server_state(engine, &state); if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_LAYOUTS)) { xkl_debug(150, "Current group from the root window property %d\n", state.group); xkl_xmm_shortcuts_ungrab(engine); xkl_xmm_actualize_group(engine, state.group); xkl_xmm_shortcuts_grab(engine); return 1; } if (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES) | xkl_engine_is_listening_for(engine, XKLL_TRACK_KEYBOARD_STATE)) { xkl_debug(150, "XMM state changed, new 'group' %d\n", state.group); xkl_engine_process_state_modification(engine, GROUP_CHANGED, state.group, 0, False); } } else /* * Configuration is changed! */ if (kpe->atom == xkl_engine_priv(engine, base_config_atom)) { xkl_engine_reset_all_info(engine, TRUE, "base config atom changed"); } return 0; } /* * XMM event handler */ gint xkl_xmm_process_x_event(XklEngine * engine, XEvent * xev) { switch (xev->type) { case KeyPress: return xkl_xmm_process_keypress_event(engine, (XKeyPressedEvent *) xev); case PropertyNotify: return xkl_xmm_process_property_event(engine, (XPropertyEvent *) xev); } return 0; } /* * We have to find which of Shift/Lock/Control/ModX masks * belong to Caps/Num/Scroll lock */ static void xkl_xmm_init_xmm_indicators_map(XklEngine * engine, guint * p_caps_lock_mask, guint * p_num_lock_mask, guint * p_scroll_lock_mask) { XModifierKeymap *xmkm = NULL; KeyCode *kcmap, nlkc, clkc, slkc; int m, k, mask; Display *display = xkl_engine_get_display(engine); xmkm = XGetModifierMapping(display); if (xmkm) { clkc = XKeysymToKeycode(display, XK_Num_Lock); nlkc = XKeysymToKeycode(display, XK_Caps_Lock); slkc = XKeysymToKeycode(display, XK_Scroll_Lock); kcmap = xmkm->modifiermap; mask = 1; for (m = 8; --m >= 0; mask <<= 1) for (k = xmkm->max_keypermod; --k >= 0; kcmap++) { if (*kcmap == clkc) *p_caps_lock_mask = mask; if (*kcmap == slkc) *p_scroll_lock_mask = mask; if (*kcmap == nlkc) *p_num_lock_mask = mask; } XFreeModifiermap(xmkm); } } void xkl_xmm_grab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers) { guint caps_lock_mask = 0, num_lock_mask = 0, scroll_lock_mask = 0; xkl_xmm_init_xmm_indicators_map(engine, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask); #define GRAB(mods) \ xkl_engine_grab_key(engine, keycode, modifiers|(mods)) GRAB(0); GRAB(caps_lock_mask); GRAB(num_lock_mask); GRAB(scroll_lock_mask); GRAB(caps_lock_mask | num_lock_mask); GRAB(caps_lock_mask | scroll_lock_mask); GRAB(num_lock_mask | scroll_lock_mask); GRAB(caps_lock_mask | num_lock_mask | scroll_lock_mask); #undef GRAB } void xkl_xmm_ungrab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers) { guint caps_lock_mask = 0, num_lock_mask = 0, scroll_lock_mask = 0; xkl_xmm_init_xmm_indicators_map(engine, &caps_lock_mask, &num_lock_mask, &scroll_lock_mask); #define UNGRAB(mods) \ xkl_engine_ungrab_key(engine, keycode, modifiers|(mods)) UNGRAB(0); UNGRAB(caps_lock_mask); UNGRAB(num_lock_mask); UNGRAB(scroll_lock_mask); UNGRAB(caps_lock_mask | num_lock_mask); UNGRAB(caps_lock_mask | scroll_lock_mask); UNGRAB(num_lock_mask | scroll_lock_mask); UNGRAB(caps_lock_mask | num_lock_mask | scroll_lock_mask); #undef UNGRAB } libxklavier-5.4/libxklavier/xklavier_private.h000066400000000000000000000325571213561201300217500ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKLAVIER_PRIVATE_H__ #define __XKLAVIER_PRIVATE_H__ #include #include #include enum { WM_NAME, WM_STATE, XKLAVIER_STATE, XKLAVIER_TRANSPARENT, XKLAVIER_ALLOW_SECONDARY, TOTAL_ATOMS }; #define XKL_NUMBER_OF_REGISTRY_DOCS 2 /* We have 3 values in XklEngineListenModes */ enum { XKLL_MANAGE_WINDOW_STATES_OFFSET = 0, XKLL_TRACK_KEYBOARD_STATE_OFFSET, XKLL_MANAGE_LAYOUTS_OFFSET, XKLL_NUMBER_OF_LISTEN_MODES }; struct _XklEnginePrivate { gboolean group_per_toplevel_window; gboolean handle_indicators; gboolean skip_one_restore; gboolean skip_one_save; gint default_group; /* * Separate counter for each of XklEngineListenModes! */ guchar listener_type_counters[XKLL_NUMBER_OF_LISTEN_MODES]; #define xkl_engine_is_listening_for(engine, type) (xkl_engine_priv((engine), listener_type_counters)[type##_OFFSET] > 0) guint secondary_groups_mask; Window root_window; Window prev_toplvl_win; Window curr_toplvl_win; XErrorHandler default_error_handler; Status last_error_code; XklState curr_state; gboolean critical_section; Atom atoms[TOTAL_ATOMS]; Display *display; /* * Backend name */ const gchar *backend_id; /* * Functions supported by the backend, combination of XKLF_* constants */ guint8 features; /* * Activates the configuration. * xkb: create proper the XkbDescRec and send it to the server * xmodmap: save the property, init layout #1 */ gboolean(*activate_config_rec) (XklEngine * engine, const XklConfigRec * data); /* * Background-specific initialization. * xkb: XkbInitAtoms - init internal xkb atoms table * xmodmap: void. */ void (*init_config_registry) (XklConfigRegistry * config); /* * Loads the registry tree into DOM (using whatever path(s)) * The XklVTConfigFreeRegistry is static - no virtualization necessary. * xkb: loads xml from XKB_BASE+"/rules/"+ruleset+".xml" * xmodmap: loads xml from XMODMAP_BASE+"/"+ruleset+".xml" */ gboolean(*load_config_registry) (XklConfigRegistry * config, gboolean if_extras_needed); /* * Write the configuration into the file (binary/textual) * xkb: write xkb or xkm file * xmodmap: if text requested, just dump XklConfigRec to the * file - not really useful. If binary - fail (not supported) */ gboolean(*write_config_rec_to_file) (XklEngine * engine, const gchar * file_name, const XklConfigRec * data, const gboolean binary); /* * Get the list of the group names * xkb: return cached list of the group names * xmodmap: return the list of layouts from the internal XklConfigRec */ const gchar **(*get_groups_names) (XklEngine * engine); /* * Get the list of the indicators names * xkb: return cached list of the indicators names * xmodmap: return NULL */ const gchar **(*get_indicators_names) (XklEngine * engine); /* * Get the maximum number of loaded groups * xkb: returns 1 or XkbNumKbdGroups * xmodmap: return 0 */ guint(*get_max_num_groups) (XklEngine * engine); /* * Get the number of loaded groups * xkb: return from the cached XkbDesc * xmodmap: return number of layouts from internal XklConfigRec */ guint(*get_num_groups) (XklEngine * engine); /* * Switches the keyboard to the group N * xkb: simple one-liner to call the XKB function * xmodmap: changes the root window property * (listener invokes xmodmap with appropriate config file). */ void (*lock_group) (XklEngine * engine, gint group); /* * Handles X events. * xkb: XkbEvent handling * xmodmap: keep track on the root window properties. What else can we do? */ gint(*process_x_event) (XklEngine * engine, XEvent * xev); /* * Handles X errors. * return 0 if further processing is needed * 1 if error was handled */ gint(*process_x_error) (XklEngine * engine, XErrorEvent * xerev); /* * Flushes the cached server config info. * xkb: frees XkbDesc * xmodmap: frees internal XklConfigRec */ void (*free_all_info) (XklEngine * engine); /* * Compares the cached info with the actual one, from the server * xkb: Compares some parts of XkbDescPtr * xmodmap: returns False */ gboolean(*if_cached_info_equals_actual) (XklEngine * engine); /* * Loads the configuration info from the server * xkb: loads XkbDesc, names, indicators * xmodmap: loads internal XklConfigRec from server */ gboolean(*load_all_info) (XklEngine * engine); /* * Gets the current state * xkb: XkbGetState and XkbGetIndicatorState * xmodmap: check the root window property (regarding the group) */ void (*get_server_state) (XklEngine * engine, XklState * current_state_out); /* * Stop tracking the keyboard-related events * xkb: XkbSelectEvents(..., 0) * xmodmap: Ungrab the switching shortcut. */ gint(*pause_listen) (XklEngine * engine); /* * Start tracking the keyboard-related events * xkb: XkbSelectEvents + XkbSelectEventDetails * xmodmap: Grab the switching shortcut. */ gint(*resume_listen) (XklEngine * engine); /* * Set the indicators state from the XklState * xkb: XklSetIndicator for all indicators * xmodmap: NULL. Not supported */ void (*set_indicators) (XklEngine * engine, const XklState * window_state); /* * Perform the cleanup */ void (*finalize) (XklEngine * engine); /* all data is private - no direct access */ /* * The base configuration atom. * xkb: _XKB_RF_NAMES_PROP_ATOM * xmodmap: "_XMM_NAMES" */ Atom base_config_atom; /* * The configuration backup atom * xkb: "_XKB_RULES_NAMES_BACKUP" * xmodmap: "_XMM_NAMES_BACKUP" */ Atom backup_config_atom; /* * Fallback for missing model */ const gchar *default_model; /* * Fallback for missing layout */ const gchar *default_layout; /* * Any stuff backend might need to put in here */ gpointer backend; }; extern XklEngine *xkl_get_the_engine(void); struct _XklConfigRegistryPrivate { XklEngine *engine; xmlDocPtr docs[XKL_NUMBER_OF_REGISTRY_DOCS]; xmlXPathContextPtr xpath_contexts[XKL_NUMBER_OF_REGISTRY_DOCS]; }; extern void xkl_engine_ensure_vtable_inited(XklEngine * engine); extern void xkl_engine_process_focus_in_evt(XklEngine * engine, XFocusChangeEvent * fev); extern void xkl_engine_process_focus_out_evt(XklEngine * engine, XFocusChangeEvent * fev); extern void xkl_engine_process_property_evt(XklEngine * engine, XPropertyEvent * rev); extern void xkl_engine_process_create_window_evt(XklEngine * engine, XCreateWindowEvent * cev); extern int xkl_process_error(Display * dpy, XErrorEvent * evt); extern void xkl_engine_process_state_modification(XklEngine * engine, XklEngineStateChange change_type, gint group, unsigned inds, gboolean set_indicators); extern Window xkl_engine_get_registered_parent(XklEngine * engine, Window win); extern void xkl_engine_reset_all_info(XklEngine * engine, gboolean force, const gchar reason[]); extern gboolean xkl_engine_load_window_tree(XklEngine * engine); extern gboolean xkl_engine_load_subtree(XklEngine * engine, Window window, gint level, XklState * init_state); extern gboolean xkl_engine_if_window_has_wm_state(XklEngine * engine, Window win); /** * Toplevel window stuff */ extern void xkl_engine_add_toplevel_window(XklEngine * engine, Window win, Window parent, gboolean force, XklState * init_state); extern gboolean xkl_engine_find_toplevel_window_bottom_to_top(XklEngine * engine, Window win, Window * toplevel_win_out); extern gboolean xkl_engine_find_toplevel_window(XklEngine * engine, Window win, Window * toplevel_win_out); extern gboolean xkl_engine_is_toplevel_window_transparent(XklEngine * engine, Window toplevel_win); extern void xkl_engine_set_toplevel_window_transparent(XklEngine * engine, Window toplevel_win, gboolean transparent); extern gboolean xkl_engine_get_toplevel_window_state(XklEngine * engine, Window toplevel_win, XklState * state_out); extern void xkl_engine_remove_toplevel_window_state(XklEngine * engine, Window toplevel_win); extern void xkl_engine_save_toplevel_window_state(XklEngine * engine, Window toplevel_win, XklState * state); /***/ extern void xkl_engine_select_input_merging(XklEngine * engine, Window win, gulong mask); extern gchar *xkl_get_debug_window_title(XklEngine * engine, Window win); extern Status xkl_engine_query_tree(XklEngine * engine, Window w, Window * root_out, Window * parent_out, Window ** children_out, guint * nchildren_out); extern void xkl_engine_try_call_state_func(XklEngine * engine, XklEngineStateChange change_type, XklState * old_state); extern gchar *xkl_engine_get_ruleset_name(XklEngine * engine, const gchar default_ruleset[]); extern gboolean xkl_config_rec_get_full_from_server(gchar ** rules_file_out, XklConfigRec * data, XklEngine * engine); extern gchar *xkl_strings_concat_comma_separated(gchar ** array); extern void xkl_strings_split_comma_separated(gchar *** array, const gchar * merged); /** * XConfigRec */ extern gchar *xkl_config_rec_merge_layouts(const XklConfigRec * data); extern gchar *xkl_config_rec_merge_variants(const XklConfigRec * data); extern gchar *xkl_config_rec_merge_options(const XklConfigRec * data); extern void xkl_config_rec_split_layouts(XklConfigRec * data, const gchar * merged); extern void xkl_config_rec_split_variants(XklConfigRec * data, const gchar * merged); extern void xkl_config_rec_split_options(XklConfigRec * data, const gchar * merged); /***/ extern void xkl_config_rec_dump(FILE * file, XklConfigRec * data); extern const gchar *xkl_event_get_name(gint type); extern void xkl_engine_update_current_state(XklEngine * engine, gint group, unsigned indicators, const gchar reason[]); extern gint xkl_xkb_init(XklEngine * engine); extern gint xkl_xmm_init(XklEngine * engine); extern gboolean xkl_engine_is_one_switch_to_secondary_group_allowed(XklEngine * engine); extern void xkl_engine_one_switch_to_secondary_group_performed(XklEngine * engine); extern gboolean xkl_config_registry_load_from_file(XklConfigRegistry * config, const gchar * file_name, gint docidx); extern void xkl_config_registry_free(XklConfigRegistry * config); extern gchar *xkl_locale_from_utf8(XklConfigRegistry * config, const gchar * utf8string); extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, const char default_ruleset[], const char base_dir[], gboolean if_extras_needed); #define XKLAVIER_STATE_PROP_LENGTH 2 /* taken from XFree86 maprules.c */ #define XKB_RF_NAMES_PROP_MAXLEN 1024 #define WINID_FORMAT "%lx" #define xkl_engine_priv(engine,member) (engine)->priv->member #define xkl_engine_backend(engine,type,member) ((type*)((engine)->priv->backend))->member #define xkl_engine_get_display(engine) (xkl_engine_priv(engine,display)) #define xkl_engine_vcall(engine,func) (*(engine)->priv->func) #define xkl_config_registry_is_initialized(config) \ ( xkl_config_registry_priv(config,xpath_contexts[0]) != NULL ) #define xkl_config_registry_priv(config,member) (config)->priv->member #define xkl_config_registry_get_engine(config) ((config)->priv->engine) #define XKBCR_MODEL_PATH "/xkbConfigRegistry/modelList/model" #define XKBCR_LAYOUT_PATH "/xkbConfigRegistry/layoutList/layout" #define XKBCR_VARIANT_PATH XKBCR_LAYOUT_PATH "/variantList/variant" #define XKBCR_GROUP_PATH "/xkbConfigRegistry/optionList/group" #define XKBCR_OPTION_PATH XKBCR_GROUP_PATH "/option" #define XML_TAG_DESCR "description" #define XML_TAG_SHORT_DESCR "shortDescription" #define XML_TAG_VENDOR "vendor" #define XML_TAG_COUNTRY_LIST "countryList" #define XML_TAG_LANGUAGE_LIST "languageList" #define XML_TAG_ISO3166ID "iso3166Id" #define XML_TAG_ISO639ID "iso639Id" extern void xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry * config, const gchar * format, const gchar * value, XklConfigItemProcessFunc func, gpointer data); extern void xkl_config_registry_foreach_in_xpath(XklConfigRegistry * config, xmlXPathCompExprPtr xpath_comp_expr, XklConfigItemProcessFunc func, gpointer data); extern gboolean xkl_read_config_item(XklConfigRegistry * config, gint doc_index, xmlNodePtr iptr, XklConfigItem * item); extern gint xkl_debug_level; extern const gchar *xkl_last_error_message; #endif libxklavier-5.4/libxklavier/xklavier_private_xkb.h000066400000000000000000000075561213561201300226150ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKLAVIER_PRIVATE_XKB_H__ #define __XKLAVIER_PRIVATE_XKB_H__ #ifdef LIBXKBFILE_PRESENT #include #include #include #define ForPhysIndicators( i, bit ) \ for ( i=0, bit=1; iindicators->phys_indicators & bit ) typedef struct _XklXkb { gint event_type; gint error_code; XkbDescPtr cached_desc; gchar *indicator_names[XkbNumIndicators]; XkbDescPtr actual_desc; gchar *group_names[XkbNumKbdGroups]; int device_id; #ifdef HAVE_XINPUT gint xi_event_type; gint xi_error_code; #endif } XklXkb; extern void xkl_engine_dump_xkb_desc(XklEngine * engine, const char *file_name, XkbDescPtr kbd); extern gboolean xkl_xkb_multiple_layouts_supported(XklEngine * engine); extern const gchar *xkl_xkb_event_get_name(gint xkb_type); extern gboolean xkl_xkb_config_native_prepare(XklEngine * engine, const XklConfigRec * data, XkbComponentNamesPtr component_names); extern void xkl_xkb_config_native_cleanup(XklEngine * engine, XkbComponentNamesPtr component_names); extern gboolean xkl_xkb_set_indicator(XklEngine * engine, gint indicator_num, gboolean set); /* Start VTable methods */ extern gboolean xkl_xkb_activate_config_rec(XklEngine * engine, const XklConfigRec * data); extern void xkl_xkb_init_config_registry(XklConfigRegistry * config); extern gboolean xkl_xkb_load_config_registry(XklConfigRegistry * config, gboolean if_extras_needed); extern gboolean xkl_xkb_write_config_rec_to_file(XklEngine * engine, const char *file_name, const XklConfigRec * data, const gboolean binary); extern gint xkl_xkb_process_x_event(XklEngine * engine, XEvent * xev); extern gint xkl_xkb_process_x_error(XklEngine * engine, XErrorEvent * xerev); extern void xkl_xkb_free_all_info(XklEngine * engine); extern const gchar **xkl_xkb_get_groups_names(XklEngine * engine); extern guint xkl_xkb_get_max_num_groups(XklEngine * engine); extern guint xkl_xkb_get_num_groups(XklEngine * engine); extern void xkl_xkb_get_server_state(XklEngine * engine, XklState * current_state_out); extern gboolean xkl_xkb_if_cached_info_equals_actual(XklEngine * engine); extern gboolean xkl_xkb_load_all_info(XklEngine * engine); extern void xkl_xkb_lock_group(XklEngine * engine, gint group); extern gint xkl_xkb_pause_listen(XklEngine * engine); extern gint xkl_xkb_resume_listen(XklEngine * engine); extern void xkl_xkb_set_indicators(XklEngine * engine, const XklState * window_state); extern void xkl_xkb_term(XklEngine * engine); /* End of VTable methods */ #else /* * VERY VERY BAD STYLE, some kind of 'protected' methods - * but some programs may want to hook into them. */ extern gboolean xkl_xkb_config_native_prepare(XklEngine * engine, const XklConfigRec * data, gpointer component_names); extern void xkl_xkb_config_native_cleanup(XklEngine * engine, gpointer component_names); #endif #endif libxklavier-5.4/libxklavier/xklavier_private_xmm.h000066400000000000000000000065371213561201300226300ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 __XKLAVIER_PRIVATE_XMM_H__ #define __XKLAVIER_PRIVATE_XMM_H__ typedef struct _XmmShortcut { guint keysym; guint modifiers; } XmmShortcut; #define MAX_SHORTCUTS_PER_OPTION 4 typedef struct _XmmSwitchOption { XmmShortcut shortcuts[MAX_SHORTCUTS_PER_OPTION + 1]; gint shortcut_steps[MAX_SHORTCUTS_PER_OPTION + 1]; } XmmSwitchOption; typedef struct _XklXmm { gchar *current_rules; XklConfigRec current_config; Atom state_atom; GHashTable *switch_options; } XklXmm; /* in the ideal world this should be a hashmap */ extern void xkl_xmm_grab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers); extern void xkl_xmm_ungrab_ignoring_indicators(XklEngine * engine, gint keycode, guint modifiers); extern void xkl_xmm_shortcuts_grab(XklEngine * engine); extern void xkl_xmm_shortcuts_ungrab(XklEngine * engine); extern const gchar *xkl_xmm_shortcut_get_current_option_name(XklEngine * engine); XmmSwitchOption *xkl_xmm_shortcut_get_current(XklEngine * engine); extern void xkl_xmm_actualize_group(XklEngine * engine, gint group); const XmmSwitchOption *xkl_xmm_find_switch_option(XklEngine * engine, gint keycode, guint state, gint * current_shortcut_out); extern void xkl_xmm_init_switch_options(XklXmm * xmm); extern void xkl_xmm_term_switch_options(XklXmm * xmm); /* Start VTable methods */ extern gboolean xkl_xmm_activate_config_rec(XklEngine * engine, const XklConfigRec * data); extern void xkl_xmm_init_config_registry(XklConfigRegistry * config); extern gboolean xkl_xmm_load_config_registry(XklConfigRegistry * config, gboolean if_extras_needed); extern gint xkl_xmm_process_x_event(XklEngine * engine, XEvent * kev); extern void xkl_xmm_free_all_info(XklEngine * engine); extern const gchar **xkl_xmm_get_groups_names(XklEngine * engine); extern guint xkl_xmm_get_max_num_groups(XklEngine * engine); extern guint xkl_xmm_get_num_groups(XklEngine * engine); extern void xkl_xmm_lock_group(XklEngine * engine, gint group); extern void xkl_xmm_get_server_state(XklEngine * engine, XklState * current_state_out); extern gboolean xkl_xmm_if_cached_info_equals_actual(XklEngine * engine); extern gboolean xkl_xmm_load_all_info(XklEngine * engine); extern gint xkl_xmm_listen_pause(XklEngine * engine); extern gint xkl_xmm_listen_resume(XklEngine * engine); extern void xkl_xmm_set_indicators(XklEngine * engine, const XklState * window_state); extern void xkl_xmm_term(XklEngine * engine); /* End of VTable methods */ #endif libxklavier-5.4/libxklavier/xklavier_props.c000066400000000000000000000331301213561201300214200ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "config.h" #include "xklavier_private.h" static GObjectClass *parent_class = NULL; static void xkl_config_rec_destroy(XklConfigRec * data); G_DEFINE_TYPE(XklConfigItem, xkl_config_item, G_TYPE_OBJECT) static void xkl_config_item_init(XklConfigItem * this) { } static void xkl_config_item_class_init(XklConfigItemClass * klass) { } XklConfigItem * xkl_config_item_new(void) { return XKL_CONFIG_ITEM(g_object_new (xkl_config_item_get_type(), NULL)); } const gchar * xkl_config_item_get_name(XklConfigItem * item) { return item->name; } void xkl_config_item_set_name(XklConfigItem * item, const gchar * name) { if (name != NULL) strncpy (item->name, name, XKL_MAX_CI_SHORT_DESC_LENGTH-1); else item->name[0] = '\0'; } const gchar * xkl_config_item_get_short_description(XklConfigItem * item) { return item->short_description; } void xkl_config_item_set_short_description(XklConfigItem * item, const gchar * short_description) { if (short_description != NULL) strncpy (item->short_description, short_description, XKL_MAX_CI_DESC_LENGTH-1); else item->short_description[0] = '\0'; } const gchar * xkl_config_item_get_description(XklConfigItem * item) { return item->description; } void xkl_config_item_set_description(XklConfigItem * item, const gchar * description) { if (description != NULL) strncpy (item->description, description, XKL_MAX_CI_NAME_LENGTH-1); else item->description[0] = '\0'; } G_DEFINE_TYPE(XklConfigRec, xkl_config_rec, G_TYPE_OBJECT) static void xkl_config_rec_finalize(GObject * obj) { XklConfigRec *this = (XklConfigRec *) obj; xkl_config_rec_destroy(this); G_OBJECT_CLASS(parent_class)->finalize(obj); } static void xkl_config_rec_class_init(XklConfigRecClass * klass) { GObjectClass *object_class; object_class = (GObjectClass *) klass; parent_class = g_type_class_peek_parent(object_class); object_class->finalize = xkl_config_rec_finalize; } XklConfigRec * xkl_config_rec_new(void) { return XKL_CONFIG_REC(g_object_new(xkl_config_rec_get_type(), NULL)); } static gboolean xkl_strings_equal(gchar * p1, gchar * p2) { if (p1 == p2) return TRUE; if ((p1 == NULL && p2 != NULL) || (p1 != NULL && p2 == NULL)) return FALSE; return !g_ascii_strcasecmp(p1, p2); } static gboolean xkl_lists_equal(gchar ** items1, gchar ** items2) { if (items1 == items2) return TRUE; if ((items1 == NULL && items2 != NULL) || (items1 != NULL && items2 == NULL)) return FALSE; while (*items1 != NULL && *items2 != NULL) if (!xkl_strings_equal(*items1++, *items2++)) return FALSE; return (*items1 == NULL && *items2 == NULL); } static gboolean xkl_engine_get_default_names_prop(XklEngine * engine, char **rules_file_out, XklConfigRec * data) { if (rules_file_out != NULL) *rules_file_out = g_strdup(XKB_DEFAULT_RULESET); data->model = g_strdup(xkl_engine_priv(engine, default_model)); /* keeping Nvariants = Nlayouts */ data->layouts = g_new0(char *, 2); data->layouts[0] = g_strdup(xkl_engine_priv(engine, default_layout)); data->variants = g_new0(char *, 2); data->variants[0] = g_strdup(""); data->options = g_new0(char *, 1); return TRUE; } gboolean xkl_config_rec_get_full_from_server(char **rules_file_out, XklConfigRec * data, XklEngine * engine) { gboolean rv = xkl_config_rec_get_from_root_window_property(data, xkl_engine_priv (engine, base_config_atom), rules_file_out, engine); if (!rv) rv = xkl_engine_get_default_names_prop(engine, rules_file_out, data); return rv; } gboolean xkl_config_rec_equals(XklConfigRec * data1, XklConfigRec * data2) { if (data1 == data2) return TRUE; if (!xkl_strings_equal(data1->model, data2->model)) return FALSE; if (!xkl_lists_equal(data1->layouts, data2->layouts)) return FALSE; if (!xkl_lists_equal(data1->variants, data2->variants)) return FALSE; return xkl_lists_equal(data1->options, data2->options); } void xkl_config_rec_set_layouts(XklConfigRec * data, const gchar ** new_layouts) { g_strfreev (data->layouts); data->layouts = g_strdupv ((gchar**) new_layouts); } void xkl_config_rec_set_variants(XklConfigRec * data, const gchar ** new_variants) { g_strfreev (data->variants); data->variants = g_strdupv ((gchar**) new_variants); } void xkl_config_rec_set_options(XklConfigRec * data, const gchar ** new_options) { g_strfreev (data->options); data->options = g_strdupv ((gchar**) new_options); } void xkl_config_rec_set_model(XklConfigRec * data, const gchar * new_model) { g_free (data->model); data->model = g_strdup (new_model); } void xkl_config_rec_init(XklConfigRec * data) { /* clear the structure VarDefsPtr... */ data->model = NULL; data->layouts = data->variants = data->options = NULL; } void xkl_config_rec_destroy(XklConfigRec * data) { if (data->model != NULL) g_free(data->model); g_strfreev(data->layouts); g_strfreev(data->variants); g_strfreev(data->options); data->layouts = data->variants = data->options = NULL; } void xkl_config_rec_reset(XklConfigRec * data) { xkl_config_rec_destroy(data); xkl_config_rec_init(data); } gboolean xkl_config_rec_get_from_server(XklConfigRec * data, XklEngine * engine) { return xkl_config_rec_get_full_from_server(NULL, data, engine); } gboolean xkl_config_rec_get_from_backup(XklConfigRec * data, XklEngine * engine) { return xkl_config_rec_get_from_root_window_property(data, xkl_engine_priv (engine, backup_config_atom), NULL, engine); } gboolean xkl_engine_backup_names_prop(XklEngine * engine) { gboolean rv = TRUE; gchar *rf = NULL; XklConfigRec *data = xkl_config_rec_new(); gboolean cgp = FALSE; if (xkl_config_rec_get_from_root_window_property (data, xkl_engine_priv(engine, backup_config_atom), NULL, engine)) { g_object_unref(G_OBJECT(data)); return TRUE; } /* "backup" property is not defined */ xkl_config_rec_reset(data); cgp = xkl_config_rec_get_full_from_server(&rf, data, engine); if (cgp) { if (!xkl_config_rec_set_to_root_window_property (data, xkl_engine_priv(engine, backup_config_atom), rf, engine)) { xkl_debug(150, "Could not backup the configuration"); rv = FALSE; } if (rf != NULL) g_free(rf); } else { xkl_debug(150, "Could not get the configuration for backup"); rv = FALSE; } g_object_unref(G_OBJECT(data)); return rv; } gboolean xkl_restore_names_prop(XklEngine * engine) { gboolean rv = TRUE; gchar *rf = NULL; XklConfigRec *data = xkl_config_rec_new(); if (!xkl_config_rec_get_from_root_window_property (data, xkl_engine_priv(engine, backup_config_atom), NULL, engine)) { g_object_unref(G_OBJECT(data)); return FALSE; } if (!xkl_config_rec_set_to_root_window_property (data, xkl_engine_priv(engine, base_config_atom), rf, engine)) { xkl_debug(150, "Could not backup the configuration"); rv = FALSE; } g_object_unref(G_OBJECT(data)); return rv; } gboolean xkl_config_rec_get_from_root_window_property(XklConfigRec * data, Atom rules_atom, gchar ** rules_file_out, XklEngine * engine) { Atom real_prop_type; int fmt; unsigned long nitems, extra_bytes; char *prop_data = NULL, *out; Status rtrn; /* no such atom! */ if (rules_atom == None) { /* property cannot exist */ xkl_last_error_message = "Could not find the atom"; return FALSE; } rtrn = XGetWindowProperty(xkl_engine_get_display(engine), xkl_engine_priv(engine, root_window), rules_atom, 0L, XKB_RF_NAMES_PROP_MAXLEN, False, XA_STRING, &real_prop_type, &fmt, &nitems, &extra_bytes, (unsigned char **) (void *) &prop_data); /* property not found! */ if (rtrn != Success) { xkl_last_error_message = "Could not get the property"; return FALSE; } /* set rules file to "" */ if (rules_file_out) *rules_file_out = NULL; /* has to be array of strings */ if ((extra_bytes > 0) || (real_prop_type != XA_STRING) || (fmt != 8)) { if (prop_data) XFree(prop_data); xkl_last_error_message = "Wrong property format"; return FALSE; } if (!prop_data) { xkl_last_error_message = "No properties returned"; return FALSE; } /* rules file */ out = prop_data; if (out && (*out) && rules_file_out) *rules_file_out = g_strdup(out); out += strlen(out) + 1; /* if user is interested in rules only - don't waste the time */ if (!data) { XFree(prop_data); return TRUE; } if ((out - prop_data) < nitems) { if (*out) data->model = g_strdup(out); out += strlen(out) + 1; } if ((out - prop_data) < nitems) { xkl_config_rec_split_layouts(data, out); out += strlen(out) + 1; } if ((out - prop_data) < nitems) { gint nv, nl; gchar **layout, **variant; xkl_config_rec_split_variants(data, out); /* Now have to ensure that number of variants matches the number of layouts The 'remainder' is filled with NULLs (not ""s!) */ nv = g_strv_length(data->variants); nl = g_strv_length(data->layouts); if (nv < nl) { data->variants = g_realloc(data->variants, (nl + 1) * sizeof(char *)); memset(data->variants + nv + 1, 0, (nl - nv) * sizeof(char *)); } /* take variants from layouts like ru(winkeys) */ layout = data->layouts; variant = data->variants; while (*layout != NULL && *variant == NULL) { gchar *varstart = g_strstr_len(*layout, -1, "("); if (varstart != NULL) { gchar *varend = g_strstr_len(varstart, -1, ")"); if (varend != NULL) { gint varlen = varend - varstart; gint laylen = varstart - *layout; /* I am not sure - but I assume variants in layout have priority */ gchar *var = *variant = (*variant != NULL) ? g_realloc(*variant, varlen) : g_new(gchar, varlen); memcpy(var, varstart + 1, --varlen); var[varlen] = '\0'; /* Resize the original layout */ *layout = g_realloc(*layout, laylen + 1); (*layout)[laylen] = '\0'; } } layout++; variant++; } out += strlen(out) + 1; } if ((out - prop_data) < nitems) { xkl_config_rec_split_options(data, out); } XFree(prop_data); return TRUE; } /* taken from XFree86 maprules.c */ gboolean xkl_config_rec_set_to_root_window_property(const XklConfigRec * data, Atom rules_atom, gchar * rules_file, XklEngine * engine) { gint len; gchar *pval; gchar *next; gchar *all_layouts = xkl_config_rec_merge_layouts(data); gchar *all_variants = xkl_config_rec_merge_variants(data); gchar *all_options = xkl_config_rec_merge_options(data); Display *display; len = (rules_file ? strlen(rules_file) : 0); len += (data->model ? strlen(data->model) : 0); len += (all_layouts ? strlen(all_layouts) : 0); len += (all_variants ? strlen(all_variants) : 0); len += (all_options ? strlen(all_options) : 0); if (len < 1) { if (all_layouts) g_free(all_layouts); if (all_variants) g_free(all_variants); if (all_options) g_free(all_options); return TRUE; } len += 5; /* trailing NULs */ pval = next = g_new(char, len + 1); if (!pval) { xkl_last_error_message = "Could not allocate buffer"; if (all_layouts != NULL) g_free(all_layouts); if (all_variants != NULL) g_free(all_variants); if (all_options != NULL) g_free(all_options); return FALSE; } if (rules_file) { strcpy(next, rules_file); next += strlen(rules_file); } *next++ = '\0'; if (data->model) { strcpy(next, data->model); next += strlen(data->model); } *next++ = '\0'; if (data->layouts) { strcpy(next, all_layouts); next += strlen(all_layouts); } *next++ = '\0'; if (data->variants) { strcpy(next, all_variants); next += strlen(all_variants); } *next++ = '\0'; if (data->options) { strcpy(next, all_options); next += strlen(all_options); } *next++ = '\0'; if ((next - pval) != len) { xkl_debug(150, "Illegal final position: %d/%d\n", (next - pval), len); if (all_layouts != NULL) g_free(all_layouts); if (all_variants != NULL) g_free(all_variants); if (all_options != NULL) g_free(all_options); g_free(pval); xkl_last_error_message = "Internal property parsing error"; return FALSE; } display = xkl_engine_get_display(engine); XChangeProperty(display, xkl_engine_priv(engine, root_window), rules_atom, XA_STRING, 8, PropModeReplace, (unsigned char *) pval, len); XSync(display, False); #if 0 for (i = len - 1; --i >= 0;) if (pval[i] == '\0') pval[i] = '?'; XklDebug(150, "Stored [%s] of length %d to [%s] of %X\n", pval, len, propName, _xklRootWindow); #endif if (all_layouts != NULL) g_free(all_layouts); if (all_variants != NULL) g_free(all_variants); if (all_options != NULL) g_free(all_options); g_free(pval); return TRUE; } libxklavier-5.4/libxklavier/xklavier_toplevel.c000066400000000000000000000243161213561201300221150ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" Window xkl_toplevel_window_prev; void xkl_engine_set_toplevel_window_transparent(XklEngine * engine, Window toplevel_win, gboolean transparent) { gboolean oldval; oldval = xkl_engine_is_toplevel_window_transparent(engine, toplevel_win); xkl_debug(150, "toplevel_win " WINID_FORMAT " was %stransparent\n", toplevel_win, oldval ? "" : "not "); if (transparent && !oldval) { CARD32 prop = 1; XChangeProperty(xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms) [XKLAVIER_TRANSPARENT], XA_INTEGER, 32, PropModeReplace, (const unsigned char *) &prop, 1); } else if (!transparent && oldval) { XDeleteProperty(xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms) [XKLAVIER_TRANSPARENT]); } } /* * "Adds" app window to the set of managed windows. * Actually, no data structures involved. The only thing we do is save app state * and register ourselves us listeners. * Note: User's callback is called */ void xkl_engine_add_toplevel_window(XklEngine * engine, Window toplevel_win, Window parent, gboolean ignore_existing_state, XklState * init_state) { XklState state = *init_state; gint default_group_to_use = -1; GValue params[3]; GValue rv; guint signal_id; if (toplevel_win == xkl_engine_priv(engine, root_window)) xkl_debug(150, "??? root app win ???\n"); xkl_debug(150, "Trying to add window " WINID_FORMAT "/%s with group %d\n", toplevel_win, xkl_get_debug_window_title(engine, toplevel_win), init_state->group); if (!ignore_existing_state) { gboolean have_state = xkl_engine_get_toplevel_window_state(engine, toplevel_win, &state); if (have_state) { xkl_debug(150, "The window " WINID_FORMAT " does not require to be added, it already has the xklavier state \n", toplevel_win); return; } } memset(params, 0, sizeof(params)); g_value_init(params, XKL_TYPE_ENGINE); g_value_set_object(params, engine); g_value_init(params + 1, G_TYPE_LONG); g_value_set_long(params + 1, toplevel_win); g_value_init(params + 2, G_TYPE_LONG); g_value_set_long(params + 2, parent); memset(&rv, 0, sizeof(rv)); g_value_init(&rv, G_TYPE_INT); g_value_set_int(&rv, default_group_to_use); signal_id = g_signal_lookup("new-toplevel-window", xkl_engine_get_type()); g_signal_emitv(params, signal_id, 0, &rv); default_group_to_use = g_value_get_int(&rv); if (default_group_to_use == -1) { Window transient_for = 0; if (XGetTransientForHint(xkl_engine_get_display(engine), toplevel_win, &transient_for)) { if (transient_for) { XklState trans_state; gboolean have_state = xkl_engine_get_toplevel_window_state(engine, transient_for, &trans_state); if (have_state) { default_group_to_use = trans_state.group; } } } } if (default_group_to_use == -1) default_group_to_use = xkl_engine_priv(engine, default_group); if (default_group_to_use != -1) state.group = default_group_to_use; xkl_engine_save_toplevel_window_state(engine, toplevel_win, &state); xkl_engine_select_input_merging(engine, toplevel_win, FocusChangeMask | PropertyChangeMask); if (default_group_to_use != -1) { if (xkl_engine_priv(engine, curr_toplvl_win) == toplevel_win) { if ((xkl_engine_priv(engine, secondary_groups_mask) & (1 << default_group_to_use)) != 0) xkl_engine_allow_one_switch_to_secondary_group (engine); xkl_engine_lock_group(engine, default_group_to_use); } } if (parent == (Window) NULL) parent = xkl_engine_get_registered_parent(engine, toplevel_win); xkl_debug(150, "done\n"); } /* * Checks the window and goes up */ gboolean xkl_engine_find_toplevel_window_bottom_to_top(XklEngine * engine, Window win, Window * toplevel_win_out) { Window parent = (Window) NULL, rwin = (Window) NULL, *children = NULL; guint num = 0; if (win == (Window) NULL || win == xkl_engine_priv(engine, root_window)) { *toplevel_win_out = win; xkl_last_error_message = "The window is either 0 or root"; return FALSE; } if (xkl_engine_if_window_has_wm_state(engine, win)) { *toplevel_win_out = win; return TRUE; } xkl_engine_priv(engine, last_error_code) = xkl_engine_query_tree(engine, win, &rwin, &parent, &children, &num); if (xkl_engine_priv(engine, last_error_code) != Success) { *toplevel_win_out = (Window) NULL; return FALSE; } if (children != NULL) XFree(children); return xkl_engine_find_toplevel_window_bottom_to_top(engine, parent, toplevel_win_out); } /* * Recursively finds "App window" (window with WM_STATE) for given window. * First, checks the window itself * Then, for first level of recursion, checks childen, * Then, goes to parent. * NOTE: root window cannot be "App window" under normal circumstances */ gboolean xkl_engine_find_toplevel_window(XklEngine * engine, Window win, Window * toplevel_win_out) { Window parent = (Window) NULL, rwin = (Window) NULL, *children = NULL, *child; guint num = 0; gboolean rv; if (win == (Window) NULL || win == PointerRoot || win == xkl_engine_priv(engine, root_window)) { *toplevel_win_out = (Window) NULL; xkl_last_error_message = "The window is either 0 or root"; xkl_debug(150, "Window " WINID_FORMAT " is either 0 or root so could not get the app window for it\n", win); return FALSE; } if (xkl_engine_if_window_has_wm_state(engine, win)) { *toplevel_win_out = win; return TRUE; } xkl_engine_priv(engine, last_error_code) = xkl_engine_query_tree(engine, win, &rwin, &parent, &children, &num); if (xkl_engine_priv(engine, last_error_code) != Success) { *toplevel_win_out = (Window) NULL; xkl_debug(150, "Could not get tree for window " WINID_FORMAT " so could not get the app window for it\n", win); return FALSE; } /* * Here we first check the children (in case win is just above some "App Window") * and then go upstairs */ child = children; while (num) { if (xkl_engine_if_window_has_wm_state(engine, *child)) { *toplevel_win_out = *child; if (children != NULL) XFree(children); return TRUE; } child++; num--; } if (children != NULL) XFree(children); rv = xkl_engine_find_toplevel_window_bottom_to_top(engine, parent, toplevel_win_out); if (!rv) xkl_debug(200, "Could not get the app window for " WINID_FORMAT "/%s\n", win, xkl_get_debug_window_title(engine, win)); return rv; } /* * Gets the state from the window property */ gboolean xkl_engine_get_toplevel_window_state(XklEngine * engine, Window toplevel_win, XklState * state_out) { Atom type_ret; int format_ret; unsigned long nitems, rest; CARD32 *prop = NULL; gboolean ret = FALSE; gint grp = -1; guint inds = 0; if ((XGetWindowProperty (xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms)[XKLAVIER_STATE], 0L, XKLAVIER_STATE_PROP_LENGTH, False, XA_INTEGER, &type_ret, &format_ret, &nitems, &rest, (unsigned char **) (void *) &prop) == Success) && (type_ret == XA_INTEGER) && (format_ret == 32)) { grp = prop[0]; if (grp >= xkl_engine_get_num_groups(engine) || grp < 0) grp = 0; inds = prop[1]; if (state_out != NULL) { state_out->group = grp; state_out->indicators = inds; } if (prop != NULL) XFree(prop); ret = TRUE; } if (ret) xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' has the group %d, indicators %X\n", toplevel_win, xkl_get_debug_window_title(engine, toplevel_win), grp, inds); else xkl_debug(150, "Appwin " WINID_FORMAT ", '%s' does not have state\n", toplevel_win, xkl_get_debug_window_title(engine, toplevel_win)); return ret; } /* * Deletes the state from the window properties */ void xkl_engine_remove_toplevel_window_state(XklEngine * engine, Window toplevel_win) { XDeleteProperty(xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms)[XKLAVIER_STATE]); } /* * Saves the state into the window properties */ void xkl_engine_save_toplevel_window_state(XklEngine * engine, Window toplevel_win, XklState * state) { CARD32 prop[XKLAVIER_STATE_PROP_LENGTH]; prop[0] = state->group; prop[1] = state->indicators; XChangeProperty(xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms)[XKLAVIER_STATE], XA_INTEGER, 32, PropModeReplace, (const unsigned char *) prop, XKLAVIER_STATE_PROP_LENGTH); xkl_debug(160, "Saved the group %d, indicators %X for appwin " WINID_FORMAT "\n", state->group, state->indicators, toplevel_win); } gboolean xkl_engine_is_toplevel_window_transparent(XklEngine * engine, Window toplevel_win) { Atom type_ret; int format_ret; unsigned long nitems, rest; CARD32 *prop = NULL; if ((XGetWindowProperty (xkl_engine_get_display(engine), toplevel_win, xkl_engine_priv(engine, atoms)[XKLAVIER_TRANSPARENT], 0L, 1, False, XA_INTEGER, &type_ret, &format_ret, &nitems, &rest, (unsigned char **) (void *) &prop) == Success) && (type_ret == XA_INTEGER) && (format_ret == 32)) { if (prop != NULL) XFree(prop); return TRUE; } return FALSE; } libxklavier-5.4/libxklavier/xklavier_util.c000066400000000000000000000204201213561201300212300ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" XklState * _xkl_state_copy(XklState * state) { XklState * copy; copy = g_new(XklState, 1); copy->group = state->group; copy->indicators = state->indicators; return copy; } G_DEFINE_BOXED_TYPE (XklState, xkl_state, _xkl_state_copy, g_free); XklState * xkl_engine_get_current_state(XklEngine * engine) { return &xkl_engine_priv(engine, curr_state); } const gchar * xkl_get_last_error() { return xkl_last_error_message; } gchar * xkl_engine_get_window_title(XklEngine * engine, Window w) { Atom type_ret; int format_ret; unsigned long nitems, rest; unsigned char *prop; if ((w == xkl_engine_priv(engine, root_window)) || (w == PointerRoot)) return g_strdup("ROOT"); if (Success == XGetWindowProperty(xkl_engine_get_display(engine), w, xkl_engine_priv(engine, atoms)[WM_NAME], 0L, -1L, False, XA_STRING, &type_ret, &format_ret, &nitems, &rest, &prop)) return (gchar *) prop; else return NULL; } gboolean xkl_engine_is_window_from_same_toplevel_window(XklEngine * engine, Window win1, Window win2) { Window app1, app2; return xkl_engine_find_toplevel_window(engine, win1, &app1) && xkl_engine_find_toplevel_window(engine, win2, &app2) && app1 == app2; } gboolean xkl_engine_get_state(XklEngine * engine, Window win, XklState * state_out) { Window app_win; if (!xkl_engine_find_toplevel_window(engine, win, &app_win)) { if (state_out != NULL) state_out->group = -1; return FALSE; } return xkl_engine_get_toplevel_window_state(engine, app_win, state_out); } void xkl_engine_delete_state(XklEngine * engine, Window win) { Window app_win; if (xkl_engine_find_toplevel_window(engine, win, &app_win)) xkl_engine_remove_toplevel_window_state(engine, app_win); } void xkl_engine_save_state(XklEngine * engine, Window win, XklState * state) { Window app_win; if (! (xkl_engine_is_listening_for (engine, XKLL_MANAGE_WINDOW_STATES))) return; if (xkl_engine_find_toplevel_window(engine, win, &app_win)) xkl_engine_save_toplevel_window_state(engine, app_win, state); } /* * Prepares the name of window suitable for debugging (32characters long). */ gchar * xkl_get_debug_window_title(XklEngine * engine, Window win) { static gchar sname[33]; gchar *name; strcpy(sname, "NULL"); if (win != (Window) NULL) { name = xkl_engine_get_window_title(engine, win); if (name != NULL) { g_snprintf(sname, sizeof(sname), "%.32s", name); g_free(name); } } return sname; } Window xkl_engine_get_current_window(XklEngine * engine) { return xkl_engine_priv(engine, curr_toplvl_win); } /* * Loads subtree. * All the windows with WM_STATE are added. * All the windows within level 0 are listened for focus and property */ gboolean xkl_engine_load_subtree(XklEngine * engine, Window window, gint level, XklState * init_state) { Window rwin = (Window) NULL, parent = (Window) NULL, *children = NULL, *child; guint num = 0; gboolean retval = True; xkl_engine_priv(engine, last_error_code) = xkl_engine_query_tree(engine, window, &rwin, &parent, &children, &num); if (xkl_engine_priv(engine, last_error_code) != Success) { return FALSE; } child = children; while (num) { if (xkl_engine_if_window_has_wm_state(engine, *child)) { xkl_debug(160, "Window " WINID_FORMAT " '%s' has WM_STATE so we'll add it\n", *child, xkl_get_debug_window_title(engine, *child)); xkl_engine_add_toplevel_window(engine, *child, window, TRUE, init_state); } else { xkl_debug(200, "Window " WINID_FORMAT " '%s' does not have have WM_STATE so we'll not add it\n", *child, xkl_get_debug_window_title(engine, *child)); if (level == 0) { xkl_debug(200, "But we are at level 0 so we'll spy on it\n"); xkl_engine_select_input_merging(engine, *child, FocusChangeMask | PropertyChangeMask); } else xkl_debug(200, "And we are at level %d so we'll not spy on it\n", level); retval = xkl_engine_load_subtree(engine, *child, level + 1, init_state); } child++; num--; } if (children != NULL) XFree(children); return retval; } /* * Checks whether given window has WM_STATE property (i.e. "App window"). */ gboolean xkl_engine_if_window_has_wm_state(XklEngine * engine, Window win) { /* ICCCM 4.1.3.1 */ Atom type = None; int format; unsigned long nitems; unsigned long after; unsigned char *data = NULL; /* Helps in the case of BadWindow error */ XGetWindowProperty(xkl_engine_get_display(engine), win, xkl_engine_priv(engine, atoms)[WM_STATE], 0, 0, False, xkl_engine_priv(engine, atoms)[WM_STATE], &type, &format, &nitems, &after, &data); if (data != NULL) XFree(data); /* To avoid an one-byte memory leak because after successfull return * data array always contains at least one nul byte (NULL-equivalent) */ return type != None; } /* * Finds out the official parent window (accortind to XQueryTree) */ Window xkl_engine_get_registered_parent(XklEngine * engine, Window win) { Window parent = (Window) NULL, rw = (Window) NULL, *children = NULL; guint nchildren = 0; xkl_engine_priv(engine, last_error_code) = xkl_engine_query_tree(engine, win, &rw, &parent, &children, &nchildren); if (children != NULL) XFree(children); return xkl_engine_priv(engine, last_error_code) == Success ? parent : (Window) NULL; } /* * Make sure about the result. Origial XQueryTree is pretty stupid beast:) */ Status xkl_engine_query_tree(XklEngine * engine, Window w, Window * root_out, Window * parent_out, Window ** children_out, guint * nchildren_out) { gboolean result; unsigned int nc; result = (gboolean) XQueryTree(xkl_engine_get_display(engine), w, root_out, parent_out, children_out, &nc); *nchildren_out = nc; if (!result) { xkl_debug(160, "Could not get tree info for window " WINID_FORMAT ": %d\n", w, result); xkl_last_error_message = "Could not get the tree info"; } return result ? Success : FirstExtensionError; } const gchar * xkl_event_get_name(gint type) { /* Not really good to use the fact of consecutivity but X protocol is already standartized so... */ static const gchar *evt_names[] = { "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify", "LASTEvent" }; type -= KeyPress; if (type < 0 || type >= (sizeof(evt_names) / sizeof(evt_names[0]))) return "UNKNOWN"; return evt_names[type]; } void xkl_engine_update_current_state(XklEngine * engine, int group, unsigned indicators, const char reason[]) { xkl_debug(150, "Updating the current state with [g:%d/i:%u], reason: %s\n", group, indicators, reason); xkl_engine_priv(engine, curr_state).group = group; xkl_engine_priv(engine, curr_state).indicators = indicators; } libxklavier-5.4/libxklavier/xklavier_xkb.c000066400000000000000000000464751213561201300210610ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "xklavier_private.h" #include "xklavier_private_xkb.h" #ifdef HAVE_XINPUT #include #include #endif #ifdef LIBXKBFILE_PRESENT const gchar ** xkl_xkb_get_groups_names(XklEngine * engine) { return (const gchar **) xkl_engine_backend(engine, XklXkb, group_names); } const gchar ** xkl_xkb_get_indicators_names(XklEngine * engine) { return (const gchar **) xkl_engine_backend(engine, XklXkb, indicator_names); } gint xkl_xkb_pause_listen(XklEngine * engine) { XkbSelectEvents(xkl_engine_get_display(engine), xkl_engine_backend(engine, XklXkb, device_id), XkbAllEventsMask, 0); return 0; } gint xkl_xkb_resume_listen(XklEngine * engine) { #ifdef HAVE_XINPUT int xitype; XEventClass xiclass; #endif /* What events we want */ #define XKB_EVT_MASK \ (XkbStateNotifyMask| \ XkbNamesNotifyMask| \ XkbControlsNotifyMask| \ XkbIndicatorStateNotifyMask| \ XkbIndicatorMapNotifyMask| \ XkbNewKeyboardNotifyMask) Display *display = xkl_engine_get_display(engine); XkbSelectEvents(display, xkl_engine_backend(engine, XklXkb, device_id), XKB_EVT_MASK, XKB_EVT_MASK); #define XKB_STATE_EVT_DTL_MASK \ (XkbGroupStateMask) XkbSelectEventDetails(display, xkl_engine_backend(engine, XklXkb, device_id), XkbStateNotify, XKB_STATE_EVT_DTL_MASK, XKB_STATE_EVT_DTL_MASK); #define XKB_NAMES_EVT_DTL_MASK \ (XkbGroupNamesMask|XkbIndicatorNamesMask) XkbSelectEventDetails(display, xkl_engine_backend(engine, XklXkb, device_id), XkbNamesNotify, XKB_NAMES_EVT_DTL_MASK, XKB_NAMES_EVT_DTL_MASK); #ifdef HAVE_XINPUT if (xkl_engine_priv(engine, features) & XKLF_DEVICE_DISCOVERY) { DevicePresence(display, xitype, xiclass); XSelectExtensionEvent(display, xkl_engine_priv(engine, root_window), &xiclass, 1); xkl_engine_backend(engine, XklXkb, xi_event_type) = xitype; } else xkl_engine_backend(engine, XklXkb, xi_event_type) = -1; #endif return 0; } guint xkl_xkb_get_max_num_groups(XklEngine * engine) { return xkl_engine_priv(engine, features) & XKLF_MULTIPLE_LAYOUTS_SUPPORTED ? XkbNumKbdGroups : 1; } guint xkl_xkb_get_num_groups(XklEngine * engine) { return xkl_engine_backend(engine, XklXkb, cached_desc)->ctrls->num_groups; } #define KBD_MASK \ ( 0 ) #define CTRLS_MASK \ ( XkbSlowKeysMask ) #define NAMES_MASK \ ( XkbGroupNamesMask | XkbIndicatorNamesMask ) void xkl_xkb_free_all_info(XklEngine * engine) { gint i; gchar **pi = xkl_engine_backend(engine, XklXkb, indicator_names); XkbDescPtr desc; for (i = 0; i < XkbNumIndicators; i++, pi++) { /* only free non-empty ones */ if (*pi && **pi) XFree(*pi); } desc = xkl_engine_backend(engine, XklXkb, cached_desc); if (desc != NULL) { int i; char **group_name = xkl_engine_backend(engine, XklXkb, group_names); for (i = desc->ctrls->num_groups; --i >= 0; group_name++) if (*group_name) { XFree(*group_name); *group_name = NULL; } XkbFreeKeyboard(desc, XkbAllComponentsMask, True); xkl_engine_backend(engine, XklXkb, cached_desc) = NULL; } /* just in case - never actually happens... */ desc = xkl_engine_backend(engine, XklXkb, actual_desc); if (desc != NULL) { XkbFreeKeyboard(desc, XkbAllComponentsMask, True); xkl_engine_backend(engine, XklXkb, actual_desc) = NULL; } } static gboolean xkl_xkb_load_actual_desc(XklEngine * engine) { gboolean rv = FALSE; Status status; Display *display = xkl_engine_get_display(engine); XkbDescPtr desc = XkbGetMap(display, KBD_MASK, xkl_engine_backend(engine, XklXkb, device_id)); xkl_engine_backend(engine, XklXkb, actual_desc) = desc; if (desc != NULL) { rv = Success == (status = XkbGetControls(display, CTRLS_MASK, desc)) && Success == (status = XkbGetNames(display, NAMES_MASK, desc)) && Success == (status = XkbGetIndicatorMap(display, XkbAllIndicatorsMask, desc)); if (!rv) { xkl_last_error_message = "Could not load controls/names/indicators"; xkl_debug(0, "%s: %d\n", xkl_last_error_message, status); XkbFreeKeyboard(desc, XkbAllComponentsMask, True); xkl_engine_backend(engine, XklXkb, actual_desc) = NULL; } } return rv; } gboolean xkl_xkb_if_cached_info_equals_actual(XklEngine * engine) { gint i; Atom *pa1, *pa2; gboolean rv = FALSE; if (xkl_xkb_load_actual_desc(engine)) { /* First, compare the number of groups */ XkbDescPtr cached = xkl_engine_backend(engine, XklXkb, cached_desc); XkbDescPtr actual = xkl_engine_backend(engine, XklXkb, actual_desc); if (cached->ctrls->num_groups == actual->ctrls->num_groups) { /* Then, compare group names, just atoms */ pa1 = cached->names->groups; pa2 = actual->names->groups; for (i = cached->ctrls->num_groups; --i >= 0; pa1++, pa2++) if (*pa1 != *pa2) break; /* Then, compare indicator names, just atoms */ if (i < 0) { pa1 = cached->names->indicators; pa2 = actual->names->indicators; for (i = XkbNumIndicators; --i >= 0; pa1++, pa2++) if (*pa1 != *pa2) break; rv = i < 0; } } /* * in case of failure, reuse in _XklXkbLoadAllInfo * in case of success - free it */ if (rv) { XkbFreeKeyboard(actual, XkbAllComponentsMask, True); xkl_engine_backend(engine, XklXkb, actual_desc) = NULL; } } else { xkl_debug(0, "Could not load the XkbDescPtr for comparison\n"); } return rv; } /* * Load some XKB parameters */ gboolean xkl_xkb_load_all_info(XklEngine * engine) { gint i; Atom *pa; gchar **group_name; gchar **pi = xkl_engine_backend(engine, XklXkb, indicator_names); Display *display = xkl_engine_get_display(engine); XkbDescPtr actual = xkl_engine_backend(engine, XklXkb, actual_desc); XkbDescPtr cached; if (actual == NULL) if (!xkl_xkb_load_actual_desc(engine)) { xkl_last_error_message = "Could not load keyboard"; return FALSE; } /* take it from the cache (in most cases LoadAll is called from ResetAll which in turn ...) */ cached = actual = xkl_engine_backend(engine, XklXkb, actual_desc); xkl_engine_backend(engine, XklXkb, cached_desc) = xkl_engine_backend(engine, XklXkb, actual_desc); xkl_engine_backend(engine, XklXkb, actual_desc) = NULL; /* First, output the number of the groups */ xkl_debug(200, "found %d groups\n", cached->ctrls->num_groups); /* Then, cache (and output) the names of the groups */ pa = cached->names->groups; group_name = xkl_engine_backend(engine, XklXkb, group_names); for (i = cached->ctrls->num_groups; --i >= 0; pa++, group_name++) { *group_name = XGetAtomName(display, *pa == None ? XInternAtom(display, "-", False) : *pa); xkl_debug(200, "Group %d has name [%s]\n", i, *group_name); } xkl_engine_priv(engine, last_error_code) = XkbGetIndicatorMap(display, XkbAllIndicatorsMask, cached); if (xkl_engine_priv(engine, last_error_code) != Success) { xkl_last_error_message = "Could not load indicator map"; return FALSE; } /* Then, cache (and output) the names of the indicators */ pa = cached->names->indicators; for (i = XkbNumIndicators; --i >= 0; pi++, pa++) { Atom a = *pa; if (a != None) *pi = XGetAtomName(display, a); else *pi = ""; xkl_debug(200, "Indicator[%d] is %s\n", i, *pi); } xkl_debug(200, "Real indicators are %X\n", cached->indicators->phys_indicators); g_signal_emit_by_name(engine, "X-config-changed"); return TRUE; } void xkl_xkb_lock_group(XklEngine * engine, gint group) { Display *display = xkl_engine_get_display(engine); xkl_debug(100, "Posted request for change the group to %d ##\n", group); XkbLockGroup(display, xkl_engine_backend(engine, XklXkb, device_id), group); XSync(display, False); } /* * Updates current internal state from X state */ void xkl_xkb_get_server_state(XklEngine * engine, XklState * current_state_out) { XkbStateRec state; Display *display = xkl_engine_get_display(engine); current_state_out->group = 0; if (Success == XkbGetState(display, xkl_engine_backend(engine, XklXkb, device_id), &state)) current_state_out->group = state.locked_group; if (Success == XkbGetIndicatorState(display, xkl_engine_backend(engine, XklXkb, device_id), ¤t_state_out->indicators)) current_state_out->indicators &= xkl_engine_backend(engine, XklXkb, cached_desc)->indicators-> phys_indicators; else current_state_out->indicators = 0; } /* * Actually taken from mxkbledpanel, valueChangedProc */ gboolean xkl_xkb_set_indicator(XklEngine * engine, gint indicator_num, gboolean set) { XkbIndicatorMapPtr map; Display *display = xkl_engine_get_display(engine); XkbDescPtr cached = xkl_engine_backend(engine, XklXkb, cached_desc); map = cached->indicators->maps + indicator_num; /* The 'flags' field tells whether this indicator is automatic * (XkbIM_NoExplicit - 0x80), explicit (XkbIM_NoAutomatic - 0x40), * or neither (both - 0xC0). * * If NoAutomatic is set, the server ignores the rest of the * fields in the indicator map (i.e. it disables automatic control * of the LED). If NoExplicit is set, the server prevents clients * from explicitly changing the value of the LED (using the core * protocol *or* XKB). If NoAutomatic *and* NoExplicit are set, * the LED cannot be changed (unless you change the map first). * If neither NoAutomatic nor NoExplicit are set, the server will * change the LED according to the indicator map, but clients can * override that (until the next automatic change) using the core * protocol or XKB. */ switch (map->flags & (XkbIM_NoExplicit | XkbIM_NoAutomatic)) { case XkbIM_NoExplicit | XkbIM_NoAutomatic: { /* Can do nothing. Just ignore the indicator */ return TRUE; } case XkbIM_NoAutomatic: { if (cached->names->indicators[indicator_num] != None) XkbSetNamedIndicator(display, xkl_engine_backend (engine, XklXkb, device_id), cached->names-> indicators [indicator_num], set, False, NULL); else { XKeyboardControl xkc; xkc.led = indicator_num; xkc.led_mode = set ? LedModeOn : LedModeOff; XChangeKeyboardControl(display, KBLed | KBLedMode, &xkc); XSync(display, False); } return TRUE; } case XkbIM_NoExplicit: break; } /* The 'ctrls' field tells what controls tell this indicator to * to turn on: RepeatKeys (0x1), SlowKeys (0x2), BounceKeys (0x4), * StickyKeys (0x8), MouseKeys (0x10), AccessXKeys (0x20), * TimeOut (0x40), Feedback (0x80), ToggleKeys (0x100), * Overlay1 (0x200), Overlay2 (0x400), GroupsWrap (0x800), * InternalMods (0x1000), IgnoreLockMods (0x2000), * PerKeyRepeat (0x3000), or ControlsEnabled (0x4000) */ if (map->ctrls) { gulong which = map->ctrls; XkbGetControls(display, XkbAllControlsMask, cached); if (set) cached->ctrls->enabled_ctrls |= which; else cached->ctrls->enabled_ctrls &= ~which; XkbSetControls(display, which | XkbControlsEnabledMask, cached); } /* The 'which_groups' field tells when this indicator turns on * for the 'groups' field: base (0x1), latched (0x2), locked (0x4), * or effective (0x8). */ if (map->groups) { gint i; guint group = 1; /* Turning on a group indicator is kind of tricky. For * now, we will just Latch or Lock the first group we find * if that is what this indicator does. Otherwise, we're * just going to punt and get out of here. */ if (set) { for (i = XkbNumKbdGroups; --i >= 0;) if ((1 << i) & map->groups) { group = i; break; } if (map->which_groups & (XkbIM_UseLocked | XkbIM_UseEffective)) { /* Important: Groups should be ignored here - because they are handled separately! */ /* XklLockGroup( group ); */ } else if (map->which_groups & XkbIM_UseLatched) XkbLatchGroup(display, xkl_engine_backend(engine, XklXkb, device_id), group); else { /* Can do nothing. Just ignore the indicator */ return TRUE; } } else /* Turning off a group indicator will mean that we just * Lock the first group that this indicator doesn't watch. */ { for (i = XkbNumKbdGroups; --i >= 0;) if (!((1 << i) & map->groups)) { group = i; break; } xkl_xkb_lock_group(engine, group); } } /* The 'which_mods' field tells when this indicator turns on * for the modifiers: base (0x1), latched (0x2), locked (0x4), * or effective (0x8). * * The 'real_mods' field tells whether this turns on when one of * the real X modifiers is set: Shift (0x1), Lock (0x2), Control (0x4), * Mod1 (0x8), Mod2 (0x10), Mod3 (0x20), Mod4 (0x40), or Mod5 (0x80). * * The 'virtual_mods' field tells whether this turns on when one of * the virtual modifiers is set. * * The 'mask' field tells what real X modifiers the virtual_modifiers * map to? */ if (map->mods.real_mods || map->mods.mask) { guint affect, mods; affect = (map->mods.real_mods | map->mods.mask); mods = set ? affect : 0; if (map->which_mods & (XkbIM_UseLocked | XkbIM_UseEffective)) XkbLockModifiers(display, xkl_engine_backend(engine, XklXkb, device_id), affect, mods); else if (map->which_mods & XkbIM_UseLatched) XkbLatchModifiers(display, xkl_engine_backend(engine, XklXkb, device_id), affect, mods); else { return TRUE; } } return TRUE; } #endif gint xkl_xkb_init(XklEngine * engine) { Display *display = xkl_engine_get_display(engine); #ifdef LIBXKBFILE_PRESENT gint opcode; gboolean xkl_xkb_ext_present; int xi_opc; xkl_engine_priv(engine, backend_id) = "XKB"; xkl_engine_priv(engine, features) = XKLF_CAN_TOGGLE_INDICATORS | XKLF_CAN_OUTPUT_CONFIG_AS_ASCII | XKLF_CAN_OUTPUT_CONFIG_AS_BINARY; xkl_engine_priv(engine, activate_config_rec) = xkl_xkb_activate_config_rec; xkl_engine_priv(engine, init_config_registry) = xkl_xkb_init_config_registry; xkl_engine_priv(engine, load_config_registry) = xkl_xkb_load_config_registry; xkl_engine_priv(engine, write_config_rec_to_file) = xkl_xkb_write_config_rec_to_file; xkl_engine_priv(engine, get_groups_names) = xkl_xkb_get_groups_names; xkl_engine_priv(engine, get_indicators_names) = xkl_xkb_get_indicators_names; xkl_engine_priv(engine, get_max_num_groups) = xkl_xkb_get_max_num_groups; xkl_engine_priv(engine, get_num_groups) = xkl_xkb_get_num_groups; xkl_engine_priv(engine, lock_group) = xkl_xkb_lock_group; xkl_engine_priv(engine, process_x_event) = xkl_xkb_process_x_event; xkl_engine_priv(engine, process_x_error) = xkl_xkb_process_x_error; xkl_engine_priv(engine, free_all_info) = xkl_xkb_free_all_info; xkl_engine_priv(engine, if_cached_info_equals_actual) = xkl_xkb_if_cached_info_equals_actual; xkl_engine_priv(engine, load_all_info) = xkl_xkb_load_all_info; xkl_engine_priv(engine, get_server_state) = xkl_xkb_get_server_state; xkl_engine_priv(engine, pause_listen) = xkl_xkb_pause_listen; xkl_engine_priv(engine, resume_listen) = xkl_xkb_resume_listen; xkl_engine_priv(engine, set_indicators) = xkl_xkb_set_indicators; xkl_engine_priv(engine, finalize) = xkl_xkb_term; if (getenv("XKL_XKB_DISABLE") != NULL) return -1; xkl_engine_priv(engine, backend) = g_new0(XklXkb, 1); xkl_engine_backend(engine, XklXkb, device_id) = XkbUseCoreKbd; xkl_xkb_ext_present = XkbQueryExtension(display, &opcode, &xkl_engine_backend(engine, XklXkb, event_type), &xkl_engine_backend(engine, XklXkb, error_code), NULL, NULL); if (!xkl_xkb_ext_present) return -1; xkl_debug(160, "xkbEvenType: %X, xkbError: %X, display: %p, root: " WINID_FORMAT "\n", xkl_engine_backend(engine, XklXkb, event_type), xkl_engine_backend(engine, XklXkb, error_code), display, xkl_engine_priv(engine, root_window)); xkl_engine_priv(engine, base_config_atom) = XInternAtom(display, _XKB_RF_NAMES_PROP_ATOM, False); xkl_engine_priv(engine, backup_config_atom) = XInternAtom(display, "_XKB_RULES_NAMES_BACKUP", False); xkl_engine_priv(engine, default_model) = "pc101"; xkl_engine_priv(engine, default_layout) = "us"; /* First, we have to assign xkl_vtable - because this function uses it */ if (xkl_xkb_multiple_layouts_supported(engine)) xkl_engine_priv(engine, features) |= XKLF_MULTIPLE_LAYOUTS_SUPPORTED; #if HAVE_XINPUT if (XQueryExtension (display, "XInputExtension", &xi_opc, &xkl_engine_backend(engine, XklXkb, xi_event_type), &xkl_engine_backend(engine, XklXkb, xi_error_code))) { XExtensionVersion *ev = XGetExtensionVersion(display, "XInputExtension"); xkl_debug(150, "XInputExtension found (%d, %d, %d) version %d.%d\n", xi_opc, xkl_engine_backend(engine, XklXkb, xi_event_type), xkl_engine_backend(engine, XklXkb, xi_error_code), ev->major_version, ev->minor_version); /* DevicePresence is available from XI 1.4 */ if ((ev->major_version * 10) + ev->minor_version >= 14) { xkl_debug(200, "DevicePresence available\n"); xkl_engine_priv(engine, features) |= XKLF_DEVICE_DISCOVERY; } else { xkl_debug(200, "DevicePresence not available\n"); } XFree(ev); } else { xkl_debug(0, "XInputExtension not found\n"); xkl_engine_backend(engine, XklXkb, xi_event_type) = -1; xkl_engine_backend(engine, XklXkb, xi_error_code) = -1; } #endif return 0; #else xkl_debug(160, "NO XKB LIBS, display: %p, root: " WINID_FORMAT "\n", display, xkl_engine_priv(engine, root_window)); return -1; #endif } void xkl_xkb_term(XklEngine * engine) { } #ifdef LIBXKBFILE_PRESENT const gchar * xkl_xkb_event_get_name(gint xkb_type) { /* Not really good to use the fact of consecutivity but XKB protocol extension is already standartized so... */ static const gchar *evt_names[] = { "XkbNewKeyboardNotify", "XkbMapNotify", "XkbStateNotify", "XkbControlsNotify", "XkbIndicatorStateNotify", "XkbIndicatorMapNotify", "XkbNamesNotify", "XkbCompatMapNotify", "XkbBellNotify", "XkbActionMessage", "XkbAccessXNotify", "XkbExtensionDeviceNotify", "LASTEvent" }; xkb_type -= XkbNewKeyboardNotify; if (xkb_type < 0 || xkb_type >= (sizeof(evt_names) / sizeof(evt_names[0]))) return "UNKNOWN/OOR"; return evt_names[xkb_type]; } #endif libxklavier-5.4/libxklavier/xklavier_xmm.c000077500000000000000000000221701213561201300210630ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "config.h" #include "xklavier_private.h" #include "xklavier_private_xmm.h" #define SHORTCUT_OPTION_PREFIX "grp:" const gchar ** xkl_xmm_get_groups_names(XklEngine * engine) { return (const gchar **) xkl_engine_backend(engine, XklXmm, current_config).layouts; } const gchar ** xkl_xmm_get_indicators_names(XklEngine * engine) { return NULL; } void xkl_xmm_shortcuts_grab(XklEngine * engine) { const XmmShortcut *shortcut; const XmmSwitchOption *option = xkl_xmm_shortcut_get_current(engine); xkl_debug(150, "Found shortcut option: %p\n", option); if (option == NULL) return; shortcut = option->shortcuts; while (shortcut->keysym != XK_VoidSymbol) { int keycode = XKeysymToKeycode(xkl_engine_get_display(engine), shortcut->keysym); xkl_xmm_grab_ignoring_indicators(engine, keycode, shortcut->modifiers); shortcut++; } } void xkl_xmm_shortcuts_ungrab(XklEngine * engine) { const XmmShortcut *shortcut; const XmmSwitchOption *option = xkl_xmm_shortcut_get_current(engine); if (option == NULL) return; shortcut = option->shortcuts; while (shortcut->keysym != XK_VoidSymbol) { int keycode = XKeysymToKeycode(xkl_engine_get_display(engine), shortcut->keysym); xkl_xmm_ungrab_ignoring_indicators(engine, keycode, shortcut->modifiers); shortcut++; } } XmmSwitchOption * xkl_xmm_shortcut_get_current(XklEngine * engine) { const gchar *option_name = xkl_xmm_shortcut_get_current_option_name(engine); xkl_debug(150, "Configured switch option: [%s]\n", option_name); if (option_name == NULL) return NULL; return (XmmSwitchOption *) g_hash_table_lookup(xkl_engine_backend (engine, XklXmm, switch_options), (gconstpointer) option_name); } const gchar * xkl_xmm_shortcut_get_current_option_name(XklEngine * engine) { gchar **option = xkl_engine_backend(engine, XklXmm, current_config).options; if (option == NULL) return NULL; while (*option != NULL) { /* starts with "grp:" */ if (strstr(*option, SHORTCUT_OPTION_PREFIX) != NULL) { return *option + sizeof SHORTCUT_OPTION_PREFIX - 1; } option++; } return NULL; } const XmmSwitchOption * xkl_xmm_find_switch_option(XklEngine * engine, gint keycode, guint state, gint * current_shortcut_rv) { const XmmSwitchOption *rv = xkl_xmm_shortcut_get_current(engine); if (rv != NULL) { const XmmShortcut *sc = rv->shortcuts; while (sc->keysym != XK_VoidSymbol) { if ((XKeysymToKeycode (xkl_engine_get_display(engine), sc->keysym) == keycode) && ((state & sc->modifiers) == sc->modifiers)) { return rv; } sc++; } } return NULL; } gint xkl_xmm_resume_listen(XklEngine * engine) { if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS)) xkl_xmm_shortcuts_grab(engine); return 0; } gint xkl_xmm_pause_listen(XklEngine * engine) { if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS)) xkl_xmm_shortcuts_ungrab(engine); return 0; } guint xkl_xmm_get_max_num_groups(XklEngine * engine) { return 0; } guint xkl_xmm_get_num_groups(XklEngine * engine) { gint rv = 0; gchar **p = xkl_engine_backend(engine, XklXmm, current_config).layouts; if (p != NULL) while (*p++ != NULL) rv++; return rv; } void xkl_xmm_free_all_info(XklEngine * engine) { gchar *current_rules = xkl_engine_backend(engine, XklXmm, current_rules); if (current_rules != NULL) { g_free(current_rules); current_rules = NULL; xkl_engine_backend(engine, XklXmm, current_rules) = NULL; } xkl_config_rec_reset(&xkl_engine_backend (engine, XklXmm, current_config)); } gboolean xkl_xmm_if_cached_info_equals_actual(XklEngine * engine) { return FALSE; } gboolean xkl_xmm_load_all_info(XklEngine * engine) { return xkl_config_rec_get_full_from_server(&xkl_engine_backend (engine, XklXmm, current_rules), &xkl_engine_backend(engine, XklXmm, current_config), engine); } void xkl_xmm_get_server_state(XklEngine * engine, XklState * state) { unsigned char *propval = NULL; Atom actual_type; int actual_format; unsigned long bytes_remaining; unsigned long actual_items; int result; memset(state, 0, sizeof(*state)); result = XGetWindowProperty(xkl_engine_get_display(engine), xkl_engine_priv(engine, root_window), xkl_engine_backend(engine, XklXmm, state_atom), 0L, 1L, False, XA_INTEGER, &actual_type, &actual_format, &actual_items, &bytes_remaining, &propval); if (Success == result) { if (actual_format == 32 || actual_items == 1) { state->group = *(CARD32 *) propval; } else { xkl_debug(160, "Could not get the xmodmap current group\n"); } XFree(propval); } else { xkl_debug(160, "Could not get the xmodmap current group: %d\n", result); } } void xkl_xmm_actualize_group(XklEngine * engine, gint group) { char cmd[1024]; int res; const gchar *layout_name = NULL; if (xkl_xmm_get_num_groups(engine) < group) return; layout_name = xkl_engine_backend(engine, XklXmm, current_config).layouts[group]; g_snprintf(cmd, sizeof cmd, "xmodmap %s/xmodmap.%s", XMODMAP_BASE, layout_name); res = system(cmd); if (res > 0) { xkl_debug(0, "xmodmap error %d\n", res); } else if (res < 0) { xkl_debug(0, "Could not execute xmodmap: %d\n", res); } XSync(xkl_engine_get_display(engine), False); } void xkl_xmm_lock_group(XklEngine * engine, gint group) { CARD32 propval; Display *display; if (xkl_xmm_get_num_groups(engine) < group) return; /* updating the status property */ propval = group; display = xkl_engine_get_display(engine); XChangeProperty(display, xkl_engine_priv(engine, root_window), xkl_engine_backend(engine, XklXmm, state_atom), XA_INTEGER, 32, PropModeReplace, (unsigned char *) &propval, 1); XSync(display, False); } void xkl_xmm_set_indicators(XklEngine * engine, const XklState * window_state) { } gint xkl_xmm_init(XklEngine * engine) { Display *display; xkl_engine_priv(engine, backend_id) = "xmodmap"; xkl_engine_priv(engine, features) = XKLF_MULTIPLE_LAYOUTS_SUPPORTED | XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT; xkl_engine_priv(engine, activate_config_rec) = xkl_xmm_activate_config_rec; xkl_engine_priv(engine, init_config_registry) = xkl_xmm_init_config_registry; xkl_engine_priv(engine, load_config_registry) = xkl_xmm_load_config_registry; xkl_engine_priv(engine, write_config_rec_to_file) = NULL; xkl_engine_priv(engine, get_groups_names) = xkl_xmm_get_groups_names; xkl_engine_priv(engine, get_indicators_names) = xkl_xmm_get_indicators_names; xkl_engine_priv(engine, get_max_num_groups) = xkl_xmm_get_max_num_groups; xkl_engine_priv(engine, get_num_groups) = xkl_xmm_get_num_groups; xkl_engine_priv(engine, lock_group) = xkl_xmm_lock_group; xkl_engine_priv(engine, process_x_event) = xkl_xmm_process_x_event; xkl_engine_priv(engine, process_x_error) = NULL; xkl_engine_priv(engine, free_all_info) = xkl_xmm_free_all_info; xkl_engine_priv(engine, if_cached_info_equals_actual) = xkl_xmm_if_cached_info_equals_actual; xkl_engine_priv(engine, load_all_info) = xkl_xmm_load_all_info; xkl_engine_priv(engine, get_server_state) = xkl_xmm_get_server_state; xkl_engine_priv(engine, pause_listen) = xkl_xmm_pause_listen; xkl_engine_priv(engine, resume_listen) = xkl_xmm_resume_listen; xkl_engine_priv(engine, set_indicators) = xkl_xmm_set_indicators; xkl_engine_priv(engine, finalize) = xkl_xmm_term; if (getenv("XKL_XMODMAP_DISABLE") != NULL) return -1; display = xkl_engine_get_display(engine); xkl_engine_priv(engine, base_config_atom) = XInternAtom(display, "_XMM_NAMES", False); xkl_engine_priv(engine, backup_config_atom) = XInternAtom(display, "_XMM_NAMES_BACKUP", False); xkl_engine_priv(engine, backend) = g_new0(XklXmm, 1); xkl_engine_backend(engine, XklXmm, state_atom) = XInternAtom(display, "_XMM_STATE", False); xkl_engine_priv(engine, default_model) = "generic"; xkl_engine_priv(engine, default_layout) = "us"; xkl_xmm_init_switch_options((XklXmm *) xkl_engine_priv(engine, backend)); return 0; } void xkl_xmm_term(XklEngine * engine) { xkl_xmm_term_switch_options((XklXmm *) xkl_engine_priv(engine, backend)); } libxklavier-5.4/libxklavier/xklavier_xmm_opts.c000066400000000000000000000065171213561201300221340ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "config.h" #include "xklavier_private.h" #include "xklavier_private_xmm.h" #define SHORTCUT_OPTION_PREFIX "grp:" static XmmSwitchOption options[] = { {{{XK_Alt_R, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Alt_L, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Caps_Lock, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Caps_Lock, ShiftMask} , {XK_VoidSymbol} } , {1}}, {{{XK_Shift_R, ShiftMask} , {XK_Shift_L, ShiftMask} , {XK_VoidSymbol} } , {1, -1}}, {{{XK_Alt_R, Mod1Mask} , {XK_Alt_L, Mod1Mask} , {XK_VoidSymbol} } , {1, -1}}, {{{XK_Control_R, ControlMask} , {XK_Control_L, ControlMask} , {XK_VoidSymbol} } , {1, -1}}, {{{XK_Control_R, ShiftMask} , {XK_Control_L, ShiftMask} , {XK_Shift_R, ControlMask} , {XK_Shift_L, ControlMask} , {XK_VoidSymbol} } , {1, -1, 1, -1}}, {{{XK_Control_R, Mod1Mask} , {XK_Control_L, Mod1Mask} , {XK_Alt_R, ControlMask} , {XK_Alt_L, ControlMask} , {XK_VoidSymbol} } , {1, -1, 1, -1}}, {{{XK_Shift_R, Mod1Mask} , {XK_Shift_L, Mod1Mask} , {XK_Alt_R, ShiftMask} , {XK_Alt_L, ShiftMask} , {XK_VoidSymbol} } , {1, -1, 1, -1}}, {{{XK_Menu, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Super_L, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Super_R, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Shift_L, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Shift_R, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Control_L, 0} , {XK_VoidSymbol} } , {1}}, {{{XK_Control_R, 0} , {XK_VoidSymbol} } , {1}} }; static const gchar *option_names[] = { "ralt_toggle", "lalt_toggle", "caps_toggle", "shift_caps_toggle", "shifts_toggle", "alts_toggle", "ctrls_toggle", "ctrl_shift_toggle", "ctrl_alt_toggle", "alt_shift_toggle", "menu_toggle", "lwin_toggle", "rwin_toggle", "lshift_toggle", "rshift_toggle", "lctrl_toggle", "rctrl_toggle" }; void xkl_xmm_init_switch_options(XklXmm * xmm) { int i; const gchar **pname = option_names; const XmmSwitchOption *poption = options; xmm->switch_options = g_hash_table_new(g_str_hash, g_str_equal); for (i = sizeof(option_names) / sizeof(option_names[0]); --i >= 0;) g_hash_table_insert(xmm->switch_options, (gpointer) (*pname++), (gpointer) (poption++)); } void xkl_xmm_term_switch_options(XklXmm * xmm) { g_hash_table_destroy(xmm->switch_options); xmm->switch_options = NULL; } libxklavier-5.4/m4/000077500000000000000000000000001213561201300142105ustar00rootroot00000000000000libxklavier-5.4/m4/introspection.m4000066400000000000000000000066141213561201300173610ustar00rootroot00000000000000dnl -*- mode: autoconf -*- dnl Copyright 2009 Johan Dahlin dnl dnl This file is free software; the author(s) gives unlimited dnl permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl # serial 1 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], [ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([LT_INIT],[$0])dnl setup libtool first dnl enable/disable introspection m4_if([$2], [require], [dnl enable_introspection=yes ],[dnl AC_ARG_ENABLE(introspection, AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], [Enable introspection for this build]),, [enable_introspection=auto]) ])dnl AC_MSG_CHECKING([for gobject-introspection]) dnl presence/version checking AS_CASE([$enable_introspection], [no], [dnl found_introspection="no (disabled, use --enable-introspection to enable)" ],dnl [yes],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0],, AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) ],dnl [auto],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) ],dnl [dnl AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) ])dnl AC_MSG_RESULT([$found_introspection]) INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi AC_SUBST(INTROSPECTION_SCANNER) AC_SUBST(INTROSPECTION_COMPILER) AC_SUBST(INTROSPECTION_GENERATE) AC_SUBST(INTROSPECTION_GIRDIR) AC_SUBST(INTROSPECTION_TYPELIBDIR) AC_SUBST(INTROSPECTION_CFLAGS) AC_SUBST(INTROSPECTION_LIBS) AC_SUBST(INTROSPECTION_MAKEFILE) AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") ]) dnl Usage: dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) ]) dnl Usage: dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ]) libxklavier-5.4/m4/vapigen.m4000066400000000000000000000064771213561201300161210ustar00rootroot00000000000000dnl vapigen.m4 dnl dnl Copyright 2012 Evan Nemerson dnl dnl This library is free software; you can redistribute it and/or dnl modify it under the terms of the GNU Lesser General Public dnl License as published by the Free Software Foundation; either dnl version 2.1 of the License, or (at your option) any later version. dnl dnl This library is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl Lesser General Public License for more details. dnl dnl You should have received a copy of the GNU Lesser General Public dnl License along with this library; if not, write to the Free Software dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # VAPIGEN_CHECK([VERSION], [API_VERSION], [FOUND_INTROSPECTION], [DEFAULT]) # -------------------------------------- # Check vapigen existence and version # # See http://live.gnome.org/Vala/UpstreamGuide for detailed documentation AC_DEFUN([VAPIGEN_CHECK], [ AS_IF([test "x$3" != "xyes"], [ m4_provide_if([GOBJECT_INTROSPECTION_CHECK], [], [ m4_provide_if([GOBJECT_INTROSPECTION_REQUIRE], [], [ AC_MSG_ERROR([[You must call GOBJECT_INTROSPECTION_CHECK or GOBJECT_INTROSPECTION_REQUIRE before using VAPIGEN_CHECK unless using the FOUND_INTROSPECTION argument is "yes"]]) ]) ]) ]) AC_ARG_ENABLE([vala], [AS_HELP_STRING([--enable-vala[=@<:@no/auto/yes@:>@]],[build Vala bindings @<:@default=]ifelse($4,,auto,$4)[@:>@])],,[ AS_IF([test "x$4" = "x"], [ enable_vala=auto ], [ enable_vala=$4 ]) ]) AS_CASE([$enable_vala], [no], [enable_vala=no], [yes], [ AS_IF([test "x$3" != "xyes" -a "x$found_introspection" != "xyes"], [ AC_MSG_ERROR([Vala bindings require GObject Introspection]) ]) ], [auto], [ AS_IF([test "x$3" != "xyes" -a "x$found_introspection" != "xyes"], [ enable_vala=no ]) ], [ AC_MSG_ERROR([Invalid argument passed to --enable-vala, should be one of @<:@no/auto/yes@:>@]) ]) AS_IF([test "x$2" = "x"], [ vapigen_pkg_name=vapigen ], [ vapigen_pkg_name=vapigen-$2 ]) AS_IF([test "x$1" = "x"], [ vapigen_pkg="$vapigen_pkg_name" ], [ vapigen_pkg="$vapigen_pkg_name >= $1" ]) PKG_PROG_PKG_CONFIG PKG_CHECK_EXISTS([$vapigen_pkg], [ AS_IF([test "$enable_vala" = "auto"], [ enable_vala=yes ]) ], [ AS_CASE([$enable_vala], [yes], [ AC_MSG_ERROR([$vapigen_pkg not found]) ], [auto], [ enable_vala=no ]) ]) AC_MSG_CHECKING([for vapigen]) AS_CASE([$enable_vala], [yes], [ VAPIGEN=`$PKG_CONFIG --variable=vapigen $vapigen_pkg_name` VAPIGEN_MAKEFILE=`$PKG_CONFIG --variable=datadir $vapigen_pkg_name`/vala/Makefile.vapigen AS_IF([test "x$2" = "x"], [ VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir $vapigen_pkg_name` ], [ VAPIGEN_VAPIDIR=`$PKG_CONFIG --variable=vapidir_versioned $vapigen_pkg_name` ]) ]) AC_MSG_RESULT([$enable_vala]) AC_SUBST([VAPIGEN]) AC_SUBST([VAPIGEN_VAPIDIR]) AC_SUBST([VAPIGEN_MAKEFILE]) AM_CONDITIONAL(ENABLE_VAPIGEN, test "x$enable_vala" = "xyes") ]) libxklavier-5.4/tests/000077500000000000000000000000001213561201300150325ustar00rootroot00000000000000libxklavier-5.4/tests/.gitignore000066400000000000000000000001161213561201300170200ustar00rootroot00000000000000Makefile Makefile.in *.o .libs .deps test_config test_monitor libxklavier.xk? libxklavier-5.4/tests/.indent.pro000066400000000000000000000000151213561201300171070ustar00rootroot00000000000000-kr -i8 -psl libxklavier-5.4/tests/Makefile.am000066400000000000000000000004141213561201300170650ustar00rootroot00000000000000check_PROGRAMS=test_config test_monitor test_config_SOURCES=test_config.c test_monitor_SOURCES=test_monitor.c AM_CFLAGS=-Wall -I$(top_srcdir) $(X_CFLAGS) $(GLIB_CFLAGS) LDADD=$(top_builddir)/libxklavier/libxklavier.la $(X_LIBS) $(GLIB_LIBS) EXTRA_DIST=test_gi.py libxklavier-5.4/tests/test_config.c000066400000000000000000000261561213561201300175140ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #ifdef HAVE_SETLOCALE # include #endif extern void xkl_config_rec_dump(FILE * file, XklConfigRec * data); enum { ACTION_NONE, ACTION_LIST, ACTION_GET, ACTION_SET, ACTION_WRITE, ACTION_SEARCH }; static void print_usage(void) { printf ("Usage: test_config (-g)|(-s -m -l -o )|(-h)|(-ws)|(-wb)(-d )|(-p pattern)\n"); printf("Options:\n"); printf(" -al - list all available layouts and variants\n"); printf(" -am - list all available models\n"); printf (" -ao - list all available options groups and options\n"); printf(" -ac - list all available ISO country codes\n"); printf(" -ag - list all available ISO language codes\n"); printf (" -g - Dump the current config, load original system settings and revert back\n"); printf (" -s - Set the configuration given my -m -l -o options. Similar to setxkbmap\n"); printf(" -ws - Write the binary XKB config file (" PACKAGE ".xkm)\n"); printf(" -wb - Write the source XKB config file (" PACKAGE ".xkb)\n"); printf(" -d - Set the debug level (by default, 0)\n"); printf(" -p - Search by pattern\n"); printf(" -h - Show this help\n"); } static void print_option(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { printf(" [%s][%s][%s]\n", item->name, item->description, item->short_description); } static void print_option_group(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { printf("[%s][%s][%s] %s multiple selection\n", item->name, item->description, item->short_description, GPOINTER_TO_INT(g_object_get_data (G_OBJECT(item), XCI_PROP_ALLOW_MULTIPLE_SELECTION)) ? "Allows" : "Does not allow"); xkl_config_registry_foreach_option(config, item->name, print_option, data); } static void print_model(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { gchar *vendor = (gchar *) g_object_get_data(G_OBJECT(item), XCI_PROP_VENDOR); printf("[%s][%s][%s] by %s\n", item->name, item->description, item->short_description, vendor == NULL ? "unknown" : vendor); } static void print_xci(XklConfigRegistry * config, const XklConfigItem * item, gint indent) { gboolean is_extra = (gboolean) GPOINTER_TO_INT(g_object_get_data (G_OBJECT(item), XCI_PROP_EXTRA_ITEM)); gchar **countries = (gchar **) g_object_get_data(G_OBJECT(item), XCI_PROP_COUNTRY_LIST); gchar **languages = (gchar **) g_object_get_data(G_OBJECT(item), XCI_PROP_LANGUAGE_LIST); gint i; printf("%*s[%s][%s][%s]%s\n", indent, "", item->name, item->description, item->short_description, is_extra ? ":extra" : ""); if (countries != NULL) for (i = 0; i < g_strv_length(countries); i++) printf("%*s country: [%s]\n", indent, "", countries[i]); if (languages != NULL) for (i = 0; i < g_strv_length(languages); i++) printf("%*s language: [%s]\n", indent, "", languages[i]); } static void print_variant(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { print_xci(config, item, 2); } static void print_layout(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { print_xci(config, item, 0); xkl_config_registry_foreach_layout_variant(config, item->name, print_variant, data); } static void print_iso_variant(XklConfigRegistry * config, const XklConfigItem * item, const XklConfigItem * subitem, gpointer data) { print_xci(config, item, 2); if (subitem) print_xci(config, subitem, 4); } static void print_country(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { printf("country: "); print_xci(config, item, 0); xkl_config_registry_foreach_country_variant(config, item->name, print_iso_variant, data); } static void print_language(XklConfigRegistry * config, const XklConfigItem * item, gpointer data) { printf("language: "); print_xci(config, item, 0); xkl_config_registry_foreach_language_variant(config, item->name, print_iso_variant, data); } static void print_found_variants(XklConfigRegistry * config, const XklConfigItem * parent_item, const XklConfigItem * child_item) { if (child_item == NULL) printf("found layout: [%s]\n", parent_item->name); else printf("found variant: [%s][%s]\n", parent_item->name, child_item->name); } int main(int argc, char *const argv[]) { int c; gchar which_list = 0; int action = ACTION_NONE; const gchar *model = NULL; const gchar *layouts = NULL; const gchar *options = NULL; const gchar *pattern = NULL; int debug_level = -1; int binary = 0; Display *dpy; XklEngine *engine; g_type_init_with_debug_flags(G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); while (1) { c = getopt(argc, argv, "ha:sgm:l:o:d:w:c:p:"); if (c == -1) break; switch (c) { case 'a': which_list = optarg[0]; printf("List the registry\n"); action = ACTION_LIST; break; case 's': printf("Set the config\n"); action = ACTION_SET; break; case 'g': printf("Get the config\n"); action = ACTION_GET; break; case 'm': printf("Model: [%s]\n", model = optarg); break; case 'l': printf("Layouts: [%s]\n", layouts = optarg); break; case 'o': printf("Options: [%s]\n", options = optarg); break; case 'p': action = ACTION_SEARCH; printf("Pattern: [%s]\n", pattern = optarg); break; case 'h': print_usage(); exit(0); case 'd': debug_level = atoi(optarg); break; case 'w': action = ACTION_WRITE; binary = ('b' == optarg[0]); default: fprintf(stderr, "?? getopt returned character code 0%o ??\n", c); print_usage(); } } if (action == ACTION_NONE) { print_usage(); exit(0); } #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); #endif dpy = XOpenDisplay(NULL); if (dpy == NULL) { fprintf(stderr, "Could not open display\n"); exit(1); } if (debug_level != -1) xkl_set_debug_level(debug_level); engine = xkl_engine_get_instance(dpy); if (engine != NULL) { XklConfigRec *current_config, *r2; XklConfigRegistry *config; xkl_debug(0, "Xklavier initialized\n"); config = xkl_config_registry_get_instance(engine); xkl_config_registry_load(config, TRUE); xkl_debug(0, "Xklavier registry loaded\n"); xkl_debug(0, "Backend: [%s]\n", xkl_engine_get_backend_name(engine)); xkl_debug(0, "Supported features: 0x0%X\n", xkl_engine_get_features(engine)); xkl_debug(0, "Max number of groups: %d\n", xkl_engine_get_max_num_groups(engine)); current_config = xkl_config_rec_new(); xkl_config_rec_get_from_server(current_config, engine); switch (action) { case ACTION_LIST: switch (which_list) { case 'l': xkl_config_registry_foreach_layout(config, print_layout, NULL); break; case 'm': xkl_config_registry_foreach_model(config, print_model, NULL); break; case 'o': xkl_config_registry_foreach_option_group (config, print_option_group, NULL); break; case 'c': xkl_config_registry_foreach_country (config, print_country, NULL); break; case 'g': xkl_config_registry_foreach_language (config, print_language, NULL); break; default: printf("Unknown list: %c\n", which_list); print_usage(); break; } break; case ACTION_GET: xkl_debug(0, "Got config from the server\n"); xkl_config_rec_dump(stdout, current_config); r2 = xkl_config_rec_new(); if (xkl_config_rec_get_from_backup(r2, engine)) { xkl_debug(0, "Got config from the backup\n"); xkl_config_rec_dump(stdout, r2); } if (xkl_config_rec_activate(r2, engine)) { xkl_debug(0, "The backup configuration restored\n"); if (xkl_config_rec_activate (current_config, engine)) { xkl_debug(0, "Reverting the configuration change\n"); } else { xkl_debug(0, "The configuration could not be reverted: %s\n", xkl_get_last_error()); } } else { xkl_debug(0, "The backup configuration could not be restored: %s\n", xkl_get_last_error()); } g_object_unref(G_OBJECT(r2)); break; case ACTION_SET: if (model != NULL) { if (current_config->model != NULL) g_free(current_config->model); current_config->model = g_strdup(model); } if (layouts != NULL) { if (current_config->layouts != NULL) g_strfreev (current_config->layouts); if (current_config->variants != NULL) g_strfreev (current_config->variants); current_config->layouts = g_new0(char *, 2); current_config->layouts[0] = g_strdup(layouts); current_config->variants = g_new0(char *, 2); current_config->variants[0] = g_strdup(""); } if (options != NULL) { if (current_config->options != NULL) g_strfreev (current_config->options); current_config->options = g_new0(char *, 2); current_config->options[0] = g_strdup(options); } xkl_debug(0, "New config:\n"); xkl_config_rec_dump(stdout, current_config); if (xkl_config_rec_activate (current_config, engine)) xkl_debug(0, "Set the config\n"); else xkl_debug(0, "Could not set the config: %s\n", xkl_get_last_error()); break; case ACTION_WRITE: xkl_config_rec_write_to_file(engine, binary ? (PACKAGE ".xkm") : (PACKAGE ".xkb"), current_config, binary); xkl_debug(0, "The file " PACKAGE "%s is written\n", binary ? ".xkm" : ".xkb"); break; case ACTION_SEARCH: xkl_config_registry_search_by_pattern(config, pattern, (TwoConfigItemsProcessFunc) print_found_variants, NULL); } g_object_unref(G_OBJECT(current_config)); g_object_unref(G_OBJECT(config)); xkl_debug(0, "Xklavier registry freed\n"); xkl_debug(0, "Xklavier terminating\n"); g_object_unref(G_OBJECT(engine)); } else { fprintf(stderr, "Could not init _xklavier\n"); exit(2); } printf("closing display: %p\n", dpy); XCloseDisplay(dpy); return 0; } libxklavier-5.4/tests/test_gi.py000077500000000000000000000120001213561201300170360ustar00rootroot00000000000000#!/usr/bin/python # # Test GI binding of libxklavier # Copyright (C) 2011 Martin Pitt # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser 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 # Lesser General Public License for more details. import sys import os # use source tree typelib os.environ['GI_TYPELIB_PATH'] = 'libxklavier:' + os.environ.get('GI_TYPELIB_PATH', '') from gi.repository import Xkl, Gdk, GdkX11 def item_str(s): '''Convert a zero-terminated byte array to a proper str''' i = s.find(b'\x00') return s[:i].decode() display = GdkX11.x11_get_default_xdisplay() print('== Engine ==') engine = Xkl.Engine.get_instance(display) print('indicator names:', engine.get_indicators_names()) print('group names:', engine.get_groups_names()) print('default layout:', engine.get_groups_names()[engine.get_default_group()]) print('features: %X' % engine.get_features()) st = engine.get_current_state() print('current state: group: %i, indicators: %u' % (st.group, st.indicators)) # check ConfigItem ctor with data i = Xkl.ConfigItem() assert item_str(i.name) == '' i.set_name('fr') assert item_str(i.name) == 'fr' # load registry registry = Xkl.ConfigRegistry.get_instance(engine) if not registry.load(False): print('Failed to load registry') sys.exit(1) print('\n== Available Layouts ==') def layout_iter(registry, item, data): print('[%s] %s, ' % (item_str(item.name), item_str(item.description))) registry.foreach_layout(layout_iter, None) print() print('\n== ConfigRec ==') rec = Xkl.ConfigRec() if not rec.get_from_server(engine): print('Failed to get configuration from server') sys.exit(1) print('Curent configuration:') print(' Model:', rec.model) print(' Layouts:', rec.layouts) print(' Variants:', rec.variants) print(' Options:', rec.options) print('Adding Danish layout...') rec.set_layouts(rec.layouts + ['dk']) rec.set_variants(rec.variants + ['']) if not rec.activate(engine): print('Failed to activate new configuration') print('Curent configuration:') rec = Xkl.ConfigRec() if not rec.get_from_server(engine): print('Failed to get configuration from server') sys.exit(1) print(' Model:', rec.model) print(' Layouts:', rec.layouts) print(' Variants:', rec.variants) print(' Options:', rec.options) print('Removing Danish layout...') rec.set_layouts(rec.layouts[:-1]) rec.set_variants(rec.variants[:-1]) if not rec.activate(engine): print('Failed to activate new configuration') print('Curent configuration:') rec = Xkl.ConfigRec() if not rec.get_from_server(engine): print('Failed to get configuration from server') sys.exit(1) print(' Model:', rec.model) print(' Layouts:', rec.layouts) print(' Variants:', rec.variants) print(' Options:', rec.options) print('Changing model to "pc105"...') original_model = rec.model rec.set_model("pc105") print('Curent configuration:') print(' Model:', rec.model) print(' Layouts:', rec.layouts) print(' Variants:', rec.variants) print(' Options:', rec.options) print('Changing back to original model...') rec.set_model(original_model) print('Curent configuration:') print(' Model:', rec.model) print(' Layouts:', rec.layouts) print(' Variants:', rec.variants) print(' Options:', rec.options) print original_options = rec.options[:] if not any("toggle" in opt for opt in rec.options): print('Adding Alt+Shift as an option for switching layouts...') rec.set_options(rec.options + ["grp:alt_shift_toggle"]) if not rec.activate(engine): print('Failed to activate new configuration') original_layouts = rec.layouts[:] original_variants = rec.variants[:] if len(rec.layouts) == 1: print('Adding Danish layout...') rec.set_layouts(rec.layouts + ['dk']) rec.set_variants(rec.variants + ['']) if not rec.activate(engine): print('Failed to activate new configuration') engine.start_listen(Xkl.EngineListenModes.TRACK_KEYBOARD_STATE) groups_names = engine.get_groups_names() state = engine.get_current_state() engine.start_listen(Xkl.EngineListenModes.TRACK_KEYBOARD_STATE) curent_layout = groups_names[state.group] print('Curent active layout: %s' % curent_layout) raw_input('Please change your layout and hit ENTER') engine.start_listen(Xkl.EngineListenModes.TRACK_KEYBOARD_STATE) groups_names = engine.get_groups_names() state = engine.get_current_state() engine.start_listen(Xkl.EngineListenModes.TRACK_KEYBOARD_STATE) curent_layout = groups_names[state.group] print('Curent active layout: %s' % curent_layout) print('Restoring original configuration...') rec.set_layouts(original_layouts) rec.set_variants(original_variants) rec.set_options(original_options) if not rec.activate(engine): print('Failed to activate new configuration') libxklavier-5.4/tests/test_monitor.c000066400000000000000000000120251213561201300177240ustar00rootroot00000000000000/* * Copyright (C) 2002-2006 Sergey V. Udaltsov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 extern void xkl_config_dump(FILE * file, XklConfigRec * data); static Display *dpy; static void print_usage() { printf ("Usage: test_monitor (-l1)(-l2)(-l3)(-h)(-d )\n"); printf("Options:\n"); printf(" -d - Set the debug level (by default, 0)\n"); printf(" -h - Show this help\n"); printf(" -l1 - listen to manage layouts\n"); printf(" -l2 - listen to manage window states\n"); printf(" -l3 - listen to track the keyboard state\n"); } static void state_changed(XklEngine * engine, XklEngineStateChange type, gint new_group, gboolean restore) { XklState *state = xkl_engine_get_current_state(engine); xkl_debug(0, "State changed: type %d, new group: %d, restore: %d. Current state %d %d\n", type, new_group, restore, state->group, state->indicators); if (type == INDICATORS_CHANGED) { Bool state; Atom capsLock = XInternAtom(dpy, "Caps Lock", False); Atom numLock = XInternAtom(dpy, "Num Lock", False); Atom scrollLock = XInternAtom(dpy, "Scroll Lock", False); XkbGetNamedIndicator(dpy, capsLock, NULL, &state, NULL, NULL); xkl_debug(0, "Caps Lock: %d\n", state); XkbGetNamedIndicator(dpy, numLock, NULL, &state, NULL, NULL); xkl_debug(0, "Num Lock: %d\n", state); XkbGetNamedIndicator(dpy, scrollLock, NULL, &state, NULL, NULL); xkl_debug(0, "Scroll Lock: %d\n", state); } } static void config_changed(XklEngine * engine) { const gchar **gn; gint gt; gint i; xkl_debug(0, "Config changed\n"); gn = xkl_engine_get_groups_names(engine); gt = xkl_engine_get_num_groups(engine); for (i = 0; i < gt; i++) xkl_debug(0, "group[%d]: [%s]\n", i, gn[i]); } static void new_device(XklEngine * engine) { xkl_debug(0, "New device attached!\n"); } int main(int argc, char *argv[]) { int c; int debug_level = -1; XkbEvent ev; XklEngine *engine; int listener_type = 0, lt; int listener_types[] = { XKLL_MANAGE_LAYOUTS, XKLL_MANAGE_WINDOW_STATES, XKLL_TRACK_KEYBOARD_STATE }; g_type_init_with_debug_flags(G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); while (1) { c = getopt(argc, argv, "hd:l:"); if (c == -1) break; switch (c) { case 'h': print_usage(); exit(0); case 'd': debug_level = atoi(optarg); break; case 'l': lt = optarg[0] - '1'; if (lt >= 0 && lt < sizeof(listener_types) / sizeof(listener_types[0])) listener_type |= listener_types[lt]; break; default: fprintf(stderr, "?? getopt returned character code 0%o ??\n", c); print_usage(); exit(0); } } dpy = XOpenDisplay(NULL); if (dpy == NULL) { fprintf(stderr, "Could not open display\n"); exit(1); } if (debug_level != -1) xkl_set_debug_level(debug_level); engine = xkl_engine_get_instance(dpy); if (engine != NULL) { XklConfigRec *current_config; const gchar **names; xkl_debug(0, "Xklavier initialized\n"); current_config = xkl_config_rec_new(); xkl_config_rec_get_from_server(current_config, engine); names = xkl_engine_get_groups_names(engine); while (names != NULL && *names != NULL && **names != 0) xkl_debug(0, "Group: [%s]\n", *names++); names = xkl_engine_get_indicators_names(engine); while (names != NULL && *names != NULL && **names != 0) xkl_debug(0, "Indicator: [%s]\n", *names++); g_signal_connect(engine, "X-state-changed", G_CALLBACK(state_changed), NULL); g_signal_connect(engine, "X-config-changed", G_CALLBACK(config_changed), NULL); g_signal_connect(engine, "X-new-device", G_CALLBACK(new_device), NULL); xkl_debug(0, "Now, listening: %X...\n", listener_type); xkl_engine_start_listen(engine, listener_type); while (1) { XNextEvent(dpy, &ev.core); if (!xkl_engine_filter_events(engine, &ev.core)) xkl_debug(200, "Unknown event %d\n", ev.type); } xkl_engine_stop_listen(engine, listener_type); g_object_unref(G_OBJECT(current_config)); g_object_unref(G_OBJECT(engine)); xkl_debug(0, "Xklavier terminating\n"); } else { fprintf(stderr, "Could not init Xklavier\n"); exit(2); } printf("closing display: %p\n", dpy); XCloseDisplay(dpy); return 0; }