diff options
Diffstat (limited to 'kmousetool')
26 files changed, 2769 insertions, 0 deletions
diff --git a/kmousetool/AUTHORS b/kmousetool/AUTHORS new file mode 100644 index 0000000..9b681c6 --- /dev/null +++ b/kmousetool/AUTHORS @@ -0,0 +1,24 @@ +Current maintainer: +Gunnar Schmidt <gunnar@schmi-dt.de>, 2003 + +Contributor: +Olaf Schmidt <ojschmidt@kde.org>, 2003 + + +KMouseTool was created by Jeff Roush <jeff@mousetool.com>, 2002 +Documentation initally written by Jeff Roush <jeff@mousetool.com>, 2002 + +The clever Smart Drag idea was suggested by Joe Betts. Thanks, Joe! + +The idea for MouseTool came to me when I was thinking about +head-tracking systems that allow you to move a cursor using +your head orientation, and then send clicks when you pause. +As far as I know, I was the first person to use this technique +with an ordinary mouse, but it is possible that I am wrong about that. +There are now other programs available for Windows and Macs that +do this; I know that some were developed after MouseTool, but +it is likely others came before. + +Other ideas in MouseTool for Windows that I hope to port to KDE were +either suggested by MouseTool users or came out of email discussions +with users. diff --git a/kmousetool/COPYING b/kmousetool/COPYING new file mode 100644 index 0000000..c13faf0 --- /dev/null +++ b/kmousetool/COPYING @@ -0,0 +1,340 @@ + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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) year 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. + + <signature of Ty Coon>, 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/kmousetool/ChangeLog b/kmousetool/ChangeLog new file mode 100644 index 0000000..86bfeaa --- /dev/null +++ b/kmousetool/ChangeLog @@ -0,0 +1,9 @@ +1-16-03 +Version 1.11: Stroke handling, several bug fixes. Uploaded to KDE CVS. +6-27-02 +Version 1.05: Added doc/ directory back to project. No other change in source. +6-21-02 +Version 1.01: increased maximum allowable value for Drag Time -- +now it is equal to the Dwell Time. +5-22-02 +Initial release, version 1.0 diff --git a/kmousetool/INSTALL b/kmousetool/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/kmousetool/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/kmousetool/Makefile.am b/kmousetool/Makefile.am new file mode 100644 index 0000000..c1dbee1 --- /dev/null +++ b/kmousetool/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = kmousetool diff --git a/kmousetool/README b/kmousetool/README new file mode 100644 index 0000000..c1863ac --- /dev/null +++ b/kmousetool/README @@ -0,0 +1,83 @@ +MouseTool is a program that clicks the mouse for you. + +I designed it to help relieve the pain that clicking mouse buttons can cause. + +For more information, see www.mousetool.com + + +How To Use MouseTool + +1 It's simple: MouseTool watches as you move the mouse. When you stop, it clicks. + +2 Practice with this. When you are comfortable with it, move on to Smart Drag. + +3 When Smart Drag is enabled, MouseTool pauses after it clicks down. If you + move the mouse, it waits until you stop moving before it clicks up. + This takes more practice, but if I can learn to do it without thinking, so can you. + +4 KMouseTool 1.1 supports strokes. When you enable strokes, a slow move to the + right and back, followed by a pause, will generate a right-click. A slow move + left and back will generate a double click. (Strokes are specified in + ~/.kde3/share/config/kmousetool_strokes.txt. This file is generated by KMouseTool + the first time it is run, but can be modified afterwards.) + +MouseTool Options: + +* Checkboxes: + Smart Drag -- enables or disables Smart Drag. Disabled is easier, so this is default. + Audible Click -- plays a sound when MouseTool clicks down. This helps, especially + with Smart Drag, but as of version 0.8, the latency is too high. + By the time you hear the click, you're doing something else. + This will be fixed in the next version. + Start with KDE -- When this is enabled, MouseTool will start each time KDE starts. + Enable Strokes -- When this is enabled, you can generate right- or double-clicks + using mouse strokes. + +* Times + Dwell Time -- The time you have to pause before MouseTool clicks. + Drag Time -- (When Smart Drag is enabled) the time MouseTool waits, after it clicks + down, before it clicks back up if you don't move the mouse. + Apply Times Button -- After changing either time, you must click this button. + +* Start Button -- Starts MouseTool. (Well, duh.) + When it says "stop", clicking it will stop MouseTool. (Duh, again.) + +* command line -- MouseTool has no command line options. + It does remembers its state when it is restarted, though. + +* Hotkeys -- None yet (as of version 1.1). They are very useful, though, and may be added. + + +Credit: + +The idea for MouseTool came to me when I was thinking about head-tracking +systems that allow you to move a cursor using your head orientation, and then +send clicks when you pause. As far as I know, I was the first person to use +this technique with an ordinary mouse, but it is quite possible that I am wrong +about that. There are now other programs available for Windows and Macs that +do this; I know that some were developed after MouseTool, but it is likely +others came before. + +If you know of another Linux- or Unix-based program that does this, please let +me know (at jeff@mousetool.com) + +The clever idea for Smart Drag was suggested by Joe Betts. Thanks, Joe! + +Other ideas in MouseTool for Windows that I hope to port to KDE were either +suggested by MouseTool users or came out of email discussions with users. + + + +Bugs and issues: +Emacs - Smart Drag and Emacs menus don't mix well; the menus don't stay visible + long enough to use. XEmacs seems to work fine. Gvim also works well. + +Taskbar - When you drag the taskbar using Smart Drag in KDE 2.x, kmousetool won't release + the drag. This can be scary if you're not expecting it, but simply clicking + the mouse button manually fixes the problem. KDE 3.x does not have this problem. + + This seems to be an issue with the internals of KDE or QT code, and similar + things happen in Windows. I haven't looked into it much under KDE, but on + Windows it happens when mousetool's timer stops while Windows waits for an + upclick, and the upclick never happens because the timer is stopped; + I'm sure the same thing is happening under KDE. diff --git a/kmousetool/TODO b/kmousetool/TODO new file mode 100644 index 0000000..7ec2ccc --- /dev/null +++ b/kmousetool/TODO @@ -0,0 +1,10 @@ +Currently version 1.11 + +For version 2.0: +Use mcop sound. +Context awareness +Visual click aid +Place on taskbar, remove window in desktop area +Hotkeys +Improve stroke handling + diff --git a/kmousetool/kmousetool.lsm b/kmousetool/kmousetool.lsm new file mode 100644 index 0000000..361c325 --- /dev/null +++ b/kmousetool/kmousetool.lsm @@ -0,0 +1,14 @@ +Begin3 +Title: KMouseTool +Version: 1.11 +Entered-date: 1/16/03 +Description: Clicks the mouse for you, reducing hand pain +Keywords: ergonomic, mouse, tendonitis, carpal tunnel syndrome +Author: Jeff Roush <jeff@mousetool.com> +Maintained-by: Jeff Roush <jeff@mousetool.com> +Primary-site: http://www.mousetool.com +Home-page: http://www.mousetool.com +Original-site: http://www.mousetool.com +Platforms: Linux and other Unices +Copying-policy: GNU Public License +End diff --git a/kmousetool/kmousetool/Makefile.am b/kmousetool/kmousetool/Makefile.am new file mode 100644 index 0000000..72c6a08 --- /dev/null +++ b/kmousetool/kmousetool/Makefile.am @@ -0,0 +1,29 @@ +bin_PROGRAMS = kmousetool + +kmousetool_SOURCES = kmousetoolui.ui mtstroke.cpp kmousetool.cpp main.cpp +kmousetool_LDADD = -lXtst $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) -lXext -lX11 $(LIBSOCKET) + +SUBDIRS = pics + +EXTRA_DIST = main.cpp version.h kmousetool.cpp kmousetool.h kmousetool.desktop mtstroke.cpp mtstroke.h mousetool_tap.wav + +kmousetooldir = $(kde_appsdir)/Applications +kmousetool_DATA = kmousetool.desktop + +sounddatadir = $(kde_datadir)/kmousetool/sounds +sounddata_DATA = mousetool_tap.wav + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +METASOURCES = AUTO + +# the library search path. +kmousetool_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/kmousetool.pot; \ + fi + diff --git a/kmousetool/kmousetool/Xmd_kmousetool.h b/kmousetool/kmousetool/Xmd_kmousetool.h new file mode 100644 index 0000000..2a35eb8 --- /dev/null +++ b/kmousetool/kmousetool/Xmd_kmousetool.h @@ -0,0 +1,201 @@ +/* $XFree86: xc/include/Xmd.h,v 3.9 2001/01/17 17:53:11 dawes Exp $ */ +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +All Rights Reserved. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +#ifndef XMD_H +#define XMD_H 1 +/* $Xorg: Xmd.h,v 1.3 2000/08/18 04:05:44 coskrey Exp $ */ +/* + * Xmd.h: MACHINE DEPENDENT DECLARATIONS. + */ + +/* + * Special per-machine configuration flags. + */ +#ifdef CRAY +#define WORD64 /* 64-bit architecture */ +#endif +#if defined(__alpha) || defined(__alpha__) || \ + defined(__ia64__) || defined(ia64) +#define LONG64 /* 32/64-bit architecture */ +#endif +#ifdef __sgi +#if (_MIPS_SZLONG == 64) +#define LONG64 +#endif +#endif + +/* + * Stuff to handle large architecture machines; the constants were generated + * on a 32-bit machine and must coorespond to the protocol. + */ +#ifdef WORD64 +#define MUSTCOPY +#endif /* WORD64 */ + + +/* + * Definition of macro used to set constants for size of network structures; + * machines with preprocessors that can't handle all of the sz_ symbols + * can define this macro to be sizeof(x) if and only if their compiler doesn't + * pad out structures (esp. the xTextElt structure which contains only two + * one-byte fields). Network structures should always define sz_symbols. + * + * The sz_ prefix is used instead of something more descriptive so that the + * symbols are no more than 32 characters long (which causes problems for some + * compilers and preprocessors). + * + * The extra indirection in the __STDC__ case is to get macro arguments to + * expand correctly before the concatenation, rather than afterward. + */ +#if ((defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)) && !defined(UNIXCPP)) || defined(ANSICPP) +#define _SIZEOF(x) sz_##x +#define SIZEOF(x) _SIZEOF(x) +#else +#define SIZEOF(x) sz_/**/x +#endif /* if ANSI C compiler else not */ + +/* + * Bitfield suffixes for the protocol structure elements, if you + * need them. Note that bitfields are not guarranteed to be signed + * (or even unsigned) according to ANSI C. + */ +#ifdef WORD64 +typedef long INT64; +typedef unsigned long CARD64; +#define B32 :32 +#define B16 :16 +#ifdef UNSIGNEDBITFIELDS +typedef unsigned int INT32; +typedef unsigned int INT16; +#else +#ifdef __STDC__ +typedef signed int INT32; +typedef signed int INT16; +#else +typedef int INT32; +typedef int INT16; +#endif +#endif +#else +#define B32 +#define B16 +#ifdef LONG64 +//typedef long INT64; +typedef int INT32; +#else +//typedef long INT32; +#endif +typedef short INT16; +#endif + +#if defined(__STDC__) || defined(sgi) || defined(AIXV3) +typedef signed char INT8; +#else +typedef char INT8; +#endif + +#ifdef LONG64 +typedef unsigned long CARD64; +typedef unsigned int CARD32; +#else +typedef unsigned long CARD32; +#endif +typedef unsigned short CARD16; +typedef unsigned char CARD8; + +typedef CARD32 BITS32; +typedef CARD16 BITS16; + +#ifndef __EMX__ +typedef CARD8 BYTE; +typedef CARD8 BOOL; +#else /* __EMX__ */ +/* + * This is bad style, but the central include file <os2.h> declares them + * as well + */ +#define BYTE CARD8 +#define BOOL CARD8 +#endif /* __EMX__ */ + +/* + * definitions for sign-extending bitfields on 64-bit architectures + */ +#if defined(WORD64) && defined(UNSIGNEDBITFIELDS) +#define cvtINT8toInt(val) (((val) & 0x00000080) ? ((val) | 0xffffffffffffff00) : (val)) +#define cvtINT16toInt(val) (((val) & 0x00008000) ? ((val) | 0xffffffffffff0000) : (val)) +#define cvtINT32toInt(val) (((val) & 0x80000000) ? ((val) | 0xffffffff00000000) : (val)) +#define cvtINT8toShort(val) cvtINT8toInt(val) +#define cvtINT16toShort(val) cvtINT16toInt(val) +#define cvtINT32toShort(val) cvtINT32toInt(val) +#define cvtINT8toLong(val) cvtINT8toInt(val) +#define cvtINT16toLong(val) cvtINT16toInt(val) +#define cvtINT32toLong(val) cvtINT32toInt(val) +#else +#define cvtINT8toInt(val) (val) +#define cvtINT16toInt(val) (val) +#define cvtINT32toInt(val) (val) +#define cvtINT8toShort(val) (val) +#define cvtINT16toShort(val) (val) +#define cvtINT32toShort(val) (val) +#define cvtINT8toLong(val) (val) +#define cvtINT16toLong(val) (val) +#define cvtINT32toLong(val) (val) +#endif /* WORD64 and UNSIGNEDBITFIELDS */ + + + +#ifdef MUSTCOPY +/* + * This macro must not cast or else pointers will get aligned and be wrong + */ +#define NEXTPTR(p,t) (((char *) p) + SIZEOF(t)) +#else /* else not MUSTCOPY, this is used for 32-bit machines */ +/* + * this version should leave result of type (t *), but that should only be + * used when not in MUSTCOPY + */ +#define NEXTPTR(p,t) (((t *)(p)) + 1) +#endif /* MUSTCOPY - used machines whose C structs don't line up with proto */ + +#endif /* XMD_H */ diff --git a/kmousetool/kmousetool/kmousetool.cpp b/kmousetool/kmousetool/kmousetool.cpp new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/kmousetool/kmousetool/kmousetool.cpp @@ -0,0 +1,641 @@ +/*************************************************************************** + kmousetool.cpp - description + ------------------- + begin : Sun Jan 20 23:27:58 PST 2002 + copyright : (C) 2002-2003 by Jeff Roush + email : jeff@mousetool.com + copyright : (C) 2003 by Olaf Schmidt + email : ojschmidt@kde.org + copyright : (C) 2003 by Gunnar Schmi Dt + email : gunnar@schmi-dt.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include "Xmd_kmousetool.h" +#include "kmousetool.h" +#include "kmousetool.moc" +#include <kconfig.h> +#include <X11/Intrinsic.h> /* Intrinsics Definitions*/ +#include <X11/StringDefs.h> /* Standard Name-String definitions*/ +#include <X11/extensions/xtestext1.h> /* Standard Name-String definitions*/ +#include <X11/extensions/XTest.h> /* Standard Name-String definitions*/ +#include <kdialog.h> +#include <klocale.h> +#include <qpushbutton.h> +#include <qpoint.h> +#include <qnamespace.h> +#include <kmessagebox.h> +#include <kaudioplayer.h> +#include <kstandarddirs.h> +#include <qsound.h> +#include <kglobalsettings.h> +#include <kdebug.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qcheckbox.h> +#include <ksystemtray.h> +#include <kiconloader.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <knuminput.h> +#include <kpopupmenu.h> +#include <kaboutapplication.h> + +//#include <arts/soundserver.h> +#include <netwm.h> + +#include <iostream> + +#include "mtstroke.h" + +//using namespace Arts; + +int currentXPosition; +int currentYPosition; + +//using namespace std; + +#undef long + +/** +* Gnarly X functions +*/ +void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask); +int CursorHasMoved(int minMovement); +void LeftClick(); +void RightClick(); +void DoubleClick(); +void LeftDn(); +void LeftUp(); + +// Declarations +Display *display; + +//SimpleSoundServer sound_server(Reference("global:Arts_SimpleSoundServer")); + + +void KMouseTool::init_vars() +{ + continue_timer = 1; + tick_count = 0; + max_ticks = dwell_time+1; + mouse_is_down = FALSE; + + loadOptions(); + + // If the ~/.mousetool directory doesn't exist, create it +// mSoundFileName = QDir::homeDirPath(); + mSoundFileName = locate("appdata", "sounds/mousetool_tap.wav"); + mplayer = new KAudioPlayer(mSoundFileName); + + + // find application file + appfilename = locate("exe", "kmousetool"); + + // find the user's autostart directory + autostartdirname = KGlobalSettings::autostartPath(); + + // SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer")); +// sound_server(Reference("global:Arts_SimpleSoundServer")); + + QDesktopWidget *d = QApplication::desktop(); + int w = d->width(); + int h = d->height(); + MTStroke::setUpperLeft(0,0); + MTStroke::setUpperRight(w-1,0); + MTStroke::setLowerLeft(0,h-1); + MTStroke::setLowerRight(w-1,h-1); +} + +void KMouseTool::resetSettings() +{ + cbDrag ->setChecked(smart_drag_on); + cbStart->setChecked(isAutostart()); + cbClick->setChecked(playSound); + cbStroke->setChecked(strokesEnabled); + movementEdit->setValue(min_movement); + dwellTimeEdit->setValue(dwell_time); + dragTimeEdit->setValue(drag_time); + settingsChanged(); +} + +void KMouseTool::setDefaultSettings() +{ + cbDrag ->setChecked(false); + cbStart->setChecked(false); + cbClick->setChecked(false); + cbStroke->setChecked(false); + movementEdit->setValue(5); + dwellTimeEdit->setValue(5); + dragTimeEdit->setValue(3); + settingsChanged(); +} + + +void KMouseTool::timerEvent( QTimerEvent * ) +{ + if (!mousetool_is_running) + return; + + if (!continue_timer) { + killTimers(); + return; + } + + max_ticks = dwell_time + drag_time; + stroke.addPt(currentXPosition, currentYPosition); + + moving = moving?CursorHasMoved(1):CursorHasMoved(min_movement); + if (moving) { + if (mousetool_just_started) { + mousetool_just_started = false; + tick_count = max_ticks; + } + else + tick_count = 0; + return; + } + + if (tick_count<max_ticks) + tick_count++; + + + // If the mouse has paused ... + if (tick_count==dwell_time) { + int strokeType = stroke.getStrokeType(); + + // if we're dragging the mouse, ignore stroke type + if (mouse_is_down) { + normalClick(); + return; + } + + if (!strokesEnabled) { + normalClick(); + return; + } + if (strokeType == MTStroke::DontClick) + return; + if (strokeType==MTStroke::bumped_mouse) + return; + + if (strokeType==MTStroke::RightClick || strokeType==MTStroke::UpperRightStroke) + RightClick(); + else if (strokeType==MTStroke::DoubleClick || strokeType==MTStroke::LowerLeftStroke) + DoubleClick(); + else + normalClick(); + } +} + +void KMouseTool::normalClick() +{ + if (smart_drag_on) { + if (!mouse_is_down) { + LeftDn(); + mouse_is_down = TRUE; + tick_count = 0; + playTickSound(); + } + else if (mouse_is_down) { + LeftUp(); + mouse_is_down = FALSE; + tick_count = max_ticks; + } + } + else { + // not smart_drag_on + LeftClick(); + playTickSound(); + } +} + +// This function isn't happy yet. +void KMouseTool::playTickSound() +{ + if (!playSound) + return; + + mplayer->play(); + // This is a bit slow. +// KAudioPlayer::play(mSoundFileName); + return; + + // the solution seems to be to use MCOP, + // but SimpleSoundServer is not cooperating + + // When using the following code, make sure to link with + // Put " -lsoundserver_idl" in the linker options in KDevelop. + +// SimpleSoundServer server = SimpleSoundServer::_fromString("global:Arts_SimpleSoundServer"); +// SimpleSoundServer *ss = new SimpleSoundServer(Reference("global:Arts_SimpleSoundServer")); +// SimpleSoundServer sound_server2(Reference("global:Arts_SimpleSoundServer")); + +// if(sound_server.isNull()) +// return; +// sound_server.play(mSoundFileName.latin1()); + + // Another approach is to try using QSound. + // QSound depends on Network Audio Server, which doesn't seem to work on my Debian Woody system. + // I haven't spent much time working on it, though. +// QSound::play(mSoundFileName); +} + +KMouseTool::KMouseTool(QWidget *parent, const char *name) : KMouseToolUI(parent, name) +{ + init_vars(); + resetSettings(); + + connect(movementEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged())); + connect(dwellTimeEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged())); + connect(dragTimeEdit, SIGNAL(valueChanged(int)), this, SLOT(settingsChanged())); + connect(cbDrag, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged())); + connect(cbStroke, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged())); + connect(cbClick, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged())); + connect(cbStart, SIGNAL(stateChanged(int)), this, SLOT(settingsChanged())); + + connect(buttonStartStop, SIGNAL(clicked()), this, SLOT(startStopSelected())); + buttonDefault->setGuiItem(KStdGuiItem::defaults()); + connect(buttonDefault, SIGNAL(clicked()), this, SLOT(defaultSelected())); + connect(buttonReset, SIGNAL(clicked()), this, SLOT(resetSelected())); + buttonApply->setGuiItem(KStdGuiItem::apply()); + connect(buttonApply, SIGNAL(clicked()), this, SLOT(applySelected())); + buttonHelp->setGuiItem(KStdGuiItem::help()); + connect(buttonHelp, SIGNAL(clicked()), this, SLOT(helpSelected())); + buttonClose->setGuiItem(KStdGuiItem::close()); + connect(buttonClose, SIGNAL(clicked()), this, SLOT(closeSelected())); +#if KDE_VERSION >= KDE_MAKE_VERSION (3,1,90) + buttonQuit->setGuiItem(KStdGuiItem::quit()); +#endif // KDE 3.2 + connect(buttonQuit, SIGNAL(clicked()), this, SLOT(quitSelected())); + + // When we first start, it's nice to not click immediately. + // So, tell MT we're just starting + mousetool_just_started = true; + + startTimer(100); + trayIcon = new KMouseToolTray (this, "systemTrayIcon"); + updateStartStopText (); + connect(trayIcon, SIGNAL(startStopSelected()), this, SLOT(startStopSelected())); + connect(trayIcon, SIGNAL(configureSelected()), this, SLOT(configureSelected())); + connect(trayIcon, SIGNAL(aboutSelected()), this, SLOT(aboutSelected())); + connect(trayIcon, SIGNAL(helpSelected()), this, SLOT(helpSelected())); + connect(trayIcon, SIGNAL(quitSelected()), this, SLOT(quitSelected())); + + aboutDlg = new KAboutApplication (0, "KMouseToolDlg", false); +} + +KMouseTool::~KMouseTool() +{ +} + +// ********************************************************* +// Raw X functions +// Begin mouse monitoring and event generation code. +// these should be moved to a separate file. +void LeftClick() +{ + XTestFakeButtonEvent(display, 1, TRUE, 0); + XTestFakeButtonEvent(display, 1, FALSE, 0); +} + +void DoubleClick() +{ + XTestFakeButtonEvent(display, 1, TRUE, 0); + XTestFakeButtonEvent(display, 1, FALSE, 100); + XTestFakeButtonEvent(display, 1, TRUE, 200); + XTestFakeButtonEvent(display, 1, FALSE, 300); +} + +void RightClick() +{ + XTestFakeButtonEvent(display, 3, TRUE, 0); + XTestFakeButtonEvent(display, 3, FALSE, 0); +} + + +void LeftDn() +{ + XTestFakeButtonEvent(display, 1, TRUE, 0); +} + + +void LeftUp() +{ + XTestFakeButtonEvent(display, 1, FALSE, 0); +} + + +void queryPointer(Window *pidRoot, int *pnRx, int *pnRy, int *pnX, int *pnY, unsigned int *puMask) +{ + Window id2, idRoot; + int screen_num; + + screen_num = DefaultScreen(display); + idRoot = RootWindow(display,screen_num); + XQueryPointer(display, idRoot, &idRoot, &id2, pnRx, pnRy, pnX, pnY, puMask); + + *pidRoot = idRoot; +} + +// return 1 if cursor has moved, 0 otherwise +int CursorHasMoved (int minMovement) +{ + static int nOldRootX = -1; + static int nOldRootY = -1; + +// XEvent evButtonEvent; + Window idRootWin; + int nRootX, nRootY, nWinX, nWinY; + unsigned int uintMask; + + queryPointer(&idRootWin, &nRootX, &nRootY, &nWinX, &nWinY, &uintMask); + + int nRes = 0; + if ((nRootX>nOldRootX?nRootX-nOldRootX:nOldRootX-nRootX) >= minMovement) + nRes = 1; + if ((nRootY>nOldRootY?nRootY-nOldRootY:nOldRootY-nRootY) >= minMovement) + nRes = 1; + + currentXPosition = nRootX; + currentYPosition = nRootY; + + if (nRes) { + nOldRootX = nRootX; + nOldRootY = nRootY; + } + + return nRes; +} +// End mouse monitoring and event creation code + + +bool KMouseTool::isAutostart() +{ + QString sym = autostartdirname; + sym += "kmousetool"; // sym is now full path to symlink + QFileInfo fi(sym); + + return fi.exists(); +} + +void KMouseTool::setAutostart (bool start) +{ + QString sym = autostartdirname; + sym += "kmousetool"; // sym is now full path to symlink + QFileInfo fi(sym); + QString cmd; + + if (start) { + if (!fi.exists()) // if it doesn't exist, make it + cmd.sprintf("ln -s %s %s", appfilename.latin1(), autostartdirname.latin1()); + } + else { + if (fi.exists()) // if it exists, delete it + cmd.sprintf("rm -f %s", sym.latin1()); + } + system(cmd.ascii()); +} + +bool KMouseTool::applySettings() +{ + int drag, dwell; + + dwell = dwellTimeEdit->value(); + drag = dragTimeEdit->value() ; + + // The drag time must be less than the dwell time + if ( dwell < drag) { + KMessageBox::sorry(this, i18n("The drag time must be less than or equal to the dwell time."), i18n("Invalid Value")); + return false; + } + + // if we got here, we must be okay. + min_movement = movementEdit->value(); + smart_drag_on = cbDrag->isChecked(); + playSound = cbClick->isChecked(); + strokesEnabled = cbStroke->isChecked(); + setAutostart (cbStart->isChecked()); + + dwell_time = dwell; + drag_time = drag; + tick_count = max_ticks; + + saveOptions(); + settingsChanged(); + return true; +} + +// Save options to kmousetoolrc file +void KMouseTool::loadOptions() +{ + kapp->config()->setGroup("UserOptions"); + + playSound = kapp->config()->readBoolEntry("AudibleClick",false); + smart_drag_on = kapp->config()->readBoolEntry("SmartDrag",false); + + dwell_time = kapp->config()->readNumEntry("DwellTime",5); + drag_time = kapp->config()->readNumEntry("DragTime",3); + min_movement = kapp->config()->readNumEntry("Movement",5); + strokesEnabled = kapp->config()->readBoolEntry("strokesEnabled",false); + + QPoint p; + int x = kapp->config()->readNumEntry("x",0); + int y = kapp->config()->readNumEntry("y",0); + p.setX(x); + p.setY(y); + move(p); + + mousetool_is_running = kapp->config()->readBoolEntry("MouseToolIsRunning",false); + display = XOpenDisplay(NULL); +} + +// Save options to kmousetoolrc file +void KMouseTool::saveOptions() +{ + QPoint p = pos(); + int x = p.x(); + int y = p.y(); + + kapp->config()->setGroup("ProgramOptions"); + kapp->config()->writeEntry("Version", KMOUSETOOL_VERSION); + kapp->config()->setGroup("UserOptions"); + kapp->config()->writeEntry("x", x); + kapp->config()->writeEntry("y", y); + kapp->config()->writeEntry("strokesEnabled", strokesEnabled); + kapp->config()->writeEntry("IsMinimized", isHidden()); + kapp->config()->writeEntry("DwellTime", dwell_time); + kapp->config()->writeEntry("DragTime", drag_time); + kapp->config()->writeEntry("Movement", min_movement); + kapp->config()->writeEntry("SmartDrag", smart_drag_on); + kapp->config()->writeEntry("AudibleClick", playSound); + kapp->config()->writeEntry("MouseToolIsRunning", mousetool_is_running); + kapp->config()->sync(); +} + +void KMouseTool::updateStartStopText() +{ + if (mousetool_is_running) + buttonStartStop->setText(i18n("&Stop")); + else + buttonStartStop->setText(i18n("&Start")); + trayIcon->updateStartStopText(mousetool_is_running); +} + +bool KMouseTool::newSettings() +{ + return ((dwell_time != dwellTimeEdit->value()) || + (drag_time != dragTimeEdit->value()) || + (min_movement != movementEdit->value()) || + (smart_drag_on != cbDrag->isChecked()) || + (playSound != cbClick->isChecked()) || + (strokesEnabled != cbStroke->isChecked()) || + (isAutostart() != cbStart->isChecked())); +} + +bool KMouseTool::defaultSettings() +{ + return ((5 == dwellTimeEdit->value()) && + (3 == dragTimeEdit->value()) && + (5 == movementEdit->value()) && + !cbDrag->isChecked() && + !cbClick->isChecked() && + !cbStroke->isChecked() && + !cbStart->isChecked()); +} + +/******** SLOTS **********/ + +// Value or state changed +void KMouseTool::settingsChanged () +{ + buttonReset->setEnabled (newSettings()); + buttonApply->setEnabled (newSettings()); + buttonDefault->setDisabled (defaultSettings()); +} + +// Buttons within the dialog +void KMouseTool::startStopSelected() +{ + mousetool_is_running = !mousetool_is_running; + updateStartStopText(); +} + +void KMouseTool::defaultSelected() +{ + setDefaultSettings(); +} + +void KMouseTool::resetSelected() +{ + resetSettings(); +} + +void KMouseTool::applySelected() +{ + applySettings(); +} + +// Buttons at the bottom of the dialog +void KMouseTool::helpSelected() +{ + kapp->invokeHelp(); +} + +void KMouseTool::closeSelected() +{ + if (newSettings()) + { + int answer = KMessageBox::questionYesNoCancel (this, + i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before closing the configuration window or discard the changes?"), + i18n("Closing Configuration Window"), + KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave"); + if (answer == KMessageBox::Yes) + applySettings(); + else if (answer == KMessageBox::No) + resetSettings(); + if (answer != KMessageBox::Cancel) + hide(); + } + else + hide(); +} + +void KMouseTool::quitSelected() +{ + if (newSettings()) + { + int answer = KMessageBox::questionYesNoCancel (this, + i18n("There are unsaved changes in the active module.\nDo you want to apply the changes before quitting KMousetool or discard the changes?"), + i18n("Quitting KMousetool"), + KStdGuiItem::apply(), KStdGuiItem::discard(), "AutomaticSave"); + if (answer == KMessageBox::Yes) + applySettings(); + if (answer != KMessageBox::Cancel) + { + saveOptions(); + kapp->quit(); + } + } + else + { + saveOptions(); + kapp->quit(); + } +} + +// Menu functions +void KMouseTool::configureSelected() +{ + show(); + raise(); + setActiveWindow(); +} + +void KMouseTool::aboutSelected() +{ + aboutDlg->show(); +} + + + +KMouseToolTray::KMouseToolTray (QWidget *parent, const char *name) : KSystemTray (parent, name) +{ + startStopId = contextMenu()->insertItem (i18n("&Start"), this, SIGNAL(startStopSelected())); + contextMenu()->insertSeparator(); + contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("configure", KIcon::Small), + i18n("&Configure KMouseTool..."), this, SIGNAL(configureSelected())); + contextMenu()->insertSeparator(); + contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("contents", KIcon::Small), + i18n("KMousetool &Handbook"), this, SIGNAL(helpSelected())); + contextMenu()->insertItem (KGlobal::iconLoader()->loadIcon("kmousetool", KIcon::Small), + i18n("&About KMouseTool"), this, SIGNAL(aboutSelected())); +} + +KMouseToolTray::~KMouseToolTray() { +} + +void KMouseToolTray::updateStartStopText(bool mousetool_is_running) +{ + QPixmap icon; + + if (mousetool_is_running) { + contextMenu()->changeItem (startStopId, i18n("&Stop")); + icon = KGlobal::iconLoader()->loadIcon("kmousetool_on", KIcon::Small); + } + else { + contextMenu()->changeItem (startStopId, i18n("&Start")); + icon = KGlobal::iconLoader()->loadIcon("kmousetool_off", KIcon::Small); + } + setPixmap (icon); + show(); +} diff --git a/kmousetool/kmousetool/kmousetool.desktop b/kmousetool/kmousetool/kmousetool.desktop new file mode 100644 index 0000000..1517c3f --- /dev/null +++ b/kmousetool/kmousetool/kmousetool.desktop @@ -0,0 +1,138 @@ +# KDE Config File +[Desktop Entry] +Type=Application +Exec=kmousetool -caption "%c" %i %m +Icon=kmousetool +DocPath=kmousetool/index.html +Comment=Clicks the mouse for you, reducing the effects of RSI +Comment[ar]=ينقر على الفأرة بدلا منك، مُخَفِّفاً عنك آلام RSI +Comment[bg]=Автоматично щракване с бутона на мишката +Comment[bs]=Klika mišem za vas, smanjujući efekte RSI-ja +Comment[ca]=Fa els clics del ratolí, reduint els efectes del RSI (índex de força relativa) +Comment[cs]=Kliká za vás myší, omezuje tak efekt RSI +Comment[cy]=Clicio'r llygoden i chi, wrth esmwytho effeithiau RSI +Comment[da]=Klikker på musen for dig, reducerer virkningen af RSI-smerte +Comment[de]=Führt Mausklicks für Sie aus +Comment[el]=Ενεργεί τα κλικ του ποντικιού για σας, μειώνοντας τις επιδράσεις των τραυμάτων από τη συνεχή επανάληψη (RSI) +Comment[eo]=Klakas la muson por vi, tio reduktas la efekton de RSI +Comment[es]=Pulsa los botones del ratón por usted, reduciendo los efectos de RSI +Comment[et]=Klõpsab hiirt sinu eest, vähendades võimalike lihasevalude ohtu +Comment[eu]=Sagua zure ordez klikatzen du, RSI-aren efektuak gutxitzeko +Comment[fa]=موشی را برایتان فشار میدهد، اثرات RSI را کاهش میدهد +Comment[fi]=Napsauttaa hiirtä puolestasi rannevammojen ehkäisemiseksi +Comment[fr]=Clique sur la souris à votre place, limitant les douleurs liées aux TMS +Comment[ga]=Cliceálann seo an luch duit, chun tionchar gortú athstraidhneála a laghdú +Comment[gl]=Preme o rato por ti, reducindo os efeitos da RSI +Comment[he]=לוחץ על העכבר עבורך, ובכך מקל על פרק היד +Comment[hi]=आपके लिए माउस क्लिक करता है, बार-बार क्लिक के कारण ऊंगलियों में होने वाली क्षति को कम करता है +Comment[hu]=Automatikus egérkattintás (RSI-szindrómában szenvedőknek) +Comment[is]=Smellir músarhnöppunum fyrir þig og dregur úr áhrifum RSI +Comment[it]=Fa clic sul mouse al posto tuo, riducendo gli effetti della RSI +Comment[ja]=RSI (反復運動過多損傷) を防ぐために、あなたの代わりにマウスをクリック +Comment[ka]=დაწკაპავს თაგუნას თქვენს მაგივრად, ამცირებს RSI ეფექტებს +Comment[km]=ចុចកណ្ដុរឲ្យអ្នក ដែលកាត់បន្ថយបែបផែនរបស់ RSI +Comment[lt]=Nuspaudžia pelės klavišą, sumažindamas skausmo sindromą +Comment[ms]=Mengklik tetikus untuk anda, mengurangkan kesan RSI +Comment[mt]=Jikklikkjalek il-maws, biex tevita wġigħ RSI +Comment[nb]=Trykker museknappen for deg, gir mindre musesyke +Comment[nds]=Klickt de Muus för Di, minnert de Effekten vun RSI af +Comment[ne]=तपाईँका लागि RSI को प्रभाव घटाएर माउस क्लिक गर्छ +Comment[nl]=Klikt de muisknop voor u, vermindert de effecten van RSI +Comment[nn]=Klikkar med musa for deg, for å hindra belastningsskadar +Comment[pa]=ਮਾਊਸ ਨੂੰ ਦਬਾਉਣ ਨਾਲ ਤੁਹਾਡੇ ਲਈ RSI ਪਰਭਾਵ ਘੱਟ ਜਾਵੇਗਾ +Comment[pl]=Klika za Ciebie myszą, ograniczając nadwyrężanie mięśni +Comment[pt]=Carrega no rato por si, aliviando dores motivadas por RSI +Comment[pt_BR]= Clica o mouse para você, facilitando a dificuldade do RSI +Comment[ro]=Execută clicuri pentru dumneavoastră, reducînd oboseala mîinii +Comment[ru]=Утилита управления мышью для облегчения болевых синдромов +Comment[sk]=Kliká za vás myšou, uľahčuje bolesti RSI +Comment[sl]=Za vas klika miško, da vam olajša bolečine v zapestju +Comment[sr]=Кликће мишем за вас, умањујући вам болове у зглобу +Comment[sr@Latn]=Klikće mišem za vas, umanjujući vam bolove u zglobu +Comment[sv]=Klickar musen åt dig, för att mildra smärta från musarm +Comment[ta]=Clicks the mouse for you, reducing the effects of RSI RSI +Comment[tg]=Зер кардани муш барои шумо, бо камшавии таъсирҳои RSI +Comment[th]=คลิ้กเม้าส์สำหรับคุณเพื่อลดความเสียงต่อการเป็นโรค RSI +Comment[tr]=RSI özelliklerini azaltarak sizin için fareyi tıklar +Comment[uk]=Клацає мишкою для вас для полегшення відчуття болі в зап'ясті +Comment[vi]=Ấn chuột giúp bạn, giảm tác động của RSI +Comment[zh_CN]=为您点击鼠标,减轻肢体重复性劳损(RSI)效应 +Comment[zh_TW]=為您點擊滑鼠, 減少重複施緊傷害(RSI)的影響 +Terminal=false +Name=KMouseTool +Name[cy]=KErfynLlygoden +Name[eo]=Kmusilo +Name[hi]=के-माउस टूल +Name[km]= KMouseTool +Name[ne]=केडीई माउस उपकरण +Name[pa]=ਕੇ ਮਾਊਸ ਸੰਦ +Name[ro]=Utilitar mouse +Name[sv]=Kmousetool +Name[ta]=கே சுட்டிக்கருவி +Name[tg]=Асбоби КМуш +Name[th]=ปรับแต่งเม้าส์ - K +Name[tr]=Kmousetool +Name[uz]=Sichqoncha vositasi +Name[uz@cyrillic]=Сичқонча воситаси +Name[vi]=Công cụ Chuột KDE +Name[zh_CN]=K 鼠标工具 +Name[zh_TW]=K-滑鼠工具 +GenericName=Automatic Mouse Click +GenericName[ar]=نقر الفأرة التلقائي +GenericName[bg]=Инструмент за мишката +GenericName[bs]=Automatsko klikanje mišem +GenericName[ca]=Clic automàtic del ratolí +GenericName[cs]=Automatické klikání myší +GenericName[cy]=Clic Llygoden Ymysgogol +GenericName[da]=Automatisk museklik +GenericName[de]=Automatische Mausklicks +GenericName[el]=Αυτόματο κλικ ποντικιού +GenericName[eo]=Aŭtomata Musklako +GenericName[es]=Pulsación automática del ratón +GenericName[et]=Hiire automaatne klõpsaja +GenericName[eu]=Saguaren klik automatikoak +GenericName[fa]=فشار خودکار موشی +GenericName[fi]=Automaattinen hiirennapsautus +GenericName[fr]=Clic de souris automatique +GenericName[ga]=Cliceáil uathoibríoch luiche +GenericName[gl]=Preme o rato automaticamente +GenericName[he]=לחיצת עכבר אוטומטית +GenericName[hi]=स्वचालित माउस क्लिक +GenericName[hu]=Automatikus kattintás +GenericName[is]=Sjálfvirkur músahnappasmellir +GenericName[it]=Clic automatico del mouse +GenericName[ja]=自動マウスクリック +GenericName[ka]=თაგუნას ავტომატური წკაპი +GenericName[km]= ចុចកណ្តុរដោយស្វ័យប្រវត្តិ +GenericName[lt]=Automatiniai pelės paspaudimai +GenericName[mk]=Автоматско кликнување на глушецот +GenericName[ms]=Klik Tetikus Automatik +GenericName[mt]=Klikk tal-Maws Awtomatiku +GenericName[nb]=Automatisk museklikk +GenericName[nds]=Automaatsche Muusklicks +GenericName[ne]=स्वचालित माउस क्लिक +GenericName[nl]=Automatische muisklik +GenericName[nn]=Automatisk museklikk +GenericName[pa]=ਐਟੋਮੈਟਿਕ ਮਾਊਸ ਕਲਿੱਕ +GenericName[pl]=Automatyczne klikanie myszą +GenericName[pt]=Carregar no Rato +GenericName[pt_BR]=Clique Automático do Mouse +GenericName[ro]=Clic automat de mouse +GenericName[ru]=Автощелчок мышью +GenericName[sk]=Automatické klikanie myšou +GenericName[sl]=Samodejni klik miške +GenericName[sr]=Аутоматски клик мишем +GenericName[sr@Latn]=Automatski klik mišem +GenericName[sv]=Automatiska musklick +GenericName[ta]=தானியங்கி சுட்டி சொடுக்கல் +GenericName[tg]=Зер кардани автоматии муш +GenericName[th]=คลิ้กเม้าส์อัตโนมัติ +GenericName[tr]=Otomatik Fare Tıklaması +GenericName[uk]=Автоматичне клацання мишкою +GenericName[uz]=Sichqonchani avto-bosish +GenericName[uz@cyrillic]=Сичқончани авто-босиш +GenericName[vi]=Ấn Chuột Tự động +GenericName[zh_CN]=自动鼠标点击 +GenericName[zh_TW]=自動滑鼠點擊 +Categories=Qt;KDE;Utility;Accessibility; + diff --git a/kmousetool/kmousetool/kmousetool.h b/kmousetool/kmousetool/kmousetool.h new file mode 100644 index 0000000..88a05ec --- /dev/null +++ b/kmousetool/kmousetool/kmousetool.h @@ -0,0 +1,209 @@ +/*************************************************************************** + kmousetool.h - description + ------------------- + begin : Sun Jan 20 23:27:58 PST 2002 + copyright : (C) 2002-2003 by Jeff Roush + email : jeff@mousetool.com + copyright : (C) 2003 by Olaf Schmidt + email : ojschmidt@kde.org + copyright : (C) 2003 by Gunnar Schmi Dt + email : gunnar@schmi-dt.de + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef KMOUSETOOL_H +#define KMOUSETOOL_H + +#include <qdir.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "version.h" + +#include <kapplication.h> +#include <ksystemtray.h> +#include <qwidget.h> +#include "mtstroke.h" +#include "kmousetoolui.h" + +class QLineEdit; +class QLabel; +class QCheckBox; +class QPushButton; +class KAudioPlayer; +class KAboutApplication; +class KMouseToolTray; + + +/** + * KMouseTool is the base class of the project + * + * It is the main widget for the dialog + * + */ + +class KMouseTool : public KMouseToolUI +{ + Q_OBJECT + +private: + MTStroke stroke; + + // boolean flags to keep track of program states + int mouse_is_down; + int continue_timer; + int tick_count; + int dwell_time; + int drag_time; + int max_ticks; + int min_movement; + bool smart_drag_on; + bool playSound; + bool mousetool_is_running; + bool mousetool_just_started; + bool moving; + bool strokesEnabled; + + QString autostartdirname; + QString rcfilename; + QString appfilename; + QString mSoundFileName; + KAudioPlayer *mplayer; + KMouseToolTray *trayIcon; + + KAboutApplication *aboutDlg; + + /** + * Initialize all variables + */ + void init_vars(); + + /** + * Take care of details of playing .wav file + * + * Currently uses KAudioPlayer::play(), which has an annoying delay. + * + * The solution seems to be to use MCOP, but I haven't been able to get that to work yet. + */ + void playTickSound(); + + /** + * Load state of program from "kmousetool.rc" in the user's local .kde folder, + * + */ + void loadOptions(); + + /** + * Save state of program under the user's local .kde folder, + * in a file named "kmousetool.rc" + * + */ + void saveOptions(); + + /** + * This function changes text on button depending on + * state of time (either "start", or "stop"). + **/ + void updateStartStopText(); + + /** + * Returns true if the current values in the settings window are different + * from the settings currently used + **/ + bool newSettings(); + + /** + * Returns true if the current values in the settings window are identical + * with the default settings + **/ + bool defaultSettings(); + + /** + * Resets the values in the settings window to the settings currently used + **/ + void resetSettings(); + + /** + * Sets the values in the settings window to the default settings + **/ + void setDefaultSettings(); + + /** + * Applies the current values in the settings window + **/ + bool applySettings(); + + bool isAutostart(); + void setAutostart (bool start); + +public slots: + /** + * This slot is called whenever a value in the settings window was changed. + * It enabled and disables the three buttons "Defaults", "Reset" and "Apply". + **/ + void settingsChanged(); + + void startStopSelected(); + + void defaultSelected(); + void resetSelected(); + void applySelected(); + + void helpSelected(); + void closeSelected(); + void quitSelected(); + + void aboutSelected(); + void configureSelected(); + +public: + /** + * This function runs the show; it is called once every + * 1/10 second. + * + * It checks to see if SmartDrag is on, and compares the + * current mouse position to its previous position to see + * whether to send a down click, and up click, or wait. + */ + void timerEvent (QTimerEvent *e); + + /** + * This generates a normal click event -- + * down, up, or down-up, depending on smart-drag settings and current state + */ + void normalClick(); + + /** + * construtor + */ + KMouseTool(QWidget* parent=0, const char *name=0); + + /** destructor */ + ~KMouseTool(); +}; + +class KMouseToolTray : public KSystemTray { + Q_OBJECT + int startStopId; +public: + KMouseToolTray (QWidget *parent=0, const char *name=0); + ~KMouseToolTray(); + + void updateStartStopText (bool mousetool_is_running); +signals: + void startStopSelected(); + void configureSelected(); + void aboutSelected(); + void helpSelected(); +}; +#endif diff --git a/kmousetool/kmousetool/kmousetoolui.ui b/kmousetool/kmousetool/kmousetoolui.ui new file mode 100644 index 0000000..05b3322 --- /dev/null +++ b/kmousetool/kmousetool/kmousetoolui.ui @@ -0,0 +1,422 @@ +<!DOCTYPE UI><UI version="3.1" stdsetdef="1"> +<class>KMouseToolUI</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KMouseToolUI</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>544</width> + <height>395</height> + </rect> + </property> + <property name="caption"> + <string>KMouseTool</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Settings</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="0" column="0"> + <property name="name"> + <cstring>dragTimeSpace</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="1"> + <property name="name"> + <cstring>dragTimeLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Drag t&ime (1/10 sec):</string> + </property> + <property name="buddy" stdset="0"> + <cstring>dragTimeEdit</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="KIntSpinBox" row="3" column="1"> + <property name="name"> + <cstring>dragTimeEdit</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>40</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>3</number> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="1"> + <property name="name"> + <cstring>dwellTimeEdit</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>40</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>movementLabel</cstring> + </property> + <property name="text"> + <string>&Minimum movement:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>movementEdit</cstring> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="1"> + <property name="name"> + <cstring>movementEdit</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>40</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>cbStroke</cstring> + </property> + <property name="text"> + <string>&Enable strokes</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>dwellTimeLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>D&well time (1/10 sec):</string> + </property> + <property name="buddy" stdset="0"> + <cstring>dwellTimeEdit</cstring> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>cbDrag</cstring> + </property> + <property name="text"> + <string>Smar&t drag</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QLayoutWidget" row="7" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonDefault</cstring> + </property> + <property name="text"> + <string>&Defaults</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonReset</cstring> + </property> + <property name="text"> + <string>&Reset</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonApply</cstring> + </property> + <property name="text"> + <string>&Apply</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox" row="6" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>cbStart</cstring> + </property> + <property name="text"> + <string>Start with &KDE</string> + </property> + </widget> + <widget class="QCheckBox" row="5" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>cbClick</cstring> + </property> + <property name="text"> + <string>A&udible click</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>KMouseTool will run as a background application after you close this dialog. To change the settings again, restart KMouseTool or use the KDE system tray.</string> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>WordBreak|AlignJustify|AlignVCenter</set> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>8</width> + <height>8</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonStartStop</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&Start</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonHelp</cstring> + </property> + <property name="text"> + <string>&Help</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>241</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonClose</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>buttonQuit</cstring> + </property> + <property name="text"> + <string>&Quit</string> + </property> + </widget> + </hbox> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>cbDrag</sender> + <signal>toggled(bool)</signal> + <receiver>dragTimeLabel</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>cbDrag</sender> + <signal>toggled(bool)</signal> + <receiver>dragTimeEdit</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kmousetool/kmousetool/main.cpp b/kmousetool/kmousetool/main.cpp new file mode 100644 index 0000000..29c5e30 --- /dev/null +++ b/kmousetool/kmousetool/main.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Sun Jan 20 23:27:58 PST 2002 + copyright : (C) 2002 by Jeff Roush + email : jeff@mousetool.com + copyright : (C) 2003 by Olaf Schmidt + email : ojschmidt@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kuniqueapplication.h> +#include <dcopclient.h> +#include <qmessagebox.h> +#include <kconfig.h> + +#include "kmousetool.h" + +static const char description[] = + I18N_NOOP("KMouseTool"); +// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE + + +static KCmdLineOptions options[] = +{ + KCmdLineLastOption + // INSERT YOUR COMMANDLINE OPTIONS HERE +}; + +int main(int argc, char *argv[]) +{ + KAboutData aboutData( "kmousetool", I18N_NOOP("KMouseTool"), + KMOUSETOOL_VERSION, description, KAboutData::License_GPL, + "(c) 2002-2003, Jeff Roush\n(c) 2003, Gunnar Schmi Dt", 0, "http://www.mousetool.com", "gunnar@schmi-dt.de"); + + aboutData.addAuthor("Gunnar Schmi Dt", I18N_NOOP("Current maintainer"), "gunnar@schmi-dt.de", "http://www.schmi-dt.de"); + aboutData.addAuthor("Olaf Schmidt", I18N_NOOP("Usability improvements"), "ojschmidt@kde.org"); + aboutData.addAuthor("Jeff Roush", I18N_NOOP("Original author"), "jeff@mousetool.com", "http://www.mousetool.com"); + + aboutData.addCredit("Joe Betts"); + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + KUniqueApplication::addCmdLineOptions(); + + if (!KUniqueApplication::start()) { + DCOPClient *client = new DCOPClient(); + client->attach(); + QByteArray data; + QCString replyType; + QByteArray replyData; + if ( !client->call("kmousetool", "qt/KMouseToolUI", "show()", + data, replyType, replyData, true) || + !client->call("kmousetool", "qt/KMouseToolUI", "raise()", + data, replyType, replyData, true) ) + fprintf(stderr, "The DCOP calls failed\n"); + delete client; + exit(0); + } + KUniqueApplication a; + + KMouseTool *kmousetool = new KMouseTool(); + + if (!kapp->config()->readBoolEntry("IsMinimized", false)) + kmousetool->show(); + + return a.exec(); +} diff --git a/kmousetool/kmousetool/mousetool_tap.wav b/kmousetool/kmousetool/mousetool_tap.wav Binary files differnew file mode 100644 index 0000000..797facb --- /dev/null +++ b/kmousetool/kmousetool/mousetool_tap.wav diff --git a/kmousetool/kmousetool/mtstroke.cpp b/kmousetool/kmousetool/mtstroke.cpp new file mode 100644 index 0000000..16b1078 --- /dev/null +++ b/kmousetool/kmousetool/mtstroke.cpp @@ -0,0 +1,288 @@ +/*************************************************************************** + mtstroke.cpp - description + ------------------- + begin : Fri Oct 11 2002 + copyright : (C) 2002 by Jeff Roush + email : jeff@mousetool.com + copyright : (C) 2003 by Olaf Schmidt + email : ojschmidt@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "mtstroke.h" +#include "kmousetool.h" +#include <iostream> + +// these are for locating the stroke information file +#include <kstandarddirs.h> +#include <qstring.h> + +// #include <string> + +using namespace std; + +const int MTStroke::DontClick = -1; +const int MTStroke::bumped_mouse = 0; +const int MTStroke::normal = 1; +const int MTStroke::RightClick = 2; +const int MTStroke::DoubleClick = 3; +const int MTStroke::circle = 4; +const int MTStroke::LowerLeftStroke = 5; +const int MTStroke::UpperRightStroke = 6; +const int MTStroke::LowerRightStroke = 7; +const int MTStroke::UpperLeftStroke = 8; + +int MTStroke::delta_xy = 10; + +const int MTStroke::min_num_points = 5; + +Pt MTStroke::LowerLeft (0,0); +Pt MTStroke::LowerRight(0,0); +Pt MTStroke::UpperLeft (0,0); +Pt MTStroke::UpperRight(0,0); + + + +MTStroke::MTStroke(){ + readSequence(); +} +MTStroke::~MTStroke(){ +} + +// add the new point, but only if it's not the same as the previous point. +void MTStroke::addPt(const int x, const int y) +{ + if (points.size()==0) { + points.push_back(Pt(x,y)); + } + else { + Pt pt(x,y); + if (!pt.sameAs(points[points.size()-1])) { + points.push_back(Pt(x,y)); + } + } +} + + +/* + * Loop over all the strokes; + * return true if the given point is included + */ +bool MTStroke::pointsContain(Pt pt) +{ + std::vector<Pt>::iterator pos; + for (pos=points.begin(); pos<points.end(); pos++) { + if (pt.x==pos->x && pt.y==pos->y) + return true; + } + return false; +} + +int MTStroke::getStrokeType() +{ + int size = points.size(); + + // If the mouse moved just a bit, it was probably bumped. Don't click. + if (size<min_num_points) + return normal; +// return bumped_mouse; + + Pt lastPoint = points[points.size()-1]; + + // If the mouse is pausing in a corner, then the user is either in the middle of a + // stroke, or wants to rest the mouse. Don't click. + if (lastPoint.sameAs(LowerLeft) || lastPoint.sameAs(LowerRight) + || lastPoint.sameAs(UpperLeft) || lastPoint.sameAs(UpperRight)) + return DontClick; + + // If the mouse visited a corner... + if (pointsContain(LowerLeft)) { + reset(); + return LowerLeftStroke; + } + if (pointsContain(UpperRight)) { + reset(); + return UpperRightStroke; + } + scale(); + + std::map<std::string, int>::iterator keypos = sequenceMap.find(sequence); + if (keypos == sequenceMap.end()) { + reset(); + return normal; + } + reset(); +// return RightClick; + return keypos->second; +} + +void MTStroke::scale() +{ + getExtent(); + int deltax = stroke_maxx - stroke_minx; + int deltay = stroke_maxy - stroke_miny; + int delta = max(deltax, deltay); + int scale = (int) delta/2; + + std::vector<Pt>::iterator pos; + for (pos=points.begin(); pos<points.end(); pos++) { + + // add an extra (scale/2) because the divide rounds _down_, and we want to + // round _up_ or _down_, depending on which is closer. + pos->x = (int) (pos->x-stroke_minx + scale/2)/scale; + pos->y = (int) (pos->y-stroke_miny + scale/2)/scale; + + // now, get the integer representing this position and add it to the stroke sequence + int n = 3*pos->y + pos->x + 1; + int index = sequence.size()-1; + n += '0'; + if (index==-1) + sequence += n; + else if (n!=sequence[index]) + sequence += n; + } +} + +int MTStroke::max(int n, int m) +{ + if (n>m) + return n; + return m; +} + + +/* + * Find the bounding rectangle for the stroke + */ +void MTStroke::getExtent() +{ + stroke_minx = UpperRight.x; + stroke_maxx = 0; + stroke_miny = LowerLeft.y; + stroke_maxy = 0; + + std::vector<Pt>::iterator pos; + for (pos=points.begin(); pos<points.end(); pos++) { + if (stroke_minx > pos->x) + stroke_minx = pos->x; + if (stroke_maxx < pos->x) + stroke_maxx = pos->x; + if (stroke_miny > pos->y) + stroke_miny = pos->y; + if (stroke_maxy < pos->y) + stroke_maxy = pos->y; + } +} + +// test if strokefile exists; if not, create it from defaults. +// if unable to create it, +bool MTStroke::readSequence() +{ + QString strokefilename; + strokefilename = locate("config", "kmousetool_strokes.txt"); + if (strokefilename.isEmpty()) { + // make default + if (sequenceMap.size()==0) + makeDefaultSequenceMap(); + writeSequence(); + return false; + } + ifstream infile (strokefilename.ascii()); + if (!infile) { + // make default + if (sequenceMap.size()==0) + makeDefaultSequenceMap(); + writeSequence(); + return false; + } + + while (!infile.eof()) { + string str; + infile >> str; + if (str[0] == '#') + readToEndOfLine(infile); + else { + // get the associated action + string str2; + infile >> str2; + int n = str2[0] - '0'; // the action is a single integer digit; convert it to an int + sequenceMap[ string(str) ] = n; + } + } + return true; +} + +bool MTStroke::writeSequence() +{ + QString strokefilename; + strokefilename = locateLocal("config", "kmousetool_strokes.txt"); + + ofstream outfile (strokefilename.ascii(), ios::out); + if (!outfile) { + return false; + } + + outfile << "# This file contains definitions for valid strokes for KMouseTool\n"; + outfile << "# To make sense of the numbers: \n"; + outfile << "# The mouse path begins and ends when the mouse is paused.\n"; + outfile << "# Imagine a square enclosing the path.\n"; + outfile << "# Divide the square into 9 boxes, and number them like so:\n"; + outfile << "# 1 2 3\n"; + outfile << "# 4 5 6\n"; + outfile << "# 7 8 9\n"; + outfile << "# \n"; + outfile << "# The mouse path can then be described by a sequence of numbers:\n"; + outfile << "# for example, \"12321\" describes the mouse moving from left to right and back.\n"; + outfile << "# This general scheme follows libstroke (http://www.etla.net/~willey/projects/libstroke/)\n"; + outfile << "# although it was reimplemented from scratch for KMouseTool.\n"; + outfile << "\n"; + outfile << "# For each stroke recognized, provide an integer describing an action\n"; + outfile << "# KMouseTool can take. At the moment, valid actions are:\n"; + outfile << "# -1 Don't click\n"; + outfile << "# 1 Normal click (use Smart Drag if that's enabled)\n"; + outfile << "# 2 Right click\n"; + outfile << "# 3 Double click\n"; + outfile << "\n"; + outfile << "#Stroke\tAction\n"; + std::map<std::string, int>::iterator pos = sequenceMap.begin(); + while (pos != sequenceMap.end()) { + outfile << pos->first << "\t" << pos->second << "\n"; + pos++; + } + return true; +} + +void MTStroke::makeDefaultSequenceMap() +{ + sequenceMap[ string("12321") ] = RightClick; + sequenceMap[ string("1321") ] = RightClick; + sequenceMap[ string("1231") ] = RightClick; + sequenceMap[ string("131") ] = RightClick; + + sequenceMap[ string("32123") ] = DoubleClick; + sequenceMap[ string("3213") ] = DoubleClick; + sequenceMap[ string("3123") ] = DoubleClick; + sequenceMap[ string("313") ] = DoubleClick; +/* + sequenceMap[ string("") ] = ; + sequenceMap[ string("") ] = ; + sequenceMap[ string("") ] = ; + sequenceMap[ string("") ] = ; + sequenceMap[ string("") ] = ; +*/ +} + +void MTStroke::readToEndOfLine(ifstream &infile) +{ + char ch = 'a'; + while (ch != '\n') + infile.get(ch); +} diff --git a/kmousetool/kmousetool/mtstroke.h b/kmousetool/kmousetool/mtstroke.h new file mode 100644 index 0000000..171204c --- /dev/null +++ b/kmousetool/kmousetool/mtstroke.h @@ -0,0 +1,103 @@ +/*************************************************************************** + mtstroke.h - description + ------------------- + begin : Fri Oct 11 2002 + copyright : (C) 2002 by Jeff Roush + email : jeff@mousetool.com + copyright : (C) 2003 by Olaf Schmidt + email : ojschmidt@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef MTSTROKE_H +#define MTSTROKE_H +#include <vector> +#include <fstream> +#include <map> +#include <string> +#include <cstdlib> + +/**Implements stroke recording for MouseTool. + *@author Jeff Roush + */ + +class Pt { + + public: + int x,y; + Pt () { } ; + Pt (const int xx, const int yy) { x=xx; y=yy; }; + bool sameAs(Pt pt) { return (x==pt.x&&y==pt.y); }; + bool nearTo(Pt pt, int delta) { return ( (std::abs(x-pt.x)<delta) && (std::abs(y-pt.y)<delta) ); } + + void dump(); +}; + +class MTStroke { + std::vector<Pt> points; +// std::vector<int> sequence; + std::string sequence; + std::map<std::string, int> sequenceMap; + + int stroke_minx; + int stroke_maxx; + int stroke_miny; + int stroke_maxy; + + void makeDefaultSequenceMap(); + +public: + // stroke types + static const int bumped_mouse; + static const int normal; + static const int RightClick; + static const int DoubleClick; + static const int circle; + static const int DontClick; + static const int LowerLeftStroke; + static const int UpperRightStroke; + static const int LowerRightStroke; + static const int UpperLeftStroke; + + // Static ints + static int delta_xy; + static Pt LowerLeft; + static Pt LowerRight; + static Pt UpperLeft; + static Pt UpperRight; + + // min points before it can be considered a "stroke" + static const int min_num_points; + + static void setLowerLeft (int x, int y) { LowerLeft.x = x; LowerLeft.y = y; }; + static void setLowerRight(int x, int y) { LowerRight.x = x; LowerRight.y = y; }; + static void setUpperLeft (int x, int y) { UpperLeft.x = x; UpperLeft.y = y; }; + static void setUpperRight(int x, int y) { UpperRight.x = x; UpperRight.y = y; }; + + void dump(); + void scale(); + void addPt(int, int); + int max(int, int); + bool pointsContain(Pt pt); + int getStrokeType(); + void getExtent(); +// void getSequence(); + bool readSequence(); + bool writeSequence(); + void readToEndOfLine(std::ifstream &infile); + + void reset() { points.clear(); sequence = ""; } + + MTStroke(); + ~MTStroke(); +}; + +#endif diff --git a/kmousetool/kmousetool/pics/Makefile.am b/kmousetool/kmousetool/pics/Makefile.am new file mode 100644 index 0000000..f80db48 --- /dev/null +++ b/kmousetool/kmousetool/pics/Makefile.am @@ -0,0 +1,3 @@ +kmousetooliconsdir = $(kde_datadir)/kmousetool/icons +kmousetoolicons_ICON = AUTO +KDE_ICON = kmousetool diff --git a/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png b/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png Binary files differnew file mode 100644 index 0000000..e1a6fed --- /dev/null +++ b/kmousetool/kmousetool/pics/hi16-action-kmousetool_off.png diff --git a/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png b/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png Binary files differnew file mode 100644 index 0000000..2745591 --- /dev/null +++ b/kmousetool/kmousetool/pics/hi16-action-kmousetool_on.png diff --git a/kmousetool/kmousetool/pics/hi16-app-kmousetool.png b/kmousetool/kmousetool/pics/hi16-app-kmousetool.png Binary files differnew file mode 100644 index 0000000..b70b4bf --- /dev/null +++ b/kmousetool/kmousetool/pics/hi16-app-kmousetool.png diff --git a/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png b/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png Binary files differnew file mode 100644 index 0000000..db81487 --- /dev/null +++ b/kmousetool/kmousetool/pics/hi32-action-kmousetool_off.png diff --git a/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png b/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png Binary files differnew file mode 100644 index 0000000..0613275 --- /dev/null +++ b/kmousetool/kmousetool/pics/hi32-action-kmousetool_on.png diff --git a/kmousetool/kmousetool/pics/hi32-app-kmousetool.png b/kmousetool/kmousetool/pics/hi32-app-kmousetool.png Binary files differnew file mode 100644 index 0000000..391b486 --- /dev/null +++ b/kmousetool/kmousetool/pics/hi32-app-kmousetool.png diff --git a/kmousetool/kmousetool/version.h b/kmousetool/kmousetool/version.h new file mode 100644 index 0000000..9560d03 --- /dev/null +++ b/kmousetool/kmousetool/version.h @@ -0,0 +1,8 @@ +// KMouseTool Version Information +// +#ifndef kmousetool_version_h +#define kmousetool_version_h + +#define KMOUSETOOL_VERSION "1.12" + +#endif /*version_h*/ |