From cc796b5193abdb53789f9721a3f3e6b83faa7efa Mon Sep 17 00:00:00 2001 From: InHong Han Date: Thu, 16 Jul 2020 19:46:41 +0900 Subject: [PATCH] Support ise-engine-loader feature Change-Id: I589c2840b42c6b316f3c7bee2a2d8e94deefafb9 --- Makefile.am | 2 +- configure.ac | 9 +- engine-loader/LICENSE | 504 +++++++++++++++++++ engine-loader/Makefile.am | 47 ++ engine-loader/include/engine_loader.h | 78 +++ engine-loader/include/engine_loader_dbus.h | 68 +++ engine-loader/src/engine_loader.cpp | 750 +++++++++++++++++++++++++++++ engine-loader/src/engine_loader_dbus.cpp | 745 ++++++++++++++++++++++++++++ engine-loader/src/engine_loader_main.cpp | 136 ++++++ ism/src/scim_helper.cpp | 61 ++- ism/src/scim_helper.h | 28 ++ packaging/engine-loader.conf | 16 + packaging/engine-loader.service | 15 + packaging/isf.spec | 19 + packaging/org.tizen.engine-loader.service | 4 + 15 files changed, 2476 insertions(+), 6 deletions(-) create mode 100644 engine-loader/LICENSE create mode 100644 engine-loader/Makefile.am create mode 100644 engine-loader/include/engine_loader.h create mode 100644 engine-loader/include/engine_loader_dbus.h create mode 100644 engine-loader/src/engine_loader.cpp create mode 100644 engine-loader/src/engine_loader_dbus.cpp create mode 100644 engine-loader/src/engine_loader_main.cpp create mode 100644 packaging/engine-loader.conf create mode 100644 packaging/engine-loader.service create mode 100644 packaging/org.tizen.engine-loader.service diff --git a/Makefile.am b/Makefile.am index f8d9e02..b6479a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,7 @@ EXTRA_DIST = config.rpath \ intltool-update.in AUTOMAKE_OPTIONS = gnu -SUBDIRS = ism/src ism/utils ism/modules ism/configs po ism/extras ism/data ism/demos +SUBDIRS = ism/src ism/utils ism/modules ism/configs po ism/extras ism/data ism/demos engine-loader/ MAINTAINERCLEANFILES = Makefile.in \ aclocal.m4 \ diff --git a/configure.ac b/configure.ac index d801d3d..89884f0 100644 --- a/configure.ac +++ b/configure.ac @@ -291,6 +291,12 @@ PKG_CHECK_MODULES(EFL_EXTENSION, [efl-extension]) # Check glib library PKG_CHECK_MODULES(GLIB, [glib-2.0]) +# Check gio library +PKG_CHECK_MODULES(GIO, [gio-2.0]) + +# Check dbus library +PKG_CHECK_MODULES(DBUS, [dbus-1]) + # Check tzplatform-config library PKG_CHECK_MODULES(TZPLATFORM_CONFIG, [libtzplatform-config]) @@ -919,7 +925,8 @@ AC_CONFIG_FILES([Makefile scim-gtkutils.pc scim.spec isf-control.pc - isf-control.spec]) + isf-control.spec + engine-loader/Makefile]) AC_OUTPUT AC_MSG_RESULT([ diff --git a/engine-loader/LICENSE b/engine-loader/LICENSE new file mode 100644 index 0000000..4ef65b3 --- /dev/null +++ b/engine-loader/LICENSE @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + 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 Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +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 other code 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. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + 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, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser 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 combine 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) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) 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. + + d) 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. + + e) 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 materials to be 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 with +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 Lesser 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/engine-loader/Makefile.am b/engine-loader/Makefile.am new file mode 100644 index 0000000..3cfc400 --- /dev/null +++ b/engine-loader/Makefile.am @@ -0,0 +1,47 @@ +MAINTAINERCLEANFILES = Makefile.in +CLEANFILES = *.bak + +AM_CPPFLAGS = -I$(top_builddir) \ + -I$(top_builddir)/ism/src \ + -I$(top_srcdir) \ + -I$(top_srcdir)/ism/src \ + -I$(top_srcdir)/ism/intl \ + -I$(top_srcdir)/ism/data \ + -I$(top_srcdir)/ism/utils \ + -I$(top_srcdir)/engine-loader/include \ + -I$(includedir) \ + -DSCIM_DATADIR=\"@SCIM_DATADIR@\" \ + -DSCIM_LOCALEDIR=\"@SCIM_LOCALEDIR@\" \ + -DSCIM_SYSCONFDIR=\"@SCIM_SYSCONFDIR@\" \ + -DSCIM_LIBEXECDIR=\"@SCIM_LIBEXECDIR@\" \ + -DSCIM_ICONDIR=\"@SCIM_ICONDIR@\" \ + -DSCIM_MODULE_PATH=\"@SCIM_MODULE_PATH@\" \ + -DSCIM_TEMPDIR=\"@SCIM_TEMPDIR@\" + + +noinst_HEADERS = + +ISE_ENGINE_LOADER = ise-engine-loader + +bin_PROGRAMS = $(ISE_ENGINE_LOADER) + +ise_engine_loader_SOURCES = src/engine_loader.cpp \ + src/engine_loader_main.cpp \ + src/engine_loader_dbus.cpp + + +ise_engine_loader_CXXFLAGS = @DLOG_CFLAGS@ \ + @GLIB_CFLAGS@ \ + @GIO_CFLAGS@ \ + @PKGMGR_INFO_CFLAGS@ \ + -fPIE + +ise_engine_loader_LDFLAGS = @LTLIBINTL@ -rpath $(libdir) \ + @DLOG_LIBS@ \ + @GLIB_LIBS@ \ + @GIO_LIBS@ \ + @PKGMGR_INFO_LIBS@ \ + -pie + +ise_engine_loader_LDADD = $(top_builddir)/ism/src/libscim@SCIM_EPOCH@.la \ + $(top_builddir)/ism/src/libprofile.la diff --git a/engine-loader/include/engine_loader.h b/engine-loader/include/engine_loader.h new file mode 100644 index 0000000..c5baa85 --- /dev/null +++ b/engine-loader/include/engine_loader.h @@ -0,0 +1,78 @@ +/* + * ISF(Input Service Framework) + * + * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. + * Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. + * + * Contact: Inhong Han + * + * 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.1 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __ENGINE_LOADER_H +#define __ENGINE_LOADER_H + +#define Uses_SCIM_IMENGINE_MODULE +#define Uses_SCIM_UTILITY +#define Uses_SCIM_CONFIG_BASE +#define Uses_SCIM_POINTER +#define Uses_SCIM_EVENT + +#include "scim.h" +#include "scim_panel_common.h" +#include "scim_visibility.h" + +class EngineLoader +{ + class EngineLoaderImpl; + EngineLoaderImpl *m_impl; + + EngineLoader(const EngineLoader &); + const EngineLoader & operator = (const EngineLoader &); + +public: + EngineLoader(); + ~EngineLoader(); + + bool set_keyboard_ise_by_uuid(const scim::String &uuid); + void flush_imengine(); + void reset_imengine(); + void send_imengine_event(int command, uint32_t value); + bool process_key_event(scim::KeyEvent key); + void focus_in(); + void focus_out(); + void update_cursor_position(int cursor_pos); + void set_autocapital_type(uint32_t type); + void set_prediction_allow(uint32_t prediction_allow); + void reset_input_context(); + void set_layout(uint32_t layout); + void set_imdata(const char* imdata, uint32_t len); + void set_input_hint(uint32_t hint); + void update_bidi_direction(uint32_t direction); + void set_trigger_property(const char* property); + void show_candidate_more_window(); + void hide_candidate_more_window(); + void select_aux(uint32_t item); + void select_candidate(uint32_t item); + void candidate_table_page_up(); + void candidate_table_page_down(); + void change_candidate_page_size(uint32_t size); + void set_candidate_item_layout(std::vector item); + void change_candidate_number(uint32_t page_num); + void long_press_candidate_item(uint32_t index); +}; + +#endif /* __ENGINE_LOADER_H */ \ No newline at end of file diff --git a/engine-loader/include/engine_loader_dbus.h b/engine-loader/include/engine_loader_dbus.h new file mode 100644 index 0000000..0ef62d5 --- /dev/null +++ b/engine-loader/include/engine_loader_dbus.h @@ -0,0 +1,68 @@ +/* + * ISF(Input Service Framework) + * + * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. + * Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. + * + * Contact: Inhong Han + * + * 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.1 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#define ENGINE_LOADER_DBUS_NAME "org.tizen.engine-loader" +#define ENGINE_LOADER_OBJECT_PATH "/org/tizen/engine/loader" +#define ENGINE_LOADER_INTERFACE_NAME "org.tizen.engine_loader" +#define ENGINE_LOADER_ISE_INTERFACE_NAME "org.tizen.ise_default" + +typedef struct monitoring_info { + int watcher_id; + char *bus_name; +} monitoring_info_s; + +int engine_loader_dbus_init(void); +int engine_loader_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable); +int engine_loader_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, + GBusNameAppearedCallback appeared_handler, GBusNameVanishedCallback vanished_handler); +int engine_loader_server_unregister(GVariant *parameters, GVariant **reply_body, const gchar *sender); +int engine_loader_send_message(GVariant *body, const char *cmd); +int engine_loader_set_imengine(GVariant *parameters, GVariant **reply_body); +int engine_loader_flush_imengine(GVariant *parameters, GVariant **reply_body); +int engine_loader_reset_imengine(GVariant *parameters, GVariant **reply_body); +int engine_loader_send_imengine_event(GVariant *parameters, GVariant **reply_body); +int engine_loader_process_key_event(GVariant *parameters, GVariant **reply_body); +int engine_loader_focus_in(GVariant *parameters, GVariant **reply_body); +int engine_loader_focus_out(GVariant *parameters, GVariant **reply_body); +int engine_loader_update_cursor_position(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_autocapital_type(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_prediction_allow(GVariant *parameters, GVariant **reply_body); +int engine_loader_reset_input_context(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_layout(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_imdata(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_input_hint(GVariant *parameters, GVariant **reply_body); +int engine_loader_update_bidi_direction(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_trigger_property(GVariant *parameters, GVariant **reply_body); +int engine_loader_show_candidate_more_window(GVariant *parameters, GVariant **reply_body); +int engine_loader_hide_candidate_more_window(GVariant *parameters, GVariant **reply_body); +int engine_loader_select_aux(GVariant *parameters, GVariant **reply_body); +int engine_loader_select_candidate(GVariant *parameters, GVariant **reply_body); +int engine_loader_candidate_table_page_up(GVariant *parameters, GVariant **reply_body); +int engine_loader_candidate_table_page_down(GVariant *parameters, GVariant **reply_body); +int engine_loader_change_candidate_page_size(GVariant *parameters, GVariant **reply_body); +int engine_loader_set_candidate_item_layout(GVariant *parameters, GVariant **reply_body); +int engine_loader_change_candidate_number(GVariant *parameters, GVariant **reply_body); +int engine_loader_long_press_candidate_item(GVariant *parameters, GVariant **reply_body); \ No newline at end of file diff --git a/engine-loader/src/engine_loader.cpp b/engine-loader/src/engine_loader.cpp new file mode 100644 index 0000000..8391bcb --- /dev/null +++ b/engine-loader/src/engine_loader.cpp @@ -0,0 +1,750 @@ +/* + * ISF(Input Service Framework) + * + * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. + * Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. + * + * Contact: Inhong Han + * + * 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.1 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "engine_loader.h" +#include "engine_loader_dbus.h" +#include "scim_imengine.h" +#include "isf_query_utility.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ENGINE_LOADER" + +using namespace std; + +static void generate_attr_builder(GVariantBuilder *builder, const AttributeList & attrs) +{ + AttributeList::const_iterator it; + GVariant *body = NULL; + + for(it = attrs.begin(); it != attrs.end(); it++) { + body = g_variant_new("(uuuu)", (guint32)(it->get_start()), (guint32)(it->get_length()), + (guint32)(it->get_type()), (guint32)(it->get_value())); + g_variant_builder_add(builder, "(v)", body); + } +} + +class EngineLoader::EngineLoaderImpl +{ +public: + EngineLoader* thiz; + IMEngineInstancePointer si; + ConfigPointer m_config; + IMEngineModule engine_module; + + uint32 layout; + bool is_focused; + + EngineLoaderImpl(EngineLoader *thiz) : thiz(thiz), layout(0), is_focused(false) + { + m_config = ConfigBase::get(true, "socket"); + if (m_config.null()) + m_config = new scim::DummyConfig(); + } + + ~EngineLoaderImpl() + { + if (!m_config.null()) { + m_config.reset(); + } + + scim::ConfigBase::set(0); + + if (!si.null()) { + si.reset(); + } + + if (engine_module.valid()) { + engine_module.unload(); + } + } + + void slot_show_preedit_string(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "show_preedit_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to show preedit string"); + } + + void slot_show_aux_string(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "show_aux_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to show aux string"); + } + + void slot_show_lookup_table(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "show_lookup_table"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to show lookup table"); + } + + void slot_hide_preedit_string(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "hide_preedit_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide preedit string"); + } + + void slot_hide_aux_string(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "hide_aux_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide aux string"); + } + + void slot_hide_lookup_table(IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "hide_lookup_table"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide lookup table"); + } + + void slot_update_preedit_caret(IMEngineInstanceBase *si, int caret) + { + int ret = engine_loader_send_message(g_variant_new("(i)", caret), "update_preedit_caret"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update preedit caret"); + } + + void slot_update_preedit_string(IMEngineInstanceBase *si, + const WideString & str, + const AttributeList & attrs, + int caret) + { + GVariantBuilder *builder = NULL; + builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + generate_attr_builder(builder, attrs); + + int ret = engine_loader_send_message(g_variant_new("(a(v)s)", builder, utf8_wcstombs(str).c_str()), "update_preedit_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update preedit string"); + + if (builder) + g_variant_builder_unref(builder); + } + + void slot_update_preedit_string_with_commit(IMEngineInstanceBase *si, + const WideString &preedit, + const WideString &commit, + const AttributeList &attrs, + int caret) + { + GVariantBuilder *builder = NULL; + builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + generate_attr_builder(builder, attrs); + + int ret = engine_loader_send_message(g_variant_new("(a(v)ssi)", builder, utf8_wcstombs(preedit).c_str(), + utf8_wcstombs(commit).c_str(), caret), "update_preedit_string_with_commit"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update preedit string with commit"); + + if (builder) + g_variant_builder_unref(builder); + } + + void slot_update_aux_string(IMEngineInstanceBase *si, + const WideString &str, + const AttributeList &attrs) + { + GVariantBuilder *builder = NULL; + builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + generate_attr_builder(builder, attrs); + + int ret = engine_loader_send_message(g_variant_new("(a(v)s)", builder, utf8_wcstombs(str).c_str()), "update_aux_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update aux string"); + + if (builder) + g_variant_builder_unref(builder); + } + + void slot_commit_string(IMEngineInstanceBase *si, const WideString &str) + { + int ret = engine_loader_send_message(g_variant_new("(s)", utf8_wcstombs(str).c_str()), "commit_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to commit string"); + } + + void slot_recapture_string(IMEngineInstanceBase *si, + int offset, + int len, + const WideString &preedit, + const WideString &commit, + const AttributeList &attrs) + { + GVariantBuilder *builder = NULL; + builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + generate_attr_builder(builder, attrs); + + int ret = engine_loader_send_message(g_variant_new("(a(v)ssii)", builder, utf8_wcstombs(preedit).c_str(), + utf8_wcstombs(commit).c_str(), offset, len), "recapture_string"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update recapture string"); + + if (builder) + g_variant_builder_unref(builder); + } + + void slot_forward_key_event(IMEngineInstanceBase *si, const KeyEvent &key) + { + GVariantBuilder *key_event_builder = NULL; + key_event_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); + g_variant_builder_add(key_event_builder, "{sv}", "key_code", g_variant_new_uint32(key.code)); + g_variant_builder_add(key_event_builder, "{sv}", "key_mask", g_variant_new_uint16(key.mask)); + g_variant_builder_add(key_event_builder, "{sv}", "key_layout", g_variant_new_uint16(key.layout)); + g_variant_builder_add(key_event_builder, "{sv}", "key_dev_class", g_variant_new_uint16(key.dev_class)); + g_variant_builder_add(key_event_builder, "{sv}", "key_dev_subclass", g_variant_new_uint16(key.dev_subclass)); + + int ret = engine_loader_send_message(g_variant_new("(a{sv}s)", key_event_builder, key.dev_name.c_str()), "forward_key_event"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to forward key event"); + + if (key_event_builder) + g_variant_builder_unref(key_event_builder); + } + + void slot_update_lookup_table(IMEngineInstanceBase *si, const LookupTable &table) + { + int num = table.number_of_candidates(); + GVariantBuilder *attr_builder = NULL; + GVariantBuilder *candidate_builder = NULL; + GVariant *body = NULL; + int page_size = table.get_page_size(); + int cursor_pos = table.get_cursor_pos(); + + attr_builder = g_variant_builder_new(G_VARIANT_TYPE("a(a(v))")); + candidate_builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + + for(int i = 0; i < num; i++) { + AttributeList attrs = table.get_attributes(i); + GVariantBuilder *inner_builder = NULL; + inner_builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + + if (attrs.empty()) { + GVariant *tmp = NULL; + tmp = g_variant_new("(uuuu)", 0, 0, 0, 0); + g_variant_builder_add(inner_builder, "(v)", tmp); + } else { + generate_attr_builder(inner_builder, attrs); + } + + body = g_variant_new("(s)", utf8_wcstombs(table.get_candidate(i)).c_str()); + + g_variant_builder_add(attr_builder, "a(v)", inner_builder); + g_variant_builder_add(candidate_builder, "(v)", body); + + if (inner_builder) + g_variant_builder_unref(inner_builder); + } + + int ret = engine_loader_send_message(g_variant_new("(a(a(v))a(v)ii)", attr_builder, candidate_builder, page_size, cursor_pos), "update_lookup_table"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update lookup table"); + + if (attr_builder) + g_variant_builder_unref(attr_builder); + + if (candidate_builder) + g_variant_builder_unref(candidate_builder); + } + + void slot_register_properties(IMEngineInstanceBase *si, const PropertyList &properties) + { + GVariantBuilder *builder = NULL; + GVariant *body = NULL; + PropertyList::const_iterator it; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)")); + for(it = properties.begin(); it != properties.end(); it++) { + body = g_variant_new("(ssss)", it->get_key().c_str(), it->get_label().c_str(), it->get_icon().c_str(), it->get_tip().c_str()); + g_variant_builder_add(builder, "(v)", body); + } + + int ret = engine_loader_send_message(g_variant_new("(a(v))", builder), "register_properties"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to register properties"); + + if (builder) + g_variant_builder_unref(builder); + } + + void slot_update_property(IMEngineInstanceBase *si, const Property &property) + { + const char *key = property.get_key().c_str(); + const char *label = property.get_label().c_str(); + const char *icon = property.get_icon().c_str(); + const char *tip = property.get_tip().c_str(); + + int ret = engine_loader_send_message(g_variant_new("(ssss)", key, label, icon, tip), "update_property"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to update property"); + } + + void slot_send_helper_event(IMEngineInstanceBase *si, + const String &helper_uuid, + const Transaction &trans) + { + } + + bool slot_get_surrounding_text(IMEngineInstanceBase *si, + WideString &text, + int &cursor, + int maxlen_before, + int maxlen_after) + { + return true; + } + + bool slot_delete_surrounding_text(IMEngineInstanceBase *si, + int offset, + int len) + { + int ret = engine_loader_send_message(g_variant_new("(ii)", offset, len), "delete_surrounding_text"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to delete surrounding text"); + return true; + } + + bool slot_get_selection(IMEngineInstanceBase *si, WideString &text) + { + return true; + } + + bool slot_set_selection(IMEngineInstanceBase *si, + int start, + int end) + { + int ret = engine_loader_send_message(g_variant_new("(ii)", start, end), "set_selection"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to delete surrounding text"); + return true; + } + + void slot_expand_candidate (IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "expand_candidate"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide lookup table"); + } + + void slot_contract_candidate (IMEngineInstanceBase *si) + { + int ret = engine_loader_send_message(g_variant_new("()"), "contract_candidate"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide lookup table"); + } + + void slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode) + { + int ret = engine_loader_send_message(g_variant_new("(ii)", (int)portrait_line, (int)mode), "set_candidate_style"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to hide lookup table"); + } + + void slot_send_private_command (IMEngineInstanceBase *si, const String &command) + { + int ret = engine_loader_send_message(g_variant_new("(s)", command.c_str()), "send_private_command"); + if (ret != TIZEN_ERROR_NONE) + LOGD("Falied to send private command"); + } + + void attach_instance() + { + si->signal_connect_show_preedit_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_show_preedit_string)); + + si->signal_connect_show_aux_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_show_aux_string)); + + si->signal_connect_show_lookup_table ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_show_lookup_table)); + + si->signal_connect_hide_preedit_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_hide_preedit_string)); + + si->signal_connect_hide_aux_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_hide_aux_string)); + + si->signal_connect_hide_lookup_table ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_hide_lookup_table)); + + si->signal_connect_update_preedit_caret ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_preedit_caret)); + + si->signal_connect_update_preedit_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_preedit_string)); + + si->signal_connect_update_preedit_string_with_commit ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_preedit_string_with_commit)); + + si->signal_connect_recapture_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_recapture_string)); + + si->signal_connect_update_aux_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_aux_string)); + + si->signal_connect_update_lookup_table ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_lookup_table)); + + si->signal_connect_commit_string ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_commit_string)); + + si->signal_connect_forward_key_event ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_forward_key_event)); + + si->signal_connect_register_properties ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_register_properties)); + + si->signal_connect_update_property ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_update_property)); + + si->signal_connect_send_helper_event ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_send_helper_event)); + + si->signal_connect_get_surrounding_text ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_get_surrounding_text)); + + si->signal_connect_delete_surrounding_text ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_delete_surrounding_text)); + + si->signal_connect_get_selection ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_get_selection)); + + si->signal_connect_set_selection ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_set_selection)); + + si->signal_connect_expand_candidate ( + slot (this, &EngineLoader::EngineLoaderImpl::slot_expand_candidate)); + + si->signal_connect_contract_candidate ( + slot (this, &EngineLoader::EngineLoaderImpl::slot_contract_candidate)); + + si->signal_connect_set_candidate_style ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_set_candidate_style)); + + si->signal_connect_send_private_command ( + slot(this, &EngineLoader::EngineLoaderImpl::slot_send_private_command)); + } +private: + EngineLoaderImpl() : thiz(NULL), layout(0), is_focused(false) { } +}; + +EngineLoader::EngineLoader() + : m_impl (new EngineLoaderImpl(this)) +{ +} + +EngineLoader::~EngineLoader() +{ + delete m_impl; +} + +bool EngineLoader::set_keyboard_ise_by_uuid(const scim::String &uuid) +{ + ImeInfoDB imeInfo; + IMEngineFactoryPointer factory; + IMEngineModule *engine_module = NULL; + static int instance_count = 1; + + if ((!m_impl->si.null ()) && m_impl->si->get_factory_uuid () == uuid) { + LOGD("Already in UUID : %s", uuid.c_str()); + return false; + } + + if (!m_impl->si.null()) { + m_impl->si->focus_out(); + m_impl->si.reset(); + } + + if (m_impl->m_config.null ()) { + LOGD("config is not working"); + return false; + } + + int ret = 0; + char *pkgid = NULL; + pkgmgrinfo_appinfo_h handle; + ret = pkgmgrinfo_appinfo_get_appinfo(uuid.c_str(), &handle); + if (ret != PMINFO_R_OK) { + LOGD("Retrieve app info failed : %s", uuid.c_str ()); + return false; + } + + ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid); + if (ret != PMINFO_R_OK) { + LOGD("Retrieve pkgid failed : %s, %p", uuid.c_str(), handle); + pkgmgrinfo_appinfo_destroy_appinfo(handle); + return false; + } + + imeInfo.module_name = pkgid; + pkgmgrinfo_appinfo_destroy_appinfo(handle); + + engine_module = &m_impl->engine_module; + if (engine_module->valid() && imeInfo.module_name != engine_module->get_module_name()) { + LOGD("imengine module %s unloaded", engine_module->get_module_name().c_str()); + engine_module->unload(); + } + + if (!engine_module->valid()) { + if (engine_module->load (imeInfo.module_name, m_impl->m_config) == false) { + LOGD("load module %s failed", imeInfo.module_name.c_str()); + return false; + } + LOGD("imengine module %s loaded", imeInfo.module_name.c_str()); + } + + for (size_t j = 0; j < engine_module->number_of_factories (); ++j) { + try { + factory = engine_module->create_factory (j); + if (factory.null () == false && factory->get_uuid () == uuid) + break; + } catch (...) { + factory.reset (); + return false; + } + } + + if (factory.null()) { + LOGD("imengine uuid %s is not found", uuid.c_str()); + return false; + } + + m_impl->si = factory->create_instance ("UTF-8", instance_count++); + if (m_impl->si.null ()) { + LOGD("create_instance %s failed", uuid.c_str ()); + return false; + } + + m_impl->attach_instance (); + LOGD("Require UUID: %s Current UUID: %s", uuid.c_str(), m_impl->si->get_factory_uuid().c_str()); + m_impl->si->set_layout (m_impl->layout); + if (m_impl->is_focused) + m_impl->si->focus_in (); + + return true; +} + +void EngineLoader::flush_imengine() +{ + if (!m_impl->si.null()) { + m_impl->si->flush (); + } +} + +void EngineLoader::reset_imengine() +{ + if (!m_impl->si.null ()) { + m_impl->si->reset (); + } +} + +void EngineLoader::send_imengine_event(int command, uint32_t value) +{ + scim::String uuid; + scim::Transaction trans; + trans.put_command(command); + trans.put_data(value); + + if (!m_impl->si.null()) { + m_impl->si->process_helper_event (uuid, trans); + } +} + +bool EngineLoader::process_key_event(scim::KeyEvent key) +{ + uint32 ret = 0; + + if (!m_impl->si.null()) { + ret = m_impl->si->process_key_event(key); + SECURE_LOGD ("imengine(%s) process key %u return %d", m_impl->si->get_factory_uuid().c_str(), key.code, ret); + } + + return ret == 0 ? false : true; +} + +void EngineLoader::focus_in() +{ + m_impl->is_focused = true; + + if (!m_impl->si.null()) { + m_impl->si->focus_in(); + } +} + +void EngineLoader::focus_out() +{ + m_impl->is_focused = false; + + if (!m_impl->si.null()) { + m_impl->si->focus_out(); + } +} + +void EngineLoader::update_cursor_position(int cursor_pos) +{ + if (!m_impl->si.null()) { + m_impl->si->update_cursor_position(cursor_pos); + } +} + +void EngineLoader::set_autocapital_type(uint32_t type) +{ + if (!m_impl->si.null()) { + m_impl->si->set_autocapital_type(type); + } +} + +void EngineLoader::set_prediction_allow(uint32_t prediction_allow) +{ + if (!m_impl->si.null()) { + m_impl->si->set_prediction_allow(prediction_allow); + } +} + +void EngineLoader::reset_input_context() +{ + if (!m_impl->si.null()) { + m_impl->si->reset(); + } +} + +void EngineLoader::set_layout(uint32_t layout) +{ + if (!m_impl->si.null()) { + m_impl->si->set_layout(layout); + } +} + +void EngineLoader::set_imdata(const char* imdata, uint32_t len) +{ + if (!m_impl->si.null()) { + m_impl->si->set_imdata(imdata, len); + } +} + +void EngineLoader::set_input_hint(uint32_t hint) +{ + if (!m_impl->si.null()) { + m_impl->si->set_input_hint(hint); + } +} + +void EngineLoader::update_bidi_direction(uint32_t direction) +{ + if (!m_impl->si.null()) { + m_impl->si->update_bidi_direction(direction); + } +} + +void EngineLoader::set_trigger_property(const char* property) +{ + if (!m_impl->si.null()) { + m_impl->si->trigger_property(property); + } +} + +void EngineLoader::show_candidate_more_window() +{ + if (!m_impl->si.null()) { + m_impl->si->candidate_more_window_show(); + } +} + +void EngineLoader::hide_candidate_more_window() +{ + if (!m_impl->si.null()) { + m_impl->si->candidate_more_window_hide(); + } +} + +void EngineLoader::select_aux(uint32_t item) +{ + if (!m_impl->si.null()) { + m_impl->si->select_aux(item); + } +} + +void EngineLoader::select_candidate(uint32_t item) +{ + if (!m_impl->si.null()) { + m_impl->si->select_candidate(item); + } +} + +void EngineLoader::candidate_table_page_up() +{ + if (!m_impl->si.null()) { + m_impl->si->lookup_table_page_up(); + } +} + +void EngineLoader::candidate_table_page_down() +{ + if (!m_impl->si.null()) { + m_impl->si->lookup_table_page_down(); + } +} + +void EngineLoader::change_candidate_page_size(uint32_t size) +{ + if (!m_impl->si.null()) { + m_impl->si->update_lookup_table_page_size(size); + } +} + +void EngineLoader::set_candidate_item_layout(std::vector item) +{ + if (!m_impl->si.null()) { + m_impl->si->update_candidate_item_layout(item); + } +} + +void EngineLoader::change_candidate_number(uint32_t page_num) +{ + if (!m_impl->si.null()) { + m_impl->si->update_displayed_candidate_number(page_num); + } +} + +void EngineLoader::long_press_candidate_item(uint32_t index) +{ + if (!m_impl->si.null()) { + m_impl->si->longpress_candidate(index); + } +} \ No newline at end of file diff --git a/engine-loader/src/engine_loader_dbus.cpp b/engine-loader/src/engine_loader_dbus.cpp new file mode 100644 index 0000000..39bc355 --- /dev/null +++ b/engine-loader/src/engine_loader_dbus.cpp @@ -0,0 +1,745 @@ +/* + * ISF(Input Service Framework) + * + * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. + * Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. + * + * Contact: Inhong Han + * + * 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.1 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#define Uses_SCIM_IMENGINE_MODULE + +#include +#include +#include +#include +#include +#include + +#include "engine_loader_dbus.h" +#include "engine_loader.h" +#include "scim.h" +#include "scim_panel_common.h" +#include "scim_visibility.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ENGINE_LOADER_DBUS" + +static GDBusConnection *g_gdbus_connection; +extern GMainLoop *main_loop; +static EngineLoader m_engine_loader; +static std::string g_sender; + +static void _on_name_appeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + LOGD("name: %s", name); +} + +static void _on_name_vanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + monitoring_info_s *info = (monitoring_info_s *)user_data; + if (info) { + g_bus_unwatch_name(info->watcher_id); + + if (info->bus_name) + free(info->bus_name); + free(info); + info = NULL; + } + + LOGD("Terminate engine loader"); + g_main_loop_quit(main_loop); +} + +static void _client_dbus_method_call_handler(GDBusConnection *conn, const gchar *sender, const gchar *object_path, + const gchar *iface_name, const gchar *method_name, GVariant *parameters, + GDBusMethodInvocation *invocation, gpointer user_data) +{ + LOGD("method_name: %s, sender: %s", method_name, sender); + + GVariant *reply_body = NULL; + g_sender = std::string(sender); + int ret = TIZEN_ERROR_UNKNOWN; + + if (g_strcmp0(method_name, "loader_service_register") == 0) { + ret = engine_loader_server_register(parameters, &reply_body, sender, _on_name_appeared, _on_name_vanished); + } else if (g_strcmp0(method_name, "loader_service_unregister") == 0) { + ret = engine_loader_server_unregister(parameters, &reply_body, sender); + } else if (g_strcmp0(method_name, "set_imengine") == 0) { + ret = engine_loader_set_imengine(parameters, &reply_body); + } else if (g_strcmp0(method_name, "flush_imengine") == 0) { + ret = engine_loader_flush_imengine(parameters, &reply_body); + } else if (g_strcmp0(method_name, "reset_imengine") == 0) { + ret = engine_loader_reset_imengine(parameters, &reply_body); + } else if (g_strcmp0(method_name, "send_imengine_event") == 0) { + ret = engine_loader_send_imengine_event(parameters, &reply_body); + } else if (g_strcmp0(method_name, "process_key_event") == 0) { + ret = engine_loader_process_key_event(parameters, &reply_body); + } else if (g_strcmp0(method_name, "focus_in") == 0) { + ret = engine_loader_focus_in(parameters, &reply_body); + } else if (g_strcmp0(method_name, "focus_out") == 0) { + ret = engine_loader_focus_out(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_cursor_position") == 0) { + ret = engine_loader_update_cursor_position(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_autocapital_type") == 0) { + ret = engine_loader_set_autocapital_type(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_prediction_allow") == 0) { + ret = engine_loader_set_prediction_allow(parameters, &reply_body); + } else if (g_strcmp0(method_name, "reset_input_context") == 0) { + ret = engine_loader_reset_input_context(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_layout") == 0) { + ret = engine_loader_set_layout(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_imdata") == 0) { + ret = engine_loader_set_imdata(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_input_hint") == 0) { + ret = engine_loader_set_input_hint(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_bidi_direction") == 0) { + ret = engine_loader_update_bidi_direction(parameters, &reply_body); + } else if (g_strcmp0(method_name, "trigger_property") == 0) { + ret = engine_loader_set_trigger_property(parameters, &reply_body); + } else if (g_strcmp0(method_name, "show_candidate_more_window") == 0) { + ret = engine_loader_show_candidate_more_window(parameters, &reply_body); + } else if (g_strcmp0(method_name, "hide_candidate_more_window") == 0) { + ret = engine_loader_hide_candidate_more_window(parameters, &reply_body); + } else if (g_strcmp0(method_name, "select_aux") == 0) { + ret = engine_loader_select_aux(parameters, &reply_body); + } else if (g_strcmp0(method_name, "select_candidate") == 0) { + ret = engine_loader_select_candidate(parameters, &reply_body); + } else if (g_strcmp0(method_name, "candidate_table_page_up") == 0) { + ret = engine_loader_candidate_table_page_up(parameters, &reply_body); + } else if (g_strcmp0(method_name, "candidate_table_page_down") == 0) { + ret = engine_loader_candidate_table_page_down(parameters, &reply_body); + } else if (g_strcmp0(method_name, "change_candidate_page_size") == 0) { + ret = engine_loader_change_candidate_page_size(parameters, &reply_body); + } else if (g_strcmp0(method_name, "set_candidate_item_layout") == 0) { + ret = engine_loader_set_candidate_item_layout(parameters, &reply_body); + } else if (g_strcmp0(method_name, "change_candidate_number") == 0) { + ret = engine_loader_change_candidate_number(parameters, &reply_body); + } else if (g_strcmp0(method_name, "long_press_candidate_item") == 0) { + ret = engine_loader_long_press_candidate_item(parameters, &reply_body); + } + + if (ret == TIZEN_ERROR_NONE) + g_dbus_method_invocation_return_value(invocation, reply_body); + else + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, ret, "engine loader error"); +} + +static const GDBusInterfaceVTable _interface_vtable = { + _client_dbus_method_call_handler, + NULL, + NULL +}; + +static int _register_dbus_interface(void) +{ + static gchar introspection_xml[] = + " " + " " + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + " " + + " " + " " + + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + " "; + + return engine_loader_server_register_dbus_interface(introspection_xml, _interface_vtable); +} + +int engine_loader_dbus_init(void) +{ + int ret; + ret = _register_dbus_interface(); + if (ret != TIZEN_ERROR_NONE) + LOGE("Failed to register dbus interface : %s", get_error_message(ret)); + + return ret; +} + +int engine_loader_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable) +{ + int ret = TIZEN_ERROR_NONE; + int own_id, registration_id; + GError *error = NULL; + GDBusNodeInfo *introspection_data = NULL; + + if (g_gdbus_connection == NULL) { + g_gdbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (g_gdbus_connection == NULL) { + if (error != NULL) { + LOGE("g_bus_get_sync error message = %s", error->message); + g_error_free(error); + } + ret = TIZEN_ERROR_UNKNOWN; + goto cleanup; + } + } + + own_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, + ENGINE_LOADER_DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, + NULL, + NULL, + NULL, NULL); + if (own_id == 0) { + LOGE("Failed to register bus name"); + ret = TIZEN_ERROR_UNKNOWN; + goto cleanup; + } + + introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); + if (introspection_data == NULL) { + LOGE("Failed to get GDBusNodeInfo"); + ret = TIZEN_ERROR_UNKNOWN; + if (error != NULL) { + LOGE("g_dbus_node_info_new_for_xml error message = %s", error->message); + g_error_free(error); + } + goto cleanup; + } + + registration_id = g_dbus_connection_register_object(g_gdbus_connection, ENGINE_LOADER_OBJECT_PATH, + introspection_data->interfaces[0], &interface_vtable, NULL, NULL, &error); + if (registration_id == 0) { + if (error != NULL) { + LOGE("Failed to register object. error message = %s", error->message); + g_error_free(error); + ret = TIZEN_ERROR_UNKNOWN; + } + goto cleanup; + } + + return TIZEN_ERROR_NONE; + +cleanup: + if (introspection_data) + g_dbus_node_info_unref(introspection_data); + + return ret; +} + +int engine_loader_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, + GBusNameAppearedCallback appeared_handler, GBusNameVanishedCallback vanished_handler) +{ + int ret = TIZEN_ERROR_NONE; + monitoring_info_s *m_info = NULL; + + if (reply_body == NULL) + return TIZEN_ERROR_INVALID_PARAMETER; + + if (sender == NULL) + return TIZEN_ERROR_INVALID_PARAMETER; + + m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s)); + if (m_info == NULL) { + LOGE("Failed to alloc memory"); + ret = TIZEN_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + m_info->bus_name = strdup(sender); + m_info->watcher_id = g_bus_watch_name_on_connection( + g_gdbus_connection, + sender, + G_BUS_NAME_WATCHER_FLAGS_NONE, + appeared_handler, + vanished_handler, + m_info, + NULL); + + if (m_info->watcher_id == 0) { + LOGE("Failed to get identifier"); + ret = TIZEN_ERROR_UNKNOWN; + goto cleanup; + } + + *reply_body = g_variant_new("(i)", m_info->watcher_id); + if (*reply_body == NULL) { + LOGE("Failed to make reply"); + ret = TIZEN_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + return TIZEN_ERROR_NONE; + +cleanup: + if (m_info) { + free(m_info); + m_info = NULL; + } + + return ret; +} + +int engine_loader_server_unregister(GVariant *parameters, GVariant **reply_body, const gchar *sender) +{ + int watcher_id = 0; + g_variant_get(parameters, "(i)", &watcher_id); + g_bus_unwatch_name(watcher_id); + return TIZEN_ERROR_NONE; +} + +int engine_loader_send_message(GVariant *body, const char *cmd) +{ + GError *err = NULL; + + if (g_variant_is_floating(body)) + g_variant_ref(body); + + if (!g_dbus_connection_emit_signal(g_gdbus_connection, + g_sender.c_str(), + ENGINE_LOADER_OBJECT_PATH, + ENGINE_LOADER_ISE_INTERFACE_NAME, + cmd, + body, + &err)) { + + if (err != NULL) { + LOGE("Failed to send dbus message : %s", err->message); + g_error_free(err); + } + + return TIZEN_ERROR_IO_ERROR; + } + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_imengine(GVariant *parameters, GVariant **reply_body) +{ + bool result = false; + char *engine_id = NULL; + + g_variant_get(parameters, "(&s)", &engine_id); + + if (engine_id) + result = m_engine_loader.set_keyboard_ise_by_uuid(scim::String(engine_id)); + + *reply_body = g_variant_new("(b)", result); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return TIZEN_ERROR_OUT_OF_MEMORY; + } + + return TIZEN_ERROR_NONE; +} + +int engine_loader_flush_imengine(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.flush_imengine(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_reset_imengine(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.reset_imengine(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_send_imengine_event(GVariant *parameters, GVariant **reply_body) +{ + int command; + uint32_t value; + + g_variant_get(parameters, "(iu)", &command, &value); + m_engine_loader.send_imengine_event(command, value); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_process_key_event(GVariant *parameters, GVariant **reply_body) +{ + bool result = false; + uint32_t code = 0; + uint16_t mask = 0; + uint16_t layout = 0; + char *dev_name = NULL; + uint16_t dev_class = 0; + uint16_t dev_subclass = 0; + GVariantIter *key_event_iter = NULL; + GVariant *value = NULL; + gchar *key = NULL; + + g_variant_get(parameters, "(a{sv}&s)", &key_event_iter, &dev_name); + if (!key_event_iter || !dev_name) + LOGD("Failed to get iter"); + + while (g_variant_iter_loop (key_event_iter, "{sv}", &key, &value)) { + if (g_strcmp0(key, "key_code") == 0) + code = g_variant_get_uint32(value); + else if (g_strcmp0(key, "key_mask") == 0) + mask = g_variant_get_uint16(value); + else if (g_strcmp0(key, "key_layout") == 0) + layout = g_variant_get_uint16(value); + else if (g_strcmp0(key, "key_dev_class") == 0) + dev_class = g_variant_get_uint16(value); + else if (g_strcmp0(key, "key_dev_subclass") == 0) + dev_subclass = g_variant_get_uint16(value); + } + + if (key) + g_free(key); + + if (value) + g_variant_unref(value); + + scim::KeyEvent key_event; + key_event.code = code; + key_event.mask = mask; + key_event.layout = layout; + key_event.dev_name = std::string(dev_name); + key_event.dev_class = dev_class; + key_event.dev_subclass = dev_subclass; + + result = m_engine_loader.process_key_event(key_event); + *reply_body = g_variant_new("(b)", result); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return TIZEN_ERROR_OUT_OF_MEMORY; + } + + return TIZEN_ERROR_NONE; +} + +int engine_loader_focus_in(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.focus_in(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_focus_out(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.focus_out(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_update_cursor_position(GVariant *parameters, GVariant **reply_body) +{ + int cursor_pos = -1; + + g_variant_get(parameters, "(i)", &cursor_pos); + if (cursor_pos >= 0) + m_engine_loader.update_cursor_position(cursor_pos); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_autocapital_type(GVariant *parameters, GVariant **reply_body) +{ + uint32_t type; + + g_variant_get(parameters, "(u)", &type); + m_engine_loader.set_autocapital_type(type); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_prediction_allow(GVariant *parameters, GVariant **reply_body) +{ + uint32_t prediction_allow; + + g_variant_get(parameters, "(u)", &prediction_allow); + m_engine_loader.set_prediction_allow(prediction_allow); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_reset_input_context(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.reset_input_context(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_layout(GVariant *parameters, GVariant **reply_body) +{ + uint32_t layout; + + g_variant_get(parameters, "(u)", &layout); + m_engine_loader.set_layout(layout); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_imdata(GVariant *parameters, GVariant **reply_body) +{ + const char *imdata; + uint32_t len; + + g_variant_get(parameters, "(&su)", &imdata, &len); + m_engine_loader.set_imdata(imdata, len); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_input_hint(GVariant *parameters, GVariant **reply_body) +{ + uint32_t hint; + + g_variant_get(parameters, "(u)", &hint); + m_engine_loader.set_input_hint(hint); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_update_bidi_direction(GVariant *parameters, GVariant **reply_body) +{ + uint32_t direction; + + g_variant_get(parameters, "(u)", &direction); + m_engine_loader.update_bidi_direction(direction); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_trigger_property(GVariant *parameters, GVariant **reply_body) +{ + const char *property; + + g_variant_get(parameters, "(&s)", &property); + m_engine_loader.set_trigger_property(property); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_show_candidate_more_window(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.show_candidate_more_window(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_hide_candidate_more_window(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.hide_candidate_more_window(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_select_aux(GVariant *parameters, GVariant **reply_body) +{ + uint32_t item; + + g_variant_get(parameters, "(u)", &item); + m_engine_loader.select_aux(item); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_select_candidate(GVariant *parameters, GVariant **reply_body) +{ + uint32_t item; + + g_variant_get(parameters, "(u)", &item); + m_engine_loader.select_candidate(item); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_candidate_table_page_up(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.candidate_table_page_up(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_candidate_table_page_down(GVariant *parameters, GVariant **reply_body) +{ + m_engine_loader.candidate_table_page_down(); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_change_candidate_page_size(GVariant *parameters, GVariant **reply_body) +{ + uint32_t size; + + g_variant_get(parameters, "(u)", &size); + m_engine_loader.change_candidate_page_size(size); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_set_candidate_item_layout(GVariant *parameters, GVariant **reply_body) +{ + bool result = true; + GVariantIter *item_iter = NULL; + GVariant *value = NULL; + std::vector item; + uint32_t layout; + + g_variant_get(parameters, "(a(v))", &item_iter); + if (!item_iter) { + LOGD("Failed to get iter"); + result = false; + } + + while (g_variant_iter_loop (item_iter, "(v)", &value)) { + g_variant_get(value, "(u)", &layout); + item.push_back(layout); + } + + m_engine_loader.set_candidate_item_layout(item); + + *reply_body = g_variant_new("(b)", result); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return TIZEN_ERROR_OUT_OF_MEMORY; + } + + if (value) + g_variant_unref(value); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_change_candidate_number(GVariant *parameters, GVariant **reply_body) +{ + uint32_t page_num; + + g_variant_get(parameters, "(u)", &page_num); + m_engine_loader.change_candidate_number(page_num); + + return TIZEN_ERROR_NONE; +} + +int engine_loader_long_press_candidate_item(GVariant *parameters, GVariant **reply_body) +{ + uint32_t index; + + g_variant_get(parameters, "(u)", &index); + m_engine_loader.long_press_candidate_item(index); + + return TIZEN_ERROR_NONE; +} \ No newline at end of file diff --git a/engine-loader/src/engine_loader_main.cpp b/engine-loader/src/engine_loader_main.cpp new file mode 100644 index 0000000..8fef269 --- /dev/null +++ b/engine-loader/src/engine_loader_main.cpp @@ -0,0 +1,136 @@ +/* + * ISF(Input Service Framework) + * + * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. + * Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. + * + * Contact: Inhong Han + * + * 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.1 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., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "engine_loader_dbus.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ENGINE_LOADER" + +#define MAX_ERROR_BUFFER 256 + +GMainLoop *main_loop = NULL; +static GIOChannel *channel = NULL; +static guint source = 0; + +static gboolean signal_handler(GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + struct signalfd_siginfo fd_signal; + ssize_t size; + int sfd; + + sfd = g_io_channel_unix_get_fd(channel); + size = read(sfd, &fd_signal, sizeof(struct signalfd_siginfo)); + if (size != sizeof(struct signalfd_siginfo)) { + LOGE("Failed to read signal"); + return TRUE; + } + + LOGE("sender : %d, signal : %d", fd_signal.ssi_pid, fd_signal.ssi_signo); + g_main_loop_quit(main_loop); + + return TRUE; +} + +static void register_signal_handler() +{ + sigset_t mask; + int sfd; + int ret; + char buf[1024] = {0}; + char *err_msg; + + ret = sigemptyset(&mask); + if (ret < 0) { + err_msg = strerror_r(errno, buf, sizeof(buf)); + LOGE("sigemptyset(): %s", err_msg); + } + + ret = sigaddset(&mask, SIGTERM); + if (ret < 0) { + err_msg = strerror_r(errno, buf, sizeof(buf)); + LOGE("sigaddset(): %s", err_msg); + } + + ret = sigprocmask(SIG_BLOCK, &mask, NULL); + if (ret < 0) { + err_msg = strerror_r(errno, buf, sizeof(buf)); + LOGE("sigprocmask(): %s", err_msg); + } + + sfd = signalfd(-1, &mask, SFD_NONBLOCK); + if (sfd < 0) { + err_msg = strerror_r(errno, buf, sizeof(buf)); + LOGE("signalfd(): %s", err_msg); + } + + channel = g_io_channel_unix_new(sfd); + g_io_channel_set_close_on_unref(channel, TRUE); + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + source = g_io_add_watch(channel, (GIOCondition)(G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_OUT), signal_handler, NULL); + LOGD("source : %u", source); +} + +static void unregister_signal_handler() +{ + if (source > 0) + g_source_remove(source); + if (channel) + g_io_channel_unref(channel); +} + +int main(int argc, char** argv) +{ + int ret; + main_loop = g_main_loop_new(NULL, FALSE); + if (main_loop == NULL) { + LOGE("Failed to create GMainLoop structure"); + return -1; + } + + ret = engine_loader_dbus_init(); + if (ret != TIZEN_ERROR_NONE) + LOGW("Failed to init dbus"); + + register_signal_handler(); + + g_main_loop_run(main_loop); + + unregister_signal_handler(); + + g_main_loop_unref(main_loop); + + return 0; +} \ No newline at end of file diff --git a/ism/src/scim_helper.cpp b/ism/src/scim_helper.cpp index 7cb5f08..c125329 100644 --- a/ism/src/scim_helper.cpp +++ b/ism/src/scim_helper.cpp @@ -236,12 +236,15 @@ public: HelperAgentSignalStringVoid signal_set_mime_type; HelperAgentSignalString signal_set_prediction_hint_data; HelperAgentSignalUintVoid signal_set_optimization_hint; + HelperAgentSignalKeyEventUint signal_process_key_event_with_imengine; + HelperAgentSignalUintVoid signal_set_autocapital_type; + HelperAgentSignalUintVoid signal_set_prediction_allow; public: HelperAgentImpl (HelperAgent* thiz) : magic(0), magic_active(0), timeout(-1), focused_ic ((uint32) -1), thiz (thiz), surrounding_text (NULL), selection_text (NULL), cursor_pos (0), need_update_surrounding_text (0), need_update_selection_text (0), - layout (0), ise_show_flag (false), need_update_entry_metadata (false), ise_focus_flag (false), + layout (0), ise_show_flag (false), need_update_entry_metadata (true), ise_focus_flag (false), finalized_text(NULL), finalized_cursor_pos(0) { } @@ -588,7 +591,7 @@ public: } } private: - HelperAgentImpl () : magic (0), magic_active (0), timeout (-1), focused_ic ((uint32) -1), thiz (NULL), surrounding_text (NULL), selection_text (NULL), cursor_pos (0), need_update_surrounding_text (0), need_update_selection_text (0), layout (0), ise_show_flag (false), need_update_entry_metadata (false), ise_focus_flag (false), finalized_text (NULL), finalized_cursor_pos (0) { } + HelperAgentImpl () : magic (0), magic_active (0), timeout (-1), focused_ic ((uint32) -1), thiz (NULL), surrounding_text (NULL), selection_text (NULL), cursor_pos (0), need_update_surrounding_text (0), need_update_selection_text (0), layout (0), ise_show_flag (false), need_update_entry_metadata (true), ise_focus_flag (false), finalized_text (NULL), finalized_cursor_pos (0) { } }; static MessageQueue message_queue; @@ -1026,8 +1029,8 @@ HelperAgent::handle_message (MessageItem *message) { MessageItemFocusIn *subclass = static_cast(message); m_impl->ise_focus_flag = true; - if (_TV) - m_impl->need_update_entry_metadata = true; + if (_WEARABLE) + m_impl->need_update_entry_metadata = false; m_impl->signal_focus_in (this, subclass->get_ic_ref(), subclass->get_ic_uuid_ref()); m_impl->focused_ic = subclass->get_ic_ref(); if (m_impl->finalized_text != NULL) @@ -1174,6 +1177,12 @@ HelperAgent::handle_message (MessageItem *message) SECURE_LOGD ("imengine(%s) process key %d return %d", m_impl->si->get_factory_uuid().c_str(), subclass->get_key_ref().code, ret); } + } else { + if (!(subclass->get_key_ref().get_key_string().compare("KeyRelease+XF86Back") == 0 || + subclass->get_key_ref().get_key_string().compare("XF86Back") == 0)) { + m_impl->signal_process_key_event_with_imengine(this, subclass->get_key_ref(), ret); + SECURE_LOGD ("imengine process key %d return %d", subclass->get_key_ref().code, ret); + } } } if (ret != keycode_ret) @@ -1442,12 +1451,14 @@ HelperAgent::handle_message (MessageItem *message) { MessageItemSetAutocapitalType *subclass = static_cast(message); if (!m_impl->si.null ()) m_impl->si->set_autocapital_type(subclass->get_auto_capital_type_ref()); + m_impl->signal_set_autocapital_type(this, subclass->get_auto_capital_type_ref()); break; } case ISM_TRANS_CMD_SET_PREDICTION_ALLOW: { MessageItemSetPredictionAllow *subclass = static_cast(message); if (!m_impl->si.null ()) m_impl->si->set_prediction_allow(subclass->get_prediction_allow_ref() == 0 ? false : true); + m_impl->signal_set_prediction_allow(this, subclass->get_prediction_allow_ref()); break; } case ISM_TRANS_CMD_SET_KEYBOARD_MODE: @@ -3615,6 +3626,48 @@ HelperAgent::signal_connect_set_optimization_hint (HelperAgentSlotUintVoid *slot return m_impl->signal_set_optimization_hint.connect (slot); } +/** + * @brief Connect a slot to Helper process key event with imengine signal. + * + * This signal is used to deliver the key event to Helper ISE. + * + * The prototype of the slot is: + * void process_key_event_with_imengine (const HelperAgent *agent, KeyEvent &key, uint32 &ret); + */ +Connection +HelperAgent::signal_connect_process_key_event_with_imengine (HelperAgentSlotKeyEventUint *slot) +{ + return m_impl->signal_process_key_event_with_imengine.connect (slot); +} + +/** + * @brief Connect a slot to Helper set autocapital type signal. + * + * This signal is used to send autocapital type to imengine. + * + * The prototype of the slot is: + * void set_autocapital_type (const HelperAgent *agent, uint32 &type); + */ +Connection +HelperAgent::signal_connect_set_autocapital_type (HelperAgentSlotUintVoid *slot) +{ + return m_impl->signal_set_autocapital_type.connect (slot); +} + +/** + * @brief Connect a slot to Helper set prediction allow signal. + * + * This signal is used to send prediction allow to imengine. + * + * The prototype of the slot is: + * void set_prediction_allow (const HelperAgent *agent, uint32 &prediction_allow); + */ +Connection +HelperAgent::signal_connect_set_prediction_allow (HelperAgentSlotUintVoid *slot) +{ + return m_impl->signal_set_prediction_allow.connect (slot); +} + } /* namespace scim */ /* diff --git a/ism/src/scim_helper.h b/ism/src/scim_helper.h index 2dc0ba0..3473cff 100644 --- a/ism/src/scim_helper.h +++ b/ism/src/scim_helper.h @@ -1428,6 +1428,34 @@ public: * void set_optimization_hint (const HelperAgent *agent, uint32 &hint); */ Connection signal_connect_set_optimization_hint (HelperAgentSlotUintVoid *slot); + + /** + * @brief Connect a slot to Helper process key event with imengine signal. + * + * The prototype of the slot is: + * void process_key_event_with_imengine (const HelperAgent *, KeyEvent &key, uint32 &ret); + */ + Connection signal_connect_process_key_event_with_imengine (HelperAgentSlotKeyEventUint *slot); + + /** + * @brief Connect a slot to Helper set autocapital type signal. + * + * This signal is used to send autocapital type to imengine. + * + * The prototype of the slot is: + * void set_autocapital_type (const HelperAgent *agent, uint32 &type); + */ + Connection signal_connect_set_autocapital_type (HelperAgentSlotUintVoid *slot); + + /** + * @brief Connect a slot to Helper set prediction allow signal. + * + * This signal is used to send prediction allow to imengine. + * + * The prototype of the slot is: + * void set_prediction_allow (const HelperAgent *agent, uint32 &prediction_allow); + */ + Connection signal_connect_set_prediction_allow (HelperAgentSlotUintVoid *slot); }; /** @} */ diff --git a/packaging/engine-loader.conf b/packaging/engine-loader.conf new file mode 100644 index 0000000..c3898b5 --- /dev/null +++ b/packaging/engine-loader.conf @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packaging/engine-loader.service b/packaging/engine-loader.service new file mode 100644 index 0000000..22b7084 --- /dev/null +++ b/packaging/engine-loader.service @@ -0,0 +1,15 @@ +[Unit] +Description=Start the ise engine loader + +[Service] +User=ui_fw +Group=ui_fw +BusName=org.tizen.engine-loader +Type=dbus +SmackProcessLabel=System +ExecStart=/usr/bin/ise-engine-loader +Restart=on-failure +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/packaging/isf.spec b/packaging/isf.spec index c639905..e440097 100644 --- a/packaging/isf.spec +++ b/packaging/isf.spec @@ -9,6 +9,9 @@ Group: Graphics & UI Framework/Input License: LGPL-2.1+ Source0: %{name}-%{version}.tar.gz Source100: %{name}.conf +Source200: engine-loader.service +Source300: org.tizen.engine-loader.service +Source400: engine-loader.conf BuildRequires: edje-bin BuildRequires: gettext-tools BuildRequires: pkgconfig(elementary) @@ -46,6 +49,8 @@ BuildRequires: pkgconfig(capi-appfw-package-manager) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(libsystemd) BuildRequires: pkgconfig(notification) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(gio-2.0) Requires(postun): /sbin/ldconfig Requires: org.tizen.isf-kbd-mode-changer @@ -72,6 +77,7 @@ Keyboard mode changer application %prep %setup -q +cp %{SOURCE300} . %build export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" @@ -115,6 +121,15 @@ cp -af ism/dump/isf_log_dump.sh %{buildroot}/%{TZ_SYS_ETC}/dump.d/module.d mkdir -p %{buildroot}/etc/scim/conf mkdir -p %{buildroot}/usr/share/upgrade/scripts/ +mkdir -p %{buildroot}%{_prefix}/lib/systemd/system +install -m 0644 %SOURCE200 %{buildroot}%{_unitdir}/engine-loader.service + +mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services +install -m 0644 %SOURCE300 %{buildroot}%{_datadir}/dbus-1/system-services/org.tizen.engine-loader.service + +mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d +install -m 0644 %SOURCE400 %{buildroot}%{_sysconfdir}/dbus-1/system.d/engine-loader.conf + %find_lang scim cat scim.lang > isf.lang @@ -135,6 +150,10 @@ cat scim.lang > isf.lang %{_datadir}/scim/icons/* %{_bindir}/isf-demo-efl %{_bindir}/isf-panel-efl +%attr(0755,ui_fw,ui_fw) %{_bindir}/ise-engine-loader +%attr(0644,root,root) %{_unitdir}/engine-loader.service +%attr(0644,root,root) %{_datadir}/dbus-1/system-services/org.tizen.engine-loader.service +%config %{_sysconfdir}/dbus-1/system.d/engine-loader.conf %{_libdir}/ecore_imf/modules/*/*/*.so %{_libdir}/scim-1.0/1.4.0/IMEngine/socket.so %{_libdir}/scim-1.0/1.4.0/PanelAgent/*.so diff --git a/packaging/org.tizen.engine-loader.service b/packaging/org.tizen.engine-loader.service new file mode 100644 index 0000000..e770ddd --- /dev/null +++ b/packaging/org.tizen.engine-loader.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.tizen.engine-loader +Exec=/bin/false +SystemdService=engine-loader.service \ No newline at end of file -- 2.7.4