diff options
author | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-11-30 14:01:38 +0000 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-11-30 14:01:38 +0000 |
commit | 2e3122b5230284422be0001cd6a52c16ef707784 (patch) | |
tree | fadf8fd8b19ea605be000555be4a4a59b555ab09 |
XtoW
-rw-r--r-- | .gitignore | 78 | ||||
-rw-r--r-- | COPYING | 339 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rwxr-xr-x | autogen.sh | 12 | ||||
-rw-r--r-- | configure.ac | 26 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/debug.c | 37 | ||||
-rw-r--r-- | src/debug.h | 24 | ||||
-rw-r--r-- | src/main.c | 124 | ||||
-rw-r--r-- | src/win.c | 958 | ||||
-rw-r--r-- | src/winmessages.h | 1054 |
11 files changed, 2665 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15cf8eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,78 @@ +# +# X.Org module default exclusion patterns +# The next section if for module specific patterns +# +# Do not edit the following section +# GNU Build System (Autotools) +aclocal.m4 +autom4te.cache/ +autoscan.log +ChangeLog +compile +config.guess +config.h +config.h.in +config.log +config-ml.in +config.py +config.status +config.status.lineno +config.sub +configure +configure.scan +depcomp +.deps/ +INSTALL +install-sh +.libs/ +libtool +libtool.m4 +ltmain.sh +lt~obsolete.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +Makefile +Makefile.in +mdate-sh +missing +mkinstalldirs +*.pc +py-compile +stamp-h? +symlink-tree +texinfo.tex +ylwrap + +# Do not edit the following section +# Edit Compile Debug Document Distribute +*~ +*.[0-9] +*.[0-9]x +*.bak +*.bin +core +*.dll +*.exe +*-ISO*.bdf +*-JIS*.bdf +*-KOI8*.bdf +*.kld +*.ko +*.ko.cmd +*.lai +*.l[oa] +*.[oa] +*.obj +*.patch +*.so +*.pcf.gz +*.pdb +*.tar.bz2 +*.tar.gz +# +# Add & Override patterns for XtoW +# +# Edit the following section as needed +# For example, !report.pc overrides *.pc. See 'man gitignore' +# @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..904cd67 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..3cb8e91 --- /dev/null +++ b/configure.ac @@ -0,0 +1,26 @@ +AC_PREREQ(2.61) +AC_INIT([XtoW], [0.1]) + +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_CONFIG_HEADER([config.h]) +AM_SILENT_RULES([yes]) + +# Initialize libtool +AC_PROG_LIBTOOL + +# Require xorg-macros: XORG_DEFAULT_OPTIONS BASE_CFLAGS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.16 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.16) +XORG_DEFAULT_OPTIONS + +# check for programs +AC_PROG_CC +AC_PROG_INSTALL + +# Checks for libraries. +PKG_CHECK_MODULES(XCWM, xcwm) + +AC_CONFIG_FILES([Makefile + src/Makefile]) +AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..1ca1a0d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS = $(XCWM_CFLAGS) + +bin_PROGRAMS = xtow + +xtow_SOURCES = \ + main.c \ + win.c \ + debug.c \ + debug.h \ + winmessages.h + +xtow_LDADD = $(XCWM_LIBS) -lgdi32 diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..2761405 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,37 @@ +// +// Copyright © Jon TURNEY 2012 +// +// This file is part of XtoW. +// +// XtoW 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. +// +// XtoW 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 XtoW. If not, see <http://www.gnu.org/licenses/>. +// + +#include <stdarg.h> +#include <stdio.h> + +#include "debug.h" + +#if 1 +int +debug(const char *format, ...) +{ + int count; + va_list ap; + va_start(ap, format); + count = fprintf(stderr, "xtow: "); + count += vfprintf(stderr, format, ap); + va_end(ap); + return count; +} +#endif diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..d446b77 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,24 @@ +// +// Copyright © Jon TURNEY 2012 +// +// This file is part of XtoW. +// +// XtoW 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. +// +// XtoW 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 XtoW. If not, see <http://www.gnu.org/licenses/>. +// + +#if 1 +#define DEBUG debug +#else +#define DEBUG(Args...) +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..01eb40f --- /dev/null +++ b/src/main.c @@ -0,0 +1,124 @@ +// +// Copyright Jon © TURNEY 2012 +// +// This file is part of XtoW. +// +// XtoW 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. +// +// XtoW 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 XtoW. If not, see <http://www.gnu.org/licenses/>. +// + +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> +#include <getopt.h> +#include <xcwm/xcwm.h> + +#include "debug.h" + +void +eventHandler(const xcwm_event_t *event) +{ + xcwm_window_t *window = xcwm_event_get_window(event); + xcwm_event_type_t type = xcwm_event_get_type(event); + + DEBUG("event %d, window 0x%08x, XID 0x%08x\n", type, window, window->window_id); + + switch (type) + { + case XCWM_EVENT_WINDOW_CREATE: + winCreateWindowsWindow(window); + break; + + case XCWM_EVENT_WINDOW_DESTROY: + winDestroyWindowsWindow(window); + break; + + case XCWM_EVENT_WINDOW_NAME: + UpdateName(window); + break; + + case XCWM_EVENT_WINDOW_DAMAGE: + UpdateImage(window); + break; + + case XCWM_EVENT_WINDOW_EXPOSE: // I don't think this event could ever be needed and is a mistake + break; + } + + free(event); +} + +static void +help(void) +{ + fprintf(stderr, "usage: xtow [options]\n"); + fprintf(stderr, "-display dpy display to manage windows on\n"); + fprintf(stderr, "-help\n"); + exit(0); +} + +int main(int argc, char **argv) +{ + char *screen = NULL; + + while (1) + { + static struct option long_options[] = + { + { "display", required_argument, 0, 'd' }, + { "help", no_argument, 0, 'h' }, + {0, 0, 0, 0 }, + }; + + int option_index = 0; + int c = getopt_long_only(argc, argv, "d:h", long_options, &option_index); + + if (c == -1) + break; + + switch (c) + { + case 'd': + screen = optarg; + break; + case 'h': + default: + help(); + } + } + + if (optind < argc) + help(); + + DEBUG("screen is '%s'\n", screen); + + xcwm_context_t *context = xcwm_context_open(screen); + + // spawn the event loop thread, and set the callback function + xcwm_event_start_loop(context, eventHandler); + + // Pump windows message queue + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) + { + DispatchMessage(&msg); + } + + // Shutdown: + // if we got WM_QUIT, message loop exits + // if server died, we get a error from xcb + // if window station is shutting down, we get WM_ENDSESSION + // if we got a signal... + + xcwm_context_close(context); +} diff --git a/src/win.c b/src/win.c new file mode 100644 index 0000000..527fa9a --- /dev/null +++ b/src/win.c @@ -0,0 +1,958 @@ +// +// Copyright © Jon TURNEY 2012 +// +// This file is part of XtoW. +// +// XtoW 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. +// +// XtoW 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 XtoW. If not, see <http://www.gnu.org/licenses/>. +// + +// +// Lots of this stuff is ripped off from the existing integrated WM +// in XWin +// + +#include <windows.h> +#include <stdbool.h> +#include <stdio.h> +#include <xcwm/xcwm.h> + +#include "debug.h" +#include "winmessages.h" + +#define WINDOW_CLASS_X "xtow" +#define WINDOW_TITLE_X "X" +#define WIN_WID_PROP "cyg_wid_prop" +#define WIN_XCWM_PROP "cyg_xcwm_prop" +#define WIN_HDWP_PROP "cyg_hdwp_prop" + +/* + * ValidateSizing - Ensures size request respects hints + */ +static int +ValidateSizing (HWND hwnd, xcwm_window_t *window, + WPARAM wParam, LPARAM lParam) +{ + RECT *rect = (RECT *)lParam; + int iWidth, iHeight; + RECT rcClient, rcWindow; + int iBorderWidthX, iBorderWidthY; + + /* Invalid input checking */ + if (lParam==0) + return FALSE; + + iWidth = rect->right - rect->left; + iHeight = rect->bottom - rect->top; + + /* Now remove size of any borders and title bar */ + GetClientRect(hwnd, &rcClient); + GetWindowRect(hwnd, &rcWindow); + iBorderWidthX = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left); + iBorderWidthY = (rcWindow.bottom - rcWindow.top) - (rcClient.bottom - rcClient.top); + iWidth -= iBorderWidthX; + iHeight -= iBorderWidthY; + + /* Constrain the size to legal values */ + xcwm_window_constrain_sizing(window, &iWidth, &iHeight); + + /* Add back the size of borders and title bar */ + iWidth += iBorderWidthX; + iHeight += iBorderWidthY; + + /* Adjust size according to where we're dragging from */ + switch (wParam) { + case WMSZ_TOP: + case WMSZ_TOPRIGHT: + case WMSZ_BOTTOM: + case WMSZ_BOTTOMRIGHT: + case WMSZ_RIGHT: + rect->right = rect->left + iWidth; + break; + default: + rect->left = rect->right - iWidth; + break; + } + + switch(wParam) { + case WMSZ_BOTTOM: + case WMSZ_BOTTOMRIGHT: + case WMSZ_BOTTOMLEFT: + case WMSZ_RIGHT: + case WMSZ_LEFT: + rect->bottom = rect->top + iHeight; + break; + default: + rect->top = rect->bottom - iHeight; + break; + } + return TRUE; +} + +/* + * winAdjustXWindow + * + * Move and resize X window with respect to corresponding Windows window. + * + * This is when the user performs any windowing operation which might change + * it's size or position (create, move, resize, minimize, maximize, restore). + * + * The functionality is the inverse of winPositionWindowMultiWindow, which + * adjusts Windows window with respect to X window. + */ +int +winAdjustXWindow (xcwm_window_t *window, HWND hWnd) +{ + RECT rcWin; + LONG x, y, w, h; + +#define WIDTH(rc) (rc.right - rc.left) +#define HEIGHT(rc) (rc.bottom - rc.top) + + if (IsIconic(hWnd)) + { + DEBUG("Immediately return because the window is iconized\n"); + + /* XXX: match WM_STATE.state to state of Windows window */ + /* XXX: send a WM_CHANGE_STATE message ? */ + + return 0; + } + + /* Get size of client area */ + GetClientRect(hWnd, &rcWin); + w = WIDTH(rcWin); + h = HEIGHT(rcWin); + + /* Get virtual desktop coordinates of top-left of client area, + and transform to X screen coordinates */ + POINT p = {0,0}; + ClientToScreen(hWnd, &p); + x = p.x - GetSystemMetrics(SM_XVIRTUALSCREEN); + y = p.y - GetSystemMetrics(SM_YVIRTUALSCREEN); + + DEBUG("ConfigureWindow to %ldx%ld @ (%ld, %ld)\n", w, h, x, y); + + xcwm_window_configure(window, x, y, w, h); + + return 1; + +#undef WIDTH +#undef HEIGHT +} + +/* + * Updates the name of a HWND according to its X WM_NAME property + */ +void +UpdateName(xcwm_window_t *window) +{ + HWND hWnd = xcwm_window_get_local_data(window); + if (!hWnd) + return; + + /* If window isn't override-redirect */ + if (xcwm_window_is_override_redirect(window)) + return; + + char *name = xcwm_window_copy_name(window); + if (name) + { + DEBUG("UpdateName: '%s'\n", name); + + /* Convert from UTF-8 to wide char */ + int iLen = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); + wchar_t *pwszWideWindowName = (wchar_t *) malloc(sizeof(wchar_t) * (iLen + 1)); + MultiByteToWideChar(CP_UTF8, 0, name, -1, pwszWideWindowName, iLen); + + /* Set the Windows window name */ + SetWindowTextW(hWnd, pwszWideWindowName); + + free(pwszWideWindowName); + free(name); + } +} + +void +UpdateImage(xcwm_window_t *window) +{ + HWND hWnd = xcwm_window_get_local_data(window); + if (!hWnd) + return; + + xcwm_rect_t *dmgRect = xcwm_window_get_damaged_rect(window); + + RECT damage; + damage.left = dmgRect->x; + damage.top = dmgRect->y; + damage.right = dmgRect->x + dmgRect->width; + damage.bottom = dmgRect->y + dmgRect->height; + + InvalidateRect(hWnd, &damage, TRUE); +} + +#if 0 + +#define MwmHintsDecorations (1L << 1) + +#define MwmDecorAll (1L << 0) +#define MwmDecorBorder (1L << 1) +#define MwmDecorHandle (1L << 2) +#define MwmDecorTitle (1L << 3) +#define MwmDecorMenu (1L << 4) +#define MwmDecorMinimize (1L << 5) +#define MwmDecorMaximize (1L << 6) + +/* This structure only contains 3 elements... the Motif 2.0 structure +contains 5... we only need the first 3... so that is all we will define */ +typedef struct MwmHints { + unsigned long flags, functions, decorations; +} MwmHints; + +#define PropMwmHintsElements 3 + +/* Windows window styles */ +#define HINT_NOFRAME (1l<<0) +#define HINT_BORDER (1L<<1) +#define HINT_SIZEBOX (1l<<2) +#define HINT_CAPTION (1l<<3) +#define HINT_NOMAXIMIZE (1L<<4) +#define HINT_NOMINIMIZE (1L<<5) +#define HINT_NOSYSMENU (1L<<6) +#define HINT_SKIPTASKBAR (1L<<7) +/* These two are used on their own */ +#define HINT_MAX (1L<<0) +#define HINT_MIN (1L<<1) + +static void +winApplyHints(xcb_drawable_t id, HWND hWnd, HWND *zstyle) +{ + static xcb_atom_t windowState, motif_wm_hints, windowType; + static xcb_atom_t hiddenState, fullscreenState, belowState, aboveState, skiptaskbarState; + static xcb_atom_t dockWindow; + static bool got_atoms = FALSE; + unsigned long hint = 0, maxmin = 0; + int nitems = 0; + unsigned long style, exStyle; + xcb_get_property_reply_t *reply; + + *zstyle = HWND_NOTOPMOST; + + if (!hWnd) + return; + if (!IsWindow(hWnd)) + return; + + if (!got_atoms) + { + windowState = atom_get(conn, "_NET_WM_STATE"); + motif_wm_hints = atom_get(conn, "_MOTIF_WM_HINTS"); + windowType = atom_get(conn, "_NET_WM_WINDOW_TYPE"); + hiddenState = atom_get(conn, "_NET_WM_STATE_HIDDEN"); + fullscreenState = atom_get(conn, "_NET_WM_STATE_FULLSCREEN"); + belowState = atom_get(conn, "_NET_WM_STATE_BELOW"); + aboveState = atom_get(conn, "_NET_WM_STATE_ABOVE"); + dockWindow = atom_get(conn, "_NET_WM_WINDOW_TYPE_DOCK"); + skiptaskbarState = atom_get(conn, "_NET_WM_STATE_SKIP_TASKBAR"); + got_atoms = TRUE; + } + + xcb_get_property_cookie_t cookie_wm_state = xcb_get_property(conn, FALSE, id, windowState, XCB_ATOM, 0L, INT_MAX); + xcb_get_property_cookie_t cookie_mwm_hint = xcb_get_property(conn, FALSE, id, motif_wm_hints, motif_wm_hints, 0L, PropMwmHintsElements); + xcb_get_property_cookie_t cookie_wm_window_type = xcb_get_property(conn, FALSE, id, windowType, XCB_ATOM, 0L, 1L); + xcb_get_property_cookie_t cookie_normal_hints = xcb_icccm_get_wm_normal_hints(conn, id); + + if ((reply = xcb_get_property_reply(conn, cookie_wm_state, NULL))) + { + int i; + nitems = xcb_get_property_value_length(reply); + xcb_atom_t *pAtom = xcb_get_property_value(reply); + + for (i = 0; i < nitems; i++) + { + if (pAtom[i] == skiptaskbarState) + hint |= HINT_SKIPTASKBAR; + if (pAtom[i] == hiddenState) + maxmin |= HINT_MIN; + else if (pAtom[i] == fullscreenState) + maxmin |= HINT_MAX; + if (pAtom[i] == belowState) + *zstyle = HWND_BOTTOM; + else if (pAtom[i] == aboveState) + *zstyle = HWND_TOPMOST; + } + + free(reply); + } + + if ((reply = xcb_get_property_reply(conn, cookie_mwm_hint, NULL))) + { + nitems = xcb_get_property_value_length(reply); + MwmHints *mwm_hint = xcb_get_property_value(reply); + + if (mwm_hint && (nitems == PropMwmHintsElements) && (mwm_hint->flags & MwmHintsDecorations)) + { + if (!mwm_hint->decorations) + hint |= HINT_NOFRAME; + else if (!(mwm_hint->decorations & MwmDecorAll)) + { + if (mwm_hint->decorations & MwmDecorBorder) + hint |= HINT_BORDER; + if (mwm_hint->decorations & MwmDecorHandle) + hint |= HINT_SIZEBOX; + if (mwm_hint->decorations & MwmDecorTitle) + hint |= HINT_CAPTION; + if (!(mwm_hint->decorations & MwmDecorMenu)) + hint |= HINT_NOSYSMENU; + if (!(mwm_hint->decorations & MwmDecorMinimize)) + hint |= HINT_NOMINIMIZE; + if (!(mwm_hint->decorations & MwmDecorMaximize)) + hint |= HINT_NOMAXIMIZE; + } + else + { + /* + MwmDecorAll means all decorations *except* those specified by other flag + bits that are set. Not yet implemented. + */ + } + } + + free(reply); + } + + if ((reply = xcb_get_property_reply(conn, cookie_wm_window_type, NULL))) + { + nitems = xcb_get_property_value_length(reply); + xcb_atom_t *pAtom = xcb_get_property_value(reply); + + if (pAtom && nitems == 1) + { + if (*pAtom == dockWindow) + { + /* puts a sizebox on dock windows */ + hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; + *zstyle = HWND_TOPMOST; + } + } + + free(reply); + } + + { + xcb_size_hints_t normal_hint; + + if (xcb_icccm_get_wm_normal_hints_reply(conn, cookie_normal_hints, &normal_hint, NULL)) + { + if (normal_hint.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) + { + /* Not maximizable if a maximum size is specified */ + hint |= HINT_NOMAXIMIZE; + + if (normal_hint.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) + { + /* + If both minimum size and maximum size are specified and are the same, + don't bother with a resizing frame + */ + if ((normal_hint.min_width == normal_hint.max_width) + && (normal_hint.min_height == normal_hint.max_height)) + hint = (hint & ~HINT_SIZEBOX); + } + } + } + } + + /* XXX: Override hint settings from above with settings from config file */ + /* XXX: set application id from class hint for native window grouping */ + + /* XXX: this should only happen on initial show */ + if (maxmin & HINT_MAX) + SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (maxmin & HINT_MIN) + SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + /* Now apply styles to window */ + style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ + if (!style) + return; /* GetWindowLongPointer returns 0 on failure, we hope this isn't a valid style */ + + if (!(hint & ~HINT_SKIPTASKBAR)) /* All on */ + style = style | WS_CAPTION | WS_SIZEBOX; + else if (hint & HINT_NOFRAME) /* All off */ + style = style & ~WS_CAPTION & ~WS_SIZEBOX; + else + style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) | + ((hint & HINT_SIZEBOX) ? WS_SIZEBOX : 0) | + ((hint & HINT_CAPTION) ? WS_CAPTION : 0); + + if (hint & HINT_NOMAXIMIZE) + style = style & ~WS_MAXIMIZEBOX; + + if (hint & HINT_NOMINIMIZE) + style = style & ~WS_MINIMIZEBOX; + + if (hint & HINT_NOSYSMENU) + style = style & ~WS_SYSMENU; + + if (hint & HINT_SKIPTASKBAR) + style = style & ~WS_MINIMIZEBOX; /* otherwise, window will become lost if minimized */ + + SetWindowLongPtr(hWnd, GWL_STYLE, style); + + exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); + if (hint & HINT_SKIPTASKBAR) + exStyle = (exStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW; + else + exStyle = (exStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW; + SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle); + + DEBUG("winApplyHints: id 0x%08x hints 0x%08x style 0x%08x exstyle 0x%08x\n", + id, hint, style, exStyle); +} + +/* + * Updates the style of a HWND according to its X style properties + */ +static void +UpdateStyle(struct client *pWin) +{ + HWND hWnd = pWin->hWnd; + HWND zstyle = HWND_NOTOPMOST; + UINT flags; +#if 0 + bool onTaskbar; +#endif + + /* Determine the Window style */ + winApplyHints(pWin->id, hWnd, &zstyle); + winUpdateWindowPosition(hWnd, &zstyle); + + /* Apply the updated window style, without changing it's show or activation state */ + flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; + if (zstyle == HWND_NOTOPMOST) + flags |= SWP_NOZORDER | SWP_NOOWNERZORDER; + SetWindowPos(hWnd, NULL, 0, 0, 0, 0, flags); + +#if 0 + /* + Use the WS_EX_TOOLWINDOW style to remove window from Alt-Tab window switcher + + According to MSDN, this is supposed to remove the window from the taskbar as well, + if we SW_HIDE before changing the style followed by SW_SHOW afterwards. + + But that doesn't seem to work reliably, so also use iTaskbarList interface to + tell the taskbar to show or hide this window. + */ + onTaskbar = GetWindowLongPtr(hWnd, GWL_EXSTYLE) & WS_EX_APPWINDOW; + wintaskbar(hWnd, onTaskbar); + + /* Check urgency hint */ + winApplyUrgency(pWMInfo->pDisplay, iWindow, hWnd); +#endif +} + +#endif + +/* Don't allow window decoration to disappear off to top-left */ +void +BumpWindowPosition(HWND hWnd) +{ + WINDOWINFO wi; + int iDx, iDy; + + wi.cbSize = sizeof(WINDOWINFO); + GetWindowInfo(hWnd, &wi); + + if (wi.rcWindow.left < GetSystemMetrics(SM_XVIRTUALSCREEN)) + { + iDx = GetSystemMetrics(SM_XVIRTUALSCREEN) - wi.rcWindow.left; + wi.rcWindow.left += iDx; + wi.rcWindow.right += iDx; + } + + if (wi.rcWindow.top < GetSystemMetrics(SM_YVIRTUALSCREEN)) + { + iDy = GetSystemMetrics(SM_YVIRTUALSCREEN) - wi.rcWindow.top; + wi.rcWindow.top += iDy; + wi.rcWindow.bottom += iDy; + } + + /* Position the Windows window */ + SetWindowPos(hWnd, 0, wi.rcWindow.left, wi.rcWindow.top, wi.rcWindow.right - wi.rcWindow.left, wi.rcWindow.bottom - wi.rcWindow.top, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); +} + +static void +winDebugWin32Message(const char* function, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static int force = 1; + + if (message >= WM_USER) + { + if (force || getenv("WIN_DEBUG_MESSAGES") || getenv("WIN_DEBUG_WM_USER")) + { + DEBUG("%s: hWnd 0x%08x wParam 0x%08x lParam 0x%08x message WM_USER + %d\n", + function, hWnd, wParam, lParam, message - WM_USER); + } + } + else if (message < MESSAGE_NAMES_LEN && MESSAGE_NAMES[message]) + { + const char *msgname = MESSAGE_NAMES[message]; + char buffer[64]; + snprintf(buffer, sizeof(buffer), "WIN_DEBUG_%s", msgname); + buffer[63] = 0; + if (force || getenv("WIN_DEBUG_MESSAGES") || getenv(buffer)) + { + DEBUG("%s: hWnd 0x%08x wParam 0x%08x lParam 0x%08x message %s\n", + function, hWnd, wParam, lParam, MESSAGE_NAMES[message]); + } + } +} + +/* + * winTopLevelWindowProc - Window procedure for all top-level Windows windows. + */ + +LRESULT CALLBACK +winTopLevelWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static bool hasEnteredSizeMove = FALSE; + + winDebugWin32Message("winTopLevelWindowProc", hWnd, message, wParam, lParam); + + if (message == WM_CREATE) + { + /* Store the xcwm window handle and X window XID in a Windows window properties */ + xcwm_window_t *window = ((LPCREATESTRUCT)lParam)->lpCreateParams; + SetProp(hWnd, WIN_XCWM_PROP, window); + SetProp(hWnd, WIN_WID_PROP, (HANDLE)window->window_id); + return 0; + } + + xcwm_window_t *window = (xcwm_window_t *)GetProp(hWnd, WIN_XCWM_PROP); + + switch (message) + { + case WM_ACTIVATE: + /* If we are being activated, acquire the input focus */ + if (LOWORD(wParam) != WA_INACTIVE) + { + xcwm_window_set_input_focus(window); + } + return 0; + + case WM_ACTIVATEAPP: + /* If focus is going to another Windows app, no X window has the X input focus */ + if (!wParam) + { + xcwm_window_set_input_focus(NULL); + } + + case WM_MOUSEACTIVATE: + /* ??? override-redirect windows should not mouse-activate */ + break; + + case WM_CLOSE: + xcwm_window_request_close(window); + return 0; + + case WM_DESTROY: + RemoveProp(hWnd, WIN_WID_PROP); + RemoveProp(hWnd, WIN_XCWM_PROP); + RemoveProp(hWnd, WIN_HDWP_PROP); + break; + + case WM_MOVE: + /* Adjust the X Window to the moved Windows window */ + if (!hasEnteredSizeMove) + winAdjustXWindow(window, hWnd); + /* else: Wait for WM_EXITSIZEMOVE */ + return 0; + + case WM_SIZE: + if (!hasEnteredSizeMove) + { + /* Adjust the X Window to the moved Windows window */ + winAdjustXWindow(window, hWnd); + } + /* else: wait for WM_EXITSIZEMOVE */ + return 0; + + case WM_SIZING: + /* Need to legalize the size according to WM_NORMAL_HINTS */ + return ValidateSizing(hWnd, window, wParam, lParam); + + case WM_ENTERSIZEMOVE: + hasEnteredSizeMove = TRUE; + return 0; + + case WM_EXITSIZEMOVE: + /* Adjust the X Window to the moved Windows window */ + hasEnteredSizeMove = FALSE; + winAdjustXWindow(window, hWnd); + return 0; + + case WM_SHOWWINDOW: + /* ??? */ + break; + + case WM_WINDOWPOSCHANGED: + /* ??? handle Z-order changes by reflecting to X */ + + /* + * Pass the message to DefWindowProc to let the function + * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE. + */ + break; + + case WM_STYLECHANGING: + /* + When the style changes, adjust the Windows window size so the client area remains the same size, + and adjust the Windows window position so that the client area remains in the same place. + */ + { + RECT newWinRect; + DWORD dwExStyle; + DWORD dwStyle; + DWORD newStyle = ((STYLESTRUCT *) lParam)->styleNew; + WINDOWINFO wi; + HDWP hDwp; + + dwExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE); + + DEBUG("winTopLevelWindowProc: WM_STYLECHANGING from %08x %08x\n", dwStyle, dwExStyle); + + if (wParam == (WPARAM)GWL_EXSTYLE) + dwExStyle = newStyle; + + if (wParam == (WPARAM)GWL_STYLE) + dwStyle = newStyle; + + DEBUG("winTopLevelWindowProc: WM_STYLECHANGING to %08x %08x\n", dwStyle, dwExStyle); + + /* Get client rect in screen coordinates */ + wi.cbSize = sizeof(WINDOWINFO); + GetWindowInfo(hWnd, &wi); + + DEBUG("winTopLevelWindowProc: WM_STYLECHANGING client area {%d, %d, %d, %d}, {%d x %d}\n", + wi.rcClient.left, wi.rcClient.top, wi.rcClient.right, + wi.rcClient.bottom, wi.rcClient.right - wi.rcClient.left, + wi.rcClient.bottom - wi.rcClient.top); + + newWinRect = wi.rcClient; + if (!AdjustWindowRectEx(&newWinRect, dwStyle, FALSE, dwExStyle)) + DEBUG("winTopLevelWindowProc: WM_STYLECHANGING AdjustWindowRectEx failed\n"); + + DEBUG("winTopLevelWindowProc: WM_STYLECHANGING window area should be {%d, %d, %d, %d}, {%d x %d}\n", + newWinRect.left, newWinRect.top, newWinRect.right, + newWinRect.bottom, newWinRect.right - newWinRect.left, + newWinRect.bottom - newWinRect.top); + + /* + Style change hasn't happened yet, so we can't adjust the window size yet, as the winAdjustXWindow() + which WM_SIZE does will use the current (unchanged) style. Instead make a note to change it when + WM_STYLECHANGED is received... + */ + hDwp = BeginDeferWindowPos(1); + hDwp = DeferWindowPos(hDwp, hWnd, NULL, newWinRect.left, + newWinRect.top, newWinRect.right - newWinRect.left, + newWinRect.bottom - newWinRect.top, + SWP_NOACTIVATE | SWP_NOZORDER); + SetProp(hWnd, WIN_HDWP_PROP, (HANDLE)hDwp); + } + return 0; + + case WM_STYLECHANGED: + { + HDWP hDwp = GetProp(hWnd, WIN_HDWP_PROP); + if (hDwp) + { + EndDeferWindowPos(hDwp); + RemoveProp(hWnd, WIN_HDWP_PROP); + } + DEBUG("winTopLevelWindowProc: WM_STYLECHANGED done\n"); + } + return 0; + + case WM_ERASEBKGND: + /* Since we are going to blit to the entire invalidated region, + there's no point erasing to background first */ + return TRUE; + + case WM_PAINT: + { + HDC hdcUpdate; + PAINTSTRUCT ps; + hdcUpdate = BeginPaint(hWnd, &ps); + + /* Don't do anything if the PAINTSTRUCT is bogus */ + if (ps.rcPaint.right == 0 && ps.rcPaint.bottom == 0 && + ps.rcPaint.left == 0 && ps.rcPaint.top == 0) + { + } + else + { + /* XXX: just eat it for now... */ + ValidateRect(hWnd, &(ps.rcPaint)); + + /* stop xcwm processing events so it doesn't can't change + this damage while we are using it */ + xcwm_event_get_thread_lock(); + + xcwm_image_t *image; + image = xcwm_image_copy_damaged(window); + if (image) + { + xcwm_rect_t *winRect = xcwm_window_get_full_rect(window); + xcwm_rect_t *dmgRect = xcwm_window_get_damaged_rect(window); + + // convert xcwm_image_t to something we can draw... + + // Remove the damage + xcwm_window_remove_damage(window); + } + xcwm_event_release_thread_lock(); + } + + EndPaint(hWnd, &ps); + return 0; + } + + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +/* + * winInitMultiWindowClass - Register our Window class + */ +static +void winInitMultiWindowClass(void) +{ + static ATOM atomXWinClass = 0; + WNDCLASSEX wcx; + + if (atomXWinClass == 0) + { + wcx.cbSize = sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW; + wcx.lpfnWndProc = winTopLevelWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = GetModuleHandle(NULL); + wcx.hIcon = NULL; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X; + wcx.hIconSm = NULL; + + DEBUG("Creating class: %s\n", WINDOW_CLASS_X); + + atomXWinClass = RegisterClassEx (&wcx); + } +} + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ +void +winCreateWindowsWindow(xcwm_window_t *window) +{ + int iX, iY, iWidth, iHeight; + HWND hWnd; + HWND hFore = NULL; + DWORD dwStyle, dwExStyle; + RECT rc; + + winInitMultiWindowClass(); + + DEBUG("winCreateWindowsWindow: window 0x%08x XID 0x%08x\n", window, window->window_id); + + xcwm_rect_t *windowSize = xcwm_window_get_full_rect(window); + iX = windowSize->x + GetSystemMetrics(SM_XVIRTUALSCREEN); + iY = windowSize->y + GetSystemMetrics(SM_YVIRTUALSCREEN); + iWidth = windowSize->width; + iHeight = windowSize->height; + +#if 0 + // XXX: xcwm can probably just ignore input only windows... + xcb_get_window_attributes_reply_t *attr; + attr = xcb_get_window_attributes_reply(conn, xcb_get_window_attributes(conn, pWin->id), NULL); + + /* If it's an InputOutput window, and so is going to end up being made visible, + make sure the window actually ends up somewhere where it will be visible */ + if (attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) + { + if ((iX < GetSystemMetrics (SM_XVIRTUALSCREEN)) || (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN))) + iX = CW_USEDEFAULT; + + if ((iY < GetSystemMetrics (SM_YVIRTUALSCREEN)) || (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN))) + iY = CW_USEDEFAULT; + } +#endif + + DEBUG("winCreateWindowsWindow: %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + const xcwm_window_t *parent = xcwm_window_get_transient_for(window); + if (parent) + { + /* + If we are transient-for another window, get the parent windows HWND + */ + hFore = xcwm_window_get_local_data(parent); + } + else + { + /* Default positions if none specified */ + if (!xcwm_window_is_override_redirect(window)) + { +#if 0 + if (!(pWin->size_hints.flags & (XCB_ICCCM_SIZE_HINT_US_POSITION | XCB_ICCCM_SIZE_HINT_P_POSITION))) + { + iX = CW_USEDEFAULT; + iY = CW_USEDEFAULT; + } +#endif + } + } + + /* Make it WS_OVERLAPPED in create call since WS_POPUP doesn't support */ + /* CW_USEDEFAULT, change back to popup after creation */ + dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + dwExStyle = WS_EX_TOOLWINDOW; + + /* + Calculate the window coordinates containing the requested client area, + being careful to preseve CW_USEDEFAULT + */ + rc.top = (iY != (int)CW_USEDEFAULT) ? iY : 0; + rc.left = (iX != (int)CW_USEDEFAULT) ? iX : 0; + rc.bottom = rc.top + iHeight; + rc.right = rc.left + iWidth; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + if (iY != (int)CW_USEDEFAULT) iY = rc.top; + if (iX != (int)CW_USEDEFAULT) iX = rc.left; + iHeight = rc.bottom - rc.top; + iWidth = rc.right - rc.left; + + DEBUG("winCreateWindowsWindow: %dx%d @ %dx%d\n", iWidth, iHeight, iX, iY); + + /* Create the window */ + hWnd = CreateWindowExA(dwExStyle, /* Extended styles */ + WINDOW_CLASS_X, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + dwStyle, /* Styles */ + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + hFore, /* Null or Parent window if transient-for */ + (HMENU) NULL, /* No menu */ + GetModuleHandle(NULL), /* Instance handle */ + (LPVOID)window); /* xcwm window handle */ + if (hWnd == NULL) + { + fprintf(stderr, "CreateWindowExA() failed: %d\n", (int) GetLastError()); + } + + /* save the HWND into the context */ + xcwm_window_set_local_data(window, hWnd); + +#if 0 + /* Set icons */ + HICON hIcon; + HICON hIconSmall; + winSelectIcons(pWin, &hIcon, &hIconSmall); + if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); +#endif + + /* Change style back to popup, already placed... */ + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + /* Adjust the X window to match the window placement we actually got... */ + winAdjustXWindow(window, hWnd); + + /* Make sure it gets the proper system menu for a WS_POPUP, too */ + GetSystemMenu(hWnd, TRUE); + + /* Establish the default style */ + if (!xcwm_window_is_override_redirect(window)) + { + if (parent) + { + /* Set the transient style flags */ + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } + else + { + /* Set the window standard style flags */ + SetWindowLongPtr(hWnd, GWL_STYLE, (WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) & ~WS_CAPTION & ~WS_SIZEBOX); + } + } + else + { + /* override-redirect window, remains un-decorated, but put it on top of all other X windows */ + /* zstyle = SWP_TOPMOST; */ + } + + /* Apply all properties which effect the window appearance or behaviour */ + UpdateName(window); + /* UpdateIcon(); */ +#if 0 + if (!xcwm_window_is_override_redirect(window)) + UpdateStyle(window); +#endif + + BumpWindowPosition(hWnd); + +#if 0 + /* Display the window without activating it */ + if (attr->_class != XCB_WINDOW_CLASS_INPUT_ONLY) +#endif + ShowWindow (hWnd, SW_SHOWNOACTIVATE); +} + +void +winDestroyWindowsWindow(xcwm_window_t *window) +{ + DEBUG("winDestroyWindowsWindow: window 0x%08x XID 0x%08x\n", window, window->window_id); + + HWND hWnd = xcwm_window_get_local_data(window); + + /* Bail out if the Windows window handle is invalid */ + if (hWnd == NULL) + return; + +#if 0 + /* Store the info we need to destroy after this window is gone */ + hIcon = (HICON)SendMessage(pWin->hWnd, WM_GETICON, ICON_BIG, 0); + hIconSm = (HICON)SendMessage(pWin->hWnd, WM_GETICON, ICON_SMALL, 0); +#endif + + /* Destroy the Windows window */ + DestroyWindow(hWnd); + + /* Null our handle to the Window so referencing it will cause an error */ + xcwm_window_set_local_data(window, NULL); + +#if 0 + /* Destroy any icons we created for this window */ + winDestroyIcon(hIcon); + winDestroyIcon(hIconSm); +#endif +} diff --git a/src/winmessages.h b/src/winmessages.h new file mode 100644 index 0000000..8b04277 --- /dev/null +++ b/src/winmessages.h @@ -0,0 +1,1054 @@ +/* + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef WINMESSAGES_H +#define WINMESSAGES_H + +static const unsigned MESSAGE_NAMES_LEN = 1024; +static const char *MESSAGE_NAMES[1024] = { + "WM_NULL", + "WM_CREATE", + "WM_DESTROY", + "WM_MOVE", + "4", + "WM_SIZE", + "WM_ACTIVATE", + "WM_SETFOCUS", + "WM_KILLFOCUS", + "9", + "WM_ENABLE", + "WM_SETREDRAW", + "WM_SETTEXT", + "WM_GETTEXT", + "WM_GETTEXTLENGTH", + "WM_PAINT", + "WM_CLOSE", + "WM_QUERYENDSESSION", + "WM_QUIT", + "WM_QUERYOPEN", + "WM_ERASEBKGND", + "WM_SYSCOLORCHANGE", + "WM_ENDSESSION", + "23", + "WM_SHOWWINDOW", + "25", + "WM_WININICHANGE", + "WM_DEVMODECHANGE", + "WM_ACTIVATEAPP", + "WM_FONTCHANGE", + "WM_TIMECHANGE", + "WM_CANCELMODE", + NULL /* WM_SETCURSOR */, + "WM_MOUSEACTIVATE", + "WM_CHILDACTIVATE", + "WM_QUEUESYNC", + "WM_GETMINMAXINFO", + "37", + "WM_PAINTICON", + "WM_ICONERASEBKGND", + "WM_NEXTDLGCTL", + "41", + "WM_SPOOLERSTATUS", + "WM_DRAWITEM", + "WM_MEASUREITEM", + "WM_DELETEITEM", + "WM_VKEYTOITEM", + "WM_CHARTOITEM", + "WM_SETFONT", + "WM_GETFONT", + "WM_SETHOTKEY", + "WM_GETHOTKEY", + "52", + "53", + "54", + "WM_QUERYDRAGICON", + "56", + "WM_COMPAREITEM", + "58", + "59", + "60", + "61", + "62", + "63", + "64", + "WM_COMPACTING", + "66", + "67", + "WM_COMMNOTIFY", + "69", + "WM_WINDOWPOSCHANGING", + "WM_WINDOWPOSCHANGED", + "WM_POWER", + "73", + "WM_COPYDATA", + "WM_CANCELJOURNAL", + "76", + "77", + "WM_NOTIFY", + "79", + "WM_INPUTLANGCHANGEREQUEST", + "WM_INPUTLANGCHANGE", + "WM_TCARD", + "WM_HELP", + "WM_USERCHANGED", + "WM_NOTIFYFORMAT", + "86", + "87", + "88", + "89", + "90", + "91", + "92", + "93", + "94", + "95", + "96", + "97", + "98", + "99", + "100", + "101", + "102", + "103", + "104", + "105", + "106", + "107", + "108", + "109", + "110", + "111", + "112", + "113", + "114", + "115", + "116", + "117", + "118", + "119", + "120", + "121", + "122", + "WM_CONTEXTMENU", + "WM_STYLECHANGING", + "WM_STYLECHANGED", + "WM_DISPLAYCHANGE", + "WM_GETICON", + "WM_SETICON", + "WM_NCCREATE", + "WM_NCDESTROY", + "WM_NCCALCSIZE", + NULL /* WM_NCHITTEST */, + "WM_NCPAINT", + "WM_NCACTIVATE", + "WM_GETDLGCODE", + "WM_SYNCPAINT", + "137", + "138", + "139", + "140", + "141", + "142", + "143", + "144", + "145", + "146", + "147", + "148", + "149", + "150", + "151", + "152", + "153", + "154", + "155", + "156", + "157", + "158", + "159", + NULL /* WM_NCMOUSEMOVE */, + "WM_NCLBUTTONDOWN", + "WM_NCLBUTTONUP", + "WM_NCLBUTTONDBLCLK", + "WM_NCRBUTTONDOWN", + "WM_NCRBUTTONUP", + "WM_NCRBUTTONDBLCLK", + "WM_NCMBUTTONDOWN", + "WM_NCMBUTTONUP", + "WM_NCMBUTTONDBLCLK", + "170", + "171", + "172", + "173", + "174", + "175", + "176", + "177", + "178", + "179", + "180", + "181", + "182", + "183", + "184", + "185", + "186", + "187", + "188", + "189", + "190", + "191", + "192", + "193", + "194", + "195", + "196", + "197", + "198", + "199", + "200", + "201", + "202", + "203", + "204", + "205", + "206", + "207", + "208", + "209", + "210", + "211", + "212", + "213", + "214", + "215", + "216", + "217", + "218", + "219", + "220", + "221", + "222", + "223", + "224", + "225", + "226", + "227", + "228", + "229", + "230", + "231", + "232", + "233", + "234", + "235", + "236", + "237", + "238", + "239", + "240", + "241", + "242", + "243", + "244", + "245", + "246", + "247", + "248", + "249", + "250", + "251", + "252", + "253", + "254", + "255", + "WM_KEYDOWN", + "WM_KEYUP", + "WM_CHAR", + "WM_DEADCHAR", + "WM_SYSKEYDOWN", + "WM_SYSKEYUP", + "WM_SYSCHAR", + "WM_SYSDEADCHAR", + "WM_CONVERTREQUESTEX", + "265", + "266", + "267", + "268", + "WM_IME_STARTCOMPOSITION", + "WM_IME_ENDCOMPOSITION", + "WM_IME_KEYLAST", + "WM_INITDIALOG", + "WM_COMMAND", + "WM_SYSCOMMAND", + NULL /* WM_TIMER */, + "WM_HSCROLL", + "WM_VSCROLL", + "WM_INITMENU", + "WM_INITMENUPOPUP", + "280", + "281", + "282", + "283", + "284", + "285", + "286", + "WM_MENUSELECT", + "WM_MENUCHAR", + "WM_ENTERIDLE", + "290", + "291", + "292", + "293", + "294", + "295", + "296", + "297", + "298", + "299", + "300", + "301", + "302", + "303", + "304", + "305", + "WM_CTLCOLORMSGBOX", + "WM_CTLCOLOREDIT", + "WM_CTLCOLORLISTBOX", + "WM_CTLCOLORBTN", + "WM_CTLCOLORDLG", + "WM_CTLCOLORSCROLLBAR", + "WM_CTLCOLORSTATIC", + "313", + "314", + "315", + "316", + "317", + "318", + "319", + "320", + "321", + "322", + "323", + "324", + "325", + "326", + "327", + "328", + "329", + "330", + "331", + "332", + "333", + "334", + "335", + "336", + "337", + "338", + "339", + "340", + "341", + "342", + "343", + "344", + "345", + "346", + "347", + "348", + "349", + "350", + "351", + "352", + "353", + "354", + "355", + "356", + "357", + "358", + "359", + "360", + "361", + "362", + "363", + "364", + "365", + "366", + "367", + "368", + "369", + "370", + "371", + "372", + "373", + "374", + "375", + "376", + "377", + "378", + "379", + "380", + "381", + "382", + "383", + "384", + "385", + "386", + "387", + "388", + "389", + "390", + "391", + "392", + "393", + "394", + "395", + "396", + "397", + "398", + "399", + "400", + "401", + "402", + "403", + "404", + "405", + "406", + "407", + "408", + "409", + "410", + "411", + "412", + "413", + "414", + "415", + "416", + "417", + "418", + "419", + "420", + "421", + "422", + "423", + "424", + "425", + "426", + "427", + "428", + "429", + "430", + "431", + "432", + "433", + "434", + "435", + "436", + "437", + "438", + "439", + "440", + "441", + "442", + "443", + "444", + "445", + "446", + "447", + "448", + "449", + "450", + "451", + "452", + "453", + "454", + "455", + "456", + "457", + "458", + "459", + "460", + "461", + "462", + "463", + "464", + "465", + "466", + "467", + "468", + "469", + "470", + "471", + "472", + "473", + "474", + "475", + "476", + "477", + "478", + "479", + "480", + "481", + "482", + "483", + "484", + "485", + "486", + "487", + "488", + "489", + "490", + "491", + "492", + "493", + "494", + "495", + "496", + "497", + "498", + "499", + "500", + "501", + "502", + "503", + "504", + "505", + "506", + "507", + "508", + "509", + "510", + "511", + NULL /* WM_MOUSEMOVE */, + "WM_LBUTTONDOWN", + "WM_LBUTTONUP", + "WM_LBUTTONDBLCLK", + "WM_RBUTTONDOWN", + "WM_RBUTTONUP", + "WM_RBUTTONDBLCLK", + "WM_MBUTTONDOWN", + "WM_MBUTTONUP", + "WM_MBUTTONDBLCLK", + "WM_MOUSEWHEEL", + "WM_XBUTTONDOWN", + "WM_XBUTTONUP", + "WM_XBUTTONDBLCLK", + "526", + "527", + "WM_PARENTNOTIFY", + "WM_ENTERMENULOOP", + "WM_EXITMENULOOP", + "WM_NEXTMENU", + "WM_SIZING", + "WM_CAPTURECHANGED", + "WM_MOVING", + "535", + "WM_POWERBROADCAST", + "WM_DEVICECHANGE", + "538", + "539", + "540", + "541", + "542", + "543", + "WM_MDICREATE", + "WM_MDIDESTROY", + "WM_MDIACTIVATE", + "WM_MDIRESTORE", + "WM_MDINEXT", + "WM_MDIMAXIMIZE", + "WM_MDITILE", + "WM_MDICASCADE", + "WM_MDIICONARRANGE", + "WM_MDIGETACTIVE", + "554", + "555", + "556", + "557", + "558", + "559", + "WM_MDISETMENU", + "WM_ENTERSIZEMOVE", + "WM_EXITSIZEMOVE", + "WM_DROPFILES", + "WM_MDIREFRESHMENU", + "565", + "566", + "567", + "568", + "569", + "570", + "571", + "572", + "573", + "574", + "575", + "576", + "577", + "578", + "579", + "580", + "581", + "582", + "583", + "584", + "585", + "586", + "587", + "588", + "589", + "590", + "591", + "592", + "593", + "594", + "595", + "596", + "597", + "598", + "599", + "600", + "601", + "602", + "603", + "604", + "605", + "606", + "607", + "608", + "609", + "610", + "611", + "612", + "613", + "614", + "615", + "616", + "617", + "618", + "619", + "620", + "621", + "622", + "623", + "624", + "625", + "626", + "627", + "628", + "629", + "630", + "631", + "632", + "633", + "634", + "635", + "636", + "637", + "638", + "639", + "640", + "WM_IME_SETCONTEXT", + "WM_IME_NOTIFY", + "WM_IME_CONTROL", + "WM_IME_COMPOSITIONFULL", + "WM_IME_SELECT", + "WM_IME_CHAR", + "647", + "648", + "649", + "650", + "651", + "652", + "653", + "654", + "655", + "WM_IME_KEYDOWN", + "WM_IME_KEYUP", + "658", + "659", + "660", + "661", + "662", + "663", + "664", + "665", + "666", + "667", + "668", + "669", + "670", + "671", + "672", + "WM_MOUSEHOVER", + "674", + "WM_MOUSELEAVE", + "676", + "677", + "678", + "679", + "680", + "681", + "682", + "683", + "684", + "685", + "686", + "687", + "688", + "689", + "690", + "691", + "692", + "693", + "694", + "695", + "696", + "697", + "698", + "699", + "700", + "701", + "702", + "703", + "704", + "705", + "706", + "707", + "708", + "709", + "710", + "711", + "712", + "713", + "714", + "715", + "716", + "717", + "718", + "719", + "720", + "721", + "722", + "723", + "724", + "725", + "726", + "727", + "728", + "729", + "730", + "731", + "732", + "733", + "734", + "735", + "736", + "737", + "738", + "739", + "740", + "741", + "742", + "743", + "744", + "745", + "746", + "747", + "748", + "749", + "750", + "751", + "752", + "753", + "754", + "755", + "756", + "757", + "758", + "759", + "760", + "761", + "762", + "763", + "764", + "765", + "766", + "767", + "WM_CUT", + "WM_COPY", + "WM_PASTE", + "WM_CLEAR", + "WM_UNDO", + "WM_RENDERFORMAT", + "WM_RENDERALLFORMATS", + "WM_DESTROYCLIPBOARD", + "WM_DRAWCLIPBOARD", + "WM_PAINTCLIPBOARD", + "WM_VSCROLLCLIPBOARD", + "WM_SIZECLIPBOARD", + "WM_ASKCBFORMATNAME", + "WM_CHANGECBCHAIN", + "WM_HSCROLLCLIPBOARD", + "WM_QUERYNEWPALETTE", + "WM_PALETTEISCHANGING", + "WM_PALETTECHANGED", + "WM_HOTKEY", + "787", + "788", + "789", + "790", + "WM_PRINT", + "WM_PRINTCLIENT", + "793", + "794", + "795", + "796", + "797", + "798", + "799", + "800", + "801", + "802", + "803", + "804", + "805", + "806", + "807", + "808", + "809", + "810", + "811", + "812", + "813", + "814", + "815", + "816", + "817", + "818", + "819", + "820", + "821", + "822", + "823", + "824", + "825", + "826", + "827", + "828", + "829", + "830", + "831", + "832", + "833", + "834", + "835", + "836", + "837", + "838", + "839", + "840", + "841", + "842", + "843", + "844", + "845", + "846", + "847", + "848", + "849", + "850", + "851", + "852", + "853", + "854", + "855", + "856", + "857", + "858", + "859", + "860", + "861", + "862", + "863", + "864", + "865", + "866", + "867", + "868", + "869", + "870", + "871", + "872", + "873", + "874", + "875", + "876", + "877", + "878", + "879", + "880", + "881", + "882", + "883", + "884", + "885", + "886", + "887", + "888", + "889", + "890", + "891", + "892", + "893", + "894", + "895", + "896", + "897", + "898", + "899", + "900", + "901", + "902", + "903", + "904", + "905", + "906", + "907", + "908", + "909", + "910", + "911", + "912", + "913", + "914", + "915", + "916", + "917", + "918", + "919", + "920", + "921", + "922", + "923", + "924", + "925", + "926", + "927", + "928", + "929", + "930", + "931", + "932", + "933", + "934", + "935", + "936", + "937", + "938", + "939", + "940", + "941", + "942", + "943", + "944", + "945", + "946", + "947", + "948", + "949", + "950", + "951", + "952", + "953", + "954", + "955", + "956", + "957", + "958", + "959", + "960", + "961", + "962", + "963", + "964", + "965", + "966", + "967", + "968", + "969", + "970", + "971", + "972", + "973", + "974", + "975", + "976", + "977", + "978", + "979", + "980", + "981", + "982", + "983", + "984", + "985", + "986", + "987", + "988", + "989", + "990", + "991", + "992", + "993", + "994", + "995", + "996", + "997", + "998", + "999", + "1000", + "1001", + "1002", + "1003", + "1004", + "1005", + "1006", + "1007", + "1008", + "1009", + "1010", + "1011", + "1012", + "1013", + "1014", + "1015", + "1016", + "1017", + "1018", + "1019", + "1020", + "1021", + "1022", + "1023" +}; + +#endif |