From 9f6fe533c12fb2bf07fa80527374d9b1610c5381 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Fri, 24 Jul 2015 21:34:55 +0300 Subject: [PATCH] kcontrol: import working touchpad KCM --- kcontrol/CMakeLists.txt | 2 + kcontrol/touchpad/CMakeLists.txt | 12 + kcontrol/touchpad/COPYING | 347 ++++++++++ kcontrol/touchpad/Messages.sh | 6 + kcontrol/touchpad/README.md | 63 ++ kcontrol/touchpad/icon/CMakeLists.txt | 2 + .../touchpad/icon/hi128-devices-input-touchpad.png | Bin 0 -> 5303 bytes .../touchpad/icon/hi16-devices-input-touchpad.png | Bin 0 -> 920 bytes .../touchpad/icon/hi22-devices-input-touchpad.png | Bin 0 -> 1115 bytes .../touchpad/icon/hi24-devices-input-touchpad.png | Bin 0 -> 1304 bytes .../touchpad/icon/hi256-devices-input-touchpad.png | Bin 0 -> 13212 bytes .../touchpad/icon/hi32-devices-input-touchpad.png | Bin 0 -> 1580 bytes .../touchpad/icon/hi48-devices-input-touchpad.png | Bin 0 -> 1735 bytes .../touchpad/icon/hi64-devices-input-touchpad.png | Bin 0 -> 2236 bytes .../touchpad/icon/hi96-devices-input-touchpad.png | Bin 0 -> 3806 bytes .../touchpad/icon/hisc-devices-input-touchpad.svgz | Bin 0 -> 11660 bytes kcontrol/touchpad/icon/makeicons.sh | 4 + kcontrol/touchpad/src/CMakeLists.txt | 85 +++ kcontrol/touchpad/src/applet/CMakeLists.txt | 36 ++ kcontrol/touchpad/src/applet/dataengine.desktop | 40 ++ kcontrol/touchpad/src/applet/qml/CMakeLists.txt | 16 + .../src/applet/qml/contents/ui/touchpad.qml | 140 ++++ kcontrol/touchpad/src/applet/qml/metadata.desktop | 89 +++ kcontrol/touchpad/src/applet/touchpad.operations | 10 + kcontrol/touchpad/src/applet/touchpad.svg | 30 + kcontrol/touchpad/src/applet/touchpadengine.cpp | 82 +++ kcontrol/touchpad/src/applet/touchpadengine.h | 47 ++ kcontrol/touchpad/src/applet/touchpadservice.cpp | 63 ++ kcontrol/touchpad/src/applet/touchpadservice.h | 42 ++ .../touchpad/src/kcm/customconfigdialogmanager.cpp | 172 +++++ .../touchpad/src/kcm/customconfigdialogmanager.h | 48 ++ kcontrol/touchpad/src/kcm/customslider.cpp | 159 +++++ kcontrol/touchpad/src/kcm/customslider.h | 92 +++ kcontrol/touchpad/src/kcm/kcm_touchpad.desktop | 84 +++ kcontrol/touchpad/src/kcm/sliderpair.cpp | 38 ++ kcontrol/touchpad/src/kcm/sliderpair.h | 40 ++ kcontrol/touchpad/src/kcm/testarea.cpp | 55 ++ kcontrol/touchpad/src/kcm/testarea.h | 42 ++ kcontrol/touchpad/src/kcm/testbutton.cpp | 60 ++ kcontrol/touchpad/src/kcm/testbutton.h | 42 ++ kcontrol/touchpad/src/kcm/touchpad.kcfg | 312 +++++++++ kcontrol/touchpad/src/kcm/touchpadconfig.cpp | 373 +++++++++++ kcontrol/touchpad/src/kcm/touchpadconfig.h | 100 +++ kcontrol/touchpad/src/kcm/touchpadparameters.kcfgc | 9 + .../touchpad/src/kcm/touchpadparametersbase.cpp | 83 +++ kcontrol/touchpad/src/kcm/touchpadparametersbase.h | 51 ++ kcontrol/touchpad/src/kcm/ui/kded.ui | 200 ++++++ kcontrol/touchpad/src/kcm/ui/pointermotion.ui | 310 +++++++++ kcontrol/touchpad/src/kcm/ui/scroll.ui | 401 ++++++++++++ kcontrol/touchpad/src/kcm/ui/sensitivity.ui | 153 +++++ kcontrol/touchpad/src/kcm/ui/tap.ui | 511 +++++++++++++++ kcontrol/touchpad/src/kcm/ui/testarea.ui | 72 +++ kcontrol/touchpad/src/kded/kcm_touchpad.notifyrc | 148 +++++ kcontrol/touchpad/src/kded/kded.cpp | 217 +++++++ kcontrol/touchpad/src/kded/kded.h | 74 +++ kcontrol/touchpad/src/kded/kded_touchpad.desktop | 53 ++ kcontrol/touchpad/src/kded/kdedactions.cpp | 48 ++ kcontrol/touchpad/src/kded/kdedactions.h | 36 ++ kcontrol/touchpad/src/kded/kdedsettings.kcfgc | 5 + kcontrol/touchpad/src/kded/touchpaddaemon.kcfg | 26 + kcontrol/touchpad/src/plugins.cpp | 60 ++ kcontrol/touchpad/src/plugins.h | 26 + kcontrol/touchpad/src/touchpadbackend.cpp | 38 ++ kcontrol/touchpad/src/touchpadbackend.h | 61 ++ kcontrol/touchpad/src/version.h.cmake | 6 + kcontrol/touchpad/src/x11/listdevices.cpp | 53 ++ kcontrol/touchpad/src/x11/synclientproperties.c | 126 ++++ kcontrol/touchpad/src/x11/synclientproperties.h | 70 ++ kcontrol/touchpad/src/x11/x11.cmake | 48 ++ kcontrol/touchpad/src/x11/xcbatom.cpp | 56 ++ kcontrol/touchpad/src/x11/xcbatom.h | 45 ++ kcontrol/touchpad/src/x11/xlibbackend.cpp | 705 +++++++++++++++++++++ kcontrol/touchpad/src/x11/xlibbackend.h | 99 +++ kcontrol/touchpad/src/x11/xlibnotifications.cpp | 156 +++++ kcontrol/touchpad/src/x11/xlibnotifications.h | 54 ++ .../touchpad/src/x11/xrecordkeyboardmonitor.cpp | 150 +++++ kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.h | 57 ++ 77 files changed, 6940 insertions(+) create mode 100644 kcontrol/touchpad/CMakeLists.txt create mode 100644 kcontrol/touchpad/COPYING create mode 100644 kcontrol/touchpad/Messages.sh create mode 100644 kcontrol/touchpad/README.md create mode 100644 kcontrol/touchpad/icon/CMakeLists.txt create mode 100644 kcontrol/touchpad/icon/hi128-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi16-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi22-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi24-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi256-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi32-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi48-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi64-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hi96-devices-input-touchpad.png create mode 100644 kcontrol/touchpad/icon/hisc-devices-input-touchpad.svgz create mode 100755 kcontrol/touchpad/icon/makeicons.sh create mode 100644 kcontrol/touchpad/src/CMakeLists.txt create mode 100644 kcontrol/touchpad/src/applet/CMakeLists.txt create mode 100644 kcontrol/touchpad/src/applet/dataengine.desktop create mode 100644 kcontrol/touchpad/src/applet/qml/CMakeLists.txt create mode 100644 kcontrol/touchpad/src/applet/qml/contents/ui/touchpad.qml create mode 100644 kcontrol/touchpad/src/applet/qml/metadata.desktop create mode 100644 kcontrol/touchpad/src/applet/touchpad.operations create mode 100644 kcontrol/touchpad/src/applet/touchpad.svg create mode 100644 kcontrol/touchpad/src/applet/touchpadengine.cpp create mode 100644 kcontrol/touchpad/src/applet/touchpadengine.h create mode 100644 kcontrol/touchpad/src/applet/touchpadservice.cpp create mode 100644 kcontrol/touchpad/src/applet/touchpadservice.h create mode 100644 kcontrol/touchpad/src/kcm/customconfigdialogmanager.cpp create mode 100644 kcontrol/touchpad/src/kcm/customconfigdialogmanager.h create mode 100644 kcontrol/touchpad/src/kcm/customslider.cpp create mode 100644 kcontrol/touchpad/src/kcm/customslider.h create mode 100644 kcontrol/touchpad/src/kcm/kcm_touchpad.desktop create mode 100644 kcontrol/touchpad/src/kcm/sliderpair.cpp create mode 100644 kcontrol/touchpad/src/kcm/sliderpair.h create mode 100644 kcontrol/touchpad/src/kcm/testarea.cpp create mode 100644 kcontrol/touchpad/src/kcm/testarea.h create mode 100644 kcontrol/touchpad/src/kcm/testbutton.cpp create mode 100644 kcontrol/touchpad/src/kcm/testbutton.h create mode 100644 kcontrol/touchpad/src/kcm/touchpad.kcfg create mode 100644 kcontrol/touchpad/src/kcm/touchpadconfig.cpp create mode 100644 kcontrol/touchpad/src/kcm/touchpadconfig.h create mode 100644 kcontrol/touchpad/src/kcm/touchpadparameters.kcfgc create mode 100644 kcontrol/touchpad/src/kcm/touchpadparametersbase.cpp create mode 100644 kcontrol/touchpad/src/kcm/touchpadparametersbase.h create mode 100644 kcontrol/touchpad/src/kcm/ui/kded.ui create mode 100644 kcontrol/touchpad/src/kcm/ui/pointermotion.ui create mode 100644 kcontrol/touchpad/src/kcm/ui/scroll.ui create mode 100644 kcontrol/touchpad/src/kcm/ui/sensitivity.ui create mode 100644 kcontrol/touchpad/src/kcm/ui/tap.ui create mode 100644 kcontrol/touchpad/src/kcm/ui/testarea.ui create mode 100644 kcontrol/touchpad/src/kded/kcm_touchpad.notifyrc create mode 100644 kcontrol/touchpad/src/kded/kded.cpp create mode 100644 kcontrol/touchpad/src/kded/kded.h create mode 100644 kcontrol/touchpad/src/kded/kded_touchpad.desktop create mode 100644 kcontrol/touchpad/src/kded/kdedactions.cpp create mode 100644 kcontrol/touchpad/src/kded/kdedactions.h create mode 100644 kcontrol/touchpad/src/kded/kdedsettings.kcfgc create mode 100644 kcontrol/touchpad/src/kded/touchpaddaemon.kcfg create mode 100644 kcontrol/touchpad/src/plugins.cpp create mode 100644 kcontrol/touchpad/src/plugins.h create mode 100644 kcontrol/touchpad/src/touchpadbackend.cpp create mode 100644 kcontrol/touchpad/src/touchpadbackend.h create mode 100644 kcontrol/touchpad/src/version.h.cmake create mode 100644 kcontrol/touchpad/src/x11/listdevices.cpp create mode 100644 kcontrol/touchpad/src/x11/synclientproperties.c create mode 100644 kcontrol/touchpad/src/x11/synclientproperties.h create mode 100644 kcontrol/touchpad/src/x11/x11.cmake create mode 100644 kcontrol/touchpad/src/x11/xcbatom.cpp create mode 100644 kcontrol/touchpad/src/x11/xcbatom.h create mode 100644 kcontrol/touchpad/src/x11/xlibbackend.cpp create mode 100644 kcontrol/touchpad/src/x11/xlibbackend.h create mode 100644 kcontrol/touchpad/src/x11/xlibnotifications.cpp create mode 100644 kcontrol/touchpad/src/x11/xlibnotifications.h create mode 100644 kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.cpp create mode 100644 kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.h diff --git a/kcontrol/CMakeLists.txt b/kcontrol/CMakeLists.txt index 3c6d43fd..669acdca 100644 --- a/kcontrol/CMakeLists.txt +++ b/kcontrol/CMakeLists.txt @@ -19,6 +19,8 @@ if(X11_Xkb_FOUND) endif(X11_Xkb_FOUND) add_subdirectory( input ) +# TODO: make conditional? +add_subdirectory( touchpad ) add_subdirectory( access ) add_subdirectory( screensaver ) add_subdirectory( dateandtime ) diff --git a/kcontrol/touchpad/CMakeLists.txt b/kcontrol/touchpad/CMakeLists.txt new file mode 100644 index 00000000..f89a3df3 --- /dev/null +++ b/kcontrol/touchpad/CMakeLists.txt @@ -0,0 +1,12 @@ +project(kcm-touchpad) + +set(TOUCHPAD_KCM_VERSION "1.1") + +find_package(KDE4 REQUIRED) +include(KDE4Defaults) + +include(KDE4Defaults) +include_directories(${KDE4_INCLUDES}) + +add_subdirectory(src) +add_subdirectory(icon) diff --git a/kcontrol/touchpad/COPYING b/kcontrol/touchpad/COPYING new file mode 100644 index 00000000..bd7680cc --- /dev/null +++ b/kcontrol/touchpad/COPYING @@ -0,0 +1,347 @@ +NOTE! The GPL below is copyrighted by the Free Software Foundation, but +the instance of code that it refers to (the kde programs) are copyrighted +by the authors who actually wrote it. + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, 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 software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, 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 redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/kcontrol/touchpad/Messages.sh b/kcontrol/touchpad/Messages.sh new file mode 100644 index 00000000..9dd5eb02 --- /dev/null +++ b/kcontrol/touchpad/Messages.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +$EXTRACTRC `find src -path src/applet -prune -o \( -name \*.rc -o -name \*.ui -o -name \*.kcfg \) -print` >> rc.cpp +$XGETTEXT rc.cpp `find src -path src/applet -prune -o \( -name \*.cpp -o -name \*.h \) -print` -o $podir/kcm_touchpad.pot + +$XGETTEXT `find src/applet -name \*.qml -o -name \*.js` -o $podir/plasma_applet_touchpad.pot diff --git a/kcontrol/touchpad/README.md b/kcontrol/touchpad/README.md new file mode 100644 index 00000000..73ae4fd2 --- /dev/null +++ b/kcontrol/touchpad/README.md @@ -0,0 +1,63 @@ +Touchpad KCM +============ + +* KCModule +* Daemon + - Automatically enable/disable touchpad when typing and/or when mouse is plugged in + - Enable/disable touchpad with keyboard shortcuts +* Applet + - Shows touchpad's state + - Toggle touchpad with single click + +Dependencies +------------ + +* KDElibs 4 +* Xlib +* xcb +* xf86-input-synaptics (headers are required to build) + + +How to install +-------------- + + $ mkdir build + $ cd build + $ cmake -DCMAKE_INSTALL_PREFIX="$(kde4-config --prefix)" .. + $ make + # make install + +### Packages + +* [Ubuntu][1] + - [Kubuntu Experimental PPA][2] +* [Arch Linux][3] + - [AUR (from git master)][4] + +Translations +------------ +Translations live in KDE's svn repository. +If they aren't shipped as part of KDE l10n packages, translations could be built and installed by adding -DTRANSLATIONS="lang1 lang2 ..." to cmake command line. +Language names are the same as in .desktop files. +.po files are fetched from svn repository automatically. +If downloading isn't possible, .po files could be placed in source directory under names "kcm_touchpad_lang1.po" and "plasma_applet_touchpad_lang1.po", where "lang1" is replaced with proper language name. + +Bugs +---- + +Bugs should be reported to [KDE Bugzilla, product: Touchpad KCM][5] + +Patches +------- +I'm always happy to accept patches at: + +* [KDE reviewboard][6], repository "kcm-touchpad". The repository contains a .reviewboardrc file. +* [GitHub with pull request][7]. + +[1]: http://packages.ubuntu.com/trusty/kde/kde-touchpad +[2]: https://code.launchpad.net/~rohangarg/+recipe/touchpad-daily +[3]: https://www.archlinux.org/packages/community/x86_64/kcm-touchpad/ +[4]: https://aur.archlinux.org/packages/kcm-touchpad-git/ +[5]: https://bugs.kde.org/enter_bug.cgi?product=Touchpad%20KCM +[6]: https://git.reviewboard.kde.org/ +[7]: https://github.com/sanya-m/kde-touchpad-config diff --git a/kcontrol/touchpad/icon/CMakeLists.txt b/kcontrol/touchpad/icon/CMakeLists.txt new file mode 100644 index 00000000..33168c7b --- /dev/null +++ b/kcontrol/touchpad/icon/CMakeLists.txt @@ -0,0 +1,2 @@ +kde4_install_icons(${ICON_INSTALL_DIR}) +kde4_update_iconcache() diff --git a/kcontrol/touchpad/icon/hi128-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi128-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc3d8707ac1167d6709d5415121029203bb919b GIT binary patch literal 5303 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 t+$|sL`=eb>~?*e*ibQu5SPU literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi22-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi22-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..68276cefed0748f4e9459d051d4463e13d96ccfd GIT binary patch literal 1115 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H3?x5i&EW)6Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$Ysfq`*$fKP}kP=SGgft#CK zR8&+G}*zyp`f4usAj^135ymj+OT26 zjvYI8?%cU?<3=F2q@<*xq5`NMs0+xQGG$6@Yim_iRb^$Rlao_GK*03r(-$sW7!eT> z7#P^m(b3b>E2|6!Dk>`4+S+=0dRkgqnwpvrL7@4UFJHcR@gmS|Cr+Gr^XAQ~SFc{b zetrG=_2b8nzkK=f+O=zM-@bkS{{4p!A3lEk`03N9&!0bk`SRuK*RS8cef$3X`;Q+# ze*XOV?%lgzzkdDx{rk_KKR0jQ{QLLsjT<+P9Xqys`Ep>e0DU)S&K#fzySuxao11~* z1`L+Pix=nT=U=*X>Ey|ihYlTj`t<4J$B)mPIRlIrzdPB%Kq|Z>$S;^dv3>sBx$`FK z_pjc$YsW4i*tu)YXP`U4;Mu#iEpLIAgTRMA zeEfJXg-KjZU0qtm)<%it?Ad}hKr0xNyxm;OkH}(RlKTz9jNIj>vw;eX zJzX3_BrZ>#nCj1BDA3mZ`XSh|a|cVS4^)Nc7nc9H?Nh#!MeiZ=`RQiot!H{J=lI*b z;>C;`JMJG*S6Q^A_P-;`zr!h0gbu{8sLbf9aes2-sOi18PokY!pGnSe5V`h%B`~Rj z$=k-);Z&EGW~k^))^%+`o?)hU4R~XNQ$05{Wu6d!pewj0v3<^j+y?R1%U|SgSr#9% zYR=496mWM-?(HipnS9R~2VP@6o*3qD${W?(I`O84y1D-T1shiESh8i!pHHuTJ^S|V z-@}bep<$uduUxxoZenJ--Dc~yt>qYL4z< z@ee$4!GOQLA=dVj+YKj!I(gaOAEr6k9lv{swJ)wB`Jv|saDBFsX&Us$iUE8*U&)M&@#lp)XLDz z%G5&Jz}(8f!23={6^e%3{FKbJO57T(8ZR6JYLEok5S*V@Ql40p%1~Zju9umYU7Va) ZkgAtols@~NjTBH3gQu&X%Q~loCIEH|5eonS literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi24-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi24-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..72bf9b36f18d38cc7c51336b17886e9d19b1a9da GIT binary patch literal 1304 zcmZ`&YfO_@7(O5nq&kre1p^u4HkCo?w_4N=QLvrmQc`GZDFcL-yH=pIU?C7|0A+Q9 zkqr&7EkO-}Ou0B<&~Td&EPMruMQJt!0YyO2g2<&dd(rq~KlUc)d*5^NUY_SU=gVgW zp4e)&%L*a1)t5mF25+~qEH}aTVI{5tXBOwp^hT(*fMAF+hrN@K5zIs=;|qk&=ODBO zN9U&zl9CXbiA0Ec6``HUWz9jJ2${^W0yuO?xP19Ckx0Za?8uQLM~@!$^70~+$!>0L z6beNqlU=-c@%=fM%k}p5=JWX>At9lmq2b}-5fKq#VPT%0p3tGHs_NFQTeY>djg5^; zrLwcLv%9-nrBbQY>cPRmfq?;ke}4}T4?3OBWHO;cVq#)uW+pT*C@3f_EL12Ia=BbA z7N?}70aE}{adB}#Kmf$)>FH9b6sT2HRER_(pa6Z`-QC%2_PKNC07gbe zMp{}LAOwO*Nl6lkBsDb^!0>oHkizVPSy)&&I5@btxHvjGLI7rKYg<=WS6^S>+}sRE z=H}*rFVLTzoqhiN`OM4=09#mC0EDkzz0<i;Ig(OG~d`zg}KmURhaLU0r?i<_(Cm zwzg(47(l4?_4T)J-x`fZjYiYj+KS_NZ*Ol;Pfu4@S9^PVOG`^bLqknXO?7oOu*=TQ zrqO61#n{*wNb%&!6P-@i-{0TX)&|N?O-)TqOpJ_-XtmnO$w|0q&fTIN;7&_|1K9{| zVTsO&zO{~CT+jc#t_Em;RTu%rds{Qy5syRNJA2yH4Vd29mG3`9#=gGV0vxX^?89XS z9KX5e+I^J@FS|ZAI{HtOr@8g^?N-*#dv+7-%6NPjYa;MJK|`0!9T~9MoXp^-!nj)jMY@FEVnUpQT6Ke3MZRY`VHBXEmupS z{6V2;xwccs!XxuF2BltARibMK{hRYjW>k8m@|)d-v;;n#%RC;=hF8GOI?m+M`FsV5 z<-E-~=&^2iblB?WX>0k+&1#F12M=_dQ#``m8?JZgKgrwbx15oRHr@L{S5l?Y>vxz~ zU@4n@_b1r%56jHyH*U}WI@)U7{PAAq$yinpm;G?yfo6D6J9O}>AU^txATjnVrY-7F z>AHv2qaB0yWhIK)C4<4994GyxPn{-A{*8SyLd$y0IaRta&L7o<^4LG}IMj!Vjuvv8 zW&GD9*Qcv1>P>mRd@oYH6bSE+Nz^6UG{JC%MrQL@L@&72Pp1l_l4FQT;<(az&s~s&eCdI-+dh#O{smT2YK;H@ literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi256-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi256-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..0e56a21e2efffe4f69ed20226266a88780d5ecb7 GIT binary patch literal 13212 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 literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi32-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi32-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..2e75e972cbe038ed265e79aa19c960f472e3d9c5 GIT binary patch literal 1580 zcmZ`&do+}J82*S;8eig=Agf9!M4_j`Z0_j#Y^{l4!C#et0OKCl}> z5Y)z+`f)EQ3L^-JFk&_96NS~zGQLW&DnwnZbK!Bm4p^lCY9*;l%8G3qpy1Kds1_oMM zT2@w8E-o%`3iGhAFnxV}m>3%y!$>3&O-xKoO-)anIH9er4XFeI0gfy!Ey-lElarIX zyE~mu4-52BN_3-eZ z(P$+lB{y&0tf;6cD=RB3EX>Z%PD)AwkA8lB&d$!jrm3k3J5Vt(F%c}o67;ayY|sYP z{r&x^RH}`Q4HVVT(11iR0#3o;7t7!%E-o%UK0Y`&*v!lfx&*Sp1$c@23}AqsK*xX? zi^U%O3{_QCXepEf5}*aBtE^z?L4o0pe2K0ZD(Gc!Fs4Kjp6A&8%vni7dbv$L~v zb93|a^9u_Li;Ig(OH0ek%PT7@VzGF2b@k)Nk85jd>+9)TAWEBXGBYxrcW4Nv&%|x!Wan^m0Nfn6exUgmEuEn9AFPEq4b6i4FPJaC{m;Rc zB!;ot)Rc1phHd0n&o(usq6MP4xuxp6l6A1Y+=xXrjEKgEe>m&uMN$e;*<%SJq|V!t zNeD;wTWeUz1zGhYHkuC2Q4HCJjC3^sDmC}rNNv{)w% zjhe%XYt+02m+JEeL|9L`6h#X~48HG^{?H(!C3r+P>&D^0!10ZS`i=3&mXn{lOKFv_ z&az%Va1ZY(n<#rxL|vK6Twg}dU&VOzDy+mEdVxj|5LD8bE%;GU<~3O{$yC-_j$h!s z+tGs5xrV)@o?BjB#wW!x1Vh z*KV|1AGH)vW##RvbU89pddaPMs9Ob-VyC$?VOW_$ZM)c-N%H8Vs2n=tIF4LsN5yrdbdnHMa+s?mIGPZ+38< zYgn~xqJTzxmHAh5M(=acUbLN0trohvRO9=ztGI&azZ9NRuzHrFtdyZ*pn(xw|J|@VXE2#Jhti;p`EQL_3VZ42#&R#fmtnk=EJX#Zv?dR zP}d5agXB8qj&v#E#f4hPU(}x}I#iAqO;o&-rK>rY$R}fu? V$?`3nH8}v65F0B8QjLXY;@_KV z&N!lk=z`JVgmjRb6HY=&6QAi$l>i>?>=!Gk_W652WLc)a0q{e;3(npSm+rRMkocz_@ zPQ=GZLJ!0~$>c|%Bms_G7|c?zpNmof<2syA+CGQhH-;?y2?HJ+t=hjxv@+7y6?|JULQy8EsR#^hqn8B zy7uz#5u0w$ifZSgWOYx%fs~!6;q`yK;>xOG&cLqd_>OMTQO?%k~w!9haVnFDJt{(`*;WDO%pW3h#$yI6a&SjEGktlKVVa*_C z{61_(gLP$m^O0<^AVlf+r@z!X8bVY;=ecr1r}`&#iHmAWCn@O@UQ|K!ivTkSVVf(1?!AmsD^-Z33*nDbBvDhj!gN)Nvf%|susxPmY zxxkQixJ{&Y`9yMqsn7bB8|0Qh`|F>-JaE5t zDvp=11tGuWT~1`xwd9-+K(}(YF}xo+Q{+(-mF3zU)_DaLaoMq~j=Onme#-;xs-Cd5 zJ<*(pN@9aE5_2JGh#a=NxcQUim+TKdx1AsNkORtBlQkZ~-=TgcS7% zDz|p+&V=YNbijRb$W-x5!vqw?;S~~H>lwKw1SDrD4vVjDkhp@x(i6^;%DnsmO4@X5 zpeAn3k_O$YgKzvmfu}AXRa^A1qeIvmFH$ps z1kO}agBmc$r2N-KqDZTRkFPTv>#mGlKXp)YU?*jK{SLYsU?wt)qp(SZJvDv^Xu{rK zx>56wzNDy+7~K4|lOOi4$q&4UavptW)$_R)Z#tFeYN94rJ{CL`W*QL{RV#=XzpF3{ zNqol3b%5nN)P-L5e^i5bwXdcW&dRZK_6d${K}kmH6p|*T(y?>z%9( zA&>p3U~H8}x4OLjW08inYn9lEGu67M&!H@y%31b8g-Mab`kEMh^?7jq=p>IA;k$rT#Wz6R^vwGCPY;eQ=#EPigD! z{;awCZpuUM8(@e(=#>o<#F9_^WE`FpcYzugjHSf{O8|_~Mi>Jlw1JU@H`)|ybQ)`F zp^rAhqS2ye+W7wnk<1GWdgA{VZfwuSNCegI6}*`AI2JV~7_e9@Lq=41ER7l+Y{-lW U`EA`wO|l8N;5~3H4wUr20Te6|DgXcg literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi64-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi64-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..65aa24afa17e420a2f99780dfa2e2904e44fe9aa GIT binary patch literal 2236 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 literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hi96-devices-input-touchpad.png b/kcontrol/touchpad/icon/hi96-devices-input-touchpad.png new file mode 100644 index 0000000000000000000000000000000000000000..b780218c21100466d54b25c65f2c704ac7c5fd28 GIT binary patch literal 3806 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 literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/hisc-devices-input-touchpad.svgz b/kcontrol/touchpad/icon/hisc-devices-input-touchpad.svgz new file mode 100644 index 0000000000000000000000000000000000000000..ad8bd2284994acfd7e610576d3eca4be7d45aa99 GIT binary patch literal 11660 zcmV;7EpyTziwFP!000000PTHSa~s#S=DU9dMtO;Ah~~auXglX&QfKN^rE01sNzF4v z0usg)!2zM0fBk&lTDuz!phb(K zc`;kwTyCz`H?Mwr@y~z!=e)d_-R%}PSBvY-&GM%gH=7s#@t5y@{BQI5?0;;Ri{0{S z_I|y4J^QblpYJXgx69d|U+;Fe7w6~i-@otHZDY6DzB>PYHlP3HyYGIyd-v+Q*=&aM z-rQYm?q2@%VzkHRc6oF6ezCiJ{c^MUS@wIoU7tH+>N(cF*zb9DIqZ1*c6%*LuP)D* z*ULA{o88^H?d zv0{Gr@n*O9FhATCcQ>^wZor)5xBbe`TXpf_8bti$#mKMYv*W?t;(x;q{f6#t^LBf= zTw%{;ceC7`|Mee#9e$jf?rL{6I!yoE4$gbbNhBT-)-JrzP?>tb-2}EWVikp7Xv4nE|f0Jwzc{yOGZ3ub)T!B zUf=*uzPw(pU%lS_^dbfM`hI=2dp&#`j=ubGyV>sMtM&C#FYf&H=FRf_ZgKN*F@JO3 zU)TBTH6HONuKD)n)#O1xT-}1~-gMRHIJx5E!HU0N$&Xjd)g71W-SAtGAMg{N>~gXF zpWDUN8vLw_blKrAzEmX;|3O49ZWrqtP~vWLy}oJ(!{P3Bo7;XB9@FmQHEy39=a-x7 z&GzC?M*jUEn>Ki|>)po-`@@U$u0KReb3pdoj9Al|7_mzzfYd+u~f?0|LY%n1|xs98%p*8*ZqlS z`MKAf{HGuL#MzdW|9!^U?DW}wl}h}!xIUp$uR(Ab*UL*Be{ubO@$qgriRk}}*V`rR z)t@HlIVShvDSWMY`1w`a_|Kd54uu*-Qq%UwtzW)qh4a%MUcQ+BbO!QL2fPRcf))e^g!O?2N6 z=ehgq3rKzEymiCI)#TFE)Y2^;j&)seY5y#KbE*f(+SjFetSO~4 z!~aO%WPQv^;1I2eByhqPpUV+}i|Mir?vTJWxGq;boI?tqtX)m6{k@RbKa==dlQ=z- z_*;{>K9l$xlXzquo=NjHgeXOOD3TjkcZf#o|VrPn}(j)dV4YF~$ab#+I&lQ;wW!mvU#SPw9a0#bdFl zIUW%HbnR+#EeP*??ox0i{%cA9ExkSv*@tk*+@x`+(H_w_=FSQ+#x#ZybjCz;$lRxE zSCeahKQ#W9Zr?MFmB!!F?|Y`P&^UZc$M2cOO5<pcK zYAHhrp|jcgbSg5Z4+{P`{}tb!6CO=+p`Oism*KN}14lia#f--We|i)Oxt~M+l_bvQ zki@ym0j%ebNnCleM>IZJyP90vh@5QAr&xS~$OCars$ffeAw_GB***!1x>Je<l^3gvDa)t>8^`koNPEhnclOX7nRVp=25!6q}{K4AQSClxm7f(Fm*NZF~|GoiIxt2H~?Q zI$nD(MPsd}xs7`X>VmJi5i}W}o`jt*6K2U7JISJ_uqHl0%RVC`yhZKJ3IGJS|M3W|p8Z6m0I(SH)Sw3btXV&k#vq-=NG3Ua)5HMzDC z)PkQM$fC|g*9aO4P}LJ4s5NGSLtUNb&^*DR)X35uTDs^hhdq9ynTg-bxuVr%XxT58NsgGVRqlF50}E=}?1!PPlEU;{ODk6VqmMr+r zvvFXOqK9VbbnR+#?Lg7=ASFtQW*c%((VW85py;7l(t-|qA<;2&35|_XYM!XM8O6grZZCz2mjQqXml4JSe@K z$(2Fue6?M`Q+f)>35Mk}FY*DTxHrrxss)dtni>uTp%e#Y38(W=wVbS7O|Bh9WdDVA zX3l-R`t{Fat^4SiI`7L-QNX9@dAxQk21?K$&p8E2J`J;^IIHRE-Fo@{yMZDv7sK7% zE?zBVObh6!Q(@Wt8&|BELX4IF9*UGJ`!f01+Q$NnzP+imm{gGP7x<9Sa5`S$9F zp4W?)%j=(B{Ec*+olyJLcJuc3&E{&^DE(qj*+zNYu-j`1`FOq9E&puJ=I~TIpWw)T z-_!qgv3uR$QyZJK+TeNK;dx&`XxDGw{Gc27&>=ZEtQyD+}-Q-YIo6p{o!yl*9r`D@MScCO1^I2g0#zb z%bU&B)eoT8=I7-FSn;AvHf|u)z9zNck7qyYc7|M*QDFsEg0=$eIvKIdAHoIt~c+8-eZ}y}7zrTte-=CI2ZmtQK$9*B>wbj>qxCyyxq=GRp1pa=lt#>VuaRCzs39 z{@=~|=HeyDbv@pS<6PYRzqgC+-eywY%tAbiwRRzu9A}raIox5`$>QO6&E`x~(FFq; zZ4ANgxA3pGF3zrJ24BoP0x>B=+x`{`xBx}ZM}&KYv(T+wg8cIGp4 z&pGFxb<)o|1Sv5mDK7b;(J_FcARb-Wv-v=@fsFGJ9p}um_BZv*?2S^S`aB!|a5>|V zowo^Jn3&~*lLur0%lBLO!RPjTLe;G}2MA~RyIlGHhvAxefezZ?QM z=nGdz9@PjQ-hlgdo9!I7@ZDnfcDo$UtlOOcwv)zy;p;(XfMcJyL|F!)`mC&%g{ zL_LSZCD;fLZte=MGupxpqDH;z4i!5>;KrVr^~~e{oyo%$2iZ%1 z#o^`<7?)j<4Ir!#IEPw>N-m#0J`q}Umc+5McS$|~CNudGM$Ex2fcsuB_ z{qY(FebW2u*}>-n3d>M2&60IJitsJRE<9Zb@wcG z1en#UC)%c0-v;fw_6)sS-qE_u|psvS6N#>*5niFveAMXKKa))?Ke-wWsjol4L z$Sk)VV7`VJ#(W~Gp;oztGGLesfgKn62kR4+$Z<>PX9VtD!x1)nPxlyx6#ckIb8YGQ6@4=3A z?je?gyIBS|&1YUF54cC!RBHtwSuwjHI+pYekJ&S0+OL)ggFH`r%0|_MDS7miTa0ah zh=j2=HPElpN4F>D5ij+A!Zfg(yWb78``q*M^0{BFqYS^;(a6~npo>4N6-KXC*c}4m zE}2r)-wM#mP^c9?iK*gjJ8P_La!|(3Q@{FH$%t$Pa*#8ICkQ^o%=|SFbq!7JhIg|dZR`a)^X1g4OSmw zzDay%lKK9T0MQ)-#I6U1!@p_NbU(uSax6I)q%2#$7HfuZFKdp)xE4Q!AV99()n+I{sb`F(S4VcP01lqc zu!SBk5*u<^`YD8!9j>ou0VMD+H~H=6>>u3;``ZLv8I=7q*+bZ$I2vkN*x!h1X3;yJ zVvZ%qh7{mB0t9gYZ%}I(;2-$Hyzx0Q}0}tcXCYIms8wKmoJ*K?qz@A%F&+_4=JcV1sSZpr+0_XG3j&Nb*)5 z$L<Xs9X>{J6Txy~N|Iy$3HK|in}NA2!(~Q5g|MTAC`Km-hqMVtctAPJDJq@kBtNxX zz-3m>hl>$`4UoyqY6;+`tnOm+r4sV7%N>?ZWg@{n$kr`SO zCu-Jk-$fA@PO4YUI@%=8EhJQ|A(Xt0ni_&g%OdAOtt!Y_-CIyQXjsE14Sax%w%NIC z6kU32;a+RFEoml&i=xx?l%QvFL2XIP0Q)Oy6c4qAH1;Q>H^W zC<($^z>ayZ0-z;4)CN@cSyHnp5S6?oYQQ$nzot6U62KP9TwkgtLV2v3IEm5!?$yLY z$P*t+p5L{HdZhbe&K_o4bsv1cIs;ciu1caa#IP-_9q^_ATV`V^^(-z2>>Ix82d%L1 z6jg{3btn}@;tMU*w%Y(*SNK_e;J}z55mh6aq2JBO+cI!cc$RV^s9(t^%Q@OfQ`~R* zWkSo3dWk>RMC^;zH&;tm{@(rc;_mM5^78KPYuTQBzwL1hg^TThCM-!^O{Z!0Y7G>y zSO*E&fnJt9jx+^6SydLEBfTOw*_@)N!o+b5VpgEPlB_BfhJX#`OdK>7nqta9N<`qT zB)tS&t`wUDr+H(xU^-8$0^J>aQ>#Wm3*4_Li-3D#a@CgyrNGY|r>T*D zmveh>sRkc3qRb;};w5LTQefWaz^37v4s4p3@UcmAF}5&l(CNNxw-k%!th4$?Rggtv zF96l4%BDmFAWzLZkVUPIgqaO{+^br!5~~C;2;C)q0#p%|)J!3ms`(=)#tIw~G}7U! zIJ=gwZ*>}-2fhzIeuW#z2y!0qYmvbJ$TB&;og7|ZpD`OO(;m=%eaqw?t9t(k(UEc* zw;n4IutFalVNH_=wb9azjstz7)NbYKG&-1_FB;1(u~pCjGghCAcz{v!B#z7=)n@Q~ zRP@m<2Q)5NP!h=_7t=#2?OjaJ z#P~ibq%Nkx{WllW602GX3W{XIOE6kj#t@V^inUM}K~ca&+Z>3XR|bHZHGmmS^Cm$) zD*~E>v5I;f#90NDAQGYx(HUS zZltG63ki9bC@1;eNm3x@lr+o<=9MFXj_@eO#A1;`0N^t9<=O3A6(ca0z}=h)>NRrg zu|`KN+lxoh(d3F#TiquLV7g5zeRTB8L@hm5)c*ZrIhN7AQ(2?HM3uEdY0yMj1PW5W zIyBMBGJZjVnwiW6-Y6-6lbI=F^|e+W7=~Mjx=Kq**$~0hEUQUv3vdw3tfx*-UPLWw z;@66$l8|WWn0%up1-m!_@+uQ41C47A0|r3?oiQrD#U*7qT*M8Xhqn7 zOLGgER%VGoGXPYUvM|dKjOHSWQU9VccoO@poJd<`%BGI9asVLIlJjv^u5j4+I4hSp zGv**G7vQ`&_b6fWj}^A37ZLdaVY3sNhmo*lSbn4#9@GpuKVhDbBbQ~{@w>%}>li6^FYB;X(^v0y~e z2~P9{hza{wtFps#bs4RwxYVfo$1@0KG*M)SC(!yXof+Df(D$NaqYDS3<4teKn&^a> zTbiPjAP0$65HvG zSl66zqS#efR``?yZ+yl@Pw{5Ehx>W+Ay4gJ7n1Gkxq)`iYAUP|bW!7hp06kN5-@}YT!wiY7dlKVCl z!3oe(PNGs8=3#XqOI|apF-e@s!npxj61C}M{3bwYK6coHR zj?<}hDg}_0R)H%*kfjuDF9h0)C!(Nja9~aGsDWHFC8K(4L=fnsGs2oFZNlXu7IY`H zw4WuO$v_ccn^i3JPW~Z zE(F5KM>1f^@JT|cnMs5M)S6>SM8tIHfNB$`EVG{%kKHpRgGI~<7)z%VToJ+8tiogr z*9sC9EX?8TfrW68idbfe9-C`&038{6Imj$K@8uxNuzbitv8^ne$t014D#i4j^q@cx zY->shd>56th=Fx_1kaQd_AFQOwXJZDDH(nc1dd_A1zOHJmJI~so*2D}0;AaTm?df0 zL?P$BLGW>J5W>(atD=D4nn9q!Y@(o*^PiA~QC;}6Ec{loAbl=JvS3()amIl~aD{+w zpyODCmb%~>C};1IuV8p7Ux6~LToh7eV@=2TyKctGv4BpAh0MS&v<~q4AX;!cD|Dls zC4iU4FxJz~=*OA`LmgRzV0#BJG<#6M)OBnRLAO!5vD9l$`tf5MtsVnB0n8Wc( z!A_xYxHQ9>1tK*ATBx7{BbG%v2gPhuDFaP_Tm^EJB=pTW014W6M!q&Fir7G*@}Q+M zdSS(Dh%72AfhqpL(n!difk6@b<6{Z*L`)B~Jgc--U(@|?gRNoLl-Qa|^VFt8h^4W0 zXgC#9qcQ_6p#5o#4YETcJ0Ol&v0KMb-(V)MV=(<1#93e~e^Jl&V~^RORvkN1wdDWKK9UP@gaj3y+SW zvXWYFV$s}e8ye8&X|<+K{dmyF8C=F%2fLoYg*4vMDwzZOS7zE&$r?S97C={CY-n3G zpJTwiN*m&^0ax3OI;Qor()o-q*t4pBgsK)JO?APBd+B|@luTvv)Ckdr(DFnq6^@pA zO()Ml1D@r?vH)r2wY1>OdXrao^c7=;K*JMePqnZJE>sg0Er5 z&`&Br=oA(Po^zKY9e}e8-z@AP z;Umdb=`;ccehKOLPQ0j2M`HahOQEXO0W_5!IxC^rU(mPmM|uCPrlyN#&**z-2^m9Q z^lP*TnRhDrI4AwcdaIi6k`iIP*lmJAJ@F7dAu#+WRb>^%h@+kVn=pgwhX%fCQ7LSR4++T9`8e z3S*xM%Ms}VrBW%p5MqzrrQ?P0@75>=8NiaVD<{sPx;&pLi4yF&6N}N(ZTA&R?PE@{}^T3sNTaj?tPbPLyFF zoDn+T%&HZ1toFc`Hk?ibGsBpOX@en?T(#DT&-q4NEA@?@wOt&2W7UuK zp@(Td9NnQZ8aYHS$k^gi_&Oh_MUa(!qZ0fBc8@b1ry~LIs>3;H!6Y?ghLJOnrp$?r zrByI{MV72!(Tpj@%d^2yBs4R4$oU*ej5DZ1dz)F@E%I5ULXw3vE!ZfX1XMUd=S)f0 zE6dAVQv#7S)3MN5k@-Y=@zR^ex|vyj`C8Hy*wWXoUo5Onrh$O^J)&hF`4FdPZP$T- zLQnA375YIQvGYNym-*q7R4BC+YLiQqnPcil^|(~0?~2YKE`<(Kr!V>< zmW-0^G%cIOlF`luVP9YyJm$HynB0c#ab%4n?&0x4e=R4q%$gPx zN|Yiws5pt;ipyZMj|}d*%R#5azzyS5^d?JTd1O1b4oZ@yLw19k_DM$ACdNZ#@>yk; zD$2M*77hp)0T#(FG3devTWI_PEs9*QW#s}}K;)aaX>9D)TZ2sTm45ciO8VR*XU&-M z@87KfF17BIOM%g$eU7HSF+l?SY>9M4ovE2c1w2^**QrCYwp=O z7O7onU5OIii&^Jwvhme-B{??LOPdy><17HcCaWdmXRR8~oW=KGzY;d!U#vWBEr;kO7?dBe1+Pr!1dg)$^xV zz8{aMET8h228N>?dUsRQ2w;_UezwmBd1eIE0DbHN+mvr+5I z`2LZTUtoa$5PV-w`99YAX}+&{%=c}4edBw1jF1JL6{`C z3#8xr&#CDFh}#q}PvFA(uEM_5A^?Gm&qz{jGjn51TCc^~Co-3GM#l{Dsr<}2Dl!19 zXsovAD-Xc&F>CV03NUshapnVif#eQd@?L{TuwYKHjcF(+NiavTjp?yXsfjHK%J85| z%TpAVsL8AAM+_hR2-`%H+=$`X+x|riZy!0s1Xk~l!0^W-PRa0`>Eovv9y+cmdRC7> z&y5s4IK90cB5HfJwOS1xt$x#*3U6EIrwuZ6FUlJfq^V7dNmSou;`GSjd*UTJs$0JP zVAJC5k$q>_kT#TKw#RTy0+*-1#>Xe`s} z)dw%w49Ht0BkN_Bs(n9Jdi8AWhX%EpT*pynEr*b`yuH-Y-ZvtqkHcS!ik6dLj}JDg zH`v68Zi8u}<$`{qyTAz^O#S9)2GOd~>_w}xxA#!A@<_657<&!bexcW3A36TUl&3d? z;UVOC_z_wVDb_Tp`NS6~a;{-w{Ey`%maj7ZrxjIwEqxp&^s$o~Yv^Mt zhTxk%R&d~?c|FRwbJhTchORTqVxuS&DpLW*ZCI$0l#(sIGbiIUT+)yNeX^!OB&Ka! z@r8m3AmrL!9Yw(70H1Z>xy%_=RYNV#M3jIZuYHO85j}o1p{EV#;q%K$;?qsPM|hOM zpUIR8R?za@Id0JJk)p3W^>m1Kk07)gjGYo&+tq6|58($zMDhaI6X zQlU*pw}SS4DnX+{F-j>&&g{s42$wic#47O! z*e`J;nTY|%+Q%vlvrt`WMG;Jc7DgjQjFJRE82nJnT*W(R&a^iin89A97WiQp2zqkX z%e#{iF|!PL;a50|Rw7S2L`R$s!53cQ;AS*JC$|YY)TstYUp)!fE}8H_nMIRs@#riIg!h_0yY zSQ-06*|D)DdGu!HdN=docIG|nw;P)49br#^J{iF&0u+FWd@n#5CuhQ_36RwhXU4V% z6_!sNW?)5(8|jWrDITDV8R4y zo%JJYjwaUFqk%PTUQOYM7^BS{i4*9&77~m2;0`$GQ1TQoL8*z41Ze@2#BM-YP@HN> zEo_@jbIon5;8iu?B}w6%Z_pei}_~!)OZKgQDXAH6P7aSLho@n2(mU zhfxEe3F!m_p%cpJ+wrYKDX4!PX%^ay7%T2cMq{ WFEtiFp5ML0pZ^aF^DUdf(*OWf(AQxA literal 0 HcmV?d00001 diff --git a/kcontrol/touchpad/icon/makeicons.sh b/kcontrol/touchpad/icon/makeicons.sh new file mode 100755 index 00000000..29a46e8c --- /dev/null +++ b/kcontrol/touchpad/icon/makeicons.sh @@ -0,0 +1,4 @@ +#!/bin/sh +for size in 16 22 24 32 48 64 96 128 256; do +convert -background none hisc-devices-input-touchpad.svgz -resize "$size"x"$size" hi"$size"-devices-input-touchpad.png +done diff --git a/kcontrol/touchpad/src/CMakeLists.txt b/kcontrol/touchpad/src/CMakeLists.txt new file mode 100644 index 00000000..015ad0d3 --- /dev/null +++ b/kcontrol/touchpad/src/CMakeLists.txt @@ -0,0 +1,85 @@ +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/version.h" +) + +SET(SRCS + plugins.cpp + touchpadbackend.cpp +) + +include(x11/x11.cmake) + +set(SRCS + ${SRCS} + kcm/customslider.cpp + kcm/sliderpair.cpp + kcm/testarea.cpp + kcm/testbutton.cpp + kcm/touchpadconfig.cpp + kcm/touchpadparametersbase.cpp + kcm/customconfigdialogmanager.cpp +) + +qt4_add_dbus_interfaces(SRCS + ${CMAKE_CURRENT_BINARY_DIR}/org.kde.touchpad.xml +) + +kde4_add_kcfg_files(SRCS kcm/touchpadparameters.kcfgc) + +kde4_add_ui_files(SRCS + kcm/ui/pointermotion.ui + kcm/ui/tap.ui + kcm/ui/scroll.ui + kcm/ui/sensitivity.ui + kcm/ui/kded.ui + kcm/ui/testarea.ui +) + +qt4_generate_dbus_interface(kded/kded.h org.kde.touchpad.xml) + +SET(SRCS + ${SRCS} + kded/kded.cpp + kded/kdedactions.cpp +) + +kde4_add_kcfg_files(SRCS kded/kdedsettings.kcfgc) + +kde4_add_plugin(kded_touchpad + ${SRCS} + ${backend_SRCS} +) +target_link_libraries(kded_touchpad + ${backend_LIBS} + ${KDE4_KDEUI_LIBS} + ${KDE4_PLASMA_LIBS} + ${KDE4_KNOTIFYCONFIG_LIBS} +) + +add_subdirectory(applet) + +install(FILES kcm/kcm_touchpad.desktop + DESTINATION ${SERVICES_INSTALL_DIR} +) + +install(FILES kded/touchpaddaemon.kcfg + DESTINATION ${KCFG_INSTALL_DIR} +) +install(FILES kded/kded_touchpad.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kded + RENAME touchpad.desktop +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.touchpad.xml + DESTINATION ${DBUS_INTERFACES_INSTALL_DIR} +) +install(FILES kded/kcm_touchpad.notifyrc + DESTINATION ${DATA_INSTALL_DIR}/kcm_touchpad +) + +install(TARGETS kded_touchpad + DESTINATION ${PLUGIN_INSTALL_DIR} +) + +install(FILES kcm/touchpad.kcfg + DESTINATION ${KCFG_INSTALL_DIR} +) diff --git a/kcontrol/touchpad/src/applet/CMakeLists.txt b/kcontrol/touchpad/src/applet/CMakeLists.txt new file mode 100644 index 00000000..f8ed2d5f --- /dev/null +++ b/kcontrol/touchpad/src/applet/CMakeLists.txt @@ -0,0 +1,36 @@ +add_subdirectory(qml) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/dataengine.desktop" + "${CMAKE_CURRENT_BINARY_DIR}/plasma-dataengine-touchpad.desktop" +) + +set(Applet_SRCS + touchpadengine.cpp + touchpadservice.cpp +) + +qt4_generate_dbus_interface(../kded/kded.h org.kde.touchpad.xml) +qt4_add_dbus_interfaces(Applet_SRCS + ${CMAKE_CURRENT_BINARY_DIR}/org.kde.touchpad.xml +) +qt4_add_dbus_interfaces(Applet_SRCS + ${KDE4_DBUS_INTERFACES_DIR}/org.kde.kded.xml +) + +kde4_add_plugin(plasma_engine_touchpad ${Applet_SRCS}) +target_link_libraries(plasma_engine_touchpad + ${KDE4_PLASMA_LIBS} +) + +install(TARGETS plasma_engine_touchpad + DESTINATION ${PLUGIN_INSTALL_DIR} +) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/plasma-dataengine-touchpad.desktop + DESTINATION ${SERVICES_INSTALL_DIR} +) +install(FILES touchpad.operations + DESTINATION ${DATA_INSTALL_DIR}/plasma/services +) +install(FILES touchpad.svg + DESTINATION ${DATA_INSTALL_DIR}/desktoptheme/default/icons +) diff --git a/kcontrol/touchpad/src/applet/dataengine.desktop b/kcontrol/touchpad/src/applet/dataengine.desktop new file mode 100644 index 00000000..e8ceff22 --- /dev/null +++ b/kcontrol/touchpad/src/applet/dataengine.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +Name=Touchpad DataEngine +Name[bs]=Pogon podataka za dodirnu povrÅ¡inu +Name[cs]=Datový stroj pro touchpad +Name[da]=Datamotor-motor +Name[de]=Touchpad-Datenquelle +Name[el]=Μηχανή δεδομένων επιφάνειας αφής +Name[es]=Motor de datos del panel táctil +Name[fi]=Kosketuslevyn tietomoottori +Name[fr]=Moteur de données du pavé tactile +Name[hu]=Érintőtábla adatmotor +Name[ko]=터치패드 데이터 엔진 +Name[lt]=Jutiklinio kilimėlio Duomenų variklis +Name[nl]=Gegevensengine voor touchpad +Name[pl]=Silnik danych gładzika +Name[pt]=Motor de Dados do Rato por Toque +Name[pt_BR]=Mecanismo de dados do touchpad +Name[ro]=Motor de date Zonă tactilă +Name[sk]=Touchpad DataEngine +Name[sl]=PodatkovniPogon za sledilno ploščico +Name[sv]=Datagränssnitt för tryckplatta +Name[tr]=Dokunmatik Yüzey Veri Motoru +Name[uk]=Рушій даних сенсорної панелі +Name[x-test]=xxTouchpad DataEnginexx +Icon=input-touchpad +Type=Service + +X-KDE-ServiceTypes=Plasma/DataEngine +X-KDE-Library=plasma_engine_touchpad +X-KDE-PluginInfo-Name=touchpad +X-KDE-PluginInfo-Category=System Information +X-KDE-PluginInfo-Author=Alexander Mezin +X-KDE-PluginInfo-Email=mezin.alexander@gmail.com +X-KDE-PluginInfo-Version=@TOUCHPAD_KCM_VERSION@ +X-KDE-PluginInfo-Website=https://projects.kde.org/projects/playground/utils/kcm-touchpad/ +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true + +X-Plasma-EngineName=touchpad diff --git a/kcontrol/touchpad/src/applet/qml/CMakeLists.txt b/kcontrol/touchpad/src/applet/qml/CMakeLists.txt new file mode 100644 index 00000000..3ab7bdd0 --- /dev/null +++ b/kcontrol/touchpad/src/applet/qml/CMakeLists.txt @@ -0,0 +1,16 @@ +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/metadata.desktop + ${CMAKE_CURRENT_BINARY_DIR}/metadata.desktop +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metadata.desktop + DESTINATION ${DATA_INSTALL_DIR}/plasma/plasmoids/touchpad +) + +install(DIRECTORY contents/ + DESTINATION ${DATA_INSTALL_DIR}/plasma/plasmoids/touchpad/contents +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metadata.desktop + DESTINATION ${SERVICES_INSTALL_DIR} + RENAME plasma-applet-touchpad.desktop +) diff --git a/kcontrol/touchpad/src/applet/qml/contents/ui/touchpad.qml b/kcontrol/touchpad/src/applet/qml/contents/ui/touchpad.qml new file mode 100644 index 00000000..c800921b --- /dev/null +++ b/kcontrol/touchpad/src/applet/qml/contents/ui/touchpad.qml @@ -0,0 +1,140 @@ +// -*- coding: iso-8859-1 -*- +/* + * Copyright 2013 Alexander Mezin + * + * This program 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 or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore +import org.kde.plasma.components 0.1 as PlasmaComponents +import org.kde.qtextracomponents 0.1 + +Item { + id: root + + Component.onCompleted: { + plasmoid.aspectRatioMode = Square + } + + PlasmaCore.DataSource { + id: dataSource + engine: "touchpad" + connectedSources: dataSource.sources + onNewData: { + if (data.enabled === null) { + return + } + + if (data.enabled) { + //Hide plasmoid from notification area after short delay + delayedStatusUpdate.restart() + } else { + plasmoid.status = ActiveStatus + } + + icon.elementId = data.enabled ? "touchpad_enabled" + : "touchpad_disabled" + + plasmoid.setAction("toggle", data.enabled ? i18n("Disable touchpad") + : i18n("Enable touchpad")) + } + } + + property bool hasTouchpad: typeof dataSource.data.touchpad != 'undefined' + property bool enabled: hasTouchpad ? dataSource.data.touchpad.enabled + : false + property bool mouse: hasTouchpad ? dataSource.data.touchpad.mousePluggedIn + : false + + Timer { + id: delayedStatusUpdate + interval: 1000 + running: true + onTriggered: { + if (!hasTouchpad) { + //Setting this in Component.onCompleted didn't work + plasmoid.status = PassiveStatus + return + } + + plasmoid.status = enabled ? PassiveStatus : ActiveStatus + } + } + + PlasmaCore.SvgItem { + id: icon + anchors.fill: parent + svg: PlasmaCore.Svg { + multipleImages: true + imagePath: "icons/touchpad" + } + } + + QIconItem { + anchors.fill: parent + visible: !hasTouchpad + icon: "dialog-warning" + } + + PlasmaCore.ToolTip { + target: root + mainText: { + if (!hasTouchpad) { + return i18n("No touchpad was found"); + } + + return enabled ? i18n("Touchpad is enabled") + : i18n("Touchpad is disabled") + } + image: { + if (!hasTouchpad) { + return "dialog-error" + } + + return enabled ? "input-touchpad" : "process-stop" + } + } + + MouseArea { + anchors.fill: parent + onClicked: action_toggle() + enabled: hasTouchpad + } + + function action_toggle() { + if (!mouse && enabled) { + confirmDialog.open() + return + } + execOp("toggle") + } + + function execOp(op) { + var service = dataSource.serviceForSource("touchpad") + service.startOperationCall(service.operationDescription(op)) + } + + PlasmaComponents.QueryDialog { + id: confirmDialog + visualParent: root + titleText: i18n("Touchpad") + titleIcon: "dialog-warning" + message: i18n("No mouse was detected.\nAre you sure you want to disable the touchpad?") + acceptButtonText: i18n("Disable") + onAccepted: execOp("disable") + } +} diff --git a/kcontrol/touchpad/src/applet/qml/metadata.desktop b/kcontrol/touchpad/src/applet/qml/metadata.desktop new file mode 100644 index 00000000..659e2a1e --- /dev/null +++ b/kcontrol/touchpad/src/applet/qml/metadata.desktop @@ -0,0 +1,89 @@ +[Desktop Entry] +Comment=Shows current touchpad state +Comment[bs]=Prikazuje trenutno stanje dodirne povrÅ¡ine +Comment[cs]=Zobrazí současný stav touchpadu +Comment[da]=Vis aktuel touchpad-tilstand +Comment[de]=Zeigt den aktuellen Status des Touchpads an +Comment[el]=Εμφανίζει την τρέχουσα κατάσταση της επιφάνειας αφής +Comment[es]=Muestra el estado actual del panel táctil +Comment[fi]=Näyttää kosketuslevyn nykyisen tilan +Comment[fr]=Affiche l'état courant du pavé tactile +Comment[hu]=Megjeleníti a jelenlegi érintőtábla állapotot +Comment[ko]=현재 터치패드 상태 표시 +Comment[lt]=Rodo dabartinę kilimėlio bÅ«sena +Comment[nl]=Huidige status van touchpad tonen +Comment[pl]=Pokazuje bieżący stan gładzika +Comment[pt]=Mostra o estado actual do rato por toque +Comment[pt_BR]=Mostra o estado atual do touchpad +Comment[ro]=Arată starea curentă a zonei tactile +Comment[sk]=Zobrazí aktuálny stav touchpadu +Comment[sl]=Prikazuje trenutno stanje sledilne ploščice +Comment[sv]=Visar tryckplattans aktuellt tillstÃ¥nd +Comment[tr]=Geçerli dokunmatik yüzey durumunu gösterir +Comment[uk]=Показує поточний стан сенсорної панелі +Comment[x-test]=xxShows current touchpad statexx +Encoding=UTF-8 +Icon=input-touchpad +Keywords=Touchpad +Keywords[bs]=Dodirna povrÅ¡ina +Keywords[cs]=Touchpad +Keywords[da]=Touchpad +Keywords[de]=Touchpad +Keywords[el]=Επιφάνεια αφής +Keywords[es]=Panel táctil +Keywords[fi]=Kosketuslevy +Keywords[fr]=Pavé tactile +Keywords[hu]=Érintőtábla +Keywords[ko]=터치패드 +Keywords[lt]=Jutiklinis kilimėlis +Keywords[nl]=Touchpad +Keywords[pl]=Gładzik +Keywords[pt]=Rato por Toque +Keywords[pt_BR]=Touchpad +Keywords[ro]=Zonă tactilă +Keywords[sk]=Touchpad +Keywords[sl]=Sledilna ploščica +Keywords[sv]=Tryckplatta +Keywords[tr]=Dokunmatik Yüzey +Keywords[uk]=Сенсорна панель +Keywords[x-test]=xxTouchpadxx +Name=Touchpad +Name[bs]=Dodirna povrÅ¡ina +Name[cs]=Touchpad +Name[da]=Touchpad +Name[de]=Touchpad +Name[el]=Επιφάνεια αφής +Name[es]=Panel táctil +Name[fi]=Kosketuslevy +Name[fr]=Pavé tactile +Name[hu]=Érintőtábla +Name[ko]=터치패드 +Name[lt]=Jutiklinis kilimėlis +Name[nl]=Touchpad +Name[pl]=Gładzik +Name[pt]=Rato por Toque +Name[pt_BR]=Touchpad +Name[ro]=Zonă tactilă +Name[sk]=Touchpad +Name[sl]=Sledilna ploščica +Name[sv]=Tryckplatta +Name[tr]=Dokunmatik Yüzey +Name[uk]=Сенсорна панель +Name[x-test]=xxTouchpadxx +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=Alexander Mezin +X-KDE-PluginInfo-Category=System Information +X-KDE-PluginInfo-Email=mezin.alexander@gmail.com +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=touchpad +X-KDE-PluginInfo-Version=@TOUCHPAD_KCM_VERSION@ +X-KDE-PluginInfo-Website=https://projects.kde.org/projects/playground/utils/kcm-touchpad/ +X-KDE-ServiceTypes=Plasma/Applet +X-Plasma-API=declarativeappletscript +X-Plasma-ConfigPlugins=kcm_touchpad +X-Plasma-DefaultSize=32,32 +X-Plasma-MainScript=ui/touchpad.qml +X-Plasma-NotificationArea=true +X-Plasma-RemoteLocation= diff --git a/kcontrol/touchpad/src/applet/touchpad.operations b/kcontrol/touchpad/src/applet/touchpad.operations new file mode 100644 index 00000000..729877fb --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpad.operations @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/kcontrol/touchpad/src/applet/touchpad.svg b/kcontrol/touchpad/src/applet/touchpad.svg new file mode 100644 index 00000000..8648ea88 --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpad.svg @@ -0,0 +1,30 @@ + + + + + + + + + + image/svg+xml + + + + + + + + touchpad_enabled + + + + + + touchpad_disabled + + + + + + diff --git a/kcontrol/touchpad/src/applet/touchpadengine.cpp b/kcontrol/touchpad/src/applet/touchpadengine.cpp new file mode 100644 index 00000000..e861ee8a --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpadengine.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "touchpadengine.h" + +#include +#include + +#include "touchpadinterface.h" +#include "touchpadservice.h" +#include "kdedinterface.h" + +TouchpadEngine::TouchpadEngine(QObject *parent, const QVariantList &args) + : Plasma::DataEngine(parent, args), m_source("touchpad"), m_daemon(0) +{ +} + +void TouchpadEngine::init() +{ + OrgKdeKdedInterface kded(QLatin1String("org.kde.kded"), + QLatin1String("/kded"), + QDBusConnection::sessionBus()); + kded.loadModule("touchpad").waitForFinished(); + + m_daemon = new OrgKdeTouchpadInterface("org.kde.kded", "/modules/touchpad", + QDBusConnection::sessionBus(), this); + if (!m_daemon->isValid()) { + return; + } + + QDBusPendingReply check(m_daemon->workingTouchpadFound()); + check.waitForFinished(); + if (!check.isValid() || !check.value()) { + return; + } + + connect(m_daemon, SIGNAL(enabledChanged(bool)), SLOT(enabledChanged(bool))); + connect(m_daemon, SIGNAL(mousePluggedInChanged(bool)), + SLOT(mousePluggedInChanged(bool))); + + enabledChanged(m_daemon->isEnabled()); + mousePluggedInChanged(m_daemon->isMousePluggedIn()); +} + +void TouchpadEngine::mousePluggedInChanged(bool value) +{ + setData(m_source, "mousePluggedIn", value); +} + +void TouchpadEngine::enabledChanged(bool value) +{ + setData(m_source, "enabled", value); +} + +Plasma::Service *TouchpadEngine::serviceForSource(const QString &source) +{ + if (source == m_source) { + return new TouchpadService(m_daemon, source, this); + } + + return Plasma::DataEngine::serviceForSource(source); +} + +TouchpadEngine::~TouchpadEngine() +{ +} + +K_EXPORT_PLASMA_DATAENGINE(touchpad, TouchpadEngine) diff --git a/kcontrol/touchpad/src/applet/touchpadengine.h b/kcontrol/touchpad/src/applet/touchpadengine.h new file mode 100644 index 00000000..bf7bd5f2 --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpadengine.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef TOUCHPADENGINE_H +#define TOUCHPADENGINE_H + +#include + +class OrgKdeTouchpadInterface; + +class TouchpadEngine : public Plasma::DataEngine +{ + Q_OBJECT + +public: + TouchpadEngine(QObject *parent, const QVariantList &args); + ~TouchpadEngine(); + + Plasma::Service *serviceForSource(const QString &source); + +protected: + void init(); + +private Q_SLOTS: + void mousePluggedInChanged(bool); + void enabledChanged(bool); + +private: + QString m_source; + OrgKdeTouchpadInterface *m_daemon; +}; + +#endif // TOUCHPADENGINE_H diff --git a/kcontrol/touchpad/src/applet/touchpadservice.cpp b/kcontrol/touchpad/src/applet/touchpadservice.cpp new file mode 100644 index 00000000..4ff960df --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpadservice.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "touchpadservice.h" + +#include + +#include "touchpadinterface.h" + +TouchpadService::TouchpadService(OrgKdeTouchpadInterface *daemon, + const QString &destination, + QObject *parent) + : Plasma::Service(parent), m_daemon(daemon), m_destination(destination) +{ + setName("touchpad"); +} + +TouchpadService::~TouchpadService() +{ +} + +class TouchpadJob : public Plasma::ServiceJob +{ +public: + TouchpadJob(OrgKdeTouchpadInterface *daemon, + const QString &destination, const QString &operation, + const QMap ¶meters, QObject *parent = 0) + : Plasma::ServiceJob(destination, operation, parameters, parent), + m_daemon(daemon) + { + } + + void start() + { + if (m_daemon) { + QMetaObject::invokeMethod(m_daemon, operationName().toAscii()); + } + emitResult(); + } + +private: + OrgKdeTouchpadInterface *m_daemon; +}; + +Plasma::ServiceJob *TouchpadService::createJob(const QString &operation, + QMap ¶ms) +{ + return new TouchpadJob(m_daemon, m_destination, operation, params, this); +} diff --git a/kcontrol/touchpad/src/applet/touchpadservice.h b/kcontrol/touchpad/src/applet/touchpadservice.h new file mode 100644 index 00000000..d561beb6 --- /dev/null +++ b/kcontrol/touchpad/src/applet/touchpadservice.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef TOUCHPADSERVICE_H +#define TOUCHPADSERVICE_H + +#include + +class OrgKdeTouchpadInterface; + +class TouchpadService : public Plasma::Service +{ + Q_OBJECT +public: + TouchpadService(OrgKdeTouchpadInterface *daemon, const QString &destination, + QObject *parent = 0); + ~TouchpadService(); + +protected: + Plasma::ServiceJob *createJob(const QString &operation, + QMap ¶meters); + +private: + OrgKdeTouchpadInterface *m_daemon; + QString m_destination; +}; + +#endif // TOUCHPADSERVICE_H diff --git a/kcontrol/touchpad/src/kcm/customconfigdialogmanager.cpp b/kcontrol/touchpad/src/kcm/customconfigdialogmanager.cpp new file mode 100644 index 00000000..298cf414 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/customconfigdialogmanager.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "customconfigdialogmanager.h" + +#include + +#include + +#include +#include +#include + +#include "customslider.h" + +CustomConfigDialogManager::CustomConfigDialogManager(QWidget *parent, + KCoreConfigSkeleton *conf, + const QStringList &supported) + : KConfigDialogManager(parent, conf), m_config(conf) +{ + static const QString kcfgPrefix("kcfg_"); + + Q_FOREACH(KConfigSkeletonItem *i, conf->items()) { + QString name(i->name()); + + QWidget *child = parent->findChild(kcfgPrefix + name); + if (!child) { + continue; + } + m_widgets[name] = child; + + if (!supported.contains(name)) { + child->setEnabled(false); + } + + KCoreConfigSkeleton::ItemEnum *asEnum = + dynamic_cast(i); + if (!asEnum) { + continue; + } + + QStringList choiceList; + Q_FOREACH(const KCoreConfigSkeleton::ItemEnum::Choice &c, + asEnum->choices()) + { + if (c.label.isEmpty()) { + choiceList.append(c.name); + } else { + choiceList.append(c.label); + } + } + + KComboBox *asComboBox = qobject_cast(child); + if (asComboBox) { + asComboBox->addItems(choiceList); + } + } +} + +CustomConfigDialogManager::~CustomConfigDialogManager() +{ +} + +QVariantHash CustomConfigDialogManager::currentWidgetProperties() const +{ + QVariantHash r; + for (QMap::ConstIterator i = m_widgets.begin(); + i != m_widgets.end(); ++i) + { + r[i.key()] = property(i.value()); + } + return r; +} + +void CustomConfigDialogManager::setWidgetProperties(const QVariantHash &p) +{ + for (QVariantHash::ConstIterator i = p.begin(); i != p.end(); ++i) { + QMap::ConstIterator j = m_widgets.find(i.key()); + if (j != m_widgets.end()) { + setProperty(j.value(), i.value()); + } + } +} + +static bool variantFuzzyCompare(const QVariant &a, const QVariant &b) +{ + if (a == b) { + return true; + } + + bool isDouble_a = false, isDouble_b = false; + float d_a = static_cast(a.toDouble(&isDouble_a)), + d_b = static_cast(b.toDouble(&isDouble_b)); + if (!isDouble_a || !isDouble_b) { + return false; + } + + return (qFuzzyIsNull(d_a) && qFuzzyIsNull(d_b)) || qFuzzyCompare(d_a, d_b); +} + +QVariant CustomConfigDialogManager::fixup(QWidget *widget, QVariant v) const +{ + bool isDouble = false; + double value = v.toDouble(&isDouble); + if (!isDouble) { + return v; + } + + QVariant decimals(widget->property("decimals")); + if (decimals.type() != QVariant::Int) { + CustomSlider *asSlider = qobject_cast(widget); + if (asSlider) { + return asSlider->fixup(value); + } + return value; + } + + double k = std::pow(10.0, decimals.toInt()); + return std::floor(value * k + 0.5) / k; //round +} + +bool CustomConfigDialogManager::compareWidgetProperties(const QVariantHash &p) const +{ + bool result = true; + for (QVariantHash::ConstIterator i = p.begin(); i != p.end(); ++i) { + QMap::ConstIterator j = m_widgets.find(i.key()); + if (j == m_widgets.end()) { + continue; + } + + QWidget *widget = j.value(); + QVariant widgetValue(fixup(widget, property(widget))); + QVariant fixed(fixup(widget, i.value())); + if (!variantFuzzyCompare(widgetValue, fixed)) { + result = false; + kDebug() << "Config mismatch:" + << widget->objectName() << widgetValue << fixed; + } + } + return result; +} + +bool CustomConfigDialogManager::hasChangedFuzzy() const +{ + for (QMap::ConstIterator i = m_widgets.begin(); + i != m_widgets.end(); ++i) + { + KConfigSkeletonItem *config = m_config->findItem(i.key()); + QWidget *widget = i.value(); + QVariant widgetValue(fixup(widget, property(widget))); + QVariant configValue(fixup(widget, config->property())); + if (!variantFuzzyCompare(widgetValue, configValue)) { + return true; + } + } + return false; +} diff --git a/kcontrol/touchpad/src/kcm/customconfigdialogmanager.h b/kcontrol/touchpad/src/kcm/customconfigdialogmanager.h new file mode 100644 index 00000000..cb6c8c05 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/customconfigdialogmanager.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSTOMCONFIGDIALOGMANAGER_H +#define CUSTOMCONFIGDIALOGMANAGER_H + +#include +#include + +#include + +class CustomConfigDialogManager : public KConfigDialogManager +{ + Q_OBJECT +public: + CustomConfigDialogManager(QWidget *parent, + KCoreConfigSkeleton *config, + const QStringList &supported); + ~CustomConfigDialogManager(); + + QVariantHash currentWidgetProperties() const; + void setWidgetProperties(const QVariantHash &); + bool compareWidgetProperties(const QVariantHash &) const; + bool hasChangedFuzzy() const; + +private: + QVariant fixup(QWidget *widget, QVariant value) const; + + QMap m_widgets; + KCoreConfigSkeleton *m_config; +}; + +#endif // CUSTOMCONFIGDIALOGMANAGER_H diff --git a/kcontrol/touchpad/src/kcm/customslider.cpp b/kcontrol/touchpad/src/kcm/customslider.cpp new file mode 100644 index 00000000..eebfd1c5 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/customslider.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "customslider.h" + +#include + +#include + +CustomSlider::Interpolator::~Interpolator() +{ +} + +double CustomSlider::Interpolator::absolute(double relative, + double minimum, + double maximum) const +{ + return relative * (maximum - minimum) + minimum; +} + +double CustomSlider::Interpolator::relative(double absolute, + double minimum, + double maximum) const +{ + return (absolute - minimum) / (maximum - minimum); +} + +double CustomSlider::SqrtInterpolator::absolute( + double relative, double minimum, double maximum) const +{ + relative *= relative; + return Interpolator::absolute(relative, minimum, maximum); +} + +double CustomSlider::SqrtInterpolator::relative( + double absolute, double minimum, double maximum) const +{ + double value = Interpolator::relative(absolute, minimum, maximum); + return std::sqrt(value); +} + +const CustomSlider::Interpolator CustomSlider::lerp; + +CustomSlider::CustomSlider(QWidget *parent) : + QSlider(parent), m_min(0.0), m_max(1.0), m_interpolator(&lerp) +{ + setSingleStep(10); + setPageStep(100); + + updateValue(); + updateRange(size()); + + connect(this, SIGNAL(actionTriggered(int)), SLOT(updateValue())); +} + +void CustomSlider::resizeEvent(QResizeEvent *e) +{ + QSlider::resizeEvent(e); + updateRange(e->size()); +} + +const CustomSlider::Interpolator *CustomSlider::interpolator() const +{ + return m_interpolator; +} + +void CustomSlider::setInterpolator(const CustomSlider::Interpolator *v) +{ + m_interpolator = v; +} + +void CustomSlider::setDoubleMinimum(double v) +{ + m_min = v; +} + +double CustomSlider::doubleMinimum() const +{ + return m_min; +} + +void CustomSlider::setDoubleMaximum(double v) +{ + m_max = v; +} + +double CustomSlider::doubleMaximum() const +{ + return m_max; +} + +double CustomSlider::doubleValue() const +{ + return qBound(m_min, m_value, m_max); +} + +void CustomSlider::setDoubleValue(double v) +{ + if (m_value == v) { + return; + } + + m_value = v; + int oldIntValue = value(); + moveSlider(); + if (value() != oldIntValue) { + Q_EMIT valueChanged(doubleValue()); + } +} + +double CustomSlider::intToDouble(int v) const +{ + double relative = lerp.relative(v, minimum(), maximum()); + return m_interpolator->absolute(relative, m_min, m_max); +} + +void CustomSlider::updateValue() +{ + m_value = intToDouble(sliderPosition()); + Q_EMIT valueChanged(doubleValue()); +} + +double CustomSlider::fixup(double v) const +{ + return intToDouble(doubleToInt(v)); +} + +int CustomSlider::doubleToInt(double v) const +{ + double relative = m_interpolator->relative(v, m_min, m_max); + double absolute = lerp.absolute(relative, minimum(), maximum()); + return static_cast(std::floor(absolute + 0.5)); +} + +void CustomSlider::moveSlider() +{ + setValue(doubleToInt(doubleValue())); +} + +void CustomSlider::updateRange(const QSize &s) +{ + setRange(0, (orientation() == Qt::Horizontal) ? s.width() : s.height()); + moveSlider(); +} diff --git a/kcontrol/touchpad/src/kcm/customslider.h b/kcontrol/touchpad/src/kcm/customslider.h new file mode 100644 index 00000000..7dbcb132 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/customslider.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSTOMSLIDER_H +#define CUSTOMSLIDER_H + +#include + +class CustomSlider : public QSlider +{ + Q_OBJECT + + Q_PROPERTY(double minimum READ doubleMinimum WRITE setDoubleMinimum) + Q_PROPERTY(double maximum READ doubleMaximum WRITE setDoubleMaximum) + Q_PROPERTY(double value READ doubleValue WRITE setDoubleValue \ + NOTIFY valueChanged USER true) + +public: + explicit CustomSlider(QWidget *parent = 0); + + void setDoubleMinimum(double); + double doubleMinimum() const; + + void setDoubleMaximum(double); + double doubleMaximum() const; + + class Interpolator + { + public: + Interpolator() { } + virtual double absolute(double relative, + double minimum, double maximum) const; + virtual double relative(double absolute, + double minimum, double maximum) const; + + virtual ~Interpolator(); + }; + + class SqrtInterpolator : public Interpolator + { + public: + SqrtInterpolator() { } + double absolute(double relative, double minimum, double maximum) const; + double relative(double absolute, double minimum, double maximum) const; + }; + + const Interpolator *interpolator() const; + void setInterpolator(const Interpolator *); + + double doubleValue() const; + double fixup(double) const; + +public Q_SLOTS: + void setDoubleValue(double); + +Q_SIGNALS: + void valueChanged(double); + +protected: + virtual void resizeEvent(QResizeEvent *); + +private Q_SLOTS: + void updateValue(); + +private: + void updateRange(const QSize &); + void moveSlider(); + int doubleToInt(double) const; + double intToDouble(int) const; + + static const Interpolator lerp; + + double m_min, m_max, m_value; + const Interpolator *m_interpolator; +}; + +#endif // CUSTOMSLIDER_H diff --git a/kcontrol/touchpad/src/kcm/kcm_touchpad.desktop b/kcontrol/touchpad/src/kcm/kcm_touchpad.desktop new file mode 100644 index 00000000..05c90d88 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/kcm_touchpad.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +Exec=kcmshell4 kcm_touchpad +Icon=input-touchpad +Type=Service +Categories=Qt;KDE;X-KDE-settings-hardware; +OnlyShowIn=KDE; + +X-KDE-ServiceTypes=KCModule,KCModuleInit +X-KDE-Init-Symbol=touchpad +X-KDE-Init-Phase=0 +X-KDE-Library=kded_touchpad +X-KDE-PluginKeyword=kcm +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=input-devices + +Name=Touchpad +Name[bs]=Dodirna povrÅ¡ina +Name[cs]=Touchpad +Name[da]=Touchpad +Name[de]=Touchpad +Name[el]=Επιφάνεια αφής +Name[es]=Panel táctil +Name[fi]=Kosketuslevy +Name[fr]=Pavé tactile +Name[hu]=Érintőtábla +Name[ko]=터치패드 +Name[lt]=Jutiklinis kilimėlis +Name[nl]=Touchpad +Name[pl]=Gładzik +Name[pt]=Rato por Toque +Name[pt_BR]=Touchpad +Name[ro]=Zonă tactilă +Name[sk]=Touchpad +Name[sl]=Sledilna ploščica +Name[sv]=Tryckplatta +Name[tr]=Dokunmatik Yüzey +Name[uk]=Сенсорна панель +Name[x-test]=xxTouchpadxx +Comment=Touchpad settings +Comment[bs]=Postavke dodirne povrÅ¡ine +Comment[cs]=Nastavení touchpadu +Comment[da]=Touchpad-indstillinger +Comment[de]=Touchpadeinstellungen +Comment[el]=Ρυθμίσεις επιφάνειας αφής +Comment[es]=Preferencias del panel táctil +Comment[fi]=Kosketuslevyn asetukset +Comment[fr]=Configuration du pavé tactile +Comment[hu]=Érintőtábla beállítások +Comment[ko]=터치패드 설정 +Comment[lt]=Jutiklinio kilimėlio nustatymai +Comment[nl]=Instellingen van touchpad +Comment[pl]=Ustawienia gładzika +Comment[pt]=Configuração do rato por toque +Comment[pt_BR]=Configurações do touchpad +Comment[ro]=Configurări zonă tactilă +Comment[sk]=Nastavenia touchpadu +Comment[sl]=Nastavitve sledilne ploščice +Comment[sv]=Inställning av tryckplatta +Comment[tr]=Dokunmatik yüzey ayarları +Comment[uk]=Параметри сенсорної панелі +Comment[x-test]=xxTouchpad settingsxx +X-KDE-Keywords=Touchpad,Synaptics +X-KDE-Keywords[bs]=Dodirna povrÅ¡ina,Synatics +X-KDE-Keywords[cs]=Touchpad,Synaptics +X-KDE-Keywords[da]=Touchpad,Synaptics +X-KDE-Keywords[de]=Touchpad,Synaptics +X-KDE-Keywords[el]=Επιφάνεια αφής,Synaptics +X-KDE-Keywords[es]=Panel táctil,Touchpad,Synaptics +X-KDE-Keywords[fi]=Touchpad,Synaptics,Kosketuslevy +X-KDE-Keywords[fr]=Pavé tactile,Synaptics +X-KDE-Keywords[hu]=Érintőtábla,Szinaptikusok +X-KDE-Keywords[ko]=Touchpad,Synaptics,터치패드 +X-KDE-Keywords[lt]=Jutiklinis kilimėlis,Synaptics +X-KDE-Keywords[nl]=Touchpad,Synaptics +X-KDE-Keywords[pl]=Gładzik,Synaptics +X-KDE-Keywords[pt]=Rato,Toque,Synaptics +X-KDE-Keywords[pt_BR]=Touchpad,Synaptics +X-KDE-Keywords[ro]=Touchpad,Synaptics,Zonă tactilă,Tactil +X-KDE-Keywords[sk]=Touchpad,Synaptics +X-KDE-Keywords[sl]=Sledilna ploščica,Synaptics +X-KDE-Keywords[sv]=Tryckplatta,Synaptics +X-KDE-Keywords[tr]=Dokunmatik Yüzey,Synaptics +X-KDE-Keywords[uk]=Touchpad,Synaptics,сенсорна,панель,тачпад,синаптикс +X-KDE-Keywords[x-test]=xxTouchpad,Synapticsxx diff --git a/kcontrol/touchpad/src/kcm/sliderpair.cpp b/kcontrol/touchpad/src/kcm/sliderpair.cpp new file mode 100644 index 00000000..3b15fd4a --- /dev/null +++ b/kcontrol/touchpad/src/kcm/sliderpair.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sliderpair.h" + +#include + +SliderPair::SliderPair(QSlider *minSlider, QSlider *maxSlider, QObject *parent) + : QObject(parent), m_minSlider(minSlider), m_maxSlider(maxSlider) +{ + connect(m_minSlider, SIGNAL(valueChanged(int)), SLOT(adjustMaxSlider())); + connect(m_maxSlider, SIGNAL(valueChanged(int)), SLOT(adjustMinSlider())); +} + +void SliderPair::adjustMaxSlider() +{ + m_maxSlider->setValue(qMax(m_maxSlider->value(), m_minSlider->value())); +} + +void SliderPair::adjustMinSlider() +{ + m_minSlider->setValue(qMin(m_maxSlider->value(), m_minSlider->value())); +} diff --git a/kcontrol/touchpad/src/kcm/sliderpair.h b/kcontrol/touchpad/src/kcm/sliderpair.h new file mode 100644 index 00000000..6b9d69ed --- /dev/null +++ b/kcontrol/touchpad/src/kcm/sliderpair.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SLIDERPAIR_H +#define SLIDERPAIR_H + +#include + +class QSlider; + +class SliderPair : public QObject +{ + Q_OBJECT +public: + SliderPair(QSlider *minSlider, QSlider *maxSlider, QObject *parent = 0); + +private Q_SLOTS: + void adjustMinSlider(); + void adjustMaxSlider(); + +private: + QSlider *m_minSlider, *m_maxSlider; +}; + +#endif // SLIDERPAIR_H diff --git a/kcontrol/touchpad/src/kcm/testarea.cpp b/kcontrol/touchpad/src/kcm/testarea.cpp new file mode 100644 index 00000000..e75e80cf --- /dev/null +++ b/kcontrol/touchpad/src/kcm/testarea.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "testarea.h" + +#include +#include +#include +#include + +#include +#include + +TestArea::TestArea(QWidget *parent) : QWidget(parent) +{ + m_ui.setupUi(this); + + QStandardItemModel *model = new QStandardItemModel(m_ui.listView); + m_ui.listView->setModel(model); + QScopedPointer item( + new QStandardItem(KIcon("folder"), i18n("Drag me"))); + model->appendRow(item.data()); + item.take(); + + QString wallpaper = Plasma::Theme::defaultTheme()->wallpaperPath(); + static const QString stylesheet("background-image: url(%1)"); + m_ui.scrollAreaWidgetContents->setStyleSheet(stylesheet.arg(wallpaper)); +} + +void TestArea::enterEvent(QEvent *e) +{ + Q_EMIT enter(); + QWidget::enterEvent(e); +} + +void TestArea::leaveEvent(QEvent *e) +{ + Q_EMIT leave(); + QWidget::leaveEvent(e); +} diff --git a/kcontrol/touchpad/src/kcm/testarea.h b/kcontrol/touchpad/src/kcm/testarea.h new file mode 100644 index 00000000..7c91c477 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/testarea.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TESTAREA_H +#define TESTAREA_H + +#include "ui_testarea.h" + +class TestArea : public QWidget +{ + Q_OBJECT +public: + explicit TestArea(QWidget *); + +Q_SIGNALS: + void enter(); + void leave(); + +protected: + void enterEvent(QEvent *); + void leaveEvent(QEvent *); + +private: + Ui::TestArea m_ui; +}; + +#endif // TESTAREA_H diff --git a/kcontrol/touchpad/src/kcm/testbutton.cpp b/kcontrol/touchpad/src/kcm/testbutton.cpp new file mode 100644 index 00000000..2b0d6365 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/testbutton.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "testbutton.h" + +#include +#include + +#include + +TestButton::TestButton(QWidget *parent) + : QPushButton(parent), m_firstClick(true) +{ +} + +void TestButton::mousePressEvent(QMouseEvent *e) +{ + if (m_firstClick) { + m_originalText = text(); + m_firstClick = false; + } + + switch (e->button()) { + case Qt::LeftButton: + setText(i18nc("Mouse button", "Left button")); + break; + case Qt::RightButton: + setText(i18nc("Mouse button", "Right button")); + break; + case Qt::MiddleButton: + setText(i18nc("Mouse button", "Middle button")); + break; + default: + break; + } + + QTimer::singleShot(500, this, SLOT(resetText())); + + QPushButton::mousePressEvent(e); +} + +void TestButton::resetText() +{ + setText(m_originalText); +} diff --git a/kcontrol/touchpad/src/kcm/testbutton.h b/kcontrol/touchpad/src/kcm/testbutton.h new file mode 100644 index 00000000..bef5af16 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/testbutton.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TESTBUTTON_H +#define TESTBUTTON_H + +#include + +class TestButton : public QPushButton +{ + Q_OBJECT + +public: + explicit TestButton(QWidget *); + +protected: + void mousePressEvent(QMouseEvent *); + +private Q_SLOTS: + void resetText(); + +private: + QString m_originalText; + bool m_firstClick; +}; + +#endif // TESTBUTTON_H diff --git a/kcontrol/touchpad/src/kcm/touchpad.kcfg b/kcontrol/touchpad/src/kcm/touchpad.kcfg new file mode 100644 index 00000000..2afe6429 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpad.kcfg @@ -0,0 +1,312 @@ + + + + + + + + OneFingerTap + TwoFingerTap + ThreeFingerTap + LTCorner + LBCorner + RTCorner + RBCorner + + + + + + + + + + + + + + + + + + systemDefaultEnum("OneFingerTapButton", LeftButton) + + + systemDefaultEnum("TwoFingerTapButton", RightButton) + + + systemDefaultEnum("ThreeFingerTapButton", MiddleButton) + + + systemDefaultEnum("LTCornerButton", NoButton) + + + systemDefaultEnum("LBCornerButton", NoButton) + + + systemDefaultEnum("RTCornerButton", NoButton) + + + systemDefaultEnum("RBCornerButton", NoButton) + + + + + systemDefault("VertEdgeScroll", true) + + + + + systemDefault("VertTwoFingerScroll", true) + + + + + systemDefault("HorizEdgeScroll", true) + + + + + systemDefault("HorizTwoFingerScroll", true) + + + + 0 + 255 + + systemDefault("MinSpeed", 0.0) + + + + 0 + 255 + + systemDefault("MaxSpeed", 255.0) + + + + 0 + 1 + + systemDefault("AccelFactor", 0.0) + + + + 0 + 100 + + systemDefault("HorizHysteresis", 0) + + + + 0 + 100 + + systemDefault("VertHysteresis", 0) + + + + + systemDefault("TapAndDragGesture", true) + + + + + systemDefault("LockedDrags", false) + + + + 0 + 30000 + + systemDefault("LockedDragTimeout", 5000) + + + + 0 + 10 + + systemDefault("VertScrollDelta", 1.0) + + + + + systemDefault("InvertVertScroll", false) + + + + 0 + 10 + + systemDefault("HorizScrollDelta", 1.0) + + + + + systemDefault("InvertHorizScroll", false) + + + + + systemDefault("CornerCoasting", false) + + + + 0.1 + 255 + + systemDefault("CoastingSpeed", 20.0) + + + + 0 + 255 + + systemDefault("CoastingFriction", 50.0) + + + + + systemDefault("Coasting", true) + + + + 0 + 255 + + systemDefault("FingerHigh", 30) + + + + 0 + 255 + + systemDefault("FingerLow", 25) + + + + + systemDefault("PalmDetect", false) + + + + 0 + 255 + + systemDefault("PalmMinZ", 200) + + + + 0 + 15 + + systemDefault("PalmMinWidth", 10) + + + + 0 + 1000 + + systemDefault("MaxTapTime", 180) + + + + 0 + 1000 + + systemDefault("MaxDoubleTapTime", 180) + + + + 0 + 1000 + + systemDefault("SingleTapTimeout", 180) + + + + 0 + 20 + + systemDefault("MaxTapMove", 2.0) + + + + 1 + 255 + + systemDefault("PressureMotionMinZ", 30) + + + + 1 + 255 + + systemDefault("PressureMotionMaxZ", 160) + + + + 0 + 10 + + systemDefault("PressureMotionMinFactor", 1.0) + + + + 0 + 10 + + systemDefault("PressureMotionMaxFactor", 1.0) + + + + + systemDefault("CircularScrolling", false) + + + + + systemDefault("CircScrollDelta", 10.0) + + 0 + 45 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + systemDefaultEnum("CircScrollTrigger", AllEdges) + + + + diff --git a/kcontrol/touchpad/src/kcm/touchpadconfig.cpp b/kcontrol/touchpad/src/kcm/touchpadconfig.cpp new file mode 100644 index 00000000..9d8e22b5 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpadconfig.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "touchpadconfig.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "customslider.h" +#include "sliderpair.h" +#include "touchpadbackend.h" +#include "plugins.h" +#include "testarea.h" +#include "touchpadinterface.h" +#include "customconfigdialogmanager.h" +#include "kded/kdedactions.h" + +void touchpadApplySavedConfig() +{ + TouchpadBackend *backend = TouchpadBackend::implementation(); + if (!backend) { + return; + } + + TouchpadParameters config; + backend->applyConfig(config.values()); +} + +extern "C" +{ + KDE_EXPORT void kcminit_touchpad() + { + TouchpadParameters::setSystemDefaults(); + touchpadApplySavedConfig(); + } +} + +static void copyHelpFromBuddy(QObject *root) +{ + QLabel *asLabel = qobject_cast(root); + if (asLabel && asLabel->buddy()) { + if (asLabel->toolTip().isEmpty()) { + asLabel->setToolTip(asLabel->buddy()->toolTip()); + } + if (asLabel->statusTip().isEmpty()) { + asLabel->setStatusTip(asLabel->buddy()->statusTip()); + } + if (asLabel->whatsThis().isEmpty()) { + asLabel->setWhatsThis(asLabel->buddy()->whatsThis()); + } + } + Q_FOREACH(QObject *child, root->children()) { + copyHelpFromBuddy(child); + } +} + +template +QWidget *addTab(KTabWidget *tabs, T &form) +{ + QScrollArea *container = new QScrollArea(tabs); + container->setWidgetResizable(true); + container->setFrameStyle(QFrame::NoFrame); + container->setAlignment(Qt::AlignHCenter | Qt::AlignTop); + + QWidget *widget = new QWidget(container); + form.setupUi(widget); + copyHelpFromBuddy(widget); + widget->setContentsMargins(20, 20, 20, 20); + widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + container->setWidget(widget); + tabs->addTab(container, widget->windowTitle()); + + return widget; +} + +TouchpadConfig::TouchpadConfig(QWidget *parent, const QVariantList &args) + : KCModule(TouchpadPluginFactory::componentData(), parent, args), + m_configOutOfSync(false) +{ + setAboutData(new KAboutData(*componentData().aboutData())); + + QGridLayout *layout = new QGridLayout(this); + QVBoxLayout *messageLayout = new QVBoxLayout(); + layout->addLayout(messageLayout, 0, 0, 1, 2); + + // Messages + + m_errorMessage = new KMessageWidget(this); + m_errorMessage->setMessageType(KMessageWidget::Error); + m_errorMessage->setVisible(false); + messageLayout->addWidget(m_errorMessage); + + m_configOutOfSyncMessage = new KMessageWidget(this); + m_configOutOfSyncMessage->setMessageType(KMessageWidget::Warning); + m_configOutOfSyncMessage->setText( + i18n("Active settings don't match saved settings.\n" + "You currently see saved settings.")); + m_configOutOfSyncMessage->setVisible(false); + messageLayout->addWidget(m_configOutOfSyncMessage); + + m_loadActiveConfiguration = new KAction(m_configOutOfSyncMessage); + m_loadActiveConfiguration->setText(i18n("Show active settings")); + connect(m_loadActiveConfiguration, SIGNAL(triggered()), + SLOT(loadActiveConfig())); + m_configOutOfSyncMessage->addAction(m_loadActiveConfiguration); + + layout->setColumnStretch(0, 3); + layout->setColumnStretch(1, 1); + + // Main UI + + m_tabs = new KTabWidget(this); + layout->addWidget(m_tabs, 1, 0, 1, 1); + + addTab(m_tabs, m_tapping); + addTab(m_tabs, m_scrolling); + addTab(m_tabs, m_pointerMotion); + addTab(m_tabs, m_sensitivity); + + static const CustomSlider::SqrtInterpolator interpolator; + m_pointerMotion.kcfg_MinSpeed->setInterpolator(&interpolator); + m_pointerMotion.kcfg_MaxSpeed->setInterpolator(&interpolator); + m_pointerMotion.kcfg_AccelFactor->setInterpolator(&interpolator); + + new SliderPair(m_pointerMotion.kcfg_MinSpeed, + m_pointerMotion.kcfg_MaxSpeed, this); + new SliderPair(m_sensitivity.kcfg_FingerLow, + m_sensitivity.kcfg_FingerHigh, this); + new SliderPair(m_pointerMotion.kcfg_PressureMotionMinZ, + m_pointerMotion.kcfg_PressureMotionMaxZ, this); + + m_backend = TouchpadBackend::implementation(); + + KConfigDialogManager::changedMap()->insert("CustomSlider", + SIGNAL(valueChanged(double))); + m_manager = new CustomConfigDialogManager(this, &m_config, + m_backend->supportedParameters()); + connect(m_manager, SIGNAL(widgetModified()), SLOT(checkChanges()), + Qt::QueuedConnection); + + // KDED settings + + m_kdedTab = addTab(m_tabs, m_kded); + m_daemonConfigManager = addConfig(&m_daemonSettings, m_kdedTab); + + KMessageWidget *kdedMessage = new KMessageWidget(m_kdedTab); + kdedMessage->setMessageType(KMessageWidget::Information); + kdedMessage->setCloseButtonVisible(false); + kdedMessage->setText( + i18n("These settings won't take effect in the testing area")); + qobject_cast(m_kdedTab->layout())-> + insertWidget(0, kdedMessage); + + connect(m_kded.configureNotificationsButton, SIGNAL(clicked()), + SLOT(showConfigureNotificationsDialog())); + m_shortcutsDialog.reset(new KShortcutsDialog(KShortcutsEditor::GlobalAction, + KShortcutsEditor::LetterShortcutsDisallowed)); + m_shortcutsDialog->addCollection(new TouchpadGlobalActions(this), + i18n("Enable/Disable Touchpad")); + connect(m_kded.configureShortcutsButton, SIGNAL(clicked()), + m_shortcutsDialog.data(), SLOT(show())); + + m_mouseCombo = new KComboBox(true, m_kded.kcfg_MouseBlacklist); + m_kded.kcfg_MouseBlacklist->setCustomEditor(m_mouseCombo); + connect(m_backend, SIGNAL(mousesChanged()), SLOT(updateMouseList())); + m_backend->watchForEvents(false); + updateMouseList(); + + m_daemon = new OrgKdeTouchpadInterface("org.kde.kded", "/modules/touchpad", + QDBusConnection::sessionBus(), this); + m_kdedTab->setEnabled(false); + QDBusPendingCallWatcher *watch; + watch = new QDBusPendingCallWatcher(m_daemon->workingTouchpadFound(), this); + connect(watch, SIGNAL(finished(QDBusPendingCallWatcher*)), + SLOT(gotReplyFromDaemon(QDBusPendingCallWatcher*))); + + // Testing area + + m_testArea = new TestArea(this); + layout->addWidget(m_testArea, 1, 1); + connect(m_testArea, SIGNAL(enter()), SLOT(beginTesting())); + connect(m_testArea, SIGNAL(leave()), SLOT(endTesting())); + connect(this, SIGNAL(changed(bool)), SLOT(onChanged())); + connect(m_tabs, SIGNAL(currentChanged(int)), SLOT(updateTestAreaEnabled())); + updateTestAreaEnabled(); +} + +void TouchpadConfig::gotReplyFromDaemon(QDBusPendingCallWatcher *watch) +{ + QDBusPendingReply reply = *watch; + if (reply.isValid() && reply.value()) { + m_kdedTab->setEnabled(true); + } + watch->deleteLater(); +} + +void TouchpadConfig::updateMouseList() +{ + QStringList mouses( + m_backend->listMouses(m_daemonSettings.mouseBlacklist())); + + for (int i = 0; i < m_mouseCombo->count(); ) { + if (!mouses.contains(m_mouseCombo->itemText(i))) { + m_mouseCombo->removeItem(i); + } else { + i++; + } + } + + Q_FOREACH (const QString &i, mouses) { + if (!m_mouseCombo->contains(i)) { + m_mouseCombo->addItem(i); + } + } +} + +QVariantHash TouchpadConfig::getActiveConfig() +{ + if (m_prevConfig) { + return *m_prevConfig; + } + + QVariantHash activeConfig; + if (!m_backend->getConfig(activeConfig)) { + m_errorMessage->setText(m_backend->errorString()); + QMetaObject::invokeMethod(m_errorMessage, "animatedShow", + Qt::QueuedConnection); + } + return activeConfig; +} + +void TouchpadConfig::loadActiveConfig() +{ + m_manager->setWidgetProperties(getActiveConfig()); + m_configOutOfSync = false; + m_configOutOfSyncMessage->animatedHide(); +} + +void TouchpadConfig::load() +{ + m_manager->updateWidgets(); + + KCModule::load(); + + m_configOutOfSync = !m_manager->compareWidgetProperties(getActiveConfig()); +} + +void TouchpadConfig::save() +{ + m_manager->updateSettings(); + + m_configOutOfSync = false; + m_configOutOfSyncMessage->animatedHide(); + + bool daemonSettingsChanged = m_daemonConfigManager->hasChanged(); + + KCModule::save(); + + if (m_backend->applyConfig(m_config.values())) { + m_errorMessage->animatedHide(); + } else { + m_errorMessage->setText(m_backend->errorString()); + m_errorMessage->animatedShow(); + } + + if (daemonSettingsChanged) { + m_daemon->reloadSettings(); + updateMouseList(); + } +} + +void TouchpadConfig::defaults() +{ + m_manager->updateWidgetsDefault(); + + KCModule::defaults(); +} + +void TouchpadConfig::checkChanges() +{ + unmanagedWidgetChangeState(m_manager->hasChangedFuzzy() + || m_configOutOfSync); + if (m_configOutOfSync) { + m_configOutOfSyncMessage->animatedShow(); + } else { + m_configOutOfSyncMessage->animatedHide(); + } +} + +void TouchpadConfig::hideEvent(QHideEvent *e) +{ + endTesting(); + KCModule::hideEvent(e); +} + +TouchpadConfig::~TouchpadConfig() +{ + endTesting(); +} + +void TouchpadConfig::onChanged() +{ + if (m_testArea->underMouse()) { + beginTesting(); + } +} + +void TouchpadConfig::beginTesting() +{ + if (!m_prevConfig) { + m_prevConfig.reset(new QVariantHash()); + m_backend->getConfig(*m_prevConfig.data()); + } + m_backend->applyConfig(m_manager->currentWidgetProperties()); +} + +void TouchpadConfig::endTesting() +{ + if (!m_prevConfig) { + return; + } + m_backend->applyConfig(*m_prevConfig.data()); + m_prevConfig.reset(); +} + +void TouchpadConfig::updateTestAreaEnabled() +{ + bool enable = true; + for (QWidget *i = m_kdedTab; i; i = i->parentWidget()) { + if (i == m_tabs->currentWidget()) { + enable = false; + break; + } + } + + m_testArea->setEnabled(enable); + m_testArea->setMouseTracking(enable); + if (!enable) { + endTesting(); + } +} + +void TouchpadConfig::showConfigureNotificationsDialog() +{ + KNotifyConfigWidget *widget = + KNotifyConfigWidget::configure(0, componentData().componentName()); + KDialog *dialog = qobject_cast(widget->topLevelWidget()); + connect(dialog, SIGNAL(finished()), dialog, SLOT(deleteLater())); +} diff --git a/kcontrol/touchpad/src/kcm/touchpadconfig.h b/kcontrol/touchpad/src/kcm/touchpadconfig.h new file mode 100644 index 00000000..3f847951 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpadconfig.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TOUCHPADCONFIG_H +#define TOUCHPADCONFIG_H + +#include +#include +#include + +#include "touchpadparameters.h" +#include "testarea.h" +#include "kdedsettings.h" + +#include "ui_pointermotion.h" +#include "ui_tap.h" +#include "ui_scroll.h" +#include "ui_sensitivity.h" +#include "ui_kded.h" + +class TouchpadBackend; +class KMessageWidget; +class OrgKdeTouchpadInterface; +class CustomConfigDialogManager; +class KAction; +class KShortcutsDialog; +class KTabWidget; +class KComboBox; +class QDBusPendingCallWatcher; + +class TouchpadConfig : public KCModule +{ + Q_OBJECT + +public: + explicit TouchpadConfig(QWidget *parent, + const QVariantList &args = QVariantList()); + virtual ~TouchpadConfig(); + + virtual void load(); + virtual void save(); + virtual void defaults(); + +protected: + virtual void hideEvent(QHideEvent *); + +private Q_SLOTS: + void beginTesting(); + void endTesting(); + void onChanged(); + void checkChanges(); + void loadActiveConfig(); + void updateTestAreaEnabled(); + void updateMouseList(); + void showConfigureNotificationsDialog(); + void gotReplyFromDaemon(QDBusPendingCallWatcher *); + +private: + QVariantHash getActiveConfig(); + + TouchpadBackend *m_backend; + TouchpadParameters m_config; + + QScopedPointer m_prevConfig; + CustomConfigDialogManager *m_manager; + TouchpadDisablerSettings m_daemonSettings; + KConfigDialogManager *m_daemonConfigManager; + KMessageWidget *m_errorMessage, *m_configOutOfSyncMessage; + TestArea *m_testArea; + OrgKdeTouchpadInterface *m_daemon; + KAction *m_loadActiveConfiguration; + bool m_configOutOfSync; + QScopedPointer m_shortcutsDialog; + QWidget *m_kdedTab; + KTabWidget *m_tabs; + KComboBox *m_mouseCombo; + + Ui::PointerMotionForm m_pointerMotion; + Ui::TapForm m_tapping; + Ui::ScrollForm m_scrolling; + Ui::SensitivityForm m_sensitivity; + Ui::KdedForm m_kded; +}; + +#endif // TOUCHPADCONFIG_H diff --git a/kcontrol/touchpad/src/kcm/touchpadparameters.kcfgc b/kcontrol/touchpad/src/kcm/touchpadparameters.kcfgc new file mode 100644 index 00000000..1a229f78 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpadparameters.kcfgc @@ -0,0 +1,9 @@ +File=touchpad.kcfg +ClassName=TouchpadParameters +Mutators=true +MemberVariables=private +GlobalEnums=true +UseEnumTypes=true +Inherits=TouchpadParametersBase +IncludeFiles=\"kcm/touchpadparametersbase.h\" +SetUserTexts=true diff --git a/kcontrol/touchpad/src/kcm/touchpadparametersbase.cpp b/kcontrol/touchpad/src/kcm/touchpadparametersbase.cpp new file mode 100644 index 00000000..b39f5937 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpadparametersbase.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "touchpadparametersbase.h" +#include "touchpadbackend.h" + +namespace +{ + +KConfigGroup &systemDefaults() +{ + static KSharedConfig::Ptr p(KSharedConfig::openConfig(".touchpaddefaults", + KConfig::SimpleConfig, + "tmp")); + static KConfigGroup group(p->group("parameters")); + return group; +} + +} + +TouchpadParametersBase::TouchpadParametersBase(const QString &configname, + QObject *parent) + : KCoreConfigSkeleton(configname, parent) +{ + if (!systemDefaults().exists()) { + setSystemDefaults(); + } +} + +QVariantHash TouchpadParametersBase::values() const +{ + QVariantHash r; + Q_FOREACH(const KConfigSkeletonItem *i, items()) { + r[i->name()] = i->property(); + } + return r; +} + +void TouchpadParametersBase::setValues(const QVariantHash &v) +{ + for (QVariantHash::ConstIterator i = v.begin(); i != v.end(); ++i) { + KConfigSkeletonItem *j = findItem(i.key()); + if (j) { + j->setProperty(i.value()); + } + } +} + +void TouchpadParametersBase::setSystemDefaults() +{ + TouchpadBackend *backend = TouchpadBackend::implementation(); + if (!backend) { + return; + } + QVariantHash v; + backend->getConfig(v); + + for (QVariantHash::ConstIterator i = v.begin(); i != v.end(); ++i) { + systemDefaults().writeEntry(i.key(), i.value()); + } + systemDefaults().sync(); +} + +QVariant TouchpadParametersBase::systemDefault(const QString &name, + const QVariant &hardcoded) +{ + return systemDefaults().readEntry(name, hardcoded); +} diff --git a/kcontrol/touchpad/src/kcm/touchpadparametersbase.h b/kcontrol/touchpad/src/kcm/touchpadparametersbase.h new file mode 100644 index 00000000..8d0a17d3 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/touchpadparametersbase.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TOUCHPADPARAMETERSBASE_H +#define TOUCHPADPARAMETERSBASE_H + +#include + +#include + +class TouchpadParametersBase : public KCoreConfigSkeleton +{ +public: + explicit TouchpadParametersBase(const QString &configname = QString(), + QObject *parent = 0); + + QVariantHash values() const; + void setValues(const QVariantHash &); + + static void setSystemDefaults(); + static QVariant systemDefault(const QString &name, + const QVariant &hardcoded = QVariant()); + template + static T systemDefault(const QString &name, const T &hardcoded = T()) + { + return qvariant_cast(systemDefault(name, QVariant(hardcoded))); + } + + template + static T systemDefaultEnum(const QString &name, const T &hardcoded = T()) + { + return static_cast(systemDefault(name, static_cast(hardcoded))); + } +}; + +#endif // TOUCHPADPARAMETERSBASE_H diff --git a/kcontrol/touchpad/src/kcm/ui/kded.ui b/kcontrol/touchpad/src/kcm/ui/kded.ui new file mode 100644 index 00000000..31bd7aba --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/kded.ui @@ -0,0 +1,200 @@ + + + KdedForm + + + + 0 + 0 + 486 + 351 + + + + Enable/Disable Touchpad + + + + + + + 0 + 0 + + + + + + + + 0 + 0 + + + + Configure + + + + + + + + + + + + Keyboard shortcuts: + + + configureShortcutsButton + + + + + + + + + + Disable touchpad when typing + + + true + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Timeout: + + + kcfg_KeyboardActivityTimeoutMs + + + + + + + If there was no keyboard activity for more than specified +number of milliseconds, touchpad will be enabled again + + + 0 + + + 10000 + + + 100 + + + ms + + + true + + + + + + + Disable click emulation and scrolling. +You will be still able to move pointer using touchpad and perform clicks with hardware buttons. + + + Disable taps and scrolling only + + + + + + + + + + Disable touchpad when mouse is plugged in + + + true + + + true + + + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + Notifications: + + + configureNotificationsButton + + + + + + + Configure + + + + + + + + + + + + + + Some devices might be incorrectly treated as a mouse. +You can add them to this list so that they will be ignored when they're plugged in. + + + KEditListWidget::Add|KEditListWidget::Remove + + + Ignored devices: + + + + + + + + + + + KEditListWidget + QWidget +
keditlistwidget.h
+
+ + KIntNumInput + QWidget +
knuminput.h
+
+
+ + configureShortcutsButton + kcfg_DisableOnKeyboardActivity + kcfg_KeyboardActivityTimeoutMs + kcfg_OnlyDisableTapAndScrollOnKeyboardActivity + kcfg_DisableWhenMousePluggedIn + + + +
diff --git a/kcontrol/touchpad/src/kcm/ui/pointermotion.ui b/kcontrol/touchpad/src/kcm/ui/pointermotion.ui new file mode 100644 index 00000000..f44f1bca --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/pointermotion.ui @@ -0,0 +1,310 @@ + + + PointerMotionForm + + + + 0 + 0 + 400 + 407 + + + + Pointer Motion + + + + + + Speed + + + true + + + + + + Minimum: + + + kcfg_MinSpeed + + + + + + + Minimum pointer speed + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + Maximum: + + + kcfg_MaxSpeed + + + + + + + Maximum pointer speed + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + Acceleration: + + + kcfg_AccelFactor + + + + + + + Acceleration factor for normal pointer movements + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + + + Pressure-Dependent Motion + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Minimum pressure: + + + kcfg_PressureMotionMinZ + + + + + + + Minimum factor: + + + kcfg_PressureMotionMinFactor + + + + + + + Maximum pressure: + + + kcfg_PressureMotionMaxZ + + + + + + + Maximum factor: + + + kcfg_PressureMotionMaxFactor + + + + + + + Finger pressure at which minimum pressure motion factor is applied + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + Finger pressure at which maximum pressure motion factor is applied + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + Lowest setting for pressure motion factor + + + x + + + true + + + + + + + Greatest setting for pressure motion factor + + + x + + + true + + + + + + + + + + Noise Cancellation + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Vertical: + + + kcfg_VertHysteresis + + + + + + + Horizontal: + + + kcfg_HorizHysteresis + + + + + + + The minimum vertical hardware distance required to generate motion events + + + 0 + + + 10 + + + units + + + true + + + + + + + The minimum horizontal hardware distance required to generate motion events + + + 0 + + + 10 + + + units + + + true + + + + + + + + + + + KDoubleNumInput + QWidget +
knuminput.h
+
+ + KIntNumInput + QWidget +
knuminput.h
+
+ + CustomSlider + QSlider +
kcm/customslider.h
+
+
+ + kcfg_MinSpeed + kcfg_MaxSpeed + kcfg_AccelFactor + kcfg_PressureMotionMinZ + kcfg_PressureMotionMinFactor + kcfg_PressureMotionMaxZ + kcfg_PressureMotionMaxFactor + kcfg_VertHysteresis + kcfg_HorizHysteresis + + + +
diff --git a/kcontrol/touchpad/src/kcm/ui/scroll.ui b/kcontrol/touchpad/src/kcm/ui/scroll.ui new file mode 100644 index 00000000..5817bf05 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/scroll.ui @@ -0,0 +1,401 @@ + + + ScrollForm + + + + 0 + 0 + 610 + 503 + + + + Scrolling + + + + + + QFormLayout::FieldsStayAtSizeHint + + + Qt::AlignHCenter|Qt::AlignTop + + + + + Edge scrolling: + + + kcfg_VertEdgeScroll + + + + + + + Enable vertical scrolling when dragging along the right edge + + + Vertical + + + + + + + Enable horizontal scrolling when dragging along the bottom edge + + + Horizontal + + + + + + + Enable vertical scrolling when dragging with two fingers anywhere on the touchpad + + + Vertical + + + + + + + Enable horizontal scrolling when dragging with two fingers anywhere on the touchpad + + + Horizontal + + + + + + + Reverse vertical scrolling + + + Vertical + + + + + + + Reverse horizontal scrolling + + + Horizontal + + + + + + + Two-finger scrolling: + + + kcfg_VertTwoFingerScroll + + + + + + + Reverse scrolling: + + + kcfg_InvertVertScroll + + + + + + + + + + 300 + 0 + + + + Scrolling Distance + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Vertical: + + + kcfg_VertScrollDelta + + + + + + + Move distance of the finger for a scroll event + + + 0.100000000000000 + + + mm + + + 1 + + + true + + + + + + + Horizontal: + + + kcfg_HorizScrollDelta + + + + + + + Move distance of the finger for a scroll event + + + 0.100000000000000 + + + mm + + + 1 + + + true + + + + + + + + + + Continue scrolling after the finger is released from the edge of the touchpad + + + Coasting + + + true + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Minimum speed: + + + kcfg_CoastingSpeed + + + + + + + Your finger needs to produce this many scrolls per second in order to start coasting + + + 1.000000000000000 + + + scrolls/sec + + + true + + + + + + + Deceleration: + + + kcfg_CoastingFriction + + + + + + + Number of scrolls/second² to decrease the coasting speed + + + 1.000000000000000 + + + scrolls/sec² + + + true + + + + + + + Corner coasting: + + + kcfg_CornerCoasting + + + + + + + Enable edge scrolling to continue while the finger stays in an edge corner + + + Enable + + + + + + + + + + Scrolling is engaged when a drag starts in the given trigger region. +Moving your finger in clockwise circles around the center of the touchpad +will scroll down and counter clockwise motion will scroll up + + + Circular Scrolling + + + true + + + true + + + + QFormLayout::ExpandingFieldsGrow + + + + + Trigger region: + + + kcfg_CircScrollTrigger + + + + + + + Trigger region on the touchpad to start circular scrolling + + + + + + + Angle: + + + kcfg_CircScrollDelta + + + + + + + + 0 + 0 + + + + Move angle (radians) of finger to generate a scroll event + + + ° + + + true + + + + + + + When used together with vertical scrolling, hitting the upper or lower right corner will seamlessly switch over from vertical to circular scrolling + + + true + + + + + + + + + + + KDoubleNumInput + QWidget +
knuminput.h
+
+ + KComboBox + QComboBox +
kcombobox.h
+
+
+ + kcfg_VertEdgeScroll + kcfg_HorizEdgeScroll + kcfg_VertTwoFingerScroll + kcfg_HorizTwoFingerScroll + kcfg_InvertVertScroll + kcfg_InvertHorizScroll + kcfg_VertScrollDelta + kcfg_HorizScrollDelta + kcfg_Coasting + kcfg_CoastingSpeed + kcfg_CoastingFriction + kcfg_CornerCoasting + kcfg_CircularScrolling + kcfg_CircScrollTrigger + kcfg_CircScrollDelta + + + +
diff --git a/kcontrol/touchpad/src/kcm/ui/sensitivity.ui b/kcontrol/touchpad/src/kcm/ui/sensitivity.ui new file mode 100644 index 00000000..253fad09 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/sensitivity.ui @@ -0,0 +1,153 @@ + + + SensitivityForm + + + + 0 + 0 + 430 + 210 + + + + Sensitivity + + + + + + Sensitivity + + + true + + + + + + Pressure for detecting a touch: + + + kcfg_FingerHigh + + + + + + + Pressure for detecting a release: + + + kcfg_FingerLow + + + + + + + When finger pressure goes above this value, the driver counts it as a touch + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + When finger pressure drops below this value, the driver counts it as a release + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + + + If palm detection should be enabled. Note that this also requires hardware/firmware support from the touchpad + + + Palm Detection + + + true + + + true + + + + + + Minimum width: + + + kcfg_PalmMinWidth + + + + + + + Minimum pressure: + + + kcfg_PalmMinZ + + + + + + + Minimum finger width at which touch is considered a palm + + + 1 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + Minimum finger pressure at which touch is considered a palm + + + Qt::Horizontal + + + QSlider::TicksBelow + + + + + + + + + + kcfg_FingerHigh + kcfg_FingerLow + kcfg_PalmDetect + kcfg_PalmMinWidth + kcfg_PalmMinZ + + + + diff --git a/kcontrol/touchpad/src/kcm/ui/tap.ui b/kcontrol/touchpad/src/kcm/ui/tap.ui new file mode 100644 index 00000000..49181e26 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/tap.ui @@ -0,0 +1,511 @@ + + + TapForm + + + + 0 + 0 + 516 + 531 + + + + Taps + + + + + + + + + 0 + 0 + + + + Mouse Click Emulation + + + true + + + + Qt::AlignHCenter|Qt::AlignTop + + + + + One finger: + + + kcfg_OneFingerTapButton + + + + + + + Which mouse button is reported on a non-corner one-finger tap + + + + + + + Two fingers: + + + kcfg_TwoFingerTapButton + + + + + + + Which mouse button is reported on a non-corner two-finger tap + + + + + + + Three fingers: + + + kcfg_ThreeFingerTapButton + + + + + + + Which mouse button is reported on a non-corner three-finger tap + + + + + + + + + + + + + + + 0 + 0 + + + + Corners + + + true + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Top left: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_LTCornerButton + + + + + + + Which mouse button is reported on a left top corner tap + + + + + + + Bottom left: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_LBCornerButton + + + + + + + Top right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_RTCornerButton + + + + + + + Which mouse button is reported on a left bottom corner tap + + + + + + + Which mouse button is reported on a right top corner tap + + + + + + + Which mouse button is reported on a right bottom corner tap + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 30 + 20 + + + + + + + + Bottom right: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_RBCornerButton + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + + + + + This gesture is an alternative way of dragging. It is performed by tapping (touching and releasing the finger), then touching again and moving the finger on the touchpad + + + Tap-and-Drag Gesture + + + true + + + true + + + + + + If off, a tap-and-drag gesture ends when you release the finger. If on, the gesture is active until you tap a second time, or until timeout expires + + + Locked Drags + + + false + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Timeout: + + + kcfg_LockedDragTimeout + + + + + + + How long it takes (in milliseconds) for the "Locked Drags" mode to be automatically turned off after the finger is released from the touchpad + + + 0 + + + 1000 + + + 1000 + + + ms + + + true + + + + + + + + + + + + + + 300 + 0 + + + + Tap Detection + + + true + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + + + + Maximum time: + + + kcfg_MaxTapTime + + + + + + + + + + Maximum finger movement: + + + kcfg_MaxTapMove + + + + + + + + + + Maximum time for double tap: + + + kcfg_MaxDoubleTapTime + + + + + + + + + + Single tap timeout: + + + kcfg_SingleTapTimeout + + + + + + + Maximum time (in milliseconds) for detecting a tap + + + 0 + + + 1000 + + + 10 + + + ms + + + true + + + + + + + Maximum movement of the finger for detecting a tap + + + 0.100000000000000 + + + mm + + + 1 + + + true + + + + + + + Maximum time (in milliseconds) for detecting a double tap + + + 0 + + + 1000 + + + 10 + + + ms + + + true + + + + + + + Timeout after a tap to recognize it as a single tap + + + 0 + + + 1000 + + + 10 + + + ms + + + true + + + + + + + + + + + KDoubleNumInput + QWidget +
knuminput.h
+
+ + KComboBox + QComboBox +
kcombobox.h
+
+ + KIntNumInput + QWidget +
knuminput.h
+
+
+ + kcfg_OneFingerTapButton + kcfg_TwoFingerTapButton + kcfg_ThreeFingerTapButton + kcfg_LTCornerButton + kcfg_RTCornerButton + kcfg_LBCornerButton + kcfg_RBCornerButton + kcfg_TapAndDragGesture + kcfg_LockedDrags + kcfg_LockedDragTimeout + kcfg_MaxTapTime + kcfg_MaxTapMove + kcfg_MaxDoubleTapTime + kcfg_SingleTapTimeout + + + +
diff --git a/kcontrol/touchpad/src/kcm/ui/testarea.ui b/kcontrol/touchpad/src/kcm/ui/testarea.ui new file mode 100644 index 00000000..05b7cba6 --- /dev/null +++ b/kcontrol/touchpad/src/kcm/ui/testarea.ui @@ -0,0 +1,72 @@ + + + TestArea + + + + 0 + 0 + 200 + 629 + + + + true + + + + + + Testing area + + + + + + Qt::NoFocus + + + Click me + + + + + + + Qt::NoFocus + + + + + 2000 + 2000 + + + + + + + + + Qt::NoFocus + + + QListView::IconMode + + + + + + + + + + + TestButton + QPushButton +
kcm/testbutton.h
+
+
+ + +
diff --git a/kcontrol/touchpad/src/kded/kcm_touchpad.notifyrc b/kcontrol/touchpad/src/kded/kcm_touchpad.notifyrc new file mode 100644 index 00000000..cefbc481 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kcm_touchpad.notifyrc @@ -0,0 +1,148 @@ +[Global] +Name=Touchpad +Name[bs]=Dodirna površina +Name[cs]=Touchpad +Name[da]=Touchpad +Name[de]=Touchpad +Name[el]=Επιφάνεια αφής +Name[es]=Panel táctil +Name[fi]=Kosketuslevy +Name[fr]=Pavé tactile +Name[hu]=Érintőtábla +Name[ko]=터치패드 +Name[lt]=Jutiklinis kilimėlis +Name[nl]=Touchpad +Name[pl]=Gładzik +Name[pt]=Rato por Toque +Name[pt_BR]=Touchpad +Name[ro]=Zonă tactilă +Name[sk]=Touchpad +Name[sl]=Sledilna ploščica +Name[sv]=Tryckplatta +Name[tr]=Dokunmatik Yüzey +Name[uk]=Сенсорна панель +Name[x-test]=xxTouchpadxx +IconName=input-touchpad +Comment=Touchpad +Comment[bs]=Dodirna površina +Comment[cs]=Touchpad +Comment[da]=Touchpad +Comment[de]=Touchpad +Comment[el]=Επιφάνεια αφής +Comment[es]=Panel táctil +Comment[fi]=Kosketuslevy +Comment[fr]=Pavé tactile +Comment[hu]=Érintőtábla +Comment[ko]=터치패드 +Comment[lt]=Jutiklinis kilimėlis +Comment[nl]=Touchpad +Comment[pl]=Gładzik +Comment[pt]=Rato por Toque +Comment[pt_BR]=Touchpad +Comment[ro]=Zonă tactilă +Comment[sk]=Touchpad +Comment[sl]=Sledilna ploščica +Comment[sv]=Tryckplatta +Comment[tr]=Dokunmatik Yüzey +Comment[uk]=Сенсорна панель +Comment[x-test]=xxTouchpadxx + +[Event/TouchpadDisabled] +Name=Touchpad was disabled +Name[bs]=Dodirna površina je isključena +Name[cs]=Touchpad byl zakázán +Name[da]=Touchpad blev deaktiveret +Name[de]=Das Touchpad wurde deaktiviert +Name[el]=Η επιφάνεια αφής απενεργοποιήθηκε +Name[es]=El panel táctil se ha desactivado +Name[fi]=Kosketuslevy poistettiin käytöstä +Name[fr]=Le pavé tactile a été désactivé +Name[hu]=Az érintőtábla le lett tiltva +Name[ko]=터치패드 비활성화됨 +Name[lt]=Jutiklinis kilimėlis išjungtas +Name[nl]=Touchpad was uitgeschakeld +Name[pl]=Gładzik został wyłączony +Name[pt]=O rato por toque foi desactivado +Name[pt_BR]=O touchpad foi desativado +Name[ro]=Zona tactilă a fost dezactivată +Name[sk]=Touchpad bol zakázaný +Name[sl]=Sledilna ploščica je bila onemogočena +Name[sv]=Tryckplattan stängdes av +Name[tr]=Dokunmatik yüzey devre dışı bırakıldı +Name[uk]=Сенсорну панель вимкнено +Name[x-test]=xxTouchpad was disabledxx +Comment=Touchpad was disabled because mouse is detected +Comment[bs]=Dodirna površina je isključena jer je miš prepoznat +Comment[cs]=Touchpad byl zakázán protože byla zjištěna myš +Comment[da]=Touchpad blev deaktiveret fordi musen blev detekteret +Comment[de]=Das Touchpad wurde deaktiviert, weil eine Maus erkannt wurde +Comment[el]=Η επιφάνειας αφής απενεργοποιήθηκε επειδή το ποντίκι ανιχνεύτηκε +Comment[es]=El panel táctil se ha desactivado porque se ha detectado un ratón +Comment[fi]=Kosketuslevy poistettiin käytöstä, koska havaittiin hiiri +Comment[fr]=Le pavé tactile a été désactivé car une souris a été détectée +Comment[hu]=Az érintőtábla le lett tiltva, mert érzékelhető egy egér +Comment[ko]=마우스가 감지되어 터치패드 비활성화됨 +Comment[lt]=Jutiklinis kilimėlis išjungtas, nes aptikta pelė +Comment[nl]=Touchpad was uitgeschakeld omdat er een muis is gedetecteerd +Comment[pl]=Gładzik został wyłączony, bo podłączono mysz +Comment[pt]=O rato por toque foi desactivado porque foi detectado um rato +Comment[pt_BR]=O touchpad foi desativado porque o mouse foi detectado +Comment[ro]=Zona tactilă a fost dezactivată deoarece s-a detectat un maus +Comment[sk]=Touchpad bol zakázaný, lebo bola zistená myš +Comment[sl]=Sledilna ploščica je bila onemogočena, ker je bila zaznana miška +Comment[sv]=Tryckplattan stängdes av eftersom en mus detekterades +Comment[tr]=Dokunmatik yüzey fare tespit edildiğinden devre dışı bırakıldı +Comment[uk]=Сенсорну панель вимкнено, оскільки виявлено мишу +Comment[x-test]=xxTouchpad was disabled because mouse is detectedxx +Sound=KDE-Sys-App-Positive.ogg +Action=Popup + +[Event/TouchpadEnabled] +Name=Touchpad was enabled +Name[bs]=Dodirna površina je uključena +Name[cs]=Touchpad byl povolen +Name[da]=Touchpad blev aktiveret +Name[de]=Das Touchpad wurde aktiviert +Name[el]=Η επιφάνεια αφής ενεργοποιήθηκε +Name[es]=El panel táctil se ha activado +Name[fi]=Kosketuslevy otettiin käyttöön +Name[fr]=Le pavé tactile a été activé +Name[hu]=Az érintőtábla engedélyezve lett +Name[ko]=터치패드 활성화됨 +Name[lt]=Jutiklinis kilimėlis įjungtas +Name[nl]=Touchpad was ingeschakeld +Name[pl]=Gładzik został włączony +Name[pt]=O rato por toque foi activado +Name[pt_BR]=O touchpad foi ativado +Name[ro]=Zona tactilă a fost activată +Name[sk]=Touchpad bol povolený +Name[sl]=Sledilna ploščica je bila omogočena +Name[sv]=Tryckplattan aktiverades +Name[tr]=Dokunmatik yüzey etkinleştirildi +Name[uk]=Сенсорну панель увімкнено +Name[x-test]=xxTouchpad was enabledxx +Comment=Touchpad was enabled because the mouse was unplugged +Comment[bs]=Dodirna površina je uključena jer je miš isključen +Comment[cs]=Touchpad byl povolen protože byla odpojena myš +Comment[da]=Touchpad blev aktiveret fordi musen blev frakoblet +Comment[de]=Das Touchpad wurde aktiviert, weil eine Maus abgezogen wurde +Comment[el]=Η επιφάνειας αφής ενεργοποιήθηκε επειδή το ποντίκι αποσυνδέθηκε +Comment[es]=El panel táctil se ha activado porque se ha desconectado el ratón +Comment[fi]=Kosketuslevy otettiin käyttöön, koska hiiri irrotettiin +Comment[fr]=Le pavé tactile a été activé car la souris a été débranchée +Comment[hu]=Az érintőtábla engedélyezve lett, mert az egér ki lett húzva +Comment[ko]=마우스가 연결 해제되어 터치패드 활성화됨 +Comment[lt]=Jutiklinis kilimėlis įjungtas, nes buvo atjungta pelė +Comment[nl]=Touchpad was ingeschakeld omdat er een muis is uitgetrokken +Comment[pl]=Gładzik został włączony, bo odłączono mysz +Comment[pt]=O rato por toque foi activado porque o rato foi desligado +Comment[pt_BR]=O touchpad foi ativado porque o mouse foi desconectado +Comment[ro]=Zona tactilă a fost activată deoarece mausul a fost deconectat +Comment[sk]=Touchpad bol povolený, pretože myš bola odpojená +Comment[sl]=Sledilna ploščica je bila omogočena, ker je bila miška odklopljena +Comment[sv]=Tryckplattan aktiverades eftersom en mus kopplades bort +Comment[tr]=Dokunmatik yüzey fare çıkarıldığından etkinleştirildi +Comment[uk]=Сенсорну панель увімкнено, оскільки мишу було від’єднано +Comment[x-test]=xxTouchpad was enabled because the mouse was unpluggedxx +Sound=KDE-Sys-App-Negative.ogg +Action=Sound diff --git a/kcontrol/touchpad/src/kded/kded.cpp b/kcontrol/touchpad/src/kded/kded.cpp new file mode 100644 index 00000000..3e217ae2 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kded.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kded.h" + +#include +#include + +#include "plugins.h" +#include "kdedactions.h" + +bool TouchpadDisabler::workingTouchpadFound() const +{ + return m_backend && !(m_backend->supportedParameters().isEmpty()); +} + +void TouchpadDisabler::serviceRegistered(const QString &service) +{ + if (!m_dependecies.removeWatchedService(service)) { + return; + } + + if (m_dependecies.watchedServices().isEmpty()) { + lateInit(); + } +} + +TouchpadDisabler::TouchpadDisabler(QObject *parent, const QVariantList &) + : KDEDModule(parent), m_backend(TouchpadBackend::implementation()), + m_enabled(true), m_keyboardActivity(false), m_mouse(false) +{ + if (!workingTouchpadFound()) { + return; + } + + m_dependecies.addWatchedService("org.kde.plasma-desktop"); + m_dependecies.addWatchedService("org.kde.kglobalaccel"); + connect(&m_dependecies, SIGNAL(serviceRegistered(QString)), + SLOT(serviceRegistered(QString))); + + connect(m_backend, SIGNAL(mousesChanged()), SLOT(mousePlugged())); + connect(m_backend, SIGNAL(keyboardActivityStarted()), + SLOT(keyboardActivityStarted())); + connect(m_backend, SIGNAL(keyboardActivityFinished()), + SLOT(keyboardActivityFinished())); + connect(m_backend, SIGNAL(touchpadStateChanged()), + SLOT(updateCurrentState())); + + connect(m_backend, SIGNAL(touchpadReset()), SLOT(handleReset())); + + m_keyboardActivityTimeout.setSingleShot(true); + connect(&m_keyboardActivityTimeout, SIGNAL(timeout()), + SLOT(timerElapsed())); + + updateCurrentState(); + reloadSettings(); + + m_dependecies.setWatchMode(QDBusServiceWatcher::WatchForRegistration); + m_dependecies.setConnection(QDBusConnection::sessionBus()); + Q_FOREACH (const QString &service, m_dependecies.watchedServices()) { + QDBusReply registered = QDBusConnection::sessionBus().interface() + ->isServiceRegistered(service); + if (!registered.isValid() || registered.value()) { + serviceRegistered(service); + } + } +} + +bool TouchpadDisabler::isEnabled() const +{ + return m_enabled; +} + +void TouchpadDisabler::updateCurrentState() +{ + bool newEnabled = m_backend->isTouchpadEnabled(); + if (newEnabled != m_enabled) { + m_enabled = newEnabled; + Q_EMIT enabledChanged(m_enabled); + } +} + +void TouchpadDisabler::toggle() +{ + m_backend->setTouchpadEnabled(!isEnabled()); +} + +void TouchpadDisabler::disable() +{ + m_backend->setTouchpadEnabled(false); +} + +void TouchpadDisabler::enable() +{ + m_backend->setTouchpadEnabled(true); +} + +void TouchpadDisabler::reloadSettings() +{ + m_settings.readConfig(); + m_keyboardActivityTimeout.setInterval( + m_settings.keyboardActivityTimeoutMs()); + + m_keyboardDisableState = + m_settings.onlyDisableTapAndScrollOnKeyboardActivity() ? + TouchpadBackend::TouchpadTapAndScrollDisabled : + TouchpadBackend::TouchpadFullyDisabled; + + mousePlugged(); + + m_backend->watchForEvents(m_settings.disableOnKeyboardActivity()); +} + +void TouchpadDisabler::keyboardActivityStarted() +{ + if (m_keyboardActivity || !m_settings.disableOnKeyboardActivity()) { + return; + } + + m_keyboardActivityTimeout.stop(); + m_keyboardActivity = true; + m_backend->setTouchpadOff(m_keyboardDisableState); +} + +void TouchpadDisabler::keyboardActivityFinished() +{ + if (!m_keyboardActivity) { + keyboardActivityStarted(); + } + m_keyboardActivityTimeout.start(); +} + +void TouchpadDisabler::timerElapsed() +{ + if (!m_keyboardActivity) { + return; + } + + m_keyboardActivity = false; + m_backend->setTouchpadOff(TouchpadBackend::TouchpadEnabled); +} + +void TouchpadDisabler::mousePlugged() +{ + if (!m_dependecies.watchedServices().isEmpty()) { + return; + } + + bool pluggedIn = isMousePluggedIn(); + Q_EMIT mousePluggedInChanged(pluggedIn); + + bool disable = pluggedIn && m_settings.disableWhenMousePluggedIn(); + if (m_mouse == disable) { + return; + } + m_mouse = disable; + + if (m_enabled == !disable) { + return; + } + + if (disable) { + showNotification("TouchpadDisabled", + i18n("Touchpad was disabled because a mouse was plugged in")); + } else { + showNotification("TouchpadEnabled", + i18n("Touchpad was enabled because the mouse was unplugged")); + } + + m_backend->setTouchpadEnabled(!disable); +} + +void TouchpadDisabler::showNotification(const QString &name, const QString &text) +{ + KNotification::event(name, text, QPixmap(), //Icon is specified in .notifyrc + 0, KNotification::CloseOnTimeout, + TouchpadPluginFactory::componentData()); +} + +bool TouchpadDisabler::isMousePluggedIn() const +{ + return !m_backend->listMouses(m_settings.mouseBlacklist()).isEmpty(); +} + +void TouchpadDisabler::lateInit() +{ + TouchpadGlobalActions *actions = new TouchpadGlobalActions(this); + connect(actions, SIGNAL(enableTriggered()), SLOT(enable())); + connect(actions, SIGNAL(disableTriggered()), SLOT(disable())); + connect(actions, SIGNAL(toggleTriggered()), SLOT(toggle())); + + updateCurrentState(); + mousePlugged(); +} + +void touchpadApplySavedConfig(); + +void TouchpadDisabler::handleReset() +{ + m_backend->setTouchpadEnabled(m_enabled); + touchpadApplySavedConfig(); +} diff --git a/kcontrol/touchpad/src/kded/kded.h b/kcontrol/touchpad/src/kded/kded.h new file mode 100644 index 00000000..90014d37 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kded.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KDED_H +#define KDED_H + +#include +#include +#include + +#include + +#include "touchpadbackend.h" +#include "kdedsettings.h" + +class TouchpadDisabler : public KDEDModule +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.touchpad") + +public: + TouchpadDisabler(QObject *, const QVariantList &); + +Q_SIGNALS: + Q_SCRIPTABLE void enabledChanged(bool); + Q_SCRIPTABLE void mousePluggedInChanged(bool); + +public Q_SLOTS: + Q_SCRIPTABLE Q_NOREPLY void reloadSettings(); + Q_SCRIPTABLE Q_NOREPLY void toggle(); + Q_SCRIPTABLE Q_NOREPLY void disable(); + Q_SCRIPTABLE Q_NOREPLY void enable(); + Q_SCRIPTABLE bool isEnabled() const; + Q_SCRIPTABLE bool workingTouchpadFound() const; + Q_SCRIPTABLE bool isMousePluggedIn() const; + +private Q_SLOTS: + void keyboardActivityStarted(); + void keyboardActivityFinished(); + void timerElapsed(); + void mousePlugged(); + void updateCurrentState(); + void serviceRegistered(const QString &); + void handleReset(); + +private: + void showNotification(const QString &name, const QString &text); + void lateInit(); + + TouchpadBackend *m_backend; + TouchpadDisablerSettings m_settings; + QTimer m_keyboardActivityTimeout; + QDBusServiceWatcher m_dependecies; + + TouchpadBackend::TouchpadOffState m_keyboardDisableState; + bool m_enabled, m_keyboardActivity, m_mouse; +}; + +#endif // KDED_H diff --git a/kcontrol/touchpad/src/kded/kded_touchpad.desktop b/kcontrol/touchpad/src/kded/kded_touchpad.desktop new file mode 100644 index 00000000..f639a21b --- /dev/null +++ b/kcontrol/touchpad/src/kded/kded_touchpad.desktop @@ -0,0 +1,53 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KDEDModule +X-KDE-Library=touchpad +X-KDE-DBus-ModuleName=touchpad +X-KDE-Kded-autoload=true +X-KDE-Kded-load-on-demand=true +Name=Touchpad +Name[bs]=Dodirna površina +Name[cs]=Touchpad +Name[da]=Touchpad +Name[de]=Touchpad +Name[el]=Επιφάνεια αφής +Name[es]=Panel táctil +Name[fi]=Kosketuslevy +Name[fr]=Pavé tactile +Name[hu]=Érintőtábla +Name[ko]=터치패드 +Name[lt]=Jutiklinis kilimėlis +Name[nl]=Touchpad +Name[pl]=Gładzik +Name[pt]=Rato por Toque +Name[pt_BR]=Touchpad +Name[ro]=Zonă tactilă +Name[sk]=Touchpad +Name[sl]=Sledilna ploščica +Name[sv]=Tryckplatta +Name[tr]=Dokunmatik Yüzey +Name[uk]=Сенсорна панель +Name[x-test]=xxTouchpadxx +Comment=Enables or disables touchpad +Comment[bs]=Uključuje ili isključuje dodirnu površinu +Comment[cs]=Povolí/zakáže touchpad +Comment[da]=Aktiverer eller deaktiverer touchpad +Comment[de]=Aktiviert oder deaktiviert das Touchpad +Comment[el]=Ενεργοποιεί ή απενεργοποιεί την επιφάνεια αφής +Comment[es]=Activa o desactiva el panel táctil +Comment[fi]=Ottaa kosketuslevyn käyttöön tai poistaa sen käytöstä +Comment[fr]=Active ou désactive le pavé tactile +Comment[hu]=Engedélyezi vagy letiltja az érintőtáblát +Comment[ko]=터치패드 활성/비활성 +Comment[lt]=Įjungia/išjungia jutiklinį kilimėlį +Comment[nl]=Schakelt het touchpad in of uit +Comment[pl]=Włącza lub wyłącza gładzik +Comment[pt]=Activa ou desactiva o rato por toque +Comment[pt_BR]=Ativa ou desativa o touchpad +Comment[ro]=Activează sau dezactivează zona tactilă +Comment[sk]=Povolí alebo zakáže touchpad +Comment[sl]=Omogoči ali onemogoči sledilno ploščico +Comment[sv]=Aktiverar eller stänger av tryckplatta +Comment[tr]=Dokunmatik yüzeyi etkinleştirir veya devre dışı bırakır +Comment[uk]=Вмикає або вимикає сенсорну панель +Comment[x-test]=xxEnables or disables touchpadxx diff --git a/kcontrol/touchpad/src/kded/kdedactions.cpp b/kcontrol/touchpad/src/kded/kdedactions.cpp new file mode 100644 index 00000000..def99a52 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kdedactions.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kdedactions.h" + +#include +#include + +#include "plugins.h" + +TouchpadGlobalActions::TouchpadGlobalActions(QObject *parent) + : KActionCollection(parent) +{ + setComponentData(TouchpadPluginFactory::componentData()); + + KAction *enable = addAction("Enable Touchpad"); + enable->setText(i18n("Enable Touchpad")); + connect(enable, SIGNAL(triggered()), SIGNAL(enableTriggered())); + + KAction *disable = addAction("Disable Touchpad"); + disable->setText(i18n("Disable Touchpad")); + connect(disable, SIGNAL(triggered()), SIGNAL(disableTriggered())); + + KAction *toggle = addAction("Toggle Touchpad"); + toggle->setText(i18n("Toggle Touchpad")); + connect(toggle, SIGNAL(triggered()), SIGNAL(toggleTriggered())); + + Q_FOREACH (QAction *i, actions()) { + KAction *act = qobject_cast(i); + act->setGlobalShortcut(KShortcut()); + act->setShortcutConfigurable(true); + } +} diff --git a/kcontrol/touchpad/src/kded/kdedactions.h b/kcontrol/touchpad/src/kded/kdedactions.h new file mode 100644 index 00000000..200e4666 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kdedactions.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KDEDACTIONS_H +#define KDEDACTIONS_H + +#include + +class TouchpadGlobalActions : public KActionCollection +{ + Q_OBJECT +public: + explicit TouchpadGlobalActions(QObject *parent); + +Q_SIGNALS: + void enableTriggered(); + void disableTriggered(); + void toggleTriggered(); +}; + +#endif // KDEDACTIONS_H diff --git a/kcontrol/touchpad/src/kded/kdedsettings.kcfgc b/kcontrol/touchpad/src/kded/kdedsettings.kcfgc new file mode 100644 index 00000000..c1737c65 --- /dev/null +++ b/kcontrol/touchpad/src/kded/kdedsettings.kcfgc @@ -0,0 +1,5 @@ +File=touchpaddaemon.kcfg +ClassName=TouchpadDisablerSettings +Mutators=true +MemberVariables=private +Inherits=KCoreConfigSkeleton diff --git a/kcontrol/touchpad/src/kded/touchpaddaemon.kcfg b/kcontrol/touchpad/src/kded/touchpaddaemon.kcfg new file mode 100644 index 00000000..477dfe8b --- /dev/null +++ b/kcontrol/touchpad/src/kded/touchpaddaemon.kcfg @@ -0,0 +1,26 @@ + + + + + + false + + + true + + + true + + + 0 + 10000 + 250 + + + TPPS/2 IBM TrackPoint,USB Trackpoint pointing device,DualPoint Stick,ThinkPad USB Keyboard with TrackPoint + + + diff --git a/kcontrol/touchpad/src/plugins.cpp b/kcontrol/touchpad/src/plugins.cpp new file mode 100644 index 00000000..aabdff28 --- /dev/null +++ b/kcontrol/touchpad/src/plugins.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "plugins.h" + +#include +#include + +#include "kcm/touchpadconfig.h" +#include "kded/kded.h" +#include "version.h" + +namespace { + +KAboutData buildAboutData() +{ + KAboutData data("kcm_touchpad", + QByteArray(), + ki18n("Touchpad KCM"), + TOUCHPAD_KCM_VERSION, + ki18n("System Settings module, daemon and Plasma applet for managing your touchpad"), + KAboutData::License_GPL_V2, + ki18n("Copyright © 2013 Alexander Mezin"), + ki18n("This program incorporates work covered by this copyright notice:\n" + "Copyright © 2002-2005,2007 Peter Osterlund"), + "https://projects.kde.org/projects/playground/utils/kcm-touchpad/"); + + data.addAuthor(ki18n("Alexander Mezin"), + ki18n("Developer"), + "mezin.alexander@gmail.com"); + data.addCredit(ki18n("Thomas Pfeiffer"), ki18nc("Credits", "Usability, testing")); + data.addCredit(ki18n("Alex Fiestas"), ki18nc("Credits", "Helped a bit")); + data.addCredit(ki18n("Peter Osterlund"), ki18nc("Credits", "Developer of synclient")); + data.addCredit(ki18n("Vadim Zaytsev"), ki18nc("Credits", "Testing")); + data.addCredit(ki18n("Violetta Raspryagayeva"), ki18nc("Credits", "Testing")); + + return data; +} + +} + +K_PLUGIN_FACTORY_DEFINITION(TouchpadPluginFactory, + registerPlugin(); + registerPlugin("kcm");) +K_EXPORT_PLUGIN(TouchpadPluginFactory(buildAboutData())) diff --git a/kcontrol/touchpad/src/plugins.h b/kcontrol/touchpad/src/plugins.h new file mode 100644 index 00000000..bc2f0f10 --- /dev/null +++ b/kcontrol/touchpad/src/plugins.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLUGINS_H +#define PLUGINS_H + +#include + +K_PLUGIN_FACTORY_DECLARATION(TouchpadPluginFactory) + +#endif // PLUGINS_H diff --git a/kcontrol/touchpad/src/touchpadbackend.cpp b/kcontrol/touchpad/src/touchpadbackend.cpp new file mode 100644 index 00000000..768a8906 --- /dev/null +++ b/kcontrol/touchpad/src/touchpadbackend.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "touchpadbackend.h" + +#include +#include + +#include "x11/xlibbackend.h" + +TouchpadBackend::TouchpadBackend(QObject *parent) : QObject(parent) +{ +} + +TouchpadBackend *TouchpadBackend::implementation() +{ + //There will be multiple backends later + static QThreadStorage > backend; + if (!backend.hasLocalData()) { + backend.setLocalData(QSharedPointer(new XlibBackend())); + } + return backend.localData().data(); +} diff --git a/kcontrol/touchpad/src/touchpadbackend.h b/kcontrol/touchpad/src/touchpadbackend.h new file mode 100644 index 00000000..d2315964 --- /dev/null +++ b/kcontrol/touchpad/src/touchpadbackend.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TOUCHPADBACKEND_H +#define TOUCHPADBACKEND_H + +#include +#include + +#include + +class KDE_EXPORT TouchpadBackend : public QObject +{ + Q_OBJECT +public: + explicit TouchpadBackend(QObject *parent); + + static TouchpadBackend *implementation(); + + virtual bool applyConfig(const QVariantHash &) = 0; + virtual bool getConfig(QVariantHash &) = 0; + virtual const QStringList &supportedParameters() const = 0; + virtual const QString &errorString() const = 0; + + enum TouchpadOffState { + TouchpadEnabled, TouchpadTapAndScrollDisabled, TouchpadFullyDisabled + }; + virtual void setTouchpadOff(TouchpadOffState) = 0; + virtual TouchpadOffState getTouchpadOff() = 0; + + virtual bool isTouchpadEnabled() = 0; + virtual void setTouchpadEnabled(bool) = 0; + + virtual QStringList listMouses(const QStringList &blacklist) = 0; + + virtual void watchForEvents(bool keyboard) = 0; + +Q_SIGNALS: + void touchpadStateChanged(); + void mousesChanged(); + void touchpadReset(); + void keyboardActivityStarted(); + void keyboardActivityFinished(); +}; + +#endif // TOUCHPADBACKEND_H diff --git a/kcontrol/touchpad/src/version.h.cmake b/kcontrol/touchpad/src/version.h.cmake new file mode 100644 index 00000000..26244897 --- /dev/null +++ b/kcontrol/touchpad/src/version.h.cmake @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define TOUCHPAD_KCM_VERSION "@TOUCHPAD_KCM_VERSION@" + +#endif // VERSION_H diff --git a/kcontrol/touchpad/src/x11/listdevices.cpp b/kcontrol/touchpad/src/x11/listdevices.cpp new file mode 100644 index 00000000..ac664e51 --- /dev/null +++ b/kcontrol/touchpad/src/x11/listdevices.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//Debug tool +//Must NOT be translated/localized + +#include + +#include +#include + +int main(void) +{ + Display *display = XOpenDisplay(0); + int nDevices = 0; + XDeviceInfo *devices = XListInputDevices(display, &nDevices); + for (int i = 0; i < nDevices; i++) { + const char *name = devices[i].name; + char *type = 0; + if (devices[i].type) { + type = XGetAtomName(display, devices[i].type); + } + const char *use; + switch (devices[i].use) { + case IsXPointer: use = "Pointer"; break; + case IsXKeyboard: use = "Keyboard"; break; + case IsXExtensionDevice: use = "Extension Device"; break; + case IsXExtensionPointer: use = "Extension Pointer"; break; + case IsXExtensionKeyboard: use = "Extension Keyboard"; break; + default: use = "Unknown"; + } + std::cout << "Name: " << name << " Type: " << (type ? type : "unknown") + << " Use: " << use << std::endl; + XFree(type); + } + XFreeDeviceList(devices); + XCloseDisplay(display); +} diff --git a/kcontrol/touchpad/src/x11/synclientproperties.c b/kcontrol/touchpad/src/x11/synclientproperties.c new file mode 100644 index 00000000..5fd1ed61 --- /dev/null +++ b/kcontrol/touchpad/src/x11/synclientproperties.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* +//krazy:excludeall=copyright + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright © 2002-2005,2007 Peter Osterlund + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Red Hat + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Red + * Hat makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Peter Osterlund (petero2@telia.com) + */ + +#include "synclientproperties.h" + +#include +#include +#include + +#define SYN_MAX_BUTTONS 12 + +const struct Parameter synapticsProperties[] = { + {"LeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 0}, + {"RightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 1}, + {"TopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 2}, + {"BottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_EDGES, 32, 3}, + {"FingerLow", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 0}, + {"FingerHigh", PT_INT, 0, 255, SYNAPTICS_PROP_FINGER, 32, 1}, + {"MaxTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_TIME, 32, 0}, + {"MaxTapMove", PT_INT, 0, 2000, SYNAPTICS_PROP_TAP_MOVE, 32, 0}, + {"MaxDoubleTapTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 1}, + {"SingleTapTimeout", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 0}, + {"ClickTime", PT_INT, 0, 1000, SYNAPTICS_PROP_TAP_DURATIONS,32, 2}, + {"FastTaps", PT_BOOL, 0, 1, SYNAPTICS_PROP_TAP_FAST, 8, 0}, + {"EmulateMidButtonTime", PT_INT, 0, 1000, SYNAPTICS_PROP_MIDDLE_TIMEOUT,32, 0}, + {"EmulateTwoFingerMinZ", PT_INT, 0, 1000, SYNAPTICS_PROP_TWOFINGER_PRESSURE, 32, 0}, + {"EmulateTwoFingerMinW", PT_INT, 0, 15, SYNAPTICS_PROP_TWOFINGER_WIDTH, 32, 0}, + {"VertScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 0}, + {"HorizScrollDelta", PT_INT, -1000, 1000, SYNAPTICS_PROP_SCROLL_DISTANCE, 32, 1}, + {"VertEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 0}, + {"HorizEdgeScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 1}, + {"CornerCoasting", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_EDGE, 8, 2}, + {"VertTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 0}, + {"HorizTwoFingerScroll", PT_BOOL, 0, 1, SYNAPTICS_PROP_SCROLL_TWOFINGER, 8, 1}, + {"MinSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 0}, + {"MaxSpeed", PT_DOUBLE, 0, 255.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 1}, + {"AccelFactor", PT_DOUBLE, 0, 1.0, SYNAPTICS_PROP_SPEED, 0, /*float */ 2}, + /*{"TouchpadOff", PT_INT, 0, 2, SYNAPTICS_PROP_OFF, 8, 0},*/ + {"LockedDrags", PT_BOOL, 0, 1, SYNAPTICS_PROP_LOCKED_DRAGS, 8, 0}, + {"LockedDragTimeout", PT_INT, 0, 30000, SYNAPTICS_PROP_LOCKED_DRAGS_TIMEOUT, 32, 0}, + {"RTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 0}, + {"RBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 1}, + {"LTCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 2}, + {"LBCornerButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 3}, + {"OneFingerTapButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 4}, + {"TwoFingerTapButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 5}, + {"ThreeFingerTapButton", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_TAP_ACTION, 8, 6}, + {"ClickFinger1", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 0}, + {"ClickFinger2", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 1}, + {"ClickFinger3", PT_INT, 0, SYN_MAX_BUTTONS, SYNAPTICS_PROP_CLICK_ACTION, 8, 2}, + {"CircularScrolling", PT_BOOL, 0, 1, SYNAPTICS_PROP_CIRCULAR_SCROLLING, 8, 0}, + {"CircScrollDelta", PT_DOUBLE, .01, 3, SYNAPTICS_PROP_CIRCULAR_SCROLLING_DIST, 0 /* float */, 0}, + {"CircScrollTrigger", PT_INT, 0, 8, SYNAPTICS_PROP_CIRCULAR_SCROLLING_TRIGGER, 8, 0}, + {"PalmDetect", PT_BOOL, 0, 1, SYNAPTICS_PROP_PALM_DETECT, 8, 0}, + {"PalmMinWidth", PT_INT, 0, 15, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 0}, + {"PalmMinZ", PT_INT, 0, 255, SYNAPTICS_PROP_PALM_DIMENSIONS, 32, 1}, + {"CoastingSpeed", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 0}, + {"CoastingFriction", PT_DOUBLE, 0, 255, SYNAPTICS_PROP_COASTING_SPEED, 0 /* float*/, 1}, + {"PressureMotionMinZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 0}, + {"PressureMotionMaxZ", PT_INT, 1, 255, SYNAPTICS_PROP_PRESSURE_MOTION, 32, 1}, + {"PressureMotionMinFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 0}, + {"PressureMotionMaxFactor", PT_DOUBLE, 0, 10.0,SYNAPTICS_PROP_PRESSURE_MOTION_FACTOR, 0 /*float*/, 1}, + {"GrabEventDevice", PT_BOOL, 0, 1, SYNAPTICS_PROP_GRAB, 8, 0}, + {"TapAndDragGesture", PT_BOOL, 0, 1, SYNAPTICS_PROP_GESTURES, 8, 0}, + {"AreaLeftEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 0}, + {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1}, + {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2}, + {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3}, + {"HorizHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 0}, + {"VertHysteresis", PT_INT, 0, 10000, SYNAPTICS_PROP_NOISE_CANCELLATION, 32, 1}, + {"ClickPad", PT_BOOL, 0, 1, SYNAPTICS_PROP_CLICKPAD, 8, 0}, + {"RightButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 0}, + {"RightButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 1}, + {"RightButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 2}, + {"RightButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 3}, + {"MiddleButtonAreaLeft", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 4}, + {"MiddleButtonAreaRight", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 5}, + {"MiddleButtonAreaTop", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 6}, + {"MiddleButtonAreaBottom", PT_INT, INT_MIN, INT_MAX, SYNAPTICS_PROP_SOFTBUTTON_AREAS, 32, 7}, + { NULL, 0, 0, 0, 0, 0, 0 } +}; diff --git a/kcontrol/touchpad/src/x11/synclientproperties.h b/kcontrol/touchpad/src/x11/synclientproperties.h new file mode 100644 index 00000000..5b32b9fd --- /dev/null +++ b/kcontrol/touchpad/src/x11/synclientproperties.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* +//krazy:excludeall=copyright + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright © 2002-2005,2007 Peter Osterlund + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Red Hat + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Red + * Hat makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Authors: + * Peter Osterlund (petero2@telia.com) + */ + +#ifndef SYNCLIENTPROPERTIES_H +#define SYNCLIENTPROPERTIES_H + +enum ParaType { + PT_INT, + PT_BOOL, + PT_DOUBLE +}; + +struct Parameter { + const char *name; /* Name of parameter */ + enum ParaType type; /* Type of parameter */ + double min_val; /* Minimum allowed value */ + double max_val; /* Maximum allowed value */ + const char *prop_name; /* Property name */ + int prop_format; /* Property format (0 for floats) */ + unsigned prop_offset; /* Offset inside property */ +}; + +extern const struct Parameter synapticsProperties[]; + +#endif diff --git a/kcontrol/touchpad/src/x11/x11.cmake b/kcontrol/touchpad/src/x11/x11.cmake new file mode 100644 index 00000000..ae2b0bbc --- /dev/null +++ b/kcontrol/touchpad/src/x11/x11.cmake @@ -0,0 +1,48 @@ +# // krazy:excludeall=copyright,license +find_package(X11 REQUIRED) +find_package(X11_XCB REQUIRED) +find_package(XCB REQUIRED) +find_package(PkgConfig REQUIRED) + +if(NOT X11_Xinput_FOUND) + message(FATAL_ERROR "Xinput not found") +endif() + +pkg_search_module(SYNAPTICS REQUIRED xorg-synaptics) +pkg_search_module(XORG REQUIRED xorg-server) + +include_directories(${XCB_INCLUDE_DIR} + ${X11_XCB_INCLUDE_DIR} + ${X11_Xinput_INCLUDE_PATH} + ${X11_X11_INCLUDE_PATH} + ${SYNAPTICS_INCLUDE_DIRS} + ${XORG_INCLUDE_DIRS} +) + +add_definitions(${X11_XCB_DEFINITIONS} ${XCB_DEFINITIONS}) + +SET(backend_SRCS + ${backend_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/x11/synclientproperties.c + ${CMAKE_CURRENT_SOURCE_DIR}/x11/xcbatom.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/x11/xlibbackend.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/x11/xlibnotifications.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/x11/xrecordkeyboardmonitor.cpp +) + +SET(backend_LIBS + ${backend_LIBS} + ${XCB_LIBRARIES} + ${X11_X11_LIB} + ${X11_XCB_LIBRARIES} + ${X11_Xinput_LIB} +) + +add_executable(kcm-touchpad-list-devices ${CMAKE_CURRENT_SOURCE_DIR}/x11/listdevices.cpp) +target_link_libraries(kcm-touchpad-list-devices + ${X11_X11_LIB} + ${X11_Xinput_LIB} +) +install(TARGETS kcm-touchpad-list-devices + DESTINATION ${INSTALL_TARGETS_DEFAULT_ARGS} +) diff --git a/kcontrol/touchpad/src/x11/xcbatom.cpp b/kcontrol/touchpad/src/x11/xcbatom.cpp new file mode 100644 index 00000000..06f7f522 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xcbatom.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "xcbatom.h" + +#include +#include + +XcbAtom::XcbAtom() : m_connection(0), m_reply(0), m_fetched(false) +{ +} + +XcbAtom::XcbAtom(xcb_connection_t *c, const char *name, bool onlyIfExists) + : m_reply(0), m_fetched(false) +{ + intern(c, name, onlyIfExists); +} + +void XcbAtom::intern(xcb_connection_t *c, const char *name, bool onlyIfExists) +{ + m_connection = c; + m_cookie = xcb_intern_atom(c, onlyIfExists, std::strlen(name), name); +} + +XcbAtom::~XcbAtom() +{ + std::free(m_reply); +} + +xcb_atom_t XcbAtom::atom() +{ + if (!m_fetched) { + m_fetched = true; + m_reply = xcb_intern_atom_reply(m_connection, m_cookie, 0); + } + if (m_reply) { + return m_reply->atom; + } else { + return 0; + } +} diff --git a/kcontrol/touchpad/src/x11/xcbatom.h b/kcontrol/touchpad/src/x11/xcbatom.h new file mode 100644 index 00000000..97905429 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xcbatom.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef XCBATOM_H +#define XCBATOM_H + +#include + +class XcbAtom +{ +public: + XcbAtom(); + XcbAtom(xcb_connection_t *, const char *name, bool onlyIfExists = true); + ~XcbAtom(); + + void intern(xcb_connection_t *, const char *name, bool onlyIfExists = true); + xcb_atom_t atom(); + operator xcb_atom_t() { return atom(); } + +private: + XcbAtom(const XcbAtom &); + XcbAtom &operator =(const XcbAtom &); + + xcb_connection_t *m_connection; + xcb_intern_atom_cookie_t m_cookie; + xcb_intern_atom_reply_t *m_reply; + bool m_fetched; +}; + +#endif // XCBATOM_H diff --git a/kcontrol/touchpad/src/x11/xlibbackend.cpp b/kcontrol/touchpad/src/x11/xlibbackend.cpp new file mode 100644 index 00000000..2ba8bc55 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xlibbackend.cpp @@ -0,0 +1,705 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include + +#include +#include + +//Includes are ordered this way because of #defines in Xorg's headers +#include "xrecordkeyboardmonitor.h" // krazy:exclude=includes +#include "xlibbackend.h" // krazy:exclude=includes +#include "xlibnotifications.h" // krazy:exclude=includes + +#include +#include +#include +#include + +#include +#include + +#include "synclientproperties.h" + +static void XDeleter(void *p) +{ + if (p) { + XFree(p); + } +} + +static void XIDeviceInfoDeleter(XIDeviceInfo *p) +{ + if (p) { + XIFreeDeviceInfo(p); + } +} + +void XlibBackend::XDisplayCleanup::cleanup(Display *p) +{ + if (p) { + XCloseDisplay(p); + } +} + +struct PropertyInfo +{ + Atom type; + int format; + QSharedPointer data; + unsigned long nitems; + + float *f; + int *i; + char *b; + + Display *display; + int device; + Atom prop; + + PropertyInfo() : + type(0), format(0), nitems(0), f(0), i(0), b(0), + display(0), device(0), prop(0) + { + } + + PropertyInfo(Display *display, int device, Atom prop, Atom floatType) + : type(0), format(0), nitems(0), f(0), i(0), b(0), + display(display), device(device), prop(prop) + { + unsigned char *dataPtr = 0; + unsigned long bytes_after; + XIGetProperty(display, device, prop, 0, 1000, False, + AnyPropertyType, &type, &format, &nitems, + &bytes_after, &dataPtr); + data = QSharedPointer(dataPtr, XDeleter); + + if (format == CHAR_BIT && type == XA_INTEGER) { + b = reinterpret_cast(dataPtr); + } + if (format == sizeof(int) * CHAR_BIT && + (type == XA_INTEGER || type == XA_CARDINAL)) + { + i = reinterpret_cast(dataPtr); + } + if (format == sizeof(float) * CHAR_BIT && + floatType && type == floatType) + { + f = reinterpret_cast(dataPtr); + } + } + + QVariant value(unsigned offset) const + { + QVariant v; + if (offset >= nitems) { + return v; + } + + if (b) { + v = QVariant(static_cast(b[offset])); + } + if (i) { + v = QVariant(i[offset]); + } + if (f) { + v = QVariant(f[offset]); + } + + return v; + } + + void set() + { + XIChangeProperty(display, device, prop, type, format, + XIPropModeReplace, data.data(), nitems); + } +}; + +XlibBackend::~XlibBackend() +{ +} + +XlibBackend::XlibBackend(QObject *parent) : + TouchpadBackend(parent), + m_display(XOpenDisplay(0)), m_connection(0), + m_resX(1), m_resY(1) +{ + if (m_display) { + m_connection = XGetXCBConnection(m_display.data()); + } + + if (!m_connection) { + m_errorString = i18n("Cannot connect to X server"); + return; + } + + m_floatType.intern(m_connection, "FLOAT"); + m_capsAtom.intern(m_connection, SYNAPTICS_PROP_CAPABILITIES); + m_enabledAtom.intern(m_connection, XI_PROP_ENABLED); + m_touchpadOffAtom.intern(m_connection, SYNAPTICS_PROP_OFF); + m_mouseAtom.intern(m_connection, XI_MOUSE); + m_keyboardAtom.intern(m_connection, XI_KEYBOARD); + XcbAtom resolutionAtom(m_connection, SYNAPTICS_PROP_RESOLUTION); + XcbAtom edgesAtom(m_connection, SYNAPTICS_PROP_EDGES); + + for (const Parameter *param = synapticsProperties; param->name; param++) { + QLatin1String name(param->prop_name); + + if (!m_atoms.contains(name)) { + m_atoms.insert(name, QSharedPointer( + new XcbAtom(m_connection, param->prop_name))); + } + } + + if (!m_capsAtom.atom()) { + m_errorString = + i18n("Synaptics driver is not installed (or is not used)"); + return; + } + + m_device = findTouchpad(); + if (m_device == XIAllDevices) { + m_errorString = i18n("No touchpad found"); + return; + } + + for (const Parameter *p = synapticsProperties; p->name; p++) { + if (getParameter(p).isValid()) { + m_supported.append(p->name); + } + } + + if (m_supported.isEmpty()) { + m_errorString = i18n("Cannot read any of touchpad's properties"); + return; + } + + m_toRadians.append("CircScrollDelta"); + + PropertyInfo edges(m_display.data(), m_device, edgesAtom, 0); + if (edges.i && edges.nitems == 4) { + int w = qAbs(edges.i[1] - edges.i[0]); + int h = qAbs(edges.i[3] - edges.i[2]); + m_resX = w / 90; + m_resY = h / 50; + kDebug() << "Width: " << w << " height: " << h; + kDebug() << "Approx. resX: " << m_resX << " resY: " << m_resY; + } + + PropertyInfo resolution(m_display.data(), m_device, resolutionAtom, 0); + if (resolution.i && resolution.nitems == 2 && + resolution.i[0] > 1 && resolution.i[1] > 1) + { + m_resY = qMin(static_cast(resolution.i[0]), + static_cast(INT_MAX)); + m_resX = qMin(static_cast(resolution.i[1]), + static_cast(INT_MAX)); + kDebug() << "Touchpad resolution: x: " << m_resX << " y: " << m_resY; + } + + m_scaleByResX.append("HorizScrollDelta"); + m_scaleByResY.append("VertScrollDelta"); + m_scaleByResX.append("MaxTapMove"); + m_scaleByResY.append("MaxTapMove"); + + m_resX = qMax(10, m_resX); + m_resY = qMax(10, m_resY); + kDebug() << "Final resolution x:" << m_resX << " y:" << m_resY; + m_negate["HorizScrollDelta"] = "InvertHorizScroll"; + m_negate["VertScrollDelta"] = "InvertVertScroll"; + m_supported.append(m_negate.values()); + m_supported.append("Coasting"); + + PropertyInfo caps(m_display.data(), m_device, m_capsAtom.atom(), 0); + if (!caps.b) { + m_errorString = i18n("Cannot read touchpad's capabilities"); + return; + } + + enum TouchpadCapabilitiy + { + TouchpadHasLeftButton, + TouchpadHasMiddleButton, + TouchpadHasRightButton, + TouchpadTwoFingerDetect, + TouchpadThreeFingerDetect, + TouchpadPressureDetect, + TouchpadPalmDetect, + TouchpadCapsCount + }; + + QVector cap(TouchpadCapsCount, false); + qCopy(caps.b, caps.b + qMin(cap.size(), static_cast(caps.nitems)), + cap.begin()); + + if (!cap[TouchpadTwoFingerDetect]) { + m_supported.removeAll("HorizTwoFingerScroll"); + m_supported.removeAll("VertTwoFingerScroll"); + m_supported.removeAll("TwoFingerTapButton"); + } + + if (!cap[TouchpadThreeFingerDetect]) { + m_supported.removeAll("ThreeFingerTapButton"); + } + + if (!cap[TouchpadPressureDetect]) { + m_supported.removeAll("FingerHigh"); + m_supported.removeAll("FingerLow"); + + m_supported.removeAll("PalmMinZ"); + m_supported.removeAll("PressureMotionMinZ"); + m_supported.removeAll("PressureMotionMinFactor"); + m_supported.removeAll("PressureMotionMaxZ"); + m_supported.removeAll("PressureMotionMaxFactor"); + m_supported.removeAll("EmulateTwoFingerMinZ"); + } + + if (!cap[TouchpadPalmDetect]) { + m_supported.removeAll("PalmDetect"); + m_supported.removeAll("PalmMinWidth"); + m_supported.removeAll("PalmMinZ"); + m_supported.removeAll("EmulateTwoFingerMinW"); + } + + for (QMap::Iterator i = m_negate.begin(); + i != m_negate.end(); ++i) + { + if (!m_supported.contains(i.key())) { + m_supported.removeAll(i.value()); + } + } +} + +int XlibBackend::findTouchpad() +{ + int nDevices = 0; + QSharedPointer deviceInfo( + XIQueryDevice(m_display.data(), XIAllDevices, &nDevices), + XIDeviceInfoDeleter); + + for (XIDeviceInfo *info = deviceInfo.data(); + info < deviceInfo.data() + nDevices; info++) + { + int nProperties = 0; + QSharedPointer properties( + XIListProperties(m_display.data(), info->deviceid, + &nProperties), XDeleter); + + if (std::count(properties.data(), properties.data() + nProperties, + m_capsAtom.atom())) + { + return info->deviceid; + } + } + + return XIAllDevices; +} + +static const Parameter *findParameter(const QString &name) +{ + for (const Parameter *par = synapticsProperties; par->name; par++) { + if (name == par->name) { + return par; + } + } + return 0; +} + +double XlibBackend::getPropertyScale(const QString &name) const +{ + if (m_scaleByResX.contains(name) && m_scaleByResY.contains(name)) { + return std::sqrt(static_cast(m_resX) * m_resX + + static_cast(m_resY) * m_resY); + } else if (m_scaleByResX.contains(name)) { + return m_resX; + } else if (m_scaleByResY.contains(name)) { + return m_resY; + } else if (m_toRadians.contains(name)) { + return M_PI_4 / 45.0; + } + return 1.0; +} + +static QVariant negateVariant(const QVariant &value) +{ + if (value.type() == QVariant::Double) { + return QVariant(-value.toDouble()); + } else if (value.type() == QVariant::Int) { + return QVariant(-value.toInt()); + } + return value; +} + +bool XlibBackend::applyConfig(const QVariantHash &p) +{ + if (m_supported.isEmpty()) { + return false; + } + + m_props.clear(); + + bool error = false; + Q_FOREACH(const QString &name, m_supported) { + QVariantHash::ConstIterator i = p.find(name); + if (i == p.end()) { + continue; + } + const Parameter *par = findParameter(name); + if (par) { + QVariant value(i.value()); + + double k = getPropertyScale(name); + if (k != 1.0) { + bool ok = false; + value = QVariant(value.toDouble(&ok) * k); + if (!ok) { + error = true; + continue; + } + } + + if (m_negate.contains(name)) { + QVariantHash::ConstIterator i = p.find(m_negate[name]); + if (i != p.end() && i.value().toBool()) { + value = negateVariant(value); + } + } + + if (name == "CoastingSpeed") { + QVariantHash::ConstIterator coastingEnabled = p.find("Coasting"); + if (coastingEnabled != p.end() && + !coastingEnabled.value().toBool()) + { + value = QVariant(0); + } + } + + if (!setParameter(par, value)) { + error = true; + } + } + } + + flush(); + + if (error) { + m_errorString = i18n("Cannot apply touchpad configuration"); + } + return !error; +} + +void XlibBackend::flush() +{ + Q_FOREACH(const QLatin1String &name, m_changed) { + m_props[name].set(); + } + m_changed.clear(); + + XFlush(m_display.data()); +} + +bool XlibBackend::getConfig(QVariantHash &p) +{ + if (m_supported.isEmpty()) { + return false; + } + + m_props.clear(); + + bool error = false; + Q_FOREACH(const QString &name, m_supported) { + const Parameter *par = findParameter(name); + if (!par) { + continue; + } + + QVariant value(getParameter(par)); + if (!value.isValid()) { + error = true; + continue; + } + + double k = getPropertyScale(name); + if (k != 1.0) { + bool ok = false; + value = QVariant(value.toDouble(&ok) / k); + if (!ok) { + error = true; + continue; + } + } + + if (m_negate.contains(name)) { + bool negative = value.toDouble() < 0.0; + p[m_negate[name]] = QVariant(negative); + if (negative) { + value = negateVariant(value); + } + } + + if (name == "CoastingSpeed") { + bool coasting = value.toDouble() != 0.0; + p["Coasting"] = QVariant(coasting); + if (!coasting) { + continue; + } + } + + p[name] = value; + } + + if (error) { + m_errorString = i18n("Cannot read touchpad configuration"); + } + return !error; +} + +QVariant XlibBackend::getParameter(const Parameter *par) +{ + PropertyInfo *p = getDevProperty(QLatin1String(par->prop_name)); + if (!p || par->prop_offset >= p->nitems) { + return QVariant(); + } + + return p->value(par->prop_offset); +} + +PropertyInfo *XlibBackend::getDevProperty(const QLatin1String &propName) +{ + if (m_props.contains(propName)) { + return &m_props[propName]; + } + + if (!m_atoms.contains(propName) || !m_atoms[propName]) { + return 0; + } + + xcb_atom_t prop = m_atoms[propName]->atom(); + if (!prop) { + return 0; + } + + PropertyInfo p(m_display.data(), m_device, prop, m_floatType.atom()); + if (!p.b && !p.f && !p.i) { + return 0; + } + return &m_props.insert(propName, p).value(); +} + +bool XlibBackend::setParameter(const Parameter *par, const QVariant &value) +{ + QLatin1String propName(par->prop_name); + PropertyInfo *p = getDevProperty(propName); + if (!p || par->prop_offset >= p->nitems) { + return false; + } + + QVariant converted(value); + QVariant::Type convType = QVariant::Int; + if (p->f) { + convType = QVariant::Double; + } else if (value.type() == QVariant::Double) { + converted = QVariant(qRound(static_cast(value.toDouble()))); + } + + if (!converted.convert(convType)) { + return false; + } + + if (converted == p->value(par->prop_offset)) { + return true; + } + + if (p->b) { + p->b[par->prop_offset] = static_cast(converted.toInt()); + } else if (p->i) { + p->i[par->prop_offset] = converted.toInt(); + } else if (p->f) { + p->f[par->prop_offset] = converted.toDouble(); + } + + m_changed.insert(propName); + return true; +} + +void XlibBackend::setTouchpadEnabled(bool enable) +{ + PropertyInfo enabled(m_display.data(), m_device, m_enabledAtom.atom(), 0); + if (enabled.b && *(enabled.b) != enable) { + *(enabled.b) = enable; + enabled.set(); + } + + flush(); +} + +void XlibBackend::setTouchpadOff(TouchpadBackend::TouchpadOffState state) +{ + int touchpadOff = 0; + switch (state) { + case TouchpadEnabled: + touchpadOff = 0; + break; + case TouchpadFullyDisabled: + touchpadOff = 1; + break; + case TouchpadTapAndScrollDisabled: + touchpadOff = 2; + break; + default: + kError() << "Unknown TouchpadOffState" << state; + return; + } + + PropertyInfo off(m_display.data(), m_device, m_touchpadOffAtom.atom(), 0); + if (off.b && *(off.b) != touchpadOff) { + *(off.b) = touchpadOff; + off.set(); + } + + flush(); +} + +bool XlibBackend::isTouchpadEnabled() +{ + PropertyInfo enabled(m_display.data(), m_device, m_enabledAtom.atom(), 0); + return enabled.value(0).toBool(); +} + +TouchpadBackend::TouchpadOffState XlibBackend::getTouchpadOff() +{ + PropertyInfo off(m_display.data(), m_device, m_touchpadOffAtom.atom(), 0); + switch (off.value(0).toInt()) { + case 0: + return TouchpadEnabled; + case 1: + return TouchpadFullyDisabled; + case 2: + return TouchpadTapAndScrollDisabled; + default: + kError() << "Unknown TouchpadOff value" << off.value(0).toInt(); + return TouchpadFullyDisabled; + } +} + +void XlibBackend::touchpadDetached() +{ + kWarning() << "Touchpad detached"; + m_device = XIAllDevices; +} + +void XlibBackend::devicePlugged(int device) +{ + if (m_device == XIAllDevices) { + m_device = findTouchpad(); + if (m_device != XIAllDevices) { + kWarning() << "Touchpad reset"; + m_notifications.reset(); + watchForEvents(m_keyboard); + Q_EMIT touchpadReset(); + } + } + if (device != m_device) { + Q_EMIT mousesChanged(); + } +} + +void XlibBackend::propertyChanged(xcb_atom_t prop) +{ + if (prop == m_touchpadOffAtom.atom() || + prop == m_enabledAtom.atom()) + { + Q_EMIT touchpadStateChanged(); + } +} + +struct DeviceListDeleter +{ + static void cleanup(XDeviceInfo *p) + { + if (p) { + XFreeDeviceList(p); + } + } +}; + +QStringList XlibBackend::listMouses(const QStringList &blacklist) +{ + int nDevices = 0; + QScopedPointer + info(XListInputDevices(m_display.data(), &nDevices)); + QStringList list; + for (XDeviceInfo *i = info.data(); i != info.data() + nDevices; i++) { + if (i->id == static_cast(m_device)) { + continue; + } + if (i->use != IsXExtensionPointer && i->use != IsXPointer) { + continue; + } + //type = KEYBOARD && use = Pointer means usb receiver for both keyboard + //and mouse + if (i->type != m_mouseAtom.atom() && i->type != m_keyboardAtom.atom()) { + continue; + } + QString name(i->name); + if (blacklist.contains(name, Qt::CaseInsensitive)) { + continue; + } + PropertyInfo enabled(m_display.data(), i->id, m_enabledAtom.atom(), 0); + if (enabled.value(0) == false) { + continue; + } + list.append(name); + } + + return list; +} + +void XlibBackend::watchForEvents(bool keyboard) +{ + if (!m_notifications) { + m_notifications.reset(new XlibNotifications(m_display.data(), m_device)); + connect(m_notifications.data(), SIGNAL(devicePlugged(int)), + SLOT(devicePlugged(int))); + connect(m_notifications.data(), SIGNAL(touchpadDetached()), + SLOT(touchpadDetached())); + connect(m_notifications.data(), SIGNAL(propertyChanged(xcb_atom_t)), + SLOT(propertyChanged(xcb_atom_t))); + } + + if (keyboard == !m_keyboard.isNull()) { + return; + } + + if (!keyboard) { + m_keyboard.reset(); + return; + } + + m_keyboard.reset(new XRecordKeyboardMonitor(m_display.data())); + connect(m_keyboard.data(), SIGNAL(keyboardActivityStarted()), + SIGNAL(keyboardActivityStarted())); + connect(m_keyboard.data(), SIGNAL(keyboardActivityFinished()), + SIGNAL(keyboardActivityFinished())); +} diff --git a/kcontrol/touchpad/src/x11/xlibbackend.h b/kcontrol/touchpad/src/x11/xlibbackend.h new file mode 100644 index 00000000..3692a604 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xlibbackend.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef XLIBBACKEND_H +#define XLIBBACKEND_H + +#include +#include +#include +#include +#include +#include +#include + +#include "touchpadbackend.h" + +#include + +#include "xcbatom.h" + +class XlibNotifications; +class XRecordKeyboardMonitor; + +class XlibBackend : public TouchpadBackend +{ + Q_OBJECT + +public: + explicit XlibBackend(QObject *parent = 0); + ~XlibBackend(); + + bool applyConfig(const QVariantHash &); + bool getConfig(QVariantHash &); + const QStringList &supportedParameters() const { return m_supported; } + const QString &errorString() const { return m_errorString; } + + void setTouchpadOff(TouchpadOffState); + TouchpadOffState getTouchpadOff(); + + void setTouchpadEnabled(bool); + bool isTouchpadEnabled(); + + void watchForEvents(bool keyboard); + + QStringList listMouses(const QStringList &blacklist); + +private slots: + void propertyChanged(xcb_atom_t); + void touchpadDetached(); + void devicePlugged(int); + +private: + struct PropertyInfo *getDevProperty(const QLatin1String &propName); + bool setParameter(const struct Parameter *, const QVariant &); + QVariant getParameter(const struct Parameter *); + void flush(); + double getPropertyScale(const QString &name) const; + + struct XDisplayCleanup { + static void cleanup(Display *); + }; + + QScopedPointer m_display; + xcb_connection_t *m_connection; + + XcbAtom m_floatType, m_capsAtom, m_enabledAtom, m_touchpadOffAtom, + m_mouseAtom, m_keyboardAtom; + + int findTouchpad(); + int m_device; + + QMap > m_atoms; + QMap m_props; + QSet m_changed; + QStringList m_supported; + QString m_errorString; + int m_resX, m_resY; + QStringList m_scaleByResX, m_scaleByResY, m_toRadians; + QMap m_negate; + QScopedPointer m_notifications; + QScopedPointer m_keyboard; +}; + +#endif // XLIBBACKEND_H diff --git a/kcontrol/touchpad/src/x11/xlibnotifications.cpp b/kcontrol/touchpad/src/x11/xlibnotifications.cpp new file mode 100644 index 00000000..e9ebca7c --- /dev/null +++ b/kcontrol/touchpad/src/x11/xlibnotifications.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "xlibnotifications.h" + +#include + +#include +#include +#include +#include +#include + +XlibNotifications::XlibNotifications(Display *display, int device) + : m_display(display), m_device(device) +{ + m_connection = XGetXCBConnection(display); + + m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), + QSocketNotifier::Read, this); + + xcb_query_extension_cookie_t inputExtCookie = + xcb_query_extension(m_connection, std::strlen(INAME), INAME); + QScopedPointer + inputExt(xcb_query_extension_reply(m_connection, inputExtCookie, 0)); + if (!inputExt) { + return; + } + m_inputOpcode = inputExt->major_opcode; + + const xcb_setup_t *setup = xcb_get_setup(m_connection); + xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); + xcb_screen_t *screen = iter.data; + + m_inputWindow = xcb_generate_id(m_connection); + xcb_create_window(m_connection, 0, m_inputWindow, screen->root, 0, 0, 1, 1, + 0, XCB_WINDOW_CLASS_INPUT_ONLY, 0, 0, 0); + xcb_flush(m_connection); + + XIEventMask masks[2]; + + unsigned char touchpadMask[] = { 0, 0, 0, 0 }; + masks[0].deviceid = device; + masks[0].mask = touchpadMask; + masks[0].mask_len = sizeof(touchpadMask); + XISetMask(touchpadMask, XI_PropertyEvent); + + unsigned char allMask[] = { 0, 0, 0, 0 }; + masks[1].deviceid = XIAllDevices; + masks[1].mask = allMask; + masks[1].mask_len = sizeof(allMask); + XISetMask(allMask, XI_HierarchyChanged); + + XISelectEvents(display, XDefaultRootWindow(display), masks, + sizeof(masks) / sizeof(XIEventMask)); + XFlush(display); + + connect(m_notifier, SIGNAL(activated(int)), SLOT(processEvents())); + m_notifier->setEnabled(true); +} + +void XlibNotifications::processEvents() +{ + while (XPending(m_display)) { + XEvent event; + XNextEvent(m_display, &event); + processEvent(&event); + } +} + +struct XEventDataDeleter +{ + XEventDataDeleter(Display *display, XGenericEventCookie *cookie) + : m_display(display), m_cookie(cookie) + { + XGetEventData(m_display, m_cookie); + } + + ~XEventDataDeleter() + { + if (m_cookie->data) { + XFreeEventData(m_display, m_cookie); + } + } + + Display *m_display; + XGenericEventCookie *m_cookie; +}; + +void XlibNotifications::processEvent(XEvent *event) +{ + if (event->xcookie.type != GenericEvent) { + return; + } + if (event->xcookie.extension != m_inputOpcode) { + return; + } + + if (event->xcookie.evtype == XI_PropertyEvent) { + XEventDataDeleter helper(m_display, &event->xcookie); + if (!event->xcookie.data) { + return; + } + + XIPropertyEvent *propEvent = + reinterpret_cast(event->xcookie.data); + Q_EMIT propertyChanged(propEvent->property); + } else if (event->xcookie.evtype == XI_HierarchyChanged) { + XEventDataDeleter helper(m_display, &event->xcookie); + if (!event->xcookie.data) { + return; + } + + XIHierarchyEvent *hierarchyEvent = + reinterpret_cast(event->xcookie.data); + for (uint16_t i = 0; i < hierarchyEvent->num_info; i++) { + if (hierarchyEvent->info[i].deviceid == m_device) { + if (hierarchyEvent->info[i].flags & XISlaveRemoved) { + Q_EMIT touchpadDetached(); + return; + } + } + if (hierarchyEvent->info[i].use != XISlavePointer) { + continue; + } + if (hierarchyEvent->info[i].flags & + (XIDeviceEnabled | XIDeviceDisabled)) + { + Q_EMIT devicePlugged(hierarchyEvent->info[i].deviceid); + } + } + } +} + +XlibNotifications::~XlibNotifications() +{ + xcb_destroy_window(m_connection, m_inputWindow); + xcb_flush(m_connection); +} + +#include "moc_xlibnotifications.cpp" diff --git a/kcontrol/touchpad/src/x11/xlibnotifications.h b/kcontrol/touchpad/src/x11/xlibnotifications.h new file mode 100644 index 00000000..ed6952b3 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xlibnotifications.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef XLIBNOTIFICATIONS_H +#define XLIBNOTIFICATIONS_H + +#include +#include +#include + +#include + +class XlibNotifications : public QObject +{ + Q_OBJECT +public: + XlibNotifications(Display *display, int device); + ~XlibNotifications(); + +Q_SIGNALS: + void propertyChanged(xcb_atom_t); + void devicePlugged(int); + void touchpadDetached(); + +private Q_SLOTS: + void processEvents(); + +private: + void processEvent(XEvent *); + + Display *m_display; + xcb_connection_t *m_connection; + QSocketNotifier *m_notifier; + xcb_window_t m_inputWindow; + uint8_t m_inputOpcode; + int m_device; +}; + +#endif // XLIBNOTIFICATIONS_H diff --git a/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.cpp b/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.cpp new file mode 100644 index 00000000..1dceee21 --- /dev/null +++ b/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "xrecordkeyboardmonitor.h" + +#include +#include + +#include + +#include +#include + +XRecordKeyboardMonitor::XRecordKeyboardMonitor(Display *display) + : m_connection(xcb_connect(XDisplayString(display), 0)), + m_modifiersPressed(0), m_keysPressed(0) +{ + if (!m_connection) { + return; + } + + xcb_get_modifier_mapping_cookie_t modmapCookie = + xcb_get_modifier_mapping(m_connection); + + m_context = xcb_generate_id(m_connection); + xcb_record_range_t range; + memset(&range, 0, sizeof(range)); + range.device_events.first = XCB_KEY_PRESS; + range.device_events.last = XCB_KEY_RELEASE; + xcb_record_client_spec_t cs = XCB_RECORD_CS_ALL_CLIENTS; + xcb_record_create_context(m_connection, m_context, 0, 1, 1, &cs, &range); + xcb_flush(m_connection); + + QScopedPointer + modmap(xcb_get_modifier_mapping_reply(m_connection, modmapCookie, 0)); + if (!modmap) { + return; + } + + int nModifiers = xcb_get_modifier_mapping_keycodes_length(modmap.data()); + xcb_keycode_t *modifiers = xcb_get_modifier_mapping_keycodes(modmap.data()); + m_modifier.fill(false, std::numeric_limits::max() + 1); + for (xcb_keycode_t *i = modifiers; i < modifiers + nModifiers; i++) { + m_modifier[*i] = true; + } + m_ignore.fill(false, std::numeric_limits::max() + 1); + for (xcb_keycode_t *i = modifiers; + i < modifiers + modmap->keycodes_per_modifier; i++) + { + m_ignore[*i] = true; + } + m_pressed.fill(false, std::numeric_limits::max() + 1); + + m_cookie = xcb_record_enable_context(m_connection, m_context); + xcb_flush(m_connection); + + m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), + QSocketNotifier::Read, this); + connect(m_notifier, SIGNAL(activated(int)), SLOT(processNextReply())); + m_notifier->setEnabled(true); +} + +XRecordKeyboardMonitor::~XRecordKeyboardMonitor() +{ + if (!m_connection) { + return; + } + + xcb_record_disable_context(m_connection, m_context); + xcb_record_free_context(m_connection, m_context); + xcb_disconnect(m_connection); +} + +void XRecordKeyboardMonitor::processNextReply() +{ + xcb_generic_event_t *event; + while ((event = xcb_poll_for_event(m_connection))) { + std::free(event); + } + + void *reply = 0; + while (xcb_poll_for_reply(m_connection, m_cookie.sequence, &reply, 0)) { + if (!reply) { + continue; + } + + QScopedPointer + data(reinterpret_cast(reply)); + process(data.data()); + } +} + +void XRecordKeyboardMonitor::process(xcb_record_enable_context_reply_t *reply) +{ + bool prevActivity = activity(); + + xcb_key_press_event_t *events = reinterpret_cast + (xcb_record_enable_context_data(reply)); + int nEvents = xcb_record_enable_context_data_length(reply) / + sizeof(xcb_key_press_event_t); + bool wasActivity = prevActivity; + for (xcb_key_press_event_t *e = events; e < events + nEvents; e++) { + if (e->response_type != XCB_KEY_PRESS && + e->response_type != XCB_KEY_RELEASE) + { + continue; + } + + if (m_ignore[e->detail]) { + continue; + } + + bool pressed = (e->response_type == XCB_KEY_PRESS); + if (m_pressed[e->detail] == pressed) { + continue; + } + m_pressed[e->detail] = pressed; + + int &counter = m_modifier[e->detail] ? m_modifiersPressed : + m_keysPressed; + if (pressed) { + counter++; + } else { + counter--; + } + + wasActivity = wasActivity || activity(); + } + + if (!prevActivity && activity()) { + Q_EMIT keyboardActivityStarted(); + } else if (!activity() && wasActivity) { + Q_EMIT keyboardActivityFinished(); + } +} diff --git a/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.h b/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.h new file mode 100644 index 00000000..79e4052f --- /dev/null +++ b/kcontrol/touchpad/src/x11/xrecordkeyboardmonitor.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 Alexander Mezin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef XRECORDKEYBOARDMONITOR_H +#define XRECORDKEYBOARDMONITOR_H + +#include +#include +#include + +#include +#include + +class XRecordKeyboardMonitor : public QObject +{ + Q_OBJECT + +public: + XRecordKeyboardMonitor(Display *display); + ~XRecordKeyboardMonitor(); + +Q_SIGNALS: + void keyboardActivityStarted(); + void keyboardActivityFinished(); + +private Q_SLOTS: + void processNextReply(); + +private: + void process(xcb_record_enable_context_reply_t *reply); + bool activity() const { return m_keysPressed && !m_modifiersPressed; } + + QSocketNotifier *m_notifier; + xcb_connection_t *m_connection; + xcb_record_context_t m_context; + xcb_record_enable_context_cookie_t m_cookie; + + QVector m_modifier, m_ignore, m_pressed; + int m_modifiersPressed, m_keysPressed; +}; + +#endif // XRECORDKEYBOARDMONITOR_H -- 2.11.0