summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormallum <mallum@b067294f-1dea-0310-9683-c47a78595994>2005-01-12 17:58:22 +0000
committermallum <mallum@b067294f-1dea-0310-9683-c47a78595994>2005-01-12 17:58:22 +0000
commit886ecf00f01de5b69477cae333215f5f928c9ae2 (patch)
tree64bc36115ed979f04a18102feaba0546c802e0da
Renamed matchbox-nest -> Xoo
git-svn-id: http://svn.o-hand.com/repos/matchbox/trunk/Xoo@1029 b067294f-1dea-0310-9683-c47a78595994
-rw-r--r--AUTHORS1
-rw-r--r--COPYING340
-rw-r--r--ChangeLog185
-rw-r--r--INSTALL229
-rw-r--r--Makefile.am6
-rw-r--r--NEWS0
-rw-r--r--README10
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.ac176
-rw-r--r--data/Makefile.am8
-rw-r--r--data/dot.pngbin0 -> 237 bytes
-rw-r--r--data/ipaq3800.pngbin0 -> 195421 bytes
-rw-r--r--data/ipaq3800.xml52
-rw-r--r--data/matchbox-nest.glade582
-rw-r--r--src/Makefile.am9
-rw-r--r--src/button.c93
-rw-r--r--src/callbacks.c76
-rw-r--r--src/callbacks.h12
-rw-r--r--src/config.c344
-rw-r--r--src/fakedev.h129
-rw-r--r--src/keys.c105
-rw-r--r--src/main.c351
-rw-r--r--src/prefs.c75
-rw-r--r--src/prefs.h12
-rw-r--r--website/default.css34
-rw-r--r--website/index.html56
-rw-r--r--website/mb-nest-1.pngbin0 -> 232430 bytes
-rw-r--r--website/ohside.pngbin0 -> 6933 bytes
28 files changed, 2888 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..46c46b8
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Matthew Allum <mallum@o-hand.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..d54e096
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,185 @@
+2004-12-03 mallum,,, <mallum@openedhand.com>
+
+ * Makefile.am:
+ Add snapshot target
+ * src/prefs.c: (onpreferences_activate):
+ Remove unused var.
+
+2004-12-02 Ross Burton <ross@burtonini.com>
+
+ * configure.ac:
+ Bump version.
+
+ * src/prefs.c:
+ Be aggressive about saving prefs and restarting the server, to
+ avoid hastles with command-line options.
+
+2004-12-02 mallum,,, <mallum@openedhand.com>
+
+ * data/matchbox-nest.glade:
+ Change 'ok' -> 'Apply', Update copyright in about dialog.
+ * src/keys.c: (keys_xnest_connect), (keys_init):
+ * src/main.c: (fakeapp_start_server), (fakeapp_restart_server):
+ Attempt to make server start failure messages more useful
+
+2004-12-02 Ross Burton <ross@burtonini.com>
+
+ * data/matchbox-nest.glade:
+ Rename the Send Signal menu item.
+
+ * src/main.c:
+ * src/fakedev.h:
+ Disable the Send Debug Signal menu item unless Xephyr is being
+ used.
+
+2004-11-30 Ross Burton <ross@burtonini.com>
+
+ * data/matchbox-nest.glade:
+ Add an About dialog, and redesign the Prefs dialog.
+
+ * src/fakedev.h:
+ * src/callbacks.c:
+ * src/callbacks.h:
+ Add an about window and generalise the hide-on-delete handler.
+
+ * src/prefs.c:
+ * src/prefs.h:
+ Restart the server if the prefs are changed.
+
+ * src/main.c:
+ Handle the about window, and handle a restarting server correctly.
+
+ * src/keys.c:
+ Fix a leak.
+
+2004-11-30 Ross Burton <ross@burtonini.com>
+
+ * configure.ac:
+ Version 0.4.
+
+2004-11-15 Ross Burton <ross@burtonini.com>
+
+ * data/matchbox-nest.glade:
+ * src/fakedev.h:
+ * src/keys.c:
+ * src/main.c:
+ Make the keyboard events work again.
+
+2004-11-14 Ross Burton <ross@burtonini.com>
+
+ * src/main.c:
+ Make the hardware buttons work again by making them visible...
+
+2004-11-12 mallum <mallum@handhelds.org>
+
+ * src/config.c: (config_reinit):
+ Add config_reinit ( just a stub for now ).
+
+ * src/main.c: (fakeapp_new), (fakeapp_start_server),
+ (fakeapp_catch_sigchild), (fakeapp_restart_server), (usage),
+ (main):
+ Hack signal handling to detect 'crashing' xserver.
+ Add fakeapp_restart_server().
+ Add --xnest-bin-options cmd line switch. Default it to '-ac'
+ Change start_server() to execv with --xnest-bin-options
+
+2004-11-12 Ross Burton <ross@burtonini.com>
+
+ * configure.ac:
+ Look for GConf at configure time.
+
+ * data/matchbox-nest.glade:
+ Remove a separator, so when the Prefs entry is hidden the menu
+ doesn't look silly.
+
+ * src/Makefile.am:
+ Only build with prefs.[ch] if GConf was found.
+
+ * src/fakedev.h:
+ * src/main.c:
+ Only hook up the Preferences dialog if GConf was found.
+
+ * src/prefs.c:
+ Handle xnest_bin_options being NULL.
+
+2004-11-11 Ross Burton <ross@burtonini.com>
+
+ * configure.ac:
+ Look for GConf.
+
+ * data/matchbox-nest.glade:
+ Add Preferences dialogue.
+
+ * src/Makefile.am:
+ * src/callbacks.h:
+ * src/fakedev.h:
+ * src/main.c:
+ * src/prefs.h:
+ * src/prefs.c:
+ Add a preferences dialogue.
+
+2004-11-11 Ross Burton <ross@burtonini.com>
+
+ * src/button.c:
+ * src/config.c:
+ * src/keys.c:
+ Sanity check, add missing includes.
+
+2004-11-10 Ross Burton <ross@burtonini.com>
+
+ * src/main.c:
+ Stop leaking GCs.
+
+2004-11-09 Ross Burton <ross@burtonini.com>
+
+ * data/Makefile.am:
+ Add the glade file to EXTRA_DIST.
+
+2004-11-08 Ross Burton <ross@openedhand.com>
+
+ * configure.ac:
+ Look for GTK+, not libmb.
+
+ * data/Makefile.am:
+ * data/matchbox-next.glade:
+ * src/Makefile.am:
+ * src/fakedev.h:
+ * src/button.c:
+ * src/callbacks.[ch]:
+ * src/config.c:
+ * src/main.c:
+ Port to GTK+, adding a few new features en route.
+
+2004-06-04 Matthew Allum,,, <mallum@handhelds.org>
+
+ reviewed by: <delete if not using a buddy>
+
+ * src/fakedev.h:
+ * src/main.c: (fakeapp_new), (fakeapp_create_gui), (usage), (main):
+ Allow user to set window title
+
+2004-06-04 Matthew Allum,,, <mallum@handhelds.org>
+
+ * AUTHORS:
+ * COPYING:
+ * INSTALL:
+ * Makefile.am:
+ * README:
+ * autogen.sh:
+ * configure.ac:
+ * data/Makefile.am:
+ * data/dot.png:
+ * data/ipaq3800.png:
+ * data/ipaq3800.xml:
+ * src/Makefile.am:
+ * src/button.c: (button_new), (button_find_from_win),
+ (button_press), (button_release), (button_activate):
+ * src/config.c: (config_load_file), (config_get_val),
+ (config_load_image), (config_handle_button_tag),
+ (config_handle_device_tag), (config_xml_start_cb), (config_init):
+ * src/fakedev.h:
+ * src/keys.c: (keys_xnest_connect), (keys_send_key), (keys_init):
+ * src/main.c: (fakeapp_new), (fakeapp_create_gui),
+ (fakeapp_start_server), (get_xevent_timed), (fakeapp_event_loop),
+ (usage), (main):
+ Initial Import into CVS.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..54caf7c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,229 @@
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
+Foundation, Inc.
+
+ This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+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, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ 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 you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' 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 awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+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 support 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.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ 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' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ 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 machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+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.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a90820b
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = src data
+
+snapshot:
+ $(MAKE) dist distdir=$(PACKAGE)-snap`date +"%Y%m%d"`
+
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..4574c70
--- /dev/null
+++ b/README
@@ -0,0 +1,10 @@
+matchbox-nest ReadMe.
+======================
+
+Matchbox-nest is a graphical wrapper around xnest. You can make Xnest
+look like a particular device's display and set up buttons on that
+device.
+
+For usage see matchbox-nest --help. For infomation on creating your own
+device see the comments in data/ipaq3800.xml.
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..b1376df
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+autoreconf -v --install || exit 1
+./configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7b8eea8
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,176 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.53)
+AC_INIT([matchbox-nest], 0.5, [mallum@handhelds.org])
+AC_CONFIG_SRCDIR([src/main.c])
+
+AM_INIT_AUTOMAKE()
+AM_CONFIG_HEADER(config.h)
+
+AC_ARG_WITH(expat-includes,
+ [ --with-expat-includes=DIR Use Expat includes in DIR],
+ expat_includes=$withval, expat_includes=yes)
+
+AC_ARG_WITH(expat-lib,
+ [ --with-expat-lib=DIR Use Expat library in DIR],
+ expat_lib=$withval, expat_lib=yes)
+
+# Checks for programs.
+AC_GNU_SOURCE
+AC_PROG_CC
+AC_PATH_XTRA
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
+AC_ARG_ENABLE(gconf,
+ AC_HELP_STRING([--enable-gconf], [Use GConf for preferences @<:@default=auto@:>@]),
+ ,enable_gconf=auto)
+GCONF_REQ=
+if test "x$enable_gconf" = "xyes"; then
+ GCONF_REQ="gconf-2.0"
+else
+ if test "x$enable_gconf" != "xno"; then
+ AC_MSG_CHECKING(for GConf)
+ if $PKG_CONFIG --exists gconf-2.0; then
+ AC_MSG_RESULT(yes)
+ GCONF_REQ="gconf-2.0"
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+fi
+if test -n "$GCONF_REQ"; then
+ AC_DEFINE([HAVE_GCONF], 1, [Defined when GConf is detected])
+fi
+AM_CONDITIONAL(HAVE_GCONF, test -n "$GCONF_REQ")
+
+
+dnl TODO: make gconf optional
+PKG_CHECK_MODULES(APP, [gtk+-2.0 libglade-2.0 $GCONF_REQ])
+
+dnl ------ XTest ------------------------------------------------------------
+
+XTEST_LIBS=
+AC_CHECK_HEADER(X11/extensions/XTest.h, [
+ AC_CHECK_LIB(Xtst, XTestQueryExtension, [
+ XTEST_LIBS="-lXtst"],
+ AC_MSG_ERROR([*** XTEST extension libs not found and required ***])
+ , $X_LIBS)
+ ])
+AC_SUBST(XTEST_LIBS)
+
+
+dnl ------ Expat ------------------------------------------------------------
+
+
+case "$expat_includes" in
+ yes|no)
+ EXPAT_CFLAGS=""
+ ;;
+ *)
+ EXPAT_CFLAGS="-I$expat_includes"
+ ;;
+esac
+
+case "$expat_lib" in
+ yes)
+
+ case "$expat" in
+ yes)
+ EXPAT_LIBS="-lexpat"
+ ;;
+ *)
+ EXPAT_LIBS="-L$expat/lib -lexpat"
+ ;;
+ esac
+
+ ;;
+no)
+ ;;
+*)
+ EXPAT_LIBS="-L$expat_lib -lexpat"
+ ;;
+esac
+
+expatsaved_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $EXPAT_CFLAGS"
+expatsaved_LIBS="$LIBS"
+LIBS="$LIBS $EXPAT_LIBS"
+
+AC_CHECK_HEADER(expat.h)
+case "$ac_cv_header_expat_h" in
+ no)
+ AC_CHECK_HEADER(xmlparse.h)
+
+ case "$ac_cv_header_xmlparse_h" in
+ no)
+ have_expat_header=no;
+ ;;
+ yes)
+ HAVE_XMLPARSE_H=1
+ AC_SUBST(HAVE_XMLPARSE_H)
+ AC_DEFINE_UNQUOTED(HAVE_XMLPARSE_H,$HAVE_XMLPARSE_H,
+ [Use xmlparse.h instead of expat.h])
+ have_expat_header=yes
+ ;;
+ esac
+ ;;
+ yes)
+ have_expat_header=yes
+ ;;
+esac
+
+case "$have_expat_header" in
+ no)
+ expat=no
+ ;;
+ yes)
+ AC_CHECK_FUNCS(XML_ParserCreate)
+
+ case "$ac_cv_func_XML_ParserCreate" in
+ no)
+ expat=no
+ ;;
+ yes)
+ HAVE_EXPAT=1
+ AC_SUBST(HAVE_EXPAT)
+ AC_DEFINE_UNQUOTED(HAVE_EXPAT,$HAVE_EXPAT,
+ [Found a useable expat library])
+ ;;
+ esac
+ ;;
+esac
+
+CPPFLAGS="$saved_CPPFLAGS"
+LIBS="$saved_LIBS"
+
+if test x$expat = xno; then
+ AC_MSG_ERROR([cannot find expat library])
+fi
+
+AC_DEFINE(USE_EXPAT, [1], [Use Expat XML Parser])
+
+
+if test "x$GCC" = "xyes"; then
+ GCC_WARNINGS="-Wall -fno-strict-aliasing"
+ APP_CFLAGS="$GCC_WARNINGS $APP_CFLAGS"
+fi
+
+AC_SUBST(APP_CFLAGS)
+AC_SUBST(APP_LIBS)
+
+AC_SUBST(EXPAT_LIBS)
+AC_SUBST(EXPAT_CFLAGS)
+
+# Checks for header files.
+
+AC_HEADER_STDC
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_PID_T
+
+
+# Checks for library functions.
+
+AC_OUTPUT([Makefile src/Makefile data/Makefile])
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..cb863f6
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,8 @@
+EXTRA_DIST = ipaq3800.xml ipaq3800.png dot.png matchbox-nest.glade
+
+devicedir = $(pkgdatadir)
+device_DATA = ipaq3800.xml ipaq3800.png dot.png
+
+uidir = $(pkgdatadir)
+ui_DATA = matchbox-nest.glade
+
diff --git a/data/dot.png b/data/dot.png
new file mode 100644
index 0000000..c1ee244
--- /dev/null
+++ b/data/dot.png
Binary files differ
diff --git a/data/ipaq3800.png b/data/ipaq3800.png
new file mode 100644
index 0000000..d605c3d
--- /dev/null
+++ b/data/ipaq3800.png
Binary files differ
diff --git a/data/ipaq3800.xml b/data/ipaq3800.xml
new file mode 100644
index 0000000..a22ef1d
--- /dev/null
+++ b/data/ipaq3800.xml
@@ -0,0 +1,52 @@
+<ipaq>
+
+<!--
+ Example config 'device' file for an ipaq.
+ Hopefully the format is pretty self explanatory.
+-->
+
+<!--
+ first define the window size, image and display geometry for your
+ 'fake' device.
+-->
+
+<device width='417' height='614'
+ display_width='240' display_height='320'
+ display_x='81' display_y='125'
+ img='ipaq3800.png' />
+
+<!-- Buttons ( optional )
+ The define each of the buttons. Note, there are a couple of extra
+ optional attributes not used here;
+
+ - 'img' - set to an image pathname for the down state of the button
+
+ - repreat = 'on|off' , Turn key repeat on/off for that key. By default
+ key repeat is on.
+ -->
+
+<!-- PIM buttons, left to right -->
+
+<button x='83' y='507' width='25' height='25' key='a'/>
+
+<button x='112' y='489' width='25' height='25' key='b'/>
+
+<button x='267' y='489' width='25' height='25' key='c'/>
+
+<button x='293' y='507' width='25' height='25' key='d'/>
+
+<!-- Direction buttons n/e/s/w -->
+
+<button x='173' y='495' width='56' height='20' key='Up'/>
+
+<button x='230' y='500' width='37' height='42' key='Right'/>
+
+<button x='173' y='535' width='56' height='20' key='Down'/>
+
+<button x='135' y='500' width='37' height='42' key='Left'/>
+
+<!-- enter button, notice image -->
+
+<button x='173' y='516' width='56' height='18' key='Return' img='dot.png'/>
+
+</ipaq> \ No newline at end of file
diff --git a/data/matchbox-nest.glade b/data/matchbox-nest.glade
new file mode 100644
index 0000000..41b5553
--- /dev/null
+++ b/data/matchbox-nest.glade
@@ -0,0 +1,582 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window">
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="events">GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK</property>
+ <property name="title" translatable="yes">Matchbox-Nest</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <signal name="destroy" handler="on_window_destroy" last_modification_time="Mon, 08 Nov 2004 12:58:27 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Device</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem1_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="select_device">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="label" translatable="yes">Select _Device...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_select_device_activate" last_modification_time="Mon, 08 Nov 2004 12:08:36 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="send_signal">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Send Debug Signal</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_send_signal_activate" last_modification_time="Mon, 08 Nov 2004 12:08:36 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="preferences">
+ <property name="visible">True</property>
+ <property name="label">gtk-preferences</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_preferences_activate" last_modification_time="Mon, 08 Nov 2004 12:08:36 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="quit">
+ <property name="visible">True</property>
+ <property name="label">gtk-quit</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_quit_activate" last_modification_time="Mon, 08 Nov 2004 12:08:36 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem4_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="about">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_About</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about_activate" last_modification_time="Mon, 08 Nov 2004 12:08:36 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFixed" id="fixed">
+ <property name="visible">True</property>
+ <signal name="button_press_event" handler="on_popup_menu_show" last_modification_time="Mon, 08 Nov 2004 15:55:45 GMT"/>
+
+ <child>
+ <widget class="GtkDrawingArea" id="winnest">
+ <property name="width_request">50</property>
+ <property name="height_request">50</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="x">48</property>
+ <property name="y">48</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkMenuBar" id="popupmenubar">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="popupmenu">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Popup</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="popupmenu_menu">
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="show_decorations">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Show decorations</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <signal name="activate" handler="on_show_decorations_toggle" last_modification_time="Mon, 08 Nov 2004 16:05:28 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="prefswindow">
+ <property name="title" translatable="yes">Preferences</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <signal name="delete_event" handler="on_delete_event_hide" last_modification_time="Wed, 01 Dec 2004 18:42:22 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox2">
+ <property name="border_width">8</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">6</property>
+ <property name="bottom_padding">6</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">4</property>
+ <property name="column_spacing">4</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Extra Options:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">X Server:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">X Display:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="entry_options">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="entry_display">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkEntry" id="entry_server">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button_browse">
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-open</property>
+ <property name="icon_size">2</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Embedded X Server&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkButton" id="button_close">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_prefs_cancel_clicked" last_modification_time="Wed, 01 Dec 2004 15:37:57 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button_apply">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-apply</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_prefs_apply_clicked" last_modification_time="Wed, 01 Dec 2004 15:38:11 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="aboutwindow">
+ <property name="title" translatable="yes">Matchbox Nest</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <signal name="delete_event" handler="on_delete_event_hide" last_modification_time="Wed, 01 Dec 2004 18:37:55 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="border_width">8</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">8</property>
+
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span size=&quot;xx-large&quot;&gt;&lt;b&gt;Matchbox Nest&lt;/b&gt;&lt;/span&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">A tool for simulating X-based small-screen devices.</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;small&gt;Copyright © 2004 OpenedHand Ltd
+info@o-hand.com&lt;/small&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="button_about_close">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_about_close_clicked" last_modification_time="Wed, 01 Dec 2004 15:46:16 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..3fffde1
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -DPKGDATADIR=\"$(pkgdatadir)\" @APP_CFLAGS@ @EXPAT_CFLAGS@ @X_CFLAGS@ -Wall
+bin_PROGRAMS = matchbox-nest
+
+if HAVE_GCONF
+GCONF_SOURCES = prefs.c prefs.h
+endif
+matchbox_nest_SOURCES = main.c button.c callbacks.h callbacks.c config.c keys.c fakedev.h $(GCONF_SOURCES)
+
+matchbox_nest_LDADD = @APP_LIBS@ @EXPAT_LIBS@ @X_LIBS@ @XTEST_LIBS@
diff --git a/src/button.c b/src/button.c
new file mode 100644
index 0000000..c95d69c
--- /dev/null
+++ b/src/button.c
@@ -0,0 +1,93 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+#include <glib/gmessages.h>
+#include <gtk/gtkimage.h>
+#include "fakedev.h"
+
+FakeButton*
+button_new(FakeApp *app,
+ int x,
+ int y,
+ int width,
+ int height,
+ KeySym ks,
+ int repeat,
+ GdkPixbuf *img)
+{
+ FakeButton *button = malloc(sizeof(FakeButton));
+ memset(button, 0, sizeof(FakeButton));
+
+ button->app = app;
+ button->x = x;
+ button->y = y;
+ button->height = height;
+ button->width = width;
+ button->keysym = ks;
+ button->overlay = img;
+ button->repeat = repeat;
+
+ if (img)
+ {
+ if (gdk_pixbuf_get_width(img) != button->width
+ || gdk_pixbuf_get_height(img) != button->height)
+ {
+ fprintf(stderr,
+ "** warning: Button image size does not equal defined button size.\n"
+ );
+
+ }
+ }
+
+ /* keysyms */
+
+ return button;
+}
+
+#if 0
+FakeButton*
+button_find_from_win(FakeApp *app, Window xevent_window_id)
+{
+ FakeButton *button;
+
+ for (button = app->button_head; button; button=button->next)
+ if (button->win == xevent_window_id)
+ return button;
+
+ return NULL;
+
+}
+#endif
+
+void button_press(GtkWidget *w, GdkEventButton *event, FakeButton *button) {
+ g_return_if_fail (button != NULL);
+ gtk_image_set_from_pixmap (GTK_IMAGE(button->image), button->active_img, NULL);
+ keys_send_key(button->app, button->keysym, KEYDOWN);
+}
+
+void button_release(GtkWidget *w, GdkEventButton *event, FakeButton *button) {
+ g_return_if_fail (button != NULL);
+ gtk_image_set_from_pixmap (GTK_IMAGE(button->image), button->normal_img, NULL);
+ keys_send_key(button->app, button->keysym, KEYUP);
+}
+
+void
+button_activate(FakeApp *app, FakeButton *button)
+{
+ ;
+}
diff --git a/src/callbacks.c b/src/callbacks.c
new file mode 100644
index 0000000..02ba81a
--- /dev/null
+++ b/src/callbacks.c
@@ -0,0 +1,76 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include "config.h"
+
+#include <signal.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkcheckmenuitem.h>
+#include <gtk/gtkwindow.h>
+#include "fakedev.h"
+
+void on_send_signal_activate (GtkMenuItem *menuitem, FakeApp *app) {
+ g_return_if_fail (app->xnest_pid != 0);
+ kill (app->xnest_pid, SIGUSR1);
+}
+
+static void quit (FakeApp *app) {
+ kill (app->xnest_pid, SIGKILL);
+ gtk_main_quit ();
+}
+
+void on_quit_activate (GtkMenuItem *menuitem, FakeApp *app) {
+ quit (app);
+}
+
+void on_window_destroy (GtkObject *object, FakeApp *app) {
+ quit (app);
+}
+
+gboolean on_popup_menu_show (GtkWidget *widget, GdkEventButton *event, FakeApp *app) {
+ if (event->button == 3) {
+ gtk_menu_popup (GTK_MENU (app->popupmenu), NULL, NULL, NULL, NULL, event->button, event->time);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void on_show_decorations_toggle (GtkCheckMenuItem *menuitem, FakeApp *app) {
+ if (gtk_window_get_decorated (GTK_WINDOW (app->window))) {
+ GdkBitmap *mask;
+ mask = gdk_pixmap_new (app->fixed->window, app->device_width, app->device_height, 1);
+ gdk_pixbuf_render_threshold_alpha (app->device_img, mask, 0, 0, 0, 0, -1, -1, 128);
+ gtk_widget_realize(app->window);
+ gdk_window_shape_combine_mask (app->window->window, mask, 0, 0);
+
+ gtk_window_set_decorated (GTK_WINDOW (app->window), FALSE);
+ gtk_check_menu_item_set_active (menuitem, FALSE);
+ } else {
+ gdk_window_shape_combine_mask (app->window->window, NULL, 0, 0);
+ gtk_window_set_decorated (GTK_WINDOW (app->window), TRUE);
+ gtk_check_menu_item_set_active (menuitem, TRUE);
+ }
+}
+
+void on_about_activate (GtkMenuItem *menuitem, FakeApp *app) {
+ gtk_window_present (GTK_WINDOW (app->about_window));
+}
+
+gboolean on_delete_event_hide (GtkWidget *widget, GdkEvent *event, FakeApp *app) {
+ gtk_widget_hide (widget);
+ return TRUE;
+}
diff --git a/src/callbacks.h b/src/callbacks.h
new file mode 100644
index 0000000..5c5d38d
--- /dev/null
+++ b/src/callbacks.h
@@ -0,0 +1,12 @@
+#include <gtk/gtkmenuitem.h>
+
+/* GTK+ callbacks */
+
+void on_send_signal_activate (GtkWidget *menuitem, FakeApp *app);
+void on_preferences_activate (GtkMenuItem *menuitem, FakeApp *app);
+void on_quit_activate (GtkMenuItem *menuitem, FakeApp *app);
+void on_about_activate (GtkMenuItem *menuitem, FakeApp *app);
+void on_window_destroy (GtkObject *widget, FakeApp *app);
+gboolean on_popup_menu_show (GtkWidget *widget, GdkEventButton *event, FakeApp *app);
+void on_show_decorations_toggle (GtkMenuItem *menuitem, FakeApp *app);
+gboolean on_delete_event_hide (GtkWidget *widget, GdkEvent *event, FakeApp *app);
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..56cfb6b
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,344 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libgen.h> /* dirname() */
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <expat.h>
+#include "fakedev.h"
+
+unsigned char*
+config_load_file(const char* filename)
+{
+ struct stat st;
+ FILE* fp;
+ unsigned char* str;
+ int len;
+ char tmp[1024];
+
+ strncpy(tmp, filename, 1024);
+
+ if (stat(tmp, &st))
+ {
+ snprintf(tmp, 1024, "%s.xml", filename);
+ if (stat(tmp, &st))
+ {
+ snprintf(tmp, 1024, PKGDATADIR "/%s", filename);
+ if (stat(tmp, &st))
+ {
+ snprintf(tmp, 1024, PKGDATADIR "/%s.xml", filename);
+ if (stat(tmp, &st))
+ return NULL;
+ }
+ }
+ }
+
+ if (!(fp = fopen(tmp, "rb"))) return NULL;
+
+ /* Read in the file. */
+ str = malloc(sizeof(char)*(st.st_size + 1));
+ len = fread(str, 1, st.st_size, fp);
+ if (len >= 0) str[len] = '\0';
+
+ fclose(fp);
+
+ /* change to the same directory as the conf file - for images */
+ chdir(dirname(tmp));
+ return str;
+}
+
+static const char *
+config_get_val (char *key, const char **attr)
+{
+ int i = 0;
+
+ while (attr[i] != NULL)
+ {
+ if (!strcmp(attr[i], key))
+ return attr[i+1];
+ i += 2;
+ }
+
+ return NULL;
+}
+
+static GdkPixbuf*
+config_load_image (FakeApp *app, const char *filename)
+{
+ GError *error = NULL;
+ GdkPixbuf *pixbuf;
+ char tmp[1024];
+ struct stat st;
+
+ strncpy(tmp, filename, 1024);
+
+ if (stat(tmp, &st))
+ {
+ snprintf(tmp, 1024, PKGDATADIR "/%s", filename);
+ if (stat(tmp, &st))
+ {
+ return NULL;
+ }
+ }
+
+ pixbuf = gdk_pixbuf_new_from_file(tmp, &error);
+ if (error == NULL) {
+ return pixbuf;
+ } else {
+ g_warning ("Could not load %s: %s", filename, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+}
+
+
+static int
+config_handle_button_tag(FakeApp *app, const char **attr)
+{
+ const char *s;
+ FakeButton *button;
+ int x,y,width,height;
+ KeySym keysym;
+ int repeat = 1;
+ GdkPixbuf *img = NULL;
+
+ if ((s = config_get_val ("width", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'button' tag missing width param");
+ return 0;
+ }
+
+ width = atoi(s);
+
+ if ((s = config_get_val ("height", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'button' tag missing height param");
+ return 0;
+ }
+
+ height = atoi(s);
+
+ if ((s = config_get_val ("x", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'button' tag missing x param");
+ return 0;
+ }
+
+ x = atoi(s);
+
+ if ((s = config_get_val ("y", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'button' tag missing y param");
+ return 0;
+ }
+
+ y = atoi(s);
+
+ if ((s = config_get_val ("key", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'button' tag missing key param");
+ return 0;
+ }
+
+ if ((keysym = XStringToKeysym(s)) == NoSymbol)
+ {
+ fprintf(stderr, "Error: Cant find keysym for '%s'", s);
+ return 0;
+ }
+
+ /* optional attributes */
+
+ if ((s = config_get_val ("img", attr)) != NULL)
+ {
+ if ((img = config_load_image (app, s)) == NULL)
+ {
+ fprintf(stderr, "Error: Falied to load '%s' image.", s);
+ }
+ }
+
+ if ( ((s = config_get_val ("repeat", attr)) != NULL)
+ && !strcasecmp(s, "off") )
+ repeat = 0;
+
+
+ if (app->button_head == NULL)
+ app->button_head = button_new(app, x, y, width, height,
+ keysym, repeat, img);
+ else
+ {
+ for (button = app->button_head; button->next; button=button->next) ;
+ button->next = button_new(app, x, y, width, height,
+ keysym, repeat, img);
+ }
+
+ return 1;
+}
+
+static int
+config_handle_device_tag(FakeApp *app, const char **attr)
+{
+ /*
+ width, height, display_width, display_height, display_x, displa_y
+ */
+ const char *s;
+
+ if ((s = config_get_val ("width", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing width param");
+ return 0;
+ }
+
+ app->device_width = atoi(s);
+
+ if ((s = config_get_val ("height", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing height param");
+ return 0;
+ }
+
+ app->device_height = atoi(s);
+
+ if ((s = config_get_val ("display_width", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing display_width param");
+ return 0;
+ }
+
+ app->device_display_width = atoi(s);
+
+ if ((s = config_get_val ("display_height", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing display_height param");
+ return 0;
+ }
+
+ app->device_display_height = atoi(s);
+
+ if ((s = config_get_val ("display_x", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing display_x param");
+ return 0;
+ }
+
+ app->device_display_x = atoi(s);
+
+ if ((s = config_get_val ("display_y", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing display_x param");
+ return 0;
+ }
+
+ app->device_display_y = atoi(s);
+
+ if ((s = config_get_val ("img", attr)) == NULL)
+ {
+ fprintf(stderr, "Error: 'device' tag missing img param");
+ return 0;
+ }
+
+ if ((app->device_img = config_load_image (app, s)) == NULL)
+ {
+ fprintf(stderr, "Error: Falied to load '%s' image.", s);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+config_xml_start_cb(void *data, const char *tag, const char **attr)
+{
+ FakeApp *app = (FakeApp *)data;
+
+ if (!strcmp(tag, "button"))
+ {
+ if (!config_handle_button_tag(app, attr))
+ {
+ fprintf(stderr, "Giving up.\n");
+ exit(1);
+ }
+ }
+ else if (!strcmp(tag, "device"))
+ {
+ if (!config_handle_device_tag(app, attr))
+ {
+ fprintf(stderr, "Giving up.\n");
+ exit(1);
+ }
+ }
+}
+
+
+int
+config_init(FakeApp *app, char *conf_file)
+{
+ unsigned char *data;
+ XML_Parser p;
+
+ if ((data = config_load_file(conf_file)) == NULL)
+ {
+ fprintf(stderr, "Couldn't find '%s' device config file\n", conf_file);
+ exit(1);
+ }
+
+ p = XML_ParserCreate(NULL);
+
+ if (! p) {
+ fprintf(stderr, "Couldn't allocate memory for XML parser\n");
+ exit(1);
+ }
+
+ XML_SetElementHandler(p, config_xml_start_cb, NULL);
+ /* XML_SetCharacterDataHandler(p, chars); */
+
+ XML_SetUserData(p, (void *)app);
+
+ if (! XML_Parse(p, data, strlen(data), 1)) {
+ fprintf(stderr, "XML Parse error at line %d:\n%s\n",
+ XML_GetCurrentLineNumber(p),
+ XML_ErrorString(XML_GetErrorCode(p)));
+ exit(1);
+ }
+
+
+ return 1;
+}
+
+void
+config_reinit(FakeApp *app, char *conf_file)
+{
+ /* Save these so we can figure out if server needs restarting */
+
+ /*
+ int prev_device_display_x = app->device_display_x;
+ int prev_device_display_y = app->device_display_y;
+ int prev_device_display_width = app->device_display_width;
+ int prev_device_display_height = app->device_display_height;
+ */
+
+ /* XXX TODO: Free up our old structure images etc XXX */
+
+ /* Reload UI - hard ? */
+
+}
diff --git a/src/fakedev.h b/src/fakedev.h
new file mode 100644
index 0000000..eec6037
--- /dev/null
+++ b/src/fakedev.h
@@ -0,0 +1,129 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#ifndef _FAKEDEV_H
+#define _FAKEDEV_H
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkimage.h>
+#include <X11/extensions/XTest.h>
+
+#include "config.h"
+
+typedef struct FakeApp FakeApp;
+typedef struct FakeButton FakeButton;
+
+struct FakeApp
+{
+ GtkWidget *window;
+ GtkWidget *fixed;
+ GtkWidget *winnest;
+ GtkWidget *popupmenu;
+ GtkWidget *debug_menu;
+
+ GtkWidget *prefs_window;
+ GtkWidget *entry_display, *entry_server, *entry_options;
+ GtkWidget *about_window;
+
+ int device_width;
+ int device_height;
+
+ int device_display_x;
+ int device_display_y;
+ int device_display_width;
+ int device_display_height;
+
+ GdkPixbuf *device_img;
+
+ /* Button stuff */
+
+ FakeButton *button_head; /* TODO: GList */
+
+ struct timeval key_rep_init_timeout;
+ struct timeval key_rep_timeout;
+
+ /* Xnest */
+
+ Display *xnest_dpy;
+ Window xnest_window;
+ char *xnest_dpy_name;
+ char *xnest_bin_path;
+ char *xnest_bin_options;
+ pid_t xnest_pid;
+
+ char *win_title;
+};
+
+struct FakeButton
+{
+ FakeApp *app;
+ GtkWidget *image;
+
+ int x,y;
+ int width,height;
+
+ KeySym keysym;
+
+ GdkPixbuf *overlay;
+ GdkPixmap *normal_img, *active_img;
+
+ int repeat;
+
+ FakeButton *next;
+};
+
+
+int
+config_init(FakeApp *app, char *conf_file);
+
+/* buttons */
+
+FakeButton*
+button_new(FakeApp *app, int x, int y, int width, int height, KeySym ks, int reepreat, GdkPixbuf *img);
+
+FakeButton*
+button_find_from_win(FakeApp *app, Window xevent_window_id);
+
+void
+button_press(GtkWidget *w, GdkEventButton *event, FakeButton *button);
+
+void
+button_release(GtkWidget *w, GdkEventButton *event, FakeButton *button);
+
+void
+button_activate(FakeApp *app, FakeButton *button);
+
+
+/* keys */
+
+#define KEYDOWN 1
+#define KEYUP 2
+#define KEYUPDOWN 3
+
+int
+keys_init(FakeApp *app);
+
+void
+keys_send_key(FakeApp *app, KeySym ks, int key_direction);
+
+#endif /* _FAKEDEV_H */
diff --git a/src/keys.c b/src/keys.c
new file mode 100644
index 0000000..d2a38ee
--- /dev/null
+++ b/src/keys.c
@@ -0,0 +1,105 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include "config.h"
+#include <X11/extensions/XTest.h>
+#include "fakedev.h"
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+static int
+keys_xnest_connect(FakeApp *app)
+{
+ int trys = 10;
+
+ do
+ {
+ if (--trys < 0) return 0;
+
+ sleep(1); /* Sleep for a second to give Xnest a chance to start */
+
+ app->xnest_dpy = XOpenDisplay(app->xnest_dpy_name);
+ {
+ int num_children;
+ Window root, parent;
+ Window *windows;
+ XQueryTree (GDK_WINDOW_XDISPLAY (app->winnest->window), GDK_WINDOW_XWINDOW(app->winnest->window), &root, &parent, &windows, &num_children);
+ if (num_children != 0) {
+ app->xnest_window = windows[0];
+ XFree (windows);
+ } else {
+ app->xnest_window = 0;
+ }
+ }
+ }
+ while ( app->xnest_dpy == NULL );
+
+ if (app->xnest_window == 0)
+ {
+ g_warning ("X Server failed to start.");
+ return 0;
+ }
+
+ return 1;
+}
+
+void
+keys_send_key(FakeApp *app, KeySym keysym, int key_direction)
+{
+ KeyCode character;
+
+ character = XKeysymToKeycode(app->xnest_dpy, keysym);
+
+ switch (key_direction)
+ {
+ case KEYDOWN:
+ XTestFakeKeyEvent(app->xnest_dpy, (unsigned int) character, True, 0);
+ break;
+ case KEYUP:
+ XTestFakeKeyEvent(app->xnest_dpy, (unsigned int) character, False, 0);
+ break;
+ case KEYUPDOWN:
+ XTestFakeKeyEvent(app->xnest_dpy, (unsigned int) character, False, 0);
+ XTestFakeKeyEvent(app->xnest_dpy, (unsigned int) character, True, 0);
+ break;
+ }
+
+ /* Make sure the event gets sent */
+ XFlush(app->xnest_dpy);
+
+}
+
+int
+keys_init(FakeApp *app)
+{
+ int event, error;
+ int major, minor;
+
+ if (keys_xnest_connect(app))
+ {
+ if (!XTestQueryExtension(app->xnest_dpy, &event, &error, &major, &minor))
+ {
+ g_warning ("XTest extension not supported on server \"%s\"\n.", DisplayString(app->xnest_dpy));
+ return 0;
+ }
+
+ return 1;
+
+ }
+
+ g_warning ("Failed to connect to X Server Display.");
+
+ return 0;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..336fb1d
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,351 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <glade/glade-xml.h>
+#include "fakedev.h"
+#include "callbacks.h"
+#include "prefs.h"
+
+#define XNEST_BIN "/usr/X11R6/bin/Xnest"
+
+/* Used by the signal handler to detect which child has died */
+static pid_t xnest_pid;
+
+static gboolean key_event (GtkWidget *widget, GdkEventKey *event, FakeApp *app);
+
+static void
+fakeapp_catch_sigchild(int sign);
+
+FakeApp*
+fakeapp_new(void)
+{
+ GladeXML *glade;
+ FakeApp *app = g_new0(FakeApp, 1);
+
+ app->xnest_dpy_name = ":1";
+ app->xnest_bin_path = XNEST_BIN ;
+ app->xnest_bin_options = strdup("-ac"); /* freed if changed */
+
+ app->key_rep_init_timeout.tv_usec = 0;
+ app->key_rep_init_timeout.tv_sec = 1;
+
+ app->key_rep_timeout.tv_usec = 40000;
+ app->key_rep_timeout.tv_sec = 0;
+
+ app->win_title = "matchbox-nest";
+
+ glade = glade_xml_new (PKGDATADIR "/matchbox-nest.glade", NULL, NULL);
+ g_assert (glade != NULL);
+
+ glade_xml_signal_connect_data (glade, "on_send_signal_activate", (GCallback)on_send_signal_activate, app);
+ glade_xml_signal_connect_data (glade, "on_quit_activate", (GCallback)on_quit_activate, app);
+ glade_xml_signal_connect_data (glade, "on_about_activate", (GCallback)on_about_activate, app);
+ glade_xml_signal_connect_data (glade, "on_window_destroy", (GCallback)on_window_destroy, app);
+ glade_xml_signal_connect_data (glade, "on_popup_menu_show", (GCallback)on_popup_menu_show, app);
+ glade_xml_signal_connect_data (glade, "on_show_decorations_toggle", (GCallback)on_show_decorations_toggle, app);
+ glade_xml_signal_connect_data (glade, "on_delete_event_hide", (GCallback)on_delete_event_hide, app);
+#if HAVE_GCONF
+ glade_xml_signal_connect_data (glade, "on_preferences_activate", (GCallback)on_preferences_activate, app);
+ glade_xml_signal_connect_data (glade, "on_prefs_apply_clicked", (GCallback)on_prefs_apply_clicked, app);
+ glade_xml_signal_connect_data (glade, "on_prefs_cancel_clicked", (GCallback)on_prefs_cancel_clicked, app);
+#else
+ gtk_widget_hide (glade_xml_get_widget (glade, "preferences"));
+#endif
+
+ app->window = glade_xml_get_widget (glade, "window");
+ app->fixed = glade_xml_get_widget (glade, "fixed");
+ gtk_fixed_set_has_window (GTK_FIXED (app->fixed), TRUE);
+ app->winnest = glade_xml_get_widget (glade, "winnest");
+ g_signal_connect(app->window, "key-press-event", (GCallback)key_event, app);
+ g_signal_connect(app->window, "key-release-event", (GCallback)key_event, app);
+
+ app->prefs_window = glade_xml_get_widget (glade, "prefswindow");
+ gtk_window_set_transient_for (GTK_WINDOW (app->prefs_window), GTK_WINDOW (app->window));
+ app->entry_display = glade_xml_get_widget (glade, "entry_display");
+ app->entry_server = glade_xml_get_widget (glade, "entry_server");
+ app->entry_options = glade_xml_get_widget (glade, "entry_options");
+
+ app->debug_menu = glade_xml_get_widget (glade, "send_signal");
+ app->popupmenu = glade_xml_get_widget (glade, "popupmenu_menu");
+ app->about_window = glade_xml_get_widget (glade, "aboutwindow");
+ gtk_window_set_transient_for (GTK_WINDOW (app->about_window), GTK_WINDOW (app->window));
+ g_signal_connect_swapped (glade_xml_get_widget (glade, "button_about_close"), "clicked", G_CALLBACK (gtk_widget_hide), app->about_window);
+
+ return app;
+}
+
+void
+fakeapp_create_gui(FakeApp *app)
+{
+ GdkPixmap *back;
+ GdkColor color;
+ GdkGC *gc;
+ FakeButton *button;
+
+ /* Configure the main window title and size */
+ gtk_window_set_title (GTK_WINDOW (app->window), app->win_title);
+ gtk_widget_set_size_request(app->window, app->device_width, app->device_height);
+
+ /* Move and set the size of the window for the Xnest. */
+ gtk_widget_set_size_request(app->winnest,
+ app->device_display_width,
+ app->device_display_height);
+ gtk_fixed_move (GTK_FIXED(app->fixed), app->winnest,
+ app->device_display_x,
+ app->device_display_y);
+
+ /* Force this widget to have X resources, so we can use it */
+ gtk_widget_realize (app->fixed);
+
+ /* Set the device image, by setting the back buffer of the widget */
+ back = gdk_pixmap_new (app->fixed->window, app->device_width, app->device_height, -1);
+ gc = gdk_gc_new (GDK_DRAWABLE (back));
+ gdk_color_parse ("black", &color);
+ gdk_gc_set_rgb_fg_color (gc, &color);
+ gdk_draw_rectangle (GDK_DRAWABLE (back), gc, TRUE, 0, 0, app->device_width, app->device_height);
+ gdk_draw_pixbuf (GDK_DRAWABLE (back), NULL, app->device_img, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
+ gdk_window_set_back_pixmap (app->fixed->window, back, FALSE);
+ g_object_unref (gc);
+
+ /* Now setup the buttons */
+ for (button = app->button_head; button; button=button->next)
+ {
+ GtkWidget *eventbox;
+ button->normal_img = gdk_pixmap_new (app->fixed->window, button->width, button->height, -1);
+ gdk_draw_pixbuf (GDK_DRAWABLE (button->normal_img), NULL, app->device_img, button->x, button->y, 0, 0, button->width, button->height, GDK_RGB_DITHER_NONE, 0, 0);
+ button->image = gtk_image_new_from_pixmap (button->normal_img, NULL);
+ gtk_widget_show (button->image);
+ eventbox = gtk_event_box_new ();
+ gtk_widget_show (eventbox);
+ gtk_container_add (GTK_CONTAINER (eventbox), button->image);
+ g_signal_connect (eventbox, "button-press-event", G_CALLBACK(button_press), button);
+ g_signal_connect (eventbox, "button-release-event", G_CALLBACK(button_release), button);
+ gtk_fixed_put (GTK_FIXED (app->fixed), eventbox, button->x, button->y);
+
+ if (button->overlay) {
+ button->active_img = gdk_pixmap_new (app->fixed->window, button->width, button->height, -1);
+ g_assert (button->active_img);
+ gc = gdk_gc_new (GDK_DRAWABLE (button->active_img));
+ gdk_draw_drawable (button->active_img, gc, button->normal_img, 0, 0, 0, 0, -1, -1);
+ gdk_draw_pixbuf (button->active_img, gc, button->overlay, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
+ } else {
+ button->active_img = gdk_pixmap_new (app->fixed->window, button->width, button->height, -1);
+ gdk_draw_pixbuf (button->active_img, NULL, app->device_img, button->x, button->y, 0, 0, button->width, button->height, GDK_RGB_DITHER_NONE, 0, 0);
+ gc = gdk_gc_new (GDK_DRAWABLE (button->active_img));
+ gdk_color_parse ("yellow", &color);
+ gdk_gc_set_rgb_fg_color (gc, &color);
+ gdk_draw_rectangle (GDK_DRAWABLE (button->active_img), gc, FALSE, 0, 0, button->width - 1, button->height - 1);
+ g_object_unref (gc);
+ }
+ }
+ gtk_widget_show (app->window);
+}
+
+static gboolean
+key_event (GtkWidget *widget, GdkEventKey *event, FakeApp *app)
+{
+ if (app->xnest_window == 0) {
+ g_warning("Skipping event send, no window to send to");
+ } else {
+ XEvent xevent;
+ xevent.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
+ xevent.xkey.window = GDK_WINDOW_XWINDOW (app->winnest->window);
+ xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (gdk_drawable_get_screen (app->winnest->window)));
+ xevent.xkey.time = event->time;
+ /* FIXME, the following might cause problems for non-GTK apps */
+ xevent.xkey.x = 0;
+ xevent.xkey.y = 0;
+ xevent.xkey.x_root = 0;
+ xevent.xkey.y_root = 0;
+ xevent.xkey.state = event->state;
+ xevent.xkey.keycode = event->hardware_keycode;
+ xevent.xkey.same_screen = TRUE;
+
+ gdk_error_trap_push ();
+ XSendEvent (GDK_WINDOW_XDISPLAY (app->winnest->window), app->xnest_window,
+ False, NoEventMask, &xevent);
+ gdk_display_sync (gtk_widget_get_display (widget));
+ if (gdk_error_trap_pop ()) {
+ g_warning("X error on XSendEvent");
+ }
+ }
+ return TRUE;
+}
+
+gboolean
+fakeapp_start_server(FakeApp *app)
+{
+ int pid;
+ gchar winid[32];
+ gchar exec_buf[2048];
+ gchar **exec_vector = NULL;
+
+ g_snprintf(winid, 32, "%li",
+ gdk_x11_drawable_get_xid(app->winnest->window));
+
+ g_snprintf(exec_buf, 2048, "%s %s %s -parent %s",
+ "Xnest",
+ app->xnest_dpy_name,
+ app->xnest_bin_options,
+ winid );
+
+ /* Split the above up into something execv can digest */
+ exec_vector = g_strsplit(exec_buf, " ", 0);
+
+ signal(SIGCHLD, fakeapp_catch_sigchild);
+
+ pid = fork();
+ switch (pid) {
+ case 0:
+ execv(app->xnest_bin_path, exec_vector);
+ g_warning( "Failed to Launch %s\n", app->xnest_bin_path);
+ exit(1);
+ case -1:
+ g_warning("Failed to Launch %s\n", app->xnest_bin_path);
+ break;
+ default:
+ g_strfreev(exec_vector);
+ app->xnest_pid = pid;
+ xnest_pid = pid;
+ }
+
+ if (pid == -1 || !keys_init(app))
+ {
+ g_warning ("'%s' Did not start correctly.", exec_buf);
+ g_warning ("Please restart with working --xnest-bin-options, --xnest-bin, options.");
+ exit(1);
+ }
+
+ /* Disable the debug signal if we are not running Xephyr */
+ if (strstr(app->xnest_bin_path, "Xephyr") == NULL) {
+ gtk_widget_set_sensitive (app->debug_menu, FALSE);
+ } else {
+ gtk_widget_set_sensitive (app->debug_menu, TRUE);
+ }
+
+ return FALSE;
+}
+
+static void
+fakeapp_catch_sigchild(int sign)
+{
+ pid_t this_pid;
+ this_pid = waitpid(-1, 0, WNOHANG);
+ if (this_pid != xnest_pid) return;
+ gtk_main_quit ();
+}
+
+gboolean
+fakeapp_restart_server(FakeApp *app)
+{
+ if (app->xnest_pid > 0)
+ {
+ XCloseDisplay(app->xnest_dpy);
+
+ signal(SIGCHLD, SIG_DFL); /* start_server() will reset this */
+ kill (app->xnest_pid, SIGTERM);
+ }
+
+ sleep(1); /* give server a chance to quit */
+
+ return fakeapp_start_server(app);
+}
+
+void
+usage(char *progname)
+{
+ fprintf(stderr,
+ "%s " VERSION " usage:\n"
+ "--xnest-dpy, -xd Display String for Xnest to use. ( default ':1')\n"
+ "--xnest-bin, -xn Location of Xnest binary ( default " XNEST_BIN ")\n"
+ "--xnest-bin-options -xo Command line opts to pass to server ( Default '-ac' )\n"
+ "--title, -t Set the window title\n"
+ "--device, -d Device config file to use\n"
+ "--help, -h Show this help\n",
+ progname);
+
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ FakeApp *app;
+ char *device = PKGDATADIR "/ipaq3800.xml";
+ int i;
+
+ gtk_init(&argc, &argv);
+ /* TODO: use popt */
+
+ app = fakeapp_new();
+
+#ifdef HAVE_GCONF
+ /* Do this here so that command line argument override the GConf prefs */
+ gconf_prefs_init(app);
+#endif
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp ("--xnest-dpy", argv[i]) || !strcmp ("-xd", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ app->xnest_dpy_name = argv[i];
+ continue;
+ }
+ if (!strcmp ("--xnest-bin", argv[i]) || !strcmp ("-xn", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ app->xnest_bin_path = argv[i];
+ continue;
+ }
+ if (!strcmp ("--xnest-bin-options", argv[i])
+ || !strcmp ("-xo", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ app->xnest_bin_options = argv[i];
+ continue;
+ }
+
+ if (!strcmp ("--device", argv[i]) || !strcmp ("-d", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ device = argv[i];
+ continue;
+ }
+ if (!strcmp ("--title", argv[i]) || !strcmp ("-t", argv[i])) {
+ if (++i>=argc) usage (argv[0]);
+ app->win_title = argv[i];
+ continue;
+ }
+
+ if (!strcmp("--help", argv[i]) || !strcmp("-h", argv[i])) {
+ usage(argv[0]);
+ }
+
+ usage(argv[0]);
+ }
+
+ config_init(app, device);
+
+ fakeapp_create_gui(app);
+
+ g_idle_add ((GSourceFunc)fakeapp_start_server, app);
+ gtk_main();
+
+ return 0;
+}
diff --git a/src/prefs.c b/src/prefs.c
new file mode 100644
index 0000000..22009fa
--- /dev/null
+++ b/src/prefs.c
@@ -0,0 +1,75 @@
+/* matchbox-nest - a graphical wrapper around xnest
+ *
+ * Copyright 2004 Matthew Allum
+ *
+ * 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, 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.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gconf/gconf-client.h>
+#include <gtk/gtk.h>
+#include "prefs.h"
+
+gboolean fakeapp_restart_server(FakeApp *app); /* TODO: move to a header */
+
+static GConfClient *gconf = NULL;
+
+void gconf_prefs_init(FakeApp *app) {
+ char *s;
+ gconf = gconf_client_get_default ();
+ g_return_if_fail (gconf != NULL);
+
+ s = gconf_client_get_string (gconf, GCONF_DISPLAY, NULL);
+ if (s != NULL && *s != '\0') {
+ app->xnest_dpy_name = s;
+ }
+
+ s = gconf_client_get_string (gconf, GCONF_SERVER, NULL);
+ if (s != NULL && *s != '\0') {
+ app->xnest_bin_path = s;
+ }
+
+ s = gconf_client_get_string (gconf, GCONF_SERVER_OPTIONS, NULL);
+ if (s != NULL && *s != '\0') {
+ app->xnest_bin_options = s;
+ }
+}
+
+void on_preferences_activate (GtkMenuItem *menuitem, FakeApp *app) {
+ gtk_entry_set_text (GTK_ENTRY (app->entry_display), app->xnest_dpy_name);
+ gtk_entry_set_text (GTK_ENTRY (app->entry_server), app->xnest_bin_path);
+ gtk_entry_set_text (GTK_ENTRY (app->entry_options), app->xnest_bin_options ? app->xnest_bin_options : "");
+ gtk_window_present (GTK_WINDOW (app->prefs_window));
+}
+
+void on_prefs_apply_clicked (GtkWidget *widget, FakeApp *app) {
+ const char *s = NULL;
+
+ s = gtk_entry_get_text (GTK_ENTRY (app->entry_display));
+ gconf_client_set_string (gconf, GCONF_DISPLAY, s, NULL);
+
+ s = gtk_entry_get_text (GTK_ENTRY (app->entry_server));
+ gconf_client_set_string (gconf, GCONF_SERVER, s, NULL);
+
+ s = gtk_entry_get_text (GTK_ENTRY (app->entry_options));
+ gconf_client_set_string (gconf, GCONF_SERVER_OPTIONS, s, NULL);
+
+ gconf_prefs_init (app);
+ fakeapp_restart_server (app);
+
+ gtk_widget_hide (app->prefs_window);
+}
+
+void on_prefs_cancel_clicked (GtkWidget *widget, FakeApp *app) {
+ gtk_widget_hide (app->prefs_window);
+}
diff --git a/src/prefs.h b/src/prefs.h
new file mode 100644
index 0000000..8dd911d
--- /dev/null
+++ b/src/prefs.h
@@ -0,0 +1,12 @@
+#include <gtk/gtkmenuitem.h>
+#include "fakedev.h"
+
+#define GCONF_DISPLAY "/apps/matchbox-nest/display"
+#define GCONF_SERVER "/apps/matchbox-nest/xserver"
+#define GCONF_SERVER_OPTIONS "/apps/matchbox-nest/xserver-options"
+
+void gconf_prefs_init(FakeApp *app);
+
+void on_preferences_activate (GtkMenuItem *menuitem, FakeApp *app);
+void on_prefs_apply_clicked (GtkWidget *widget, FakeApp *app);
+void on_prefs_cancel_clicked (GtkWidget *widget, FakeApp *app);
diff --git a/website/default.css b/website/default.css
new file mode 100644
index 0000000..1a38e0f
--- /dev/null
+++ b/website/default.css
@@ -0,0 +1,34 @@
+body {
+ margin: 0px;
+ padding-top: 0px;
+ background-color: white;
+ font-family: sans-serif;
+ color: black;
+}
+
+#header {
+ background: url(ohside.png) no-repeat right top;
+ height: 100px;
+}
+
+#header h1 {
+ color: #069;
+ margin-top: 0px;
+ margin-left: 20px;
+ padding-top: 20px;
+ padding-right: 100px;
+ font-size: 200%;
+ text-align: right;
+}
+
+#content {
+ margin-left: 30px;
+ margin-right: 30px;
+
+
+}
+
+#footer {
+ color: #ccc;
+ text-align: center;
+} \ No newline at end of file
diff --git a/website/index.html b/website/index.html
new file mode 100644
index 0000000..53f6f3e
--- /dev/null
+++ b/website/index.html
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>Matchbox Nest</title>
+ <link rel="stylesheet" type="text/css" href="default.css" />
+ <link rel="icon" href="http://www.openedhand.com/images/favicon.ico" />
+ <meta name="description" content="matchbox nest embedded x" />
+ </head>
+
+ <body>
+ <div id="header">
+ <h1>Matchbox Nest</h1>
+ </div>
+
+ <div id="content">
+ <p>
+ Matchbox Nest is a graphical wrapper around Xnest or Xephyr. It is
+ intended for embedded developers that want to simulate a target device
+ (with an accurate display size, working hardware buttons, etc) on a
+ desktop machine.
+ </p>
+
+ <p>
+ The size of the embedded X server, and the image around it, are
+ themable by the user. The default theme is based on a Compaq iPaq,
+ and supports the hardware buttons. Creating new themes is done by
+ writing a single simple XML file.
+ </p>
+
+ <p>
+ The embedded X server can either be <tt>Xnest</tt> (XFree86/X.org) or <a
+ href="http://www.freedesktop.org/wiki/Software_2fXephyr"><tt>Xephyr</tt></a>
+ (kdrive). The advantage of using <tt>Xephyr</tt> is that it supports
+ the newer X extensions such as Render, RandR, Composite, and Damage;
+ allowing you to test applications using these extensions even if your
+ native X server doesn't. Matchbox Nest can also send a signal to
+ <tt>Xephyr</tt> so that it will highlight the region it is painting, to
+ help debug redraw problems.
+ </p>
+
+ <h2>Screenshots</h2>
+ <p>
+ This is the default theme, a Compaq iPaq.
+ </p>
+ <img src="mb-nest-1.png" alt="Compaq iPaq theme"/>
+
+ <h2>Download</h2>
+ <p>
+ Tarballs for download are available at <a
+ href="http://projects.o-hand.com/matchbox/sources/matchbox-nest/"><tt>http://projects.o-hand.com/matchbox/sources/matchbox-nest/</tt></a>.
+ Debian packages are prepared and should be in <tt>unstable</tt> shortly.
+ </p>
+ </div>
+ </body>
+</html>
diff --git a/website/mb-nest-1.png b/website/mb-nest-1.png
new file mode 100644
index 0000000..bf93c64
--- /dev/null
+++ b/website/mb-nest-1.png
Binary files differ
diff --git a/website/ohside.png b/website/ohside.png
new file mode 100644
index 0000000..78c0c28
--- /dev/null
+++ b/website/ohside.png
Binary files differ