summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--COPYING3
-rw-r--r--COPYING.GPL340
-rw-r--r--COPYING.MIT21
-rw-r--r--ChangeLog0
-rw-r--r--INSTALL9
-rw-r--r--Makefile.am10
-rw-r--r--NEWS0
-rw-r--r--README8
-rw-r--r--TODO22
-rwxr-xr-xautogen.sh3
-rw-r--r--compiz.pc.in12
-rw-r--r--configure.ac219
-rw-r--r--gnome/Makefile.am22
-rw-r--r--gnome/compiz-window-manager.c400
-rw-r--r--gnome/compiz-window-manager.h39
-rw-r--r--gnome/compiz.desktop13
-rw-r--r--gnome/compiz.desktop.in13
-rw-r--r--gnome/window-decorator/Makefile.am9
-rw-r--r--gnome/window-decorator/TODO6
-rw-r--r--gnome/window-decorator/gnome-window-decorator.c3163
-rw-r--r--images/Makefile.am8
-rw-r--r--images/background.pngbin0 -> 127 bytes
-rw-r--r--images/window.pngbin0 -> 9989 bytes
-rw-r--r--include/Makefile.am2
-rw-r--r--include/compiz.h1605
-rw-r--r--kde/Makefile.am1
-rw-r--r--kde/window-decorator/Makefile.am7
-rw-r--r--plugins/Makefile.am76
-rw-r--r--plugins/cube.c831
-rw-r--r--plugins/decoration.c1321
-rw-r--r--plugins/fade.c720
-rw-r--r--plugins/gconf.c1036
-rw-r--r--plugins/minimize.c820
-rw-r--r--plugins/move.c549
-rw-r--r--plugins/place.c1081
-rw-r--r--plugins/resize.c691
-rw-r--r--plugins/rotate.c1092
-rw-r--r--plugins/scale.c1263
-rw-r--r--plugins/switcher.c1565
-rw-r--r--plugins/wobbly.c2593
-rw-r--r--plugins/zoom.c823
-rw-r--r--src/Makefile.am22
-rw-r--r--src/action.c41
-rw-r--r--src/display.c1844
-rw-r--r--src/event.c1005
-rw-r--r--src/main.c211
-rw-r--r--src/option.c292
-rw-r--r--src/paint.c864
-rw-r--r--src/plugin.c404
-rw-r--r--src/privates.c68
-rw-r--r--src/readpng.c266
-rw-r--r--src/screen.c2521
-rw-r--r--src/texture.c337
-rw-r--r--src/window.c2903
55 files changed, 31175 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..41c6efe
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+David Reveman <davidr@novell.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..028ccfe
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,3 @@
+All code is licensed either under the GPL or the MIT license.
+
+For More information see COPYING.GPL and COPYING.MIT.
diff --git a/COPYING.GPL b/COPYING.GPL
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING.GPL
@@ -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/COPYING.MIT b/COPYING.MIT
new file mode 100644
index 0000000..69ef1bf
--- /dev/null
+++ b/COPYING.MIT
@@ -0,0 +1,21 @@
+
+Copyright © 2005 Novell, Inc.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without
+fee, provided that the above copyright notice appear in all copies
+and that both that copyright notice and this permission notice
+appear in supporting documentation, and that the name of
+Novell, Inc. not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+Novell, Inc. makes no representations about the suitability of this
+software for any purpose. It is provided "as is" without express or
+implied warranty.
+
+NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..038f661
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,9 @@
+compiz uses automake, in order to generate the Makefiles for compiz use:
+
+ $ autogen.sh
+
+After that, standard build procedures apply:
+
+ $ make
+ # make install
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..3c7c0b1
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,10 @@
+SUBDIRS = include src plugins images gnome kde
+
+EXTRA_DIST = \
+ COPYING \
+ COPYING.GPL \
+ COPYING.MIT \
+ compiz.pc.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = compiz.pc
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..d57217e
--- /dev/null
+++ b/README
@@ -0,0 +1,8 @@
+compiz - OpenGL window and compositing manager
+
+Compiz is an OpenGL compositing manager that use GLX_EXT_texture_from_pixmap
+for binding redirected top-level windows to texture objects. It has a flexible
+plug-in system and it is designed to run well on most graphics hardware.
+
+David Reveman
+davidr@novell.com
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..ac6bbc9
--- /dev/null
+++ b/TODO
@@ -0,0 +1,22 @@
+
+General:
+
+* Session management
+
+* Various window management improvements
+
+* Window shade mode
+
+* Support for multiple desktops
+
+* Multi-screen support
+
+
+KDE:
+
+* Remove glib dependency from place plugin
+
+* QT/KDE configuration plugin similar to the gconf plugin
+
+* QT/KDE decoration program
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..fa9b3b9
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+autoreconf -v --install || exit 1
+./configure "$@"
diff --git a/compiz.pc.in b/compiz.pc.in
new file mode 100644
index 0000000..bd6ba1c
--- /dev/null
+++ b/compiz.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: glxcompmgr
+Description: OpenGL compositing manager
+Version: @VERSION@
+
+Requires: @GLXCOMP_REQUIRES@
+Libs: @GLXCOMP_LIBS@ @GL_LIBS@
+Cflags: @GLXCOMP_CFLAGS@ @GL_CFLAGS@ -I${includedir}/glxcomp
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..ce985e8
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,219 @@
+AC_PREREQ(2.57)
+
+AC_INIT([compiz], [0.0.1], [davidr@novell.com])
+
+AC_CONFIG_AUX_DIR(config)
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+AC_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_LIBTOOL
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h sys/time.h unistd.h])
+
+if test "x$GCC" = "xyes"; then
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wall[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wall" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wpointer-arith[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wpointer-arith" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wstrict-prototypes[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wstrict-prototypes" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wmissing-prototypes[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wmissing-declarations[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-Wnested-externs[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -Wnested-externs" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-fno-strict-aliasing[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -fno-strict-aliasing" ;;
+ esac
+
+ if test "x$enable_ansi" = "xyes"; then
+ case " $CFLAGS " in
+ *[[\ \ ]]-ansi[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -ansi" ;;
+ esac
+
+ case " $CFLAGS " in
+ *[[\ \ ]]-pedantic[[\ \ ]]*) ;;
+ *) CFLAGS="$CFLAGS -pedantic" ;;
+ esac
+ fi
+fi
+
+AC_C_BIGENDIAN
+
+plugindir=$libdir/compiz
+AC_SUBST(plugindir)
+
+imagedir=$datadir/compiz
+AC_SUBST(imagedir)
+
+COMPIZ_REQUIRES="libpng \
+ xcomposite \
+ xfixes \
+ xdamage \
+ xrandr \
+ ice \
+ sm \
+ libstartup-notification-1.0 >= 0.7"
+
+PKG_CHECK_MODULES(COMPIZ, $COMPIZ_REQUIRES)
+AC_SUBST(COMPIZ_REQUIRES)
+
+AC_MSG_CHECKING(for GL_CFLAGS)
+AC_ARG_WITH(gl-cflags, [ --with-gl-cflags=CFLAGS ],
+ [GL_CFLAGS="$withval"],
+ [GL_CFLAGS=""])
+
+AC_MSG_RESULT($GL_CFLAGS)
+AC_MSG_CHECKING(for GL_LIBS)
+AC_ARG_WITH(gl-libs, [ --with-gl-libs=LIBS ],
+ [GL_LIBS="$withval"],
+ [GL_LIBS="-lGL"])
+AC_MSG_RESULT($GL_LIBS)
+
+AC_SUBST(GL_CFLAGS)
+AC_SUBST(GL_LIBS)
+
+AC_ARG_ENABLE(gconf,
+ [ --disable-gconf Disable gconf plugin],
+ [use_gconf=$enableval], [use_gconf=yes])
+
+if test "x$use_gconf" = "xyes"; then
+ PKG_CHECK_MODULES(GCONF, gconf-2.0, [use_gconf=yes], [use_gconf=no])
+fi
+
+AM_CONDITIONAL(GCONF_PLUGIN, test "x$use_gconf" = "xyes")
+if test "$use_gconf" = yes; then
+ AC_DEFINE(USE_GCONF, 1, [Build gconf plugin])
+fi
+
+AC_ARG_ENABLE(place,
+ [ --disable-place Disable window placement plugin],
+ [use_place=$enableval], [use_place=yes])
+
+if test "x$use_place" = "xyes"; then
+ PKG_CHECK_MODULES(PLACE, glib-2.0, [use_place=yes], [use_place=no])
+fi
+
+AM_CONDITIONAL(PLACE_PLUGIN, test "x$use_place" = "xyes")
+if test "$use_place" = yes; then
+ AC_DEFINE(USE_PLACE, 1, [Build placement plugin])
+fi
+
+AC_ARG_ENABLE(menu,
+ [ --disable-menu Disable window menu plugin],
+ [use_menu=$enableval], [use_menu=yes])
+
+if test "x$use_menu" = "xyes"; then
+ PKG_CHECK_MODULES(MENU, gtk+-2.0, [use_menu=yes], [use_menu=no])
+fi
+
+AM_CONDITIONAL(MENU_PLUGIN, test "x$use_menu" = "xyes")
+if test "$use_menu" = yes; then
+ AC_DEFINE(USE_MENU, 1, [Build menu plugin])
+fi
+
+AC_ARG_ENABLE(libsvg-cairo,
+ [ --enable-libsvg-cairo Enable svg support],
+ [use_libsvg_cairo=$enableval], [use_libsvg_cairo=no])
+
+if test "x$use_libsvg_cairo" = "xyes"; then
+ PKG_CHECK_MODULES(LIBSVG_CAIRO, libsvg-cairo,
+ [use_libsvg_cairo=yes],
+ [use_libsvg_cairo=no])
+fi
+
+AM_CONDITIONAL(USE_LIBSVG_CAIRO, [test x$use_libsvg_cairo = xyes])
+if test "$use_libsvg_cairo" = yes; then
+ AC_DEFINE(USE_LIBSVG_CAIRO, 1, [libsvg-cairo for SVG support])
+fi
+
+AC_ARG_ENABLE(gnome,
+ [ --disable-gnome Disable gnome window decorator and settings module],
+ [use_gnome=$enableval], [use_gnome=yes])
+
+if test "x$use_gnome" = "xyes"; then
+ PKG_CHECK_MODULES(GNOME_WINDOW_DECORATOR,
+ gtk+-2.0 libwnck-1.0 pangocairo,
+ [use_gnome=yes], [use_gnome=no])
+ if test "x$use_gnome" = "xyes"; then
+ PKG_CHECK_MODULES(GNOME_WINDOW_SETTINGS,
+ gnome-window-settings-2.0 gnome-desktop-2.0,
+ [use_gnome=yes], [use_gnome=no])
+ fi
+ windowsettingsdatadir=`pkg-config --variable=prefix gnome-window-settings-2.0`/share
+ windowsettingslibdir=`pkg-config --variable=libdir gnome-window-settings-2.0`
+fi
+
+AC_SUBST(windowsettingsdatadir)
+AC_SUBST(windowsettingslibdir)
+
+AM_CONDITIONAL(USE_GNOME, test "x$use_gnome" = "xyes")
+if test "$use_gnome" = yes; then
+ AC_DEFINE(USE_GNOME, 1, [Build gnome window decorator and settings module])
+fi
+
+AC_ARG_ENABLE(kde,
+ [ --disable-kde Disable kde window decorator],
+ [use_kde=$enableval], [use_kde=yes])
+
+if test "x$use_kde" = "xyes"; then
+ PKG_CHECK_MODULES(KDE_WINDOW_DECORATOR, QtCore,
+ [use_kde=yes], [use_kde=no])
+fi
+
+AM_CONDITIONAL(USE_KDE, test "x$use_kde" = "xyes")
+if test "$use_kde" = yes; then
+ AC_DEFINE(USE_KDE, 1, [Build kde window decorator])
+fi
+
+AC_OUTPUT([
+compiz.pc
+Makefile
+src/Makefile
+include/Makefile
+plugins/Makefile
+images/Makefile
+gnome/Makefile
+gnome/window-decorator/Makefile
+gnome/compiz.desktop
+kde/Makefile
+kde/window-decorator/Makefile
+])
+
+echo ""
+echo "the following optional plugins will be compiled:"
+echo " gconf: $use_gconf"
+echo " place: $use_place"
+echo " menu: $use_menu"
+echo " svg: $use_libsvg_cairo"
+echo ""
+echo "and the following optional features will be compiled:"
+echo " gnome: $use_gnome"
+echo " kde: $use_kde"
+echo ""
diff --git a/gnome/Makefile.am b/gnome/Makefile.am
new file mode 100644
index 0000000..29a5624
--- /dev/null
+++ b/gnome/Makefile.am
@@ -0,0 +1,22 @@
+SUBDIRS = window-decorator
+
+if USE_GNOME
+libcompiz_la_LDFLAGS = -export-dynamic -avoid-version
+libcompiz_la_LIBADD = @GNOME_WINDOW_SETTINGS_LIBS@
+libcompiz_la_SOURCES = \
+ compiz-window-manager.c \
+ compiz-window-manager.h
+libcompiz_module = libcompiz.la
+
+desktopfilesdir = $(windowsettingsdatadir)/gnome/wm-properties
+desktopfiles_in_files = compiz.desktop.in
+desktopfiles_files = $(desktopfiles_in_files:.desktop.in=.desktop)
+desktopfiles_DATA = $(desktopfiles_files)
+endif
+
+INCLUDES = @GNOME_WINDOW_SETTINGS_CFLAGS@
+
+moduledir = $(windowsettingslibdir)/window-manager-settings
+
+module_LTLIBRARIES = \
+ $(libcompiz_module)
diff --git a/gnome/compiz-window-manager.c b/gnome/compiz-window-manager.c
new file mode 100644
index 0000000..75e5779
--- /dev/null
+++ b/gnome/compiz-window-manager.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <config.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <gconf/gconf-client.h>
+
+#include "compiz-window-manager.h"
+
+#define COMPIZ_CLICK_TO_FOCUS_KEY \
+ "/apps/compiz/general/allscreens/options/click_to_focus"
+
+#define COMPIZ_AUTORAISE_KEY \
+ "/apps/compiz/general/allscreens/options/autoraise"
+
+#define COMPIZ_AUTORAISE_DELAY_KEY \
+ "/apps/compiz/general/allscreens/options/autoraise_delay"
+
+#define COMPIZ_MOUSE_MOVE_KEY \
+ "/apps/compiz/plugins/move/screen0/options/initiate"
+
+#define COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY \
+ "/apps/compiz/general/allscreens/options/action_double_click_titlebar"
+
+enum {
+ DOUBLE_CLICK_MAXIMIZE
+};
+
+static GnomeWindowManagerClass *parent_class;
+
+struct _CompizWindowManagerPrivate {
+ GConfClient *gconf;
+ char *mouse_modifier;
+};
+
+static void
+value_changed (GConfClient *client,
+ const gchar *key,
+ GConfValue *value,
+ void *data)
+{
+ CompizWindowManager *wm;
+
+ wm = COMPIZ_WINDOW_MANAGER (data);
+
+ gnome_window_manager_settings_changed (GNOME_WINDOW_MANAGER (wm));
+}
+
+/* this function is called when the shared lib is loaded */
+GObject *
+window_manager_new (int expected_interface_version)
+{
+ GObject *wm;
+
+ if (expected_interface_version != GNOME_WINDOW_MANAGER_INTERFACE_VERSION)
+ {
+ g_warning ("Compiz window manager module wasn't compiled with the "
+ "current version of gnome-control-center");
+ return NULL;
+ }
+
+ wm = g_object_new (compiz_window_manager_get_type (), NULL);
+
+ return wm;
+}
+
+static void
+compiz_change_settings (GnomeWindowManager *wm,
+ const GnomeWMSettings *settings)
+{
+ CompizWindowManager *cwm;
+
+ cwm = COMPIZ_WINDOW_MANAGER (wm);
+
+ if (settings->flags & GNOME_WM_SETTING_MOUSE_FOCUS)
+ gconf_client_set_bool (cwm->p->gconf,
+ COMPIZ_CLICK_TO_FOCUS_KEY,
+ settings->focus_follows_mouse == FALSE,
+ NULL);
+
+ if (settings->flags & GNOME_WM_SETTING_AUTORAISE)
+ gconf_client_set_bool (cwm->p->gconf,
+ COMPIZ_AUTORAISE_KEY,
+ settings->autoraise, NULL);
+
+ if (settings->flags & GNOME_WM_SETTING_AUTORAISE_DELAY)
+ gconf_client_set_int (cwm->p->gconf,
+ COMPIZ_AUTORAISE_DELAY_KEY,
+ settings->autoraise_delay, NULL);
+
+ if (settings->flags & GNOME_WM_SETTING_MOUSE_MOVE_MODIFIER)
+ {
+ char *value;
+
+ value = g_strdup_printf ("<%s>Button1", settings->mouse_move_modifier);
+ gconf_client_set_string (cwm->p->gconf,
+ COMPIZ_MOUSE_MOVE_KEY,
+ value, NULL);
+ g_free (value);
+ }
+
+/*
+ if (settings->flags & GNOME_WM_SETTING_DOUBLE_CLICK_ACTION)
+ {
+ const char *action = NULL;
+
+ switch (settings->double_click_action) {
+ case DOUBLE_CLICK_SHADE:
+ action = "toggle_shade";
+ break;
+ case DOUBLE_CLICK_MAXIMIZE:
+ action = "toggle_maximize";
+ break;
+ }
+
+ if (action)
+ gconf_client_set_string (meta_wm->p->gconf,
+ COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY,
+ action, NULL);
+ }
+*/
+
+}
+
+static void
+compiz_get_settings (GnomeWindowManager *wm,
+ GnomeWMSettings *settings)
+{
+ CompizWindowManager *cwm;
+ int to_get;
+
+ cwm = COMPIZ_WINDOW_MANAGER (wm);
+
+ to_get = settings->flags;
+ settings->flags = 0;
+
+ if (to_get & GNOME_WM_SETTING_MOUSE_FOCUS)
+ {
+ settings->focus_follows_mouse =
+ gconf_client_get_bool (cwm->p->gconf,
+ COMPIZ_CLICK_TO_FOCUS_KEY, NULL) == FALSE;
+
+ settings->flags |= GNOME_WM_SETTING_MOUSE_FOCUS;
+ }
+
+ if (to_get & GNOME_WM_SETTING_AUTORAISE)
+ {
+ settings->autoraise = FALSE;
+
+ settings->autoraise = gconf_client_get_bool (cwm->p->gconf,
+ COMPIZ_AUTORAISE_KEY,
+ NULL);
+
+ settings->flags |= GNOME_WM_SETTING_AUTORAISE;
+ }
+
+ if (to_get & GNOME_WM_SETTING_AUTORAISE_DELAY)
+ {
+ settings->autoraise_delay =
+ gconf_client_get_int (cwm->p->gconf,
+ COMPIZ_AUTORAISE_DELAY_KEY,
+ NULL);
+
+ settings->flags |= GNOME_WM_SETTING_AUTORAISE_DELAY;
+ }
+
+ if (to_get & GNOME_WM_SETTING_MOUSE_MOVE_MODIFIER)
+ {
+ const char *new;
+ char *str;
+
+ str = gconf_client_get_string (cwm->p->gconf,
+ COMPIZ_MOUSE_MOVE_KEY,
+ NULL);
+
+ if (str == NULL)
+ str = g_strdup ("<Super>");
+
+ if (strncmp (str, "<Super>", 7) == 0)
+ new = "Super";
+ else if (strncmp (str, "<Alt>", 5) == 0)
+ new = "Alt";
+ else if (strncmp (str, "<Meta>", 6) == 0)
+ new = "Meta";
+ else if (strncmp (str, "<Hyper>", 7) == 0)
+ new = "Hyper";
+ else if (strncmp (str, "<Control>", 9) == 0)
+ new = "Control";
+ else
+ new = NULL;
+
+ if (new && cwm->p->mouse_modifier &&
+ strcmp (new, cwm->p->mouse_modifier) == 0)
+ {
+ /* unchanged */;
+ }
+ else
+ {
+ g_free (cwm->p->mouse_modifier);
+ cwm->p->mouse_modifier = g_strdup (new ? new : "");
+ }
+
+ g_free (str);
+
+ settings->mouse_move_modifier = cwm->p->mouse_modifier;
+
+ settings->flags |= GNOME_WM_SETTING_MOUSE_MOVE_MODIFIER;
+ }
+
+ if (to_get & GNOME_WM_SETTING_DOUBLE_CLICK_ACTION)
+ {
+/*
+ char *str;
+
+ str = gconf_client_get_string (cwm->p->gconf,
+ COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY,
+ NULL);
+
+ if (str == NULL)
+ str = g_strdup ("toggle_shade");
+
+ if (strcmp (str, "toggle_shade") == 0)
+ settings->double_click_action = DOUBLE_CLICK_SHADE;
+ else if (strcmp (str, "toggle_maximize") == 0)
+ settings->double_click_action = DOUBLE_CLICK_MAXIMIZE;
+ else
+ settings->double_click_action = DOUBLE_CLICK_SHADE;
+
+ g_free (str);
+
+ settings->flags |= GNOME_WM_SETTING_DOUBLE_CLICK_ACTION;
+*/
+ }
+}
+
+static int
+compiz_get_settings_mask (GnomeWindowManager *wm)
+{
+ return
+/* GNOME_WM_SETTING_FONT | */
+ GNOME_WM_SETTING_MOUSE_FOCUS |
+ GNOME_WM_SETTING_AUTORAISE |
+ GNOME_WM_SETTING_AUTORAISE_DELAY |
+ GNOME_WM_SETTING_MOUSE_MOVE_MODIFIER |
+/* GNOME_WM_SETTING_THEME | */
+/* GNOME_WM_SETTING_DOUBLE_CLICK_ACTION */ 0;
+}
+
+static GList *
+compiz_get_theme_list (GnomeWindowManager *wm)
+{
+ return NULL;
+}
+
+static char *
+compiz_get_user_theme_folder (GnomeWindowManager *wm)
+{
+ return NULL;
+}
+
+static void
+compiz_get_double_click_actions (GnomeWindowManager *wm,
+ const GnomeWMDoubleClickAction **actions_p,
+ int *n_actions_p)
+{
+ static GnomeWMDoubleClickAction actions[] = {
+ { DOUBLE_CLICK_MAXIMIZE, "Maximize" }
+ };
+ static gboolean initialized = FALSE;
+
+ if (!initialized)
+ {
+ int i = 0;
+
+ initialized = TRUE;
+ while (i < (int) G_N_ELEMENTS (actions))
+ {
+ g_assert (actions[i].number == i);
+ actions[i].human_readable_name = actions[i].human_readable_name;
+
+ ++i;
+ }
+ }
+
+ *actions_p = actions;
+ *n_actions_p = (int) G_N_ELEMENTS (actions);
+}
+
+static void
+compiz_window_manager_init (CompizWindowManager *cwm,
+ CompizWindowManagerClass *class)
+{
+ cwm->p = g_new0 (CompizWindowManagerPrivate, 1);
+ cwm->p->gconf = gconf_client_get_default ();
+ cwm->p->mouse_modifier = NULL;
+
+ gconf_client_add_dir (cwm->p->gconf,
+ "/apps/compiz",
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ g_signal_connect (G_OBJECT (cwm->p->gconf),
+ "value_changed",
+ G_CALLBACK (value_changed),
+ cwm);
+}
+
+static void
+compiz_window_manager_finalize (GObject *object)
+{
+ CompizWindowManager *cwm;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_COMPIZ_WINDOW_MANAGER (object));
+
+ cwm = COMPIZ_WINDOW_MANAGER (object);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (cwm->p->gconf),
+ G_CALLBACK (value_changed),
+ cwm);
+
+ g_object_unref (G_OBJECT (cwm->p->gconf));
+ g_free (cwm->p);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+compiz_window_manager_class_init (CompizWindowManagerClass *class)
+{
+ GObjectClass *object_class;
+ GnomeWindowManagerClass *wm_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ wm_class = GNOME_WINDOW_MANAGER_CLASS (class);
+
+ object_class->finalize = compiz_window_manager_finalize;
+
+ wm_class->change_settings = compiz_change_settings;
+ wm_class->get_settings = compiz_get_settings;
+ wm_class->get_settings_mask = compiz_get_settings_mask;
+ wm_class->get_theme_list = compiz_get_theme_list;
+ wm_class->get_user_theme_folder = compiz_get_user_theme_folder;
+ wm_class->get_double_click_actions = compiz_get_double_click_actions;
+
+ parent_class = g_type_class_peek_parent (class);
+}
+
+GType
+compiz_window_manager_get_type (void)
+{
+ static GType compiz_window_manager_type = 0;
+
+ if (!compiz_window_manager_type)
+ {
+ static GTypeInfo compiz_window_manager_info = {
+ sizeof (CompizWindowManagerClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) compiz_window_manager_class_init,
+ NULL,
+ NULL,
+ sizeof (CompizWindowManager),
+ 0,
+ (GInstanceInitFunc) compiz_window_manager_init,
+ NULL
+ };
+
+ compiz_window_manager_type =
+ g_type_register_static (gnome_window_manager_get_type (),
+ "CompizWindowManager",
+ &compiz_window_manager_info, 0);
+ }
+
+ return compiz_window_manager_type;
+}
diff --git a/gnome/compiz-window-manager.h b/gnome/compiz-window-manager.h
new file mode 100644
index 0000000..5506e63
--- /dev/null
+++ b/gnome/compiz-window-manager.h
@@ -0,0 +1,39 @@
+#ifndef COMPIZ_WINDOW_MANAGER_H
+#define COMPIZ_WINDOW_MANAGER_H
+
+#include <glib-object.h>
+
+#include "gnome-window-manager.h"
+
+#define COMPIZ_WINDOW_MANAGER(obj) \
+ G_TYPE_CHECK_INSTANCE_CAST (obj, compiz_window_manager_get_type (), \
+ CompizWindowManager)
+
+#define COMPIZ_WINDOW_MANAGER_CLASS(klass) \
+ G_TYPE_CHECK_CLASS_CAST (klass, compiz_window_manager_get_type (), \
+ MetacityWindowManagerClass)
+
+#define IS_COMPIZ_WINDOW_MANAGER(obj) \
+ G_TYPE_CHECK_INSTANCE_TYPE (obj, compiz_window_manager_get_type ())
+
+
+typedef struct _CompizWindowManager CompizWindowManager;
+typedef struct _CompizWindowManagerClass CompizWindowManagerClass;
+typedef struct _CompizWindowManagerPrivate CompizWindowManagerPrivate;
+
+struct _CompizWindowManager {
+ GnomeWindowManager parent;
+ CompizWindowManagerPrivate *p;
+};
+
+struct _CompizWindowManagerClass {
+ GnomeWindowManagerClass klass;
+};
+
+GType
+compiz_window_manager_get_type (void);
+
+GObject *
+window_manager_new (int expected_interface_version);
+
+#endif
diff --git a/gnome/compiz.desktop b/gnome/compiz.desktop
new file mode 100644
index 0000000..cde9bae
--- /dev/null
+++ b/gnome/compiz.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Compiz
+Exec=compiz
+# name of loadable control center module
+X-GNOME-WMSettingsModule=compiz
+# name we put on the WM spec check window
+X-GNOME-WMName=compiz
+# back compat only
+X-GnomeWMSettingsLibrary=compiz
+
+[Window Manager]
+SessionManaged=false
diff --git a/gnome/compiz.desktop.in b/gnome/compiz.desktop.in
new file mode 100644
index 0000000..cde9bae
--- /dev/null
+++ b/gnome/compiz.desktop.in
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Compiz
+Exec=compiz
+# name of loadable control center module
+X-GNOME-WMSettingsModule=compiz
+# name we put on the WM spec check window
+X-GNOME-WMName=compiz
+# back compat only
+X-GnomeWMSettingsLibrary=compiz
+
+[Window Manager]
+SessionManaged=false
diff --git a/gnome/window-decorator/Makefile.am b/gnome/window-decorator/Makefile.am
new file mode 100644
index 0000000..9702084
--- /dev/null
+++ b/gnome/window-decorator/Makefile.am
@@ -0,0 +1,9 @@
+if USE_GNOME
+gnome_window_decorator_LDADD = @GNOME_WINDOW_DECORATOR_LIBS@
+gnome_window_decorator_SOURCES = gnome-window-decorator.c
+gnome_window_decorator_program = gnome-window-decorator
+endif
+
+INCLUDES = @GNOME_WINDOW_DECORATOR_CFLAGS@
+
+bin_PROGRAMS = $(gnome_window_decorator_program) \ No newline at end of file
diff --git a/gnome/window-decorator/TODO b/gnome/window-decorator/TODO
new file mode 100644
index 0000000..d1b8e93
--- /dev/null
+++ b/gnome/window-decorator/TODO
@@ -0,0 +1,6 @@
+
+* Plugin interface
+
+* Plugin with SVG-based theme support
+
+* Plugin that supports old metacity themes \ No newline at end of file
diff --git a/gnome/window-decorator/gnome-window-decorator.c b/gnome/window-decorator/gnome-window-decorator.c
new file mode 100644
index 0000000..871c75a
--- /dev/null
+++ b/gnome/window-decorator/gnome-window-decorator.c
@@ -0,0 +1,3163 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+
+#ifndef GTK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#endif
+
+#include <gtk/gtk.h>
+#include <gtk/gtkwindow.h>
+#include <gdk/gdkx.h>
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+#include <libwnck/window-action-menu.h>
+
+#include <cairo.h>
+#include <cairo-xlib.h>
+
+#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 1, 0)
+#define CAIRO_EXTEND_PAD CAIRO_EXTEND_NONE
+#endif
+
+#include <pango/pango-context.h>
+#include <pango/pangocairo.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+
+#define LEFT_SPACE 12
+#define RIGHT_SPACE 14
+#define TOP_SPACE 27
+#define BOTTOM_SPACE 14
+
+#define ICON_SPACE 20
+#define BUTTON_SPACE 52
+
+typedef struct _extents {
+ gint left;
+ gint right;
+ gint top;
+ gint bottom;
+} extents;
+
+#define GRAVITY_WEST (0)
+#define GRAVITY_EAST (1 << 0)
+#define GRAVITY_NORTH (0)
+#define GRAVITY_SOUTH (1 << 1)
+
+#define ALIGN_LEFT (0)
+#define ALIGN_RIGHT (1 << 0)
+#define ALIGN_TOP (0)
+#define ALIGN_BOTTOM (1 << 1)
+
+#define XX_MASK (1 << 6)
+#define XY_MASK (1 << 7)
+#define YX_MASK (1 << 8)
+#define YY_MASK (1 << 9)
+
+#define WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define WM_MOVERESIZE_SIZE_TOP 1
+#define WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define WM_MOVERESIZE_SIZE_RIGHT 3
+#define WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define WM_MOVERESIZE_SIZE_BOTTOM 5
+#define WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define WM_MOVERESIZE_SIZE_LEFT 7
+#define WM_MOVERESIZE_MOVE 8
+#define WM_MOVERESIZE_SIZE_KEYBOARD 9
+#define WM_MOVERESIZE_MOVE_KEYBOARD 10
+
+typedef struct _point {
+ gint x;
+ gint y;
+ gint gravity;
+} point;
+
+typedef struct _quad {
+ point p1;
+ point p2;
+ gint max_width;
+ gint max_height;
+ gint align;
+ cairo_matrix_t m;
+} quad;
+
+#ifdef __SUNPRO_C
+#pragma align 4 (_shadow)
+#endif
+#ifdef __GNUC__
+static const guint8 _shadow[] __attribute__ ((__aligned__ (4))) =
+#else
+ static const guint8 _shadow[] =
+#endif
+{ ""
+ /* Pixbuf magic (0x47646b50) */
+ "GdkP"
+ /* length: header (24) + pixel_data (400) */
+ "\0\0\1\250"
+ /* pixdata_type (0x1010002) */
+ "\1\1\0\2"
+ /* rowstride (40) */
+ "\0\0\0("
+ /* width (10) */
+ "\0\0\0\12"
+ /* height (10) */
+ "\0\0\0\12"
+ /* pixel_data: */
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\3\0\0\0\5\0\0\0\7\0\0\0\7\0\0\0\5"
+ "\0\0\0\3\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0\3\0\0\0\7\0\0\0\15\0\0\0\22\0"
+ "\0\0\22\0\0\0\15\0\0\0\7\0\0\0\3\0\0\0\1\0\0\0\1\0\0\0\5\0\0\0\15\0\0"
+ "\0\30\0\0\0\40\0\0\0\40\0\0\0\30\0\0\0\15\0\0\0\5\0\0\0\1\0\0\0\2\0\0"
+ "\0\7\0\0\0\22\0\0\0\40\377\377\377\377\0\0\0+\0\0\0\40\0\0\0\22\0\0\0"
+ "\7\0\0\0\2\0\0\0\2\0\0\0\7\0\0\0\22\0\0\0\40\0\0\0+\0\0\0+\0\0\0\40\0"
+ "\0\0\22\0\0\0\7\0\0\0\2\0\0\0\1\0\0\0\5\0\0\0\15\0\0\0\30\0\0\0\40\0"
+ "\0\0\40\0\0\0\30\0\0\0\15\0\0\0\5\0\0\0\1\0\0\0\1\0\0\0\3\0\0\0\7\0\0"
+ "\0\15\0\0\0\22\0\0\0\22\0\0\0\15\0\0\0\7\0\0\0\3\0\0\0\1\0\0\0\0\0\0"
+ "\0\1\0\0\0\3\0\0\0\5\0\0\0\7\0\0\0\7\0\0\0\5\0\0\0\3\0\0\0\1\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\0\0\0"
+ "\0\0\0\0\0\0"
+};
+
+static extents _shadow_extents = { 0, 0, 0, 0 };
+
+static quad _shadow_quads[] = {
+ {
+ { -4, -4, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_NORTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, 0.0
+ }
+ }, {
+ { 0, -4, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 4.0, 0.0
+ }
+ }, {
+ { 0, -4, GRAVITY_NORTH | GRAVITY_EAST },
+ { 5, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 4.0, 0.0
+ }
+ },
+
+ {
+ { -4, 0, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 0.0,
+ 0.0, 4.0
+ }
+ }, {
+
+ { 0, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ { 5, 0, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 0.0,
+ 5.0, 4.0
+ }
+ },
+
+ {
+ { -4, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ { 0, 5, GRAVITY_SOUTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, 5.0
+ }
+ }, {
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ { 0, 5, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 4.0, 5.0
+ }
+ }, {
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_EAST },
+ { 5, 5, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 5.0, 5.0
+ }
+ }
+};
+
+#ifdef __SUNPRO_C
+#pragma align 4 (_large_shadow)
+#endif
+#ifdef __GNUC__
+static const guint8 _large_shadow[] __attribute__ ((__aligned__ (4))) =
+#else
+ static const guint8 _large_shadow[] =
+#endif
+{ ""
+ /* Pixbuf magic (0x47646b50) */
+ "GdkP"
+ /* length: header (24) + pixel_data (2916) */
+ "\0\0\13|"
+ /* pixdata_type (0x1010002) */
+ "\1\1\0\2"
+ /* rowstride (108) */
+ "\0\0\0l"
+ /* width (27) */
+ "\0\0\0\33"
+ /* height (27) */
+ "\0\0\0\33"
+ /* pixel_data: */
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0"
+ "\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\6"
+ "\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\6\0\0\0\10\0\0\0\12\0\0\0\13\0"
+ "\0\0\15\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0\11\0\0\0\7\0\0\0\5\0\0\0\4\0"
+ "\0\0\2\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\5\0\0\0\10\0\0\0\13\0\0\0\16"
+ "\0\0\0\22\0\0\0\24\0\0\0\26\0\0\0\26\0\0\0\26\0\0\0\23\0\0\0\21\0\0\0"
+ "\15\0\0\0\12\0\0\0\7\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\6\0\0\0\11\0\0"
+ "\0\16\0\0\0\23\0\0\0\30\0\0\0\35\0\0\0\40\0\0\0#\0\0\0#\0\0\0\"\0\0\0"
+ "\37\0\0\0\33\0\0\0\26\0\0\0\21\0\0\0\14\0\0\0\10\0\0\0\5\0\0\0\2\0\0"
+ "\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\3\0\0\0\5"
+ "\0\0\0\12\0\0\0\17\0\0\0\26\0\0\0\35\0\0\0$\0\0\0+\0\0\0""0\0\0\0""4"
+ "\0\0\0""4\0\0\0""2\0\0\0.\0\0\0)\0\0\0\"\0\0\0\32\0\0\0\23\0\0\0\15\0"
+ "\0\0\10\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0"
+ "\2\0\0\0\4\0\0\0\10\0\0\0\16\0\0\0\26\0\0\0\37\0\0\0(\0\0\0""2\0\0\0"
+ ";\0\0\0A\0\0\0F\0\0\0G\0\0\0D\0\0\0@\0\0\0""8\0\0\0/\0\0\0%\0\0\0\34"
+ "\0\0\0\23\0\0\0\14\0\0\0\7\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\1\0"
+ "\0\0\1\0\0\0\3\0\0\0\7\0\0\0\13\0\0\0\23\0\0\0\35\0\0\0)\0\0\0""5\0\0"
+ "\0A\0\0\0L\0\0\0S\0\0\0X\0\0\0Y\0\0\0W\0\0\0Q\0\0\0I\0\0\0=\0\0\0""1"
+ "\0\0\0%\0\0\0\32\0\0\0\21\0\0\0\12\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\0\0"
+ "\0\0\1\0\0\0\2\0\0\0\4\0\0\0\10\0\0\0\17\0\0\0\31\0\0\0%\0\0\0""3\0\0"
+ "\0A\0\0\0P\0\0\0[\0\0\0d\0\0\0i\0\0\0k\0\0\0h\0\0\0b\0\0\0X\0\0\0L\0"
+ "\0\0=\0\0\0/\0\0\0\"\0\0\0\26\0\0\0\15\0\0\0\7\0\0\0\4\0\0\0\2\0\0\0"
+ "\1\0\0\0\1\0\0\0\2\0\0\0\5\0\0\0\13\0\0\0\23\0\0\0\36\0\0\0,\0\0\0=\0"
+ "\0\0M\0\0\0\\\0\0\0i\0\0\0r\0\0\0w\0\0\0y\0\0\0v\0\0\0p\0\0\0e\0\0\0"
+ "X\0\0\0I\0\0\0""8\0\0\0)\0\0\0\33\0\0\0\21\0\0\0\12\0\0\0\5\0\0\0\2\0"
+ "\0\0\1\0\0\0\1\0\0\0\3\0\0\0\7\0\0\0\15\0\0\0\26\0\0\0#\0\0\0""3\0\0"
+ "\0D\0\0\0V\0\0\0f\0\0\0s\0\0\0|\0\0\0\202\0\0\0\203\0\0\0\200\0\0\0z"
+ "\0\0\0p\0\0\0b\0\0\0R\0\0\0@\0\0\0/\0\0\0\40\0\0\0\24\0\0\0\13\0\0\0"
+ "\6\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\4\0\0\0\7\0\0\0\16\0\0\0\31\0\0\0'\0"
+ "\0\0""8\0\0\0K\0\0\0^\0\0\0n\0\0\0{\0\0\0\204\0\0\0\211\0\0\0\213\0\0"
+ "\0\210\0\0\0\202\0\0\0x\0\0\0k\0\0\0Z\0\0\0G\0\0\0""5\0\0\0%\0\0\0\27"
+ "\0\0\0\15\0\0\0\7\0\0\0\3\0\0\0\1\0\0\0\1\0\0\0\4\0\0\0\10\0\0\0\20\0"
+ "\0\0\33\0\0\0*\0\0\0<\0\0\0O\0\0\0b\0\0\0s\0\0\0\200\0\0\0\211\0\0\0"
+ "\216\0\0\0\217\0\0\0\215\0\0\0\210\0\0\0~\0\0\0p\0\0\0_\0\0\0M\0\0\0"
+ "9\0\0\0(\0\0\0\31\0\0\0\16\0\0\0\10\0\0\0\4\0\0\0\1\0\0\0\1\0\0\0\3\0"
+ "\0\0\7\0\0\0\16\0\0\0\27\0\0\0%\0\0\0""6\0\0\0I\0\0\0[\0\0\0k\0\0\0y"
+ "\0\0\0\202\0\0\0\210\0\0\0\211\0\0\0\210\0\0\0\202\0\0\0y\0\0\0k\0\0"
+ "\0[\0\0\0I\0\0\0""6\0\0\0%\0\0\0\27\0\0\0\16\0\0\0\7\0\0\0\3\0\0\0\1"
+ "\0\0\0\1\0\0\0\2\0\0\0\6\0\0\0\14\0\0\0\25\0\0\0!\0\0\0""1\0\0\0A\0\0"
+ "\0S\0\0\0c\0\0\0p\0\0\0z\0\0\0\200\0\0\0\202\0\0\0\200\0\0\0z\0\0\0p"
+ "\0\0\0c\0\0\0S\0\0\0A\0\0\0""0\0\0\0!\0\0\0\24\0\0\0\14\0\0\0\6\0\0\0"
+ "\3\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\5\0\0\0\12\0\0\0\21\0\0\0\34\0\0\0)"
+ "\0\0\0""9\0\0\0I\0\0\0X\0\0\0e\0\0\0n\0\0\0t\0\0\0v\0\0\0t\0\0\0n\0\0"
+ "\0e\0\0\0X\0\0\0I\0\0\0""9\0\0\0)\0\0\0\34\0\0\0\21\0\0\0\12\0\0\0\5"
+ "\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\4\0\0\0\10\0\0\0\16\0\0\0\27\0"
+ "\0\0\"\0\0\0/\0\0\0=\0\0\0K\0\0\0W\0\0\0`\0\0\0e\0\0\0h\0\0\0e\0\0\0"
+ "`\0\0\0W\0\0\0K\0\0\0=\0\0\0/\0\0\0\"\0\0\0\27\0\0\0\16\0\0\0\10\0\0"
+ "\0\4\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\5\0\0\0\12\0\0\0\21"
+ "\0\0\0\32\0\0\0%\0\0\0""1\0\0\0=\0\0\0G\0\0\0O\0\0\0U\0\0\0V\0\0\0U\0"
+ "\0\0O\0\0\0G\0\0\0=\0\0\0""1\0\0\0%\0\0\0\32\0\0\0\21\0\0\0\12\0\0\0"
+ "\5\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\4\0\0\0\7\0"
+ "\0\0\14\0\0\0\23\0\0\0\34\0\0\0%\0\0\0.\0\0\0""7\0\0\0>\0\0\0B\0\0\0"
+ "C\0\0\0B\0\0\0>\0\0\0""7\0\0\0.\0\0\0%\0\0\0\34\0\0\0\23\0\0\0\14\0\0"
+ "\0\7\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2"
+ "\0\0\0\5\0\0\0\10\0\0\0\15\0\0\0\23\0\0\0\32\0\0\0!\0\0\0(\0\0\0,\0\0"
+ "\0""0\0\0\0""1\0\0\0""0\0\0\0,\0\0\0(\0\0\0!\0\0\0\32\0\0\0\23\0\0\0"
+ "\15\0\0\0\10\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\5\0\0\0\10\0\0\0\14\0\0\0\20\0\0\0\26"
+ "\0\0\0\32\0\0\0\36\0\0\0\40\0\0\0!\0\0\0\40\0\0\0\36\0\0\0\32\0\0\0\26"
+ "\0\0\0\20\0\0\0\14\0\0\0\10\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\4\0\0\0"
+ "\7\0\0\0\12\0\0\0\15\0\0\0\20\0\0\0\23\0\0\0\24\0\0\0\24\0\0\0\24\0\0"
+ "\0\23\0\0\0\20\0\0\0\15\0\0\0\12\0\0\0\7\0\0\0\4\0\0\0\2\0\0\0\1\0\0"
+ "\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"
+ "\0\0\0\1\0\0\0\2\0\0\0\4\0\0\0\5\0\0\0\7\0\0\0\10\0\0\0\12\0\0\0\13\0"
+ "\0\0\13\0\0\0\13\0\0\0\12\0\0\0\10\0\0\0\7\0\0\0\5\0\0\0\4\0\0\0\2\0"
+ "\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\4\0\0\0\4\0"
+ "\0\0\5\0\0\0\5\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\2\0\0\0"
+ "\2\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0"
+ "\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0"
+ "\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0"
+ "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0"
+};
+
+static extents _win_extents = { 6, 6, 21, 6 };
+
+static quad _win_quads[] = {
+ {
+ { -LEFT_SPACE, -TOP_SPACE, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_NORTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, 0.0
+ }
+ }, {
+ { 0, -TOP_SPACE, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ ALIGN_LEFT,
+ {
+ 0.0, 0.0,
+ 0.0, 1.0,
+ LEFT_SPACE + 1, 0.0
+ }
+ }, {
+ { 0, -TOP_SPACE, GRAVITY_NORTH | GRAVITY_EAST },
+ { RIGHT_SPACE, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ LEFT_SPACE + 1.0, 0.0
+ }
+ },
+
+ {
+ { -LEFT_SPACE, 0, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 0.0,
+ 0.0, TOP_SPACE + 1.0
+ }
+ }, {
+
+ { 0, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ { RIGHT_SPACE, 0, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 0.0,
+ LEFT_SPACE + 1.0, TOP_SPACE + 1.0
+ }
+ },
+
+ {
+ { -LEFT_SPACE, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ { 0, 16, GRAVITY_SOUTH | GRAVITY_WEST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, TOP_SPACE + 1
+ }
+ }, {
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_WEST },
+ { 0, BOTTOM_SPACE, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 0.0, 0.0,
+ 0.0, 1.0,
+ LEFT_SPACE, TOP_SPACE + 1
+ }
+ }, {
+ { 0, 0, GRAVITY_SOUTH | GRAVITY_EAST },
+ { RIGHT_SPACE, BOTTOM_SPACE, GRAVITY_SOUTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ LEFT_SPACE + 1, TOP_SPACE + 1
+ }
+ }
+};
+
+static quad _win_button_quads[] = {
+ {
+ { 0 /* + title width */, -TOP_SPACE, GRAVITY_NORTH | GRAVITY_WEST },
+ { -BUTTON_SPACE, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ SHRT_MAX, SHRT_MAX,
+ 0,
+ {
+ 0.0, 0.0,
+ 0.0, 1.0,
+ 0.0 /* title width */, 0.0
+ }
+ }, {
+ { 0 /* title width + 1 */, -TOP_SPACE, GRAVITY_NORTH | GRAVITY_WEST },
+ { 0, 0, GRAVITY_NORTH | GRAVITY_EAST },
+ BUTTON_SPACE, SHRT_MAX,
+ ALIGN_RIGHT,
+ {
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 0.0 /* title width + 1.0 */, 0.0
+ }
+ }
+};
+
+static GdkPixmap *shadow_pixmap = NULL;
+static GdkPixmap *large_shadow_pixmap = NULL;
+static GdkPixmap *decor_normal_pixmap = NULL;
+static GdkPixmap *decor_active_pixmap = NULL;
+
+static cairo_pattern_t *shadow_pattern;
+
+static Atom frame_window_atom;
+static Atom win_decor_atom;
+static Atom win_decor_sync_atom;
+static Atom wm_move_resize_atom;
+
+#define C(name) { 0, XC_ ## name }
+
+static struct _cursor {
+ Cursor cursor;
+ unsigned int shape;
+} cursor[3][3] = {
+ { C (top_left_corner), C (top_side), C (top_right_corner) },
+ { C (left_side), C (left_ptr), C (right_side) },
+ { C (bottom_left_corner), C (bottom_side), C (bottom_right_corner) }
+};
+
+static struct _pos {
+ int x, y, w, h;
+ int xw, yh, ww, hh;
+} pos[3][3] = {
+ {
+ { 0, 0, 10, 21, 0, 0, 0, 0 },
+ { 10, 0, -8, 6, 0, 0, 1, 0 },
+ { 2, 0, 10, 21, 1, 0, 0, 0 }
+ }, {
+ { 0, 10, 6, 11, 0, 0, 0, 1 },
+ { 6, 6, 0, 15, 0, 0, 1, 0 },
+ { 6, 10, 6, 11, 1, 0, 0, 1 }
+ }, {
+ { 0, 17, 10, 10, 0, 1, 0, 0 },
+ { 10, 21, -8, 6, 0, 1, 1, 0 },
+ { 2, 17, 10, 10, 1, 1, 0, 0 }
+ }
+}, bpos[3] = {
+ { -10, 6, 16, 16, 1, 0, 0, 0 },
+ { -26, 6, 16, 16, 1, 0, 0, 0 },
+ { -42, 6, 16, 16, 1, 0, 0, 0 }
+};
+
+typedef struct _decor_color {
+ double r;
+ double g;
+ double b;
+} decor_color_t;
+
+#define IN_EVENT_WINDOW (1 << 0)
+#define PRESSED_EVENT_WINDOW (1 << 1)
+
+typedef struct _decor {
+ Window event_windows[3][3];
+ Window button_windows[3];
+ guint button_states[3];
+ GdkPixmap *pixmap;
+ GdkPixmap *buffer_pixmap;
+ GdkGC *gc;
+ gint width;
+ gint height;
+ gboolean decorated;
+ gboolean active;
+ PangoLayout *layout;
+ gchar *name;
+ cairo_pattern_t *icon;
+ GdkPixmap *icon_pixmap;
+ WnckWindowState state;
+ WnckWindowActions actions;
+ XID prop_xid;
+} decor_t;
+
+typedef void (*event_callback) (WnckWindow *win, XEvent *event);
+
+static GtkWidget *style_window;
+
+static gboolean double_buffering = TRUE;
+static GHashTable *frame_table;
+static GtkWidget *action_menu = NULL;
+static gboolean action_menu_mapped = FALSE;
+static decor_color_t _title_color[2];
+static PangoContext *pango_context;
+static gint double_click_timeout = 250;
+
+static GtkWidget *tip_window;
+static GtkWidget *tip_label;
+static GTimeVal tooltip_last_popdown = { -1, -1 };
+static gint tooltip_timer_tag = 0;
+
+static GSList *draw_list = NULL;
+static guint draw_idle_id = 0;
+
+static void
+send_decor_sync_notify (decor_t *d)
+{
+ Display *xdisplay;
+ GdkDisplay *gdkdisplay;
+ GdkScreen *screen;
+ Window xroot;
+ XEvent ev;
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
+ screen = gdk_display_get_default_screen (gdkdisplay);
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ ev.xclient.type = ClientMessage;
+ ev.xclient.display = xdisplay;
+
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = TRUE;
+
+ ev.xclient.window = xroot;
+ ev.xclient.message_type = win_decor_sync_atom;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = GDK_PIXMAP_XID (d->pixmap);
+ ev.xclient.data.l[1] = 0;
+ ev.xclient.data.l[2] = 0;
+ ev.xclient.data.l[3] = 0;
+ ev.xclient.data.l[4] = 0;
+
+ XSendEvent (xdisplay, xroot, FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &ev);
+}
+
+/*
+ decoration property
+ -------------------
+
+ data[0] = pixmap
+
+ data[1] = input left
+ data[2] = input right
+ data[3] = input top
+ data[4] = input bottom
+
+ flags
+
+ 1st and 2nd bit p1 gravity, 3rd and 4th bit p2 gravity,
+ 5rd and 6th bit alignment, 7th bit XX, 8th bit XY, 9th bit YX, 10th bit YY.
+
+ data[4 + n * 9 + 1] = flags
+ data[4 + n * 9 + 2] = p1 x
+ data[4 + n * 9 + 3] = p1 y
+ data[4 + n * 9 + 4] = p2 x
+ data[4 + n * 9 + 5] = p2 y
+ data[4 + n * 9 + 6] = widthMax
+ data[4 + n * 9 + 7] = heightMax
+ data[4 + n * 9 + 8] = x0
+ data[4 + n * 9 + 9] = y0
+ */
+static void
+decoration_to_property (long *data,
+ Pixmap pixmap,
+ extents *input,
+ quad *quad,
+ int nQuad)
+{
+ memcpy (data++, &pixmap, sizeof (Pixmap));
+
+ *data++ = input->left;
+ *data++ = input->right;
+ *data++ = input->top;
+ *data++ = input->bottom;
+
+ while (nQuad--)
+ {
+ *data++ =
+ (quad->p1.gravity << 0) |
+ (quad->p2.gravity << 2) |
+ (quad->align << 4) |
+ (quad->m.xx ? XX_MASK : 0) |
+ (quad->m.xy ? XY_MASK : 0) |
+ (quad->m.yx ? YX_MASK : 0) |
+ (quad->m.yy ? YY_MASK : 0);
+
+ *data++ = quad->p1.x;
+ *data++ = quad->p1.y;
+ *data++ = quad->p2.x;
+ *data++ = quad->p2.y;
+ *data++ = quad->max_width;
+ *data++ = quad->max_height;
+ *data++ = quad->m.x0;
+ *data++ = quad->m.y0;
+
+ quad++;
+ }
+}
+
+static void
+decor_update_window_property (decor_t *d)
+{
+ long data[128];
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ gint nQuad = sizeof (_win_quads) / sizeof (_win_quads[0]);
+ gint nButtonQuad = sizeof (_win_button_quads) /
+ sizeof (_win_button_quads[0]);
+ quad quads[nQuad + nButtonQuad];
+
+ memcpy (quads, _win_quads, nQuad * sizeof (quad));
+ memcpy (quads + nQuad, _win_button_quads, nButtonQuad * sizeof (quad));
+
+ quads[2].m.x0 = quads[4].m.x0 = quads[7].m.x0 = d->width - RIGHT_SPACE;
+ quads[1].m.xx = 1.0;
+
+ quads[1].max_width = d->width - LEFT_SPACE - RIGHT_SPACE - BUTTON_SPACE;
+
+ quads[8].p1.x = d->width - LEFT_SPACE - RIGHT_SPACE - BUTTON_SPACE;
+ quads[8].m.x0 = d->width - RIGHT_SPACE - BUTTON_SPACE;
+
+ quads[9].p1.x = d->width - LEFT_SPACE - RIGHT_SPACE - BUTTON_SPACE;
+ quads[9].m.x0 = d->width - RIGHT_SPACE - BUTTON_SPACE;
+
+ quads[9].max_width = BUTTON_SPACE;
+
+ nQuad += nButtonQuad;
+
+ decoration_to_property (data, GDK_PIXMAP_XID (d->pixmap),
+ &_win_extents, quads, nQuad);
+
+ gdk_error_trap_push ();
+ XChangeProperty (xdisplay, d->prop_xid,
+ win_decor_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data, 5 + 9 * nQuad);
+ XSync (xdisplay, FALSE);
+ gdk_error_trap_pop ();
+}
+
+static void
+gdk_cairo_set_source_color_alpha (cairo_t *cr,
+ GdkColor *color,
+ double alpha)
+{
+ cairo_set_source_rgba (cr,
+ color->red / 65535.0,
+ color->green / 65535.0,
+ color->blue / 65535.0,
+ alpha);
+}
+
+#define CORNER_TOPLEFT (1 << 0)
+#define CORNER_TOPRIGHT (1 << 1)
+#define CORNER_BOTTOMRIGHT (1 << 2)
+#define CORNER_BOTTOMLEFT (1 << 3)
+
+static void
+rounded_rectangle (cairo_t *cr,
+ double x,
+ double y,
+ double w,
+ double h,
+ double radius,
+ int corner)
+{
+ if (corner & CORNER_TOPLEFT)
+ cairo_move_to (cr, x + radius, y);
+ else
+ cairo_move_to (cr, x, y);
+
+ if (corner & CORNER_TOPRIGHT)
+ cairo_arc (cr, x + w - radius, y + radius, radius,
+ M_PI * 1.5, M_PI * 2.0);
+ else
+ cairo_line_to (cr, x + w, y);
+
+ if (corner & CORNER_BOTTOMRIGHT)
+ cairo_arc (cr, x + w - radius, y + h - radius, radius,
+ 0.0, M_PI * 0.5);
+ else
+ cairo_line_to (cr, x + w, y + h);
+
+ if (corner & CORNER_BOTTOMLEFT)
+ cairo_arc (cr, x + radius, y + h - radius, radius,
+ M_PI * 0.5, M_PI);
+ else
+ cairo_line_to (cr, x, y + h);
+
+ if (corner & CORNER_TOPLEFT)
+ cairo_arc (cr, x + radius, y + radius, radius, M_PI, M_PI * 1.5);
+ else
+ cairo_line_to (cr, x, y);
+}
+
+#define SHADE_LEFT (1 << 0)
+#define SHADE_RIGHT (1 << 1)
+#define SHADE_TOP (1 << 2)
+#define SHADE_BOTTOM (1 << 3)
+
+static void
+fill_rounded_rectangle (cairo_t *cr,
+ double x,
+ double y,
+ double w,
+ double h,
+ double radius,
+ int corner,
+ decor_color_t *c0,
+ double alpha0,
+ decor_color_t *c1,
+ double alpha1,
+ int gravity)
+{
+ cairo_pattern_t *pattern;
+
+ rounded_rectangle (cr, x, y, w, h, radius, corner);
+
+ if (gravity & SHADE_RIGHT)
+ {
+ x = x + w;
+ w = -w;
+ }
+ else if (!(gravity & SHADE_LEFT))
+ {
+ x = w = 0;
+ }
+
+ if (gravity & SHADE_BOTTOM)
+ {
+ y = y + h;
+ h = -h;
+ }
+ else if (!(gravity & SHADE_TOP))
+ {
+ y = h = 0;
+ }
+
+ if (w && h)
+ {
+ cairo_matrix_t matrix;
+
+ pattern = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, w);
+
+ cairo_matrix_init_scale (&matrix, 1.0, w / h);
+ cairo_matrix_translate (&matrix, -(x + w), -(y + h));
+
+ cairo_pattern_set_matrix (pattern, &matrix);
+ }
+ else
+ {
+ pattern = cairo_pattern_create_linear (x + w, y + h, x, y);
+ }
+
+ cairo_pattern_add_color_stop_rgba (pattern, 0.0, c0->r, c0->g, c0->b,
+ alpha0);
+
+ cairo_pattern_add_color_stop_rgba (pattern, 1.0, c1->r, c1->g, c1->b,
+ alpha1);
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
+
+ cairo_set_source (cr, pattern);
+ cairo_fill (cr);
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+draw_shadow_background (decor_t *d,
+ cairo_t *cr)
+{
+ cairo_matrix_t matrix;
+ double w, h, x2, y2;
+
+ w = d->width - 13.0 - 14.0;
+ h = d->height - 13.0 - 14.0;
+
+ x2 = d->width - 14.0;
+ y2 = d->height - 14.0;
+
+ /* top left */
+ cairo_matrix_init_identity (&matrix);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, 0.0, 0.0, 13.0, 13.0);
+ cairo_fill (cr);
+
+ /* top */
+ cairo_matrix_init_translate (&matrix, 13.0, 0.0);
+ cairo_matrix_scale (&matrix, 1.0 / w, 1.0);
+ cairo_matrix_translate (&matrix, -13.0, 0.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, 13.0, 0.0, w, 13.0);
+ cairo_fill (cr);
+
+ /* top right */
+ cairo_matrix_init_translate (&matrix, 13.0 - x2, 0.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, x2, 0.0, 14.0, 13.0);
+ cairo_fill (cr);
+
+ /* left */
+ cairo_matrix_init_translate (&matrix, 0.0, 13.0);
+ cairo_matrix_scale (&matrix, 1.0, 1.0 / h);
+ cairo_matrix_translate (&matrix, 0.0, -13.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, 0.0, 13.0, 13.0, h);
+ cairo_fill (cr);
+
+ /* right */
+ cairo_matrix_init_translate (&matrix, 13.0 - x2, 13.0);
+ cairo_matrix_scale (&matrix, 1.0, 1.0 / h);
+ cairo_matrix_translate (&matrix, 0.0, -13.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, x2, 13.0, 14.0, h);
+ cairo_fill (cr);
+
+ /* bottom right */
+ cairo_matrix_init_translate (&matrix, 0.0, -15.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, 0.0, y2, 13.0, 14.0);
+ cairo_fill (cr);
+
+ /* bottom */
+ cairo_matrix_init_translate (&matrix, 13.0, -15.0);
+ cairo_matrix_scale (&matrix, 1.0 / w, 1.0);
+ cairo_matrix_translate (&matrix, -13.0, 0.0);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, 13.0, y2, w, 14.0);
+ cairo_fill (cr);
+
+ /* right */
+ cairo_matrix_init_translate (&matrix, 13.0 - x2, 13.0 - y2);
+ cairo_pattern_set_matrix (shadow_pattern, &matrix);
+ cairo_set_source (cr, shadow_pattern);
+ cairo_rectangle (cr, x2, y2, 14.0, 14.0);
+ cairo_fill (cr);
+}
+
+static void
+draw_close_button (decor_t *d,
+ cairo_t *cr,
+ double s)
+{
+ cairo_rel_move_to (cr, 0.0, s);
+
+ cairo_rel_line_to (cr, s, -s);
+ cairo_rel_line_to (cr, s, s);
+ cairo_rel_line_to (cr, s, -s);
+ cairo_rel_line_to (cr, s, s);
+
+ cairo_rel_line_to (cr, -s, s);
+ cairo_rel_line_to (cr, s, s);
+ cairo_rel_line_to (cr, -s, s);
+ cairo_rel_line_to (cr, -s, -s);
+
+ cairo_rel_line_to (cr, -s, s);
+ cairo_rel_line_to (cr, -s, -s);
+ cairo_rel_line_to (cr, s, -s);
+
+ cairo_close_path (cr);
+}
+
+static void
+draw_max_button (decor_t *d,
+ cairo_t *cr,
+ double s)
+{
+ cairo_rel_line_to (cr, 12.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, 12.0);
+ cairo_rel_line_to (cr, -12.0, 0.0);
+
+ cairo_close_path (cr);
+
+ cairo_rel_move_to (cr, 2.0, s);
+
+ cairo_rel_line_to (cr, 12.0 - 4.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, 12.0 - s - 2.0);
+ cairo_rel_line_to (cr, -(12.0 - 4.0), 0.0);
+
+ cairo_close_path (cr);
+}
+
+static void
+draw_unmax_button (decor_t *d,
+ cairo_t *cr,
+ double s)
+{
+ cairo_rel_move_to (cr, 1.0, 1.0);
+
+ cairo_rel_line_to (cr, 10.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, 10.0);
+ cairo_rel_line_to (cr, -10.0, 0.0);
+
+ cairo_close_path (cr);
+
+ cairo_rel_move_to (cr, 2.0, s);
+
+ cairo_rel_line_to (cr, 10.0 - 4.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, 10.0 - s - 2.0);
+ cairo_rel_line_to (cr, -(10.0 - 4.0), 0.0);
+
+ cairo_close_path (cr);
+}
+
+static void
+draw_min_button (decor_t *d,
+ cairo_t *cr,
+ double s)
+{
+ cairo_rel_move_to (cr, 0.0, 8.0);
+
+ cairo_rel_line_to (cr, 12.0, 0.0);
+ cairo_rel_line_to (cr, 0.0, s);
+ cairo_rel_line_to (cr, -12.0, 0.0);
+
+ cairo_close_path (cr);
+}
+
+static void
+button_state_offsets (gdouble x,
+ gdouble y,
+ guint state,
+ gdouble *return_x,
+ gdouble *return_y,
+ gdouble *return_sx,
+ gdouble *return_sy)
+{
+ static double off[] = { 0.0, 0.0, 0.0, 1.0 };
+ static double shadow_off[] = { 1.0, 1.0, 1.0, 0.0 };
+
+ *return_x = x + off[state];
+ *return_y = y + off[state];
+ *return_sx = x + shadow_off[state];
+ *return_sy = y + shadow_off[state];
+}
+
+static void
+draw_window_decoration (decor_t *d)
+{
+ cairo_t *cr;
+ GtkStyle *style;
+ decor_color_t color;
+ double alpha;
+ double x1, y1, x2, y2, x, y, sx, sy;
+ int corners = SHADE_LEFT | SHADE_RIGHT | SHADE_TOP | SHADE_BOTTOM;
+
+ if (!d->pixmap)
+ return;
+
+ style = gtk_widget_get_style (style_window);
+
+ if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ corners = 0;
+
+ color.r = style->bg[GTK_STATE_NORMAL].red / 65535.0;
+ color.g = style->bg[GTK_STATE_NORMAL].green / 65535.0;
+ color.b = style->bg[GTK_STATE_NORMAL].blue / 65535.0;
+
+ if (d->buffer_pixmap)
+ cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap));
+ else
+ cr = gdk_cairo_create (GDK_DRAWABLE (d->pixmap));
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ x1 = LEFT_SPACE - _win_extents.left;
+ y1 = TOP_SPACE - _win_extents.top;
+ x2 = d->width - RIGHT_SPACE + _win_extents.right;
+ y2 = d->height - BOTTOM_SPACE + _win_extents.bottom;
+
+ cairo_set_line_width (cr, 1.0);
+
+ draw_shadow_background (d, cr);
+
+ if (d->active)
+ {
+ decor_color_t *title_color = _title_color;
+
+ alpha = 0.8;
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + 0.5,
+ _win_extents.left - 0.5,
+ _win_extents.top - 0.5,
+ 5.0, CORNER_TOPLEFT & corners,
+ &title_color[0], 1.0, &title_color[1], alpha,
+ SHADE_TOP | SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x1 + _win_extents.left,
+ y1 + 0.5,
+ x2 - x1 - _win_extents.left -
+ _win_extents.right,
+ _win_extents.top - 0.5,
+ 5.0, 0,
+ &title_color[0], 1.0, &title_color[1], alpha,
+ SHADE_TOP);
+
+ fill_rounded_rectangle (cr,
+ x2 - _win_extents.right,
+ y1 + 0.5,
+ _win_extents.right - 0.5,
+ _win_extents.top - 0.5,
+ 5.0, CORNER_TOPRIGHT & corners,
+ &title_color[0], 1.0, &title_color[1], alpha,
+ SHADE_TOP | SHADE_RIGHT);
+ }
+ else
+ {
+ alpha = 0.5;
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + 0.5,
+ _win_extents.left - 0.5,
+ _win_extents.top - 0.5,
+ 5.0, CORNER_TOPLEFT & corners,
+ &color, 1.0, &color, alpha,
+ SHADE_TOP | SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x1 + _win_extents.left,
+ y1 + 0.5,
+ x2 - x1 - _win_extents.left -
+ _win_extents.right,
+ _win_extents.top - 0.5,
+ 5.0, 0,
+ &color, 1.0, &color, alpha,
+ SHADE_TOP);
+
+ fill_rounded_rectangle (cr,
+ x2 - _win_extents.right,
+ y1 + 0.5,
+ _win_extents.right - 0.5,
+ _win_extents.top - 0.5,
+ 5.0, CORNER_TOPRIGHT & corners,
+ &color, 1.0, &color, alpha,
+ SHADE_TOP | SHADE_RIGHT);
+ }
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + _win_extents.top,
+ _win_extents.left - 0.5,
+ 1,
+ 5.0, 0,
+ &color, 1.0, &color, alpha,
+ SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x2 - _win_extents.right,
+ y1 + _win_extents.top,
+ _win_extents.right - 0.5,
+ 1,
+ 5.0, 0,
+ &color, 1.0, &color, alpha,
+ SHADE_RIGHT);
+
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y2 - _win_extents.bottom,
+ _win_extents.left - 0.5,
+ _win_extents.bottom - 0.5,
+ 5.0, CORNER_BOTTOMLEFT & corners,
+ &color, 1.0, &color, alpha,
+ SHADE_BOTTOM | SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x1 + _win_extents.left,
+ y2 - _win_extents.bottom,
+ x2 - x1 - _win_extents.left -
+ _win_extents.right,
+ _win_extents.bottom - 0.5,
+ 5.0, 0,
+ &color, 1.0, &color, alpha,
+ SHADE_BOTTOM);
+
+ fill_rounded_rectangle (cr,
+ x2 - _win_extents.right,
+ y2 - _win_extents.bottom,
+ _win_extents.right - 0.5,
+ _win_extents.bottom - 0.5,
+ 5.0, CORNER_BOTTOMRIGHT & corners,
+ &color, 1.0, &color, alpha,
+ SHADE_BOTTOM | SHADE_RIGHT);
+
+ cairo_rectangle (cr,
+ LEFT_SPACE, TOP_SPACE,
+ d->width - LEFT_SPACE - RIGHT_SPACE, 1);
+ gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
+ cairo_fill (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ if (d->active)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ 0.7);
+
+ cairo_move_to (cr, x1 + 0.5, y1 + _win_extents.top - 0.5);
+ cairo_rel_line_to (cr, x2 - x1 - 1.0, 0.0);
+
+ cairo_stroke (cr);
+ }
+
+ rounded_rectangle (cr,
+ x1 + 0.5, y1 + 0.5,
+ x2 - x1 - 1.0, y2 - y1 - 1.0,
+ 5.0,
+ (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
+ CORNER_BOTTOMRIGHT) & corners);
+
+ cairo_clip (cr);
+
+ cairo_translate (cr, 1.0, 1.0);
+
+ rounded_rectangle (cr,
+ x1 + 0.5, y1 + 0.5,
+ x2 - x1 - 1.0, y2 - y1 - 1.0,
+ 5.0,
+ (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
+ CORNER_BOTTOMRIGHT) & corners);
+
+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.4);
+ cairo_stroke (cr);
+
+ cairo_translate (cr, -2.0, -2.0);
+
+ rounded_rectangle (cr,
+ x1 + 0.5, y1 + 0.5,
+ x2 - x1 - 1.0, y2 - y1 - 1.0,
+ 5.0,
+ (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
+ CORNER_BOTTOMRIGHT) & corners);
+
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.1);
+ cairo_stroke (cr);
+
+ cairo_translate (cr, 1.0, 1.0);
+
+ cairo_reset_clip (cr);
+
+ rounded_rectangle (cr,
+ x1 + 0.5, y1 + 0.5,
+ x2 - x1 - 1.0, y2 - y1 - 1.0,
+ 5.0,
+ (CORNER_TOPLEFT | CORNER_TOPRIGHT | CORNER_BOTTOMLEFT |
+ CORNER_BOTTOMRIGHT) & corners);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+
+ cairo_stroke (cr);
+
+ if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
+ {
+ button_state_offsets (d->width - RIGHT_SPACE - BUTTON_SPACE + 39.0,
+ 11.0, d->button_states[0], &x, &y, &sx, &sy);
+
+ if (d->active)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+ cairo_move_to (cr, sx, sy);
+ draw_close_button (d, cr, 3.0);
+ cairo_fill (cr);
+
+ if (d->button_states[0] & IN_EVENT_WINDOW)
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ else
+ cairo_set_source_rgba (cr, color.r, color.g, color.b, 0.95);
+
+ cairo_move_to (cr, x, y);
+ draw_close_button (d, cr, 3.0);
+ cairo_fill (cr);
+ }
+ else
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha * 0.75);
+ cairo_move_to (cr, x, y);
+ draw_close_button (d, cr, 3.0);
+ cairo_fill (cr);
+ }
+ }
+
+ if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
+ {
+ button_state_offsets (d->width - RIGHT_SPACE - BUTTON_SPACE + 21.0,
+ 11.0, d->button_states[1], &x, &y, &sx, &sy);
+
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+
+ if (d->active)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+ cairo_move_to (cr, sx, sy);
+
+ if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ draw_unmax_button (d, cr, 4.0);
+ else
+ draw_max_button (d, cr, 4.0);
+
+ cairo_fill (cr);
+
+ if (d->button_states[1] & IN_EVENT_WINDOW)
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ else
+ cairo_set_source_rgba (cr, color.r, color.g, color.b, 0.95);
+
+ cairo_move_to (cr, x, y);
+
+ if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ draw_unmax_button (d, cr, 4.0);
+ else
+ draw_max_button (d, cr, 4.0);
+
+ cairo_fill (cr);
+ }
+ else
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha * 0.75);
+ cairo_move_to (cr, x, y);
+
+ if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ draw_unmax_button (d, cr, 4.0);
+ else
+ draw_max_button (d, cr, 4.0);
+
+ cairo_fill (cr);
+ }
+ }
+
+ if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE)
+ {
+ button_state_offsets (d->width - RIGHT_SPACE - BUTTON_SPACE + 3.0,
+ 11.0, d->button_states[2], &x, &y, &sx, &sy);
+
+ if (d->active)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+ cairo_move_to (cr, sx, sy);
+ draw_min_button (d, cr, 4.0);
+ cairo_fill (cr);
+
+ if (d->button_states[2] & IN_EVENT_WINDOW)
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ else
+ cairo_set_source_rgba (cr, color.r, color.g, color.b, 0.95);
+
+ cairo_move_to (cr, x, y);
+ draw_min_button (d, cr, 4.0);
+ cairo_fill (cr);
+ }
+ else
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha * 0.75);
+ cairo_move_to (cr, x, y);
+ draw_min_button (d, cr, 4.0);
+ cairo_fill (cr);
+ }
+ }
+
+ if (d->layout)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+
+ if (d->active)
+ {
+ cairo_move_to (cr, 33.0, 9.0);
+
+ pango_cairo_show_layout (cr, d->layout);
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ }
+
+ cairo_move_to (cr, 32.0, 8.0);
+
+ pango_cairo_show_layout (cr, d->layout);
+ }
+
+ if (d->icon)
+ {
+ cairo_translate (cr, LEFT_SPACE, 9.0);
+ cairo_set_source (cr, d->icon);
+ cairo_rectangle (cr, 0.0, 0.0, 16.0, 16.0);
+ cairo_clip (cr);
+
+ if (d->active)
+ cairo_paint (cr);
+ else
+ cairo_paint_with_alpha (cr, alpha);
+ }
+
+ cairo_destroy (cr);
+
+ if (d->buffer_pixmap)
+ gdk_draw_drawable (d->pixmap,
+ d->gc,
+ d->buffer_pixmap,
+ 0,
+ 0,
+ 0,
+ 0,
+ d->width,
+ d->height);
+
+ if (d->prop_xid)
+ {
+ decor_update_window_property (d);
+ d->prop_xid = 0;
+ }
+
+ send_decor_sync_notify (d);
+}
+
+static gboolean
+draw_decor_list (void *data)
+{
+ GSList *list;
+
+ draw_idle_id = 0;
+
+ for (list = draw_list; list; list = list->next)
+ draw_window_decoration ((decor_t *) list->data);
+
+ g_slist_free (draw_list);
+ draw_list = NULL;
+
+ return FALSE;
+}
+
+static void
+queue_decor_draw (decor_t *d)
+{
+ if (g_slist_find (draw_list, d))
+ return;
+
+ draw_list = g_slist_append (draw_list, d);
+
+ if (!draw_idle_id)
+ draw_idle_id = g_idle_add (draw_decor_list, NULL);
+}
+
+static GdkPixmap *
+create_pixmap (int w,
+ int h)
+{
+ GdkPixmap *pixmap;
+ GdkVisual *visual;
+ GdkColormap *colormap;
+
+ visual = gdk_visual_get_best_with_depth (32);
+ if (!visual)
+ return NULL;
+
+ pixmap = gdk_pixmap_new (NULL, w, h, 32);
+ if (!pixmap)
+ return NULL;
+
+ colormap = gdk_colormap_new (visual, FALSE);
+ if (!colormap)
+ {
+ gdk_pixmap_unref (pixmap);
+ return NULL;
+ }
+
+ gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), colormap);
+ gdk_colormap_unref (colormap);
+
+ return pixmap;
+}
+
+static GdkPixmap *
+pixmap_new_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ GdkPixmap *pixmap;
+ guint width, height;
+ cairo_t *cr;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ pixmap = create_pixmap (width, height);
+ if (!pixmap)
+ return NULL;
+
+ cr = (cairo_t *) gdk_cairo_create (GDK_DRAWABLE (pixmap));
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ return pixmap;
+}
+
+static GdkPixmap *
+pixmap_new_from_inline (const guint8 *data)
+{
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_inline (-1, data, FALSE, NULL);
+ if (!pixbuf)
+ return NULL;
+
+ return pixmap_new_from_pixbuf (pixbuf);
+}
+
+static void
+update_default_decorations (GdkScreen *screen)
+{
+ long data[128];
+ Window xroot;
+ GdkDisplay *gdkdisplay = gdk_display_get_default ();
+ Display *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ Atom atom;
+ int nQuad;
+ decor_t d;
+
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ atom = XInternAtom (xdisplay, "_NET_WINDOW_DECOR_BARE", FALSE);
+ nQuad = sizeof (_shadow_quads) / sizeof (_shadow_quads[0]);
+ decoration_to_property (data, GDK_PIXMAP_XID (shadow_pixmap),
+ &_shadow_extents, _shadow_quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data, 5 + 9 * nQuad);
+
+ d.width = LEFT_SPACE + 1 + RIGHT_SPACE;
+ d.height = TOP_SPACE + 1 + BOTTOM_SPACE;
+
+ if (!decor_normal_pixmap)
+ decor_normal_pixmap = create_pixmap (d.width, d.height);
+
+ if (decor_normal_pixmap)
+ {
+ d.pixmap = decor_normal_pixmap;
+ d.buffer_pixmap = NULL;
+ d.active = FALSE;
+ d.layout = NULL;
+ d.icon = NULL;
+ d.state = 0;
+ d.actions = 0;
+ d.prop_xid = 0;
+
+ draw_window_decoration (&d);
+
+ atom = XInternAtom (xdisplay, "_NET_WINDOW_DECOR_NORMAL", FALSE);
+ nQuad = sizeof (_win_quads) / sizeof (_win_quads[0]);
+ decoration_to_property (data, GDK_PIXMAP_XID (d.pixmap),
+ &_win_extents, _win_quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data, 5 + 9 * nQuad);
+ }
+
+ if (!decor_active_pixmap)
+ decor_active_pixmap = create_pixmap (d.width, d.height);
+
+ if (decor_active_pixmap)
+ {
+ d.pixmap = decor_active_pixmap;
+ d.buffer_pixmap = NULL;
+ d.active = TRUE;
+ d.layout = NULL;
+ d.icon = NULL;
+ d.state = 0;
+ d.actions = 0;
+ d.prop_xid = 0;
+
+ draw_window_decoration (&d);
+
+ atom = XInternAtom (xdisplay, "_NET_WINDOW_DECOR_ACTIVE", FALSE);
+ nQuad = sizeof (_win_quads) / sizeof (_win_quads[0]);
+ decoration_to_property (data, GDK_PIXMAP_XID (d.pixmap),
+ &_win_extents, _win_quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data, 5 + 9 * nQuad);
+ }
+}
+
+static void
+set_dm_check_hint (GdkScreen *screen)
+{
+ XSetWindowAttributes attrs;
+ unsigned long data[1];
+ Window xroot;
+ GdkDisplay *gdkdisplay = gdk_display_get_default ();
+ Display *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ Atom atom;
+
+ attrs.override_redirect = TRUE;
+ attrs.event_mask = PropertyChangeMask;
+
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ data[0] = XCreateWindow (xdisplay,
+ xroot,
+ -100, -100, 1, 1,
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ (Visual *) CopyFromParent,
+ CWOverrideRedirect | CWEventMask,
+ &attrs);
+
+ atom = XInternAtom (xdisplay, "_NET_SUPPORTING_DM_CHECK", FALSE);
+
+ XChangeProperty (xdisplay, xroot,
+ atom,
+ XA_WINDOW,
+ 32, PropModeReplace, (guchar *) data, 1);
+}
+
+static gboolean
+check_dm_hint (GdkScreen *screen)
+{
+ Window xroot;
+ GdkDisplay *gdkdisplay = gdk_display_get_default ();
+ Display *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ Atom actual;
+ int result, format;
+ unsigned long n, left;
+ unsigned char *data;
+ Atom atom;
+ gboolean dm = FALSE;
+
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ atom = XInternAtom (xdisplay, "_NET_SUPPORTING_DM_CHECK", FALSE);
+
+ result = XGetWindowProperty (xdisplay, xroot,
+ atom, 0L, 1L, FALSE,
+ XA_WINDOW, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && n && data)
+ {
+ XWindowAttributes attr;
+ Window window;
+
+ memcpy (&window, data, sizeof (Window));
+
+ XFree (data);
+
+ gdk_error_trap_push ();
+
+ XGetWindowAttributes (xdisplay, window, &attr);
+ XSync (xdisplay, FALSE);
+
+ if (!gdk_error_trap_pop ())
+ dm = TRUE;
+ }
+
+ return dm;
+}
+
+static gboolean
+get_window_prop (Window xwindow,
+ Atom atom,
+ Window *val)
+{
+ Atom type;
+ int format;
+ gulong nitems;
+ gulong bytes_after;
+ Window *w;
+ int err, result;
+
+ *val = 0;
+
+ gdk_error_trap_push ();
+
+ type = None;
+ result = XGetWindowProperty (gdk_display,
+ xwindow,
+ atom,
+ 0, G_MAXLONG,
+ False, XA_WINDOW, &type, &format, &nitems,
+ &bytes_after, (void*) &w);
+ err = gdk_error_trap_pop ();
+ if (err != Success || result != Success)
+ return FALSE;
+
+ if (type != XA_WINDOW)
+ {
+ XFree (w);
+ return FALSE;
+ }
+
+ *val = *w;
+ XFree (w);
+
+ return TRUE;
+}
+
+static void
+update_event_windows (WnckWindow *win)
+{
+ Display *xdisplay;
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ gint x0, y0, width, height, x, y, w, h;
+ gint i, j;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ wnck_window_get_geometry (win, &x0, &y0, &width, &height);
+
+ gdk_error_trap_push ();
+
+ for (i = 0; i < 3; i++)
+ {
+ static guint event_window_actions[3][3] = {
+ {
+ WNCK_WINDOW_ACTION_RESIZE,
+ WNCK_WINDOW_ACTION_RESIZE,
+ WNCK_WINDOW_ACTION_RESIZE
+ }, {
+ WNCK_WINDOW_ACTION_RESIZE,
+ WNCK_WINDOW_ACTION_MOVE,
+ WNCK_WINDOW_ACTION_RESIZE
+ }, {
+ WNCK_WINDOW_ACTION_RESIZE,
+ WNCK_WINDOW_ACTION_RESIZE,
+ WNCK_WINDOW_ACTION_RESIZE
+ }
+ };
+
+ for (j = 0; j < 3; j++)
+ {
+ if (d->actions & event_window_actions[i][j])
+ {
+ x = pos[i][j].x + pos[i][j].xw * width;
+ y = pos[i][j].y + pos[i][j].yh * height;
+ w = pos[i][j].w + pos[i][j].ww * width;
+ h = pos[i][j].h + pos[i][j].hh * height;
+
+ XMapWindow (xdisplay, d->event_windows[i][j]);
+ XMoveResizeWindow (xdisplay, d->event_windows[i][j],
+ x, y, w, h);
+ }
+ else
+ {
+ XUnmapWindow (xdisplay, d->event_windows[i][j]);
+ }
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ static guint button_actions[3] = {
+ WNCK_WINDOW_ACTION_CLOSE,
+ WNCK_WINDOW_ACTION_MAXIMIZE,
+ WNCK_WINDOW_ACTION_MINIMIZE
+ };
+
+ if (d->actions & button_actions[i])
+ {
+ x = bpos[i].x + bpos[i].xw * width;
+ y = bpos[i].y + bpos[i].yh * height;
+ w = bpos[i].w + bpos[i].ww * width;
+ h = bpos[i].h + bpos[i].hh * height;
+
+ XMapWindow (xdisplay, d->button_windows[i]);
+ XMoveResizeWindow (xdisplay, d->button_windows[i], x, y, w, h);
+ }
+ else
+ XUnmapWindow (xdisplay, d->button_windows[i]);
+ }
+
+ XSync (xdisplay, FALSE);
+ gdk_error_trap_pop ();
+}
+
+static gint
+max_window_name_width (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ const gchar *name;
+ gint w;
+
+ name = wnck_window_get_name (win);
+ if (!name)
+ return 0;
+
+ if (!d->layout)
+ {
+ d->layout = pango_layout_new (pango_context);
+ if (!d->layout)
+ return 0;
+
+ pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR);
+ }
+
+ pango_layout_set_width (d->layout, -1);
+ pango_layout_set_text (d->layout, name, strlen (name));
+ pango_layout_get_pixel_size (d->layout, &w, NULL);
+
+ if (d->name)
+ pango_layout_set_text (d->layout, d->name, strlen (d->name));
+
+ return w + 4;
+}
+
+static void
+update_window_decoration_name (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ const gchar *name;
+ glong name_length;
+ PangoLayoutLine *line;
+
+ if (d->name)
+ {
+ g_free (d->name);
+ d->name = NULL;
+ }
+
+ name = wnck_window_get_name (win);
+ if (name && (name_length = strlen (name)))
+ {
+ gint w, n_line;
+
+ w = d->width - LEFT_SPACE - RIGHT_SPACE - BUTTON_SPACE - ICON_SPACE - 4;
+ if (w < 1)
+ w = 1;
+
+ pango_layout_set_width (d->layout, w * PANGO_SCALE);
+ pango_layout_set_text (d->layout, name, name_length);
+
+ n_line = pango_layout_get_line_count (d->layout);
+
+ line = pango_layout_get_line (d->layout, 0);
+
+ name_length = line->length;
+ if (pango_layout_get_line_count (d->layout) > 1)
+ {
+ if (name_length < 4)
+ {
+ g_object_unref (G_OBJECT (d->layout));
+ d->layout = NULL;
+ return;
+ }
+
+ d->name = g_strndup (name, name_length);
+ strcpy (d->name + name_length - 3, "...");
+ }
+ else
+ d->name = g_strndup (name, name_length);
+
+ pango_layout_set_text (d->layout, d->name, name_length);
+ }
+ else if (d->layout)
+ {
+ g_object_unref (G_OBJECT (d->layout));
+ d->layout = NULL;
+ }
+}
+
+static void
+update_window_decoration_icon (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ GdkPixbuf *icon;
+
+ if (d->icon)
+ {
+ cairo_pattern_destroy (d->icon);
+ d->icon = NULL;
+ }
+
+ if (d->icon_pixmap)
+ {
+ gdk_pixmap_unref (d->icon_pixmap);
+ d->icon_pixmap = NULL;
+ }
+
+ icon = wnck_window_get_mini_icon (win);
+ if (icon)
+ {
+ cairo_t *cr;
+
+ d->icon_pixmap = pixmap_new_from_pixbuf (icon);
+ cr = gdk_cairo_create (GDK_DRAWABLE (d->icon_pixmap));
+ d->icon = cairo_pattern_create_for_surface (cairo_get_target (cr));
+ cairo_destroy (cr);
+ }
+}
+
+static void
+update_window_decoration_state (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ d->state = wnck_window_get_state (win);
+}
+
+static void
+update_window_decoration_actions (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ d->actions = wnck_window_get_actions (win);
+}
+
+static gboolean
+update_window_decoration_size (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ GdkPixmap *pixmap, *buffer_pixmap = NULL;
+ gint width, height;
+ gint w;
+
+ width = max_window_name_width (win) + BUTTON_SPACE + ICON_SPACE;
+
+ wnck_window_get_geometry (win, NULL, NULL, &w, NULL);
+ if (w < width)
+ width = MAX (ICON_SPACE + BUTTON_SPACE, w);
+
+ width += LEFT_SPACE + RIGHT_SPACE;
+ height = TOP_SPACE + 1 + BOTTOM_SPACE;
+
+ if (width == d->width && height == d->height)
+ return FALSE;
+
+ pixmap = create_pixmap (width, height);
+ if (!pixmap)
+ return FALSE;
+
+ if (double_buffering)
+ {
+ buffer_pixmap = create_pixmap (width, height);
+ if (!buffer_pixmap)
+ {
+ gdk_pixmap_unref (pixmap);
+ return FALSE;
+ }
+ }
+
+ if (d->pixmap)
+ gdk_pixmap_unref (d->pixmap);
+
+ if (d->buffer_pixmap)
+ gdk_pixmap_unref (d->buffer_pixmap);
+
+ if (d->gc)
+ gdk_gc_unref (d->gc);
+
+ d->pixmap = pixmap;
+ d->buffer_pixmap = buffer_pixmap;
+ d->gc = gdk_gc_new (pixmap);
+
+ d->width = width;
+ d->height = height;
+
+ d->prop_xid = wnck_window_get_xid (win);
+
+ update_window_decoration_name (win);
+
+ queue_decor_draw (d);
+
+ return TRUE;
+}
+
+static void
+add_frame_window (WnckWindow *win,
+ Window frame)
+{
+ Display *xdisplay;
+ XSetWindowAttributes attr;
+ gulong xid = wnck_window_get_xid (win);
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ gint i, j;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ attr.event_mask = ButtonPressMask | EnterWindowMask | LeaveWindowMask;
+ attr.override_redirect = TRUE;
+
+ gdk_error_trap_push ();
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ d->event_windows[i][j] =
+ XCreateWindow (xdisplay,
+ frame,
+ 0, 0, 1, 1, 0,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWEventMask, &attr);
+
+ if (cursor[i][j].cursor)
+ XDefineCursor (xdisplay, d->event_windows[i][j],
+ cursor[i][j].cursor);
+ }
+ }
+
+ attr.event_mask |= ButtonReleaseMask;
+
+ for (i = 0; i < 3; i++)
+ {
+ d->button_windows[i] =
+ XCreateWindow (xdisplay,
+ frame,
+ 0, 0, 1, 1, 0,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWEventMask, &attr);
+
+ d->button_states[i] = 0;
+ }
+
+ XSync (xdisplay, FALSE);
+ if (!gdk_error_trap_pop ())
+ {
+ d->decorated = TRUE;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ g_hash_table_insert (frame_table,
+ GINT_TO_POINTER (d->event_windows[i][j]),
+ GINT_TO_POINTER (xid));
+
+ for (i = 0; i < 3; i++)
+ g_hash_table_insert (frame_table,
+ GINT_TO_POINTER (d->button_windows[i]),
+ GINT_TO_POINTER (xid));
+
+
+ update_window_decoration_state (win);
+ update_window_decoration_actions (win);
+ update_window_decoration_icon (win);
+ update_window_decoration_size (win);
+
+ update_event_windows (win);
+ }
+ else
+ {
+ memset (d->event_windows, 0, sizeof (d->event_windows));
+ }
+}
+
+static void
+remove_frame_window (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->pixmap)
+ {
+ gdk_pixmap_unref (d->pixmap);
+ d->pixmap = NULL;
+ }
+
+ if (d->buffer_pixmap)
+ {
+ gdk_pixmap_unref (d->buffer_pixmap);
+ d->buffer_pixmap = NULL;
+ }
+
+ if (d->gc)
+ {
+ gdk_gc_unref (d->gc);
+ d->gc = NULL;
+ }
+
+ if (d->name)
+ {
+ g_free (d->name);
+ d->name = NULL;
+ }
+
+ if (d->layout)
+ {
+ g_object_unref (G_OBJECT (d->layout));
+ d->layout = NULL;
+ }
+
+ if (d->icon)
+ {
+ cairo_pattern_destroy (d->icon);
+ d->icon = NULL;
+ }
+
+ if (d->icon_pixmap)
+ {
+ gdk_pixmap_unref (d->icon_pixmap);
+ d->icon_pixmap = NULL;
+ }
+
+ d->width = 0;
+ d->height = 0;
+
+ d->decorated = FALSE;
+
+ d->state = 0;
+ d->actions = 0;
+
+ draw_list = g_slist_remove (draw_list, d);
+}
+
+static void
+window_name_changed (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ if (update_window_decoration_size (win))
+ queue_decor_draw (d);
+ }
+}
+
+static void
+window_geometry_changed (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ update_window_decoration_size (win);
+ update_event_windows (win);
+ }
+}
+
+static void
+window_icon_changed (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ update_window_decoration_icon (win);
+ queue_decor_draw (d);
+ }
+}
+
+static void
+window_state_changed (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ update_window_decoration_state (win);
+ queue_decor_draw (d);
+ }
+}
+
+static void
+window_actions_changed (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ update_window_decoration_actions (win);
+ queue_decor_draw (d);
+ }
+}
+
+static void
+connect_window (WnckWindow *win)
+{
+ g_signal_connect_object (win, "name_changed",
+ G_CALLBACK (window_name_changed),
+ 0, 0);
+ g_signal_connect_object (win, "geometry_changed",
+ G_CALLBACK (window_geometry_changed),
+ 0, 0);
+ g_signal_connect_object (win, "icon_changed",
+ G_CALLBACK (window_icon_changed),
+ 0, 0);
+ g_signal_connect_object (win, "state_changed",
+ G_CALLBACK (window_state_changed),
+ 0, 0);
+ g_signal_connect_object (win, "actions_changed",
+ G_CALLBACK (window_actions_changed),
+ 0, 0);
+}
+
+static void
+active_window_changed (WnckScreen *screen)
+{
+ WnckWindow *win;
+ decor_t *d;
+
+ win = wnck_screen_get_previously_active_window (screen);
+ if (win)
+ {
+ d = g_object_get_data (G_OBJECT (win), "decor");
+ if (d->pixmap)
+ {
+ d->active = wnck_window_is_active (win);
+ queue_decor_draw (d);
+ }
+ }
+
+ win = wnck_screen_get_active_window (screen);
+ if (win)
+ {
+ d = g_object_get_data (G_OBJECT (win), "decor");
+ if (d->pixmap)
+ {
+ d->active = wnck_window_is_active (win);
+ queue_decor_draw (d);
+ }
+ }
+}
+
+static void
+window_opened (WnckScreen *screen,
+ WnckWindow *win)
+{
+ decor_t *d;
+ Window frame;
+ gulong xid;
+
+ d = g_malloc (sizeof (decor_t));
+ if (!d)
+ return;
+
+ d->pixmap = NULL;
+ d->buffer_pixmap = NULL;
+ d->gc = NULL;
+
+ d->icon = NULL;
+ d->icon_pixmap = NULL;
+
+ d->width = 0;
+ d->height = 0;
+
+ d->active = wnck_window_is_active (win);
+
+ d->layout = NULL;
+ d->name = NULL;
+
+ d->state = 0;
+ d->actions = 0;
+
+ d->prop_xid = 0;
+
+ d->decorated = FALSE;
+
+ g_object_set_data (G_OBJECT (win), "decor", d);
+
+ connect_window (win);
+
+ xid = wnck_window_get_xid (win);
+
+ if (get_window_prop (xid, frame_window_atom, &frame))
+ add_frame_window (win, frame);
+}
+
+static void
+window_closed (WnckScreen *screen,
+ WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ remove_frame_window (win);
+
+ g_free (d);
+}
+
+static void
+connect_screen (WnckScreen *screen)
+{
+ GList *windows;
+
+ g_signal_connect_object (G_OBJECT (screen), "active_window_changed",
+ G_CALLBACK (active_window_changed),
+ 0, 0);
+ g_signal_connect_object (G_OBJECT (screen), "window_opened",
+ G_CALLBACK (window_opened),
+ 0, 0);
+ g_signal_connect_object (G_OBJECT (screen), "window_closed",
+ G_CALLBACK (window_closed),
+ 0, 0);
+
+ windows = wnck_screen_get_windows (screen);
+ while (windows != NULL)
+ {
+ window_opened (screen, windows->data);
+ windows = windows->next;
+ }
+}
+
+static void
+move_resize_window (WnckWindow *win,
+ int direction,
+ XEvent *xevent)
+{
+ Display *xdisplay;
+ GdkDisplay *gdkdisplay;
+ GdkScreen *screen;
+ Window xroot;
+ XEvent ev;
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
+ screen = gdk_display_get_default_screen (gdkdisplay);
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ if (action_menu_mapped)
+ {
+ gtk_object_destroy (GTK_OBJECT (action_menu));
+ action_menu_mapped = FALSE;
+ action_menu = NULL;
+ return;
+ }
+
+ ev.xclient.type = ClientMessage;
+ ev.xclient.display = xdisplay;
+
+ ev.xclient.serial = 0;
+ ev.xclient.send_event = TRUE;
+
+ ev.xclient.window = wnck_window_get_xid (win);
+ ev.xclient.message_type = wm_move_resize_atom;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = xevent->xbutton.x_root;
+ ev.xclient.data.l[1] = xevent->xbutton.y_root;
+ ev.xclient.data.l[2] = direction;
+ ev.xclient.data.l[3] = xevent->xbutton.button;
+ ev.xclient.data.l[4] = 1;
+
+ XUngrabPointer (xdisplay, xevent->xbutton.time);
+ XUngrabKeyboard (xdisplay, xevent->xbutton.time);
+
+ XSendEvent (xdisplay, xroot, FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &ev);
+
+ XSync (xdisplay, FALSE);
+}
+
+/* stolen from gtktooltip.c */
+
+#define DEFAULT_DELAY 500 /* Default delay in ms */
+#define STICKY_DELAY 0 /* Delay before popping up next tip
+ * if we're sticky
+ */
+#define STICKY_REVERT_DELAY 1000 /* Delay before sticky tooltips revert
+ * to normal
+ */
+
+static void
+show_tooltip (const char *text)
+{
+ GdkDisplay *gdkdisplay;
+ GtkRequisition requisition;
+ gint x, y, w, h;
+ GdkScreen *screen;
+ gint monitor_num;
+ GdkRectangle monitor;
+
+ gdkdisplay = gdk_display_get_default ();
+
+ gtk_label_set_text (GTK_LABEL (tip_label), text);
+
+ gtk_widget_size_request (tip_window, &requisition);
+
+ w = requisition.width;
+ h = requisition.height;
+
+ gdk_display_get_pointer (gdkdisplay, &screen, &x, &y, NULL);
+
+ x -= (w / 2 + 4);
+
+ monitor_num = gdk_screen_get_monitor_at_point (screen, x, y);
+ gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+
+ if ((x + w) > monitor.x + monitor.width)
+ x -= (x + w) - (monitor.x + monitor.width);
+ else if (x < monitor.x)
+ x = monitor.x;
+
+ if ((y + h + 16) > monitor.y + monitor.height)
+ y = y - h - 16;
+ else
+ y = y + 16;
+
+ gtk_window_move (GTK_WINDOW (tip_window), x, y);
+ gtk_widget_show (tip_window);
+}
+
+static void
+hide_tooltip (void)
+{
+ if (GTK_WIDGET_VISIBLE (tip_window))
+ g_get_current_time (&tooltip_last_popdown);
+
+ gtk_widget_hide (tip_window);
+
+ if (tooltip_timer_tag)
+ {
+ g_source_remove (tooltip_timer_tag);
+ tooltip_timer_tag = 0;
+ }
+}
+
+static gboolean
+tooltip_recently_shown (void)
+{
+ GTimeVal now;
+ glong msec;
+
+ g_get_current_time (&now);
+
+ msec = (now.tv_sec - tooltip_last_popdown.tv_sec) * 1000 +
+ (now.tv_usec - tooltip_last_popdown.tv_usec) / 1000;
+
+ return (msec < STICKY_REVERT_DELAY);
+}
+
+static gint
+tooltip_timeout (gpointer data)
+{
+ tooltip_timer_tag = 0;
+
+ show_tooltip ((const char *) data);
+
+ return FALSE;
+}
+
+static void
+tooltip_start_delay (const char *text)
+{
+ guint delay = DEFAULT_DELAY;
+
+ if (tooltip_timer_tag)
+ return;
+
+ if (tooltip_recently_shown ())
+ delay = STICKY_DELAY;
+
+ tooltip_timer_tag = g_timeout_add (delay,
+ tooltip_timeout,
+ (gpointer) text);
+}
+
+static gint
+tooltip_paint_window (GtkWidget *tooltip)
+{
+ GtkRequisition req;
+
+ gtk_widget_size_request (tip_window, &req);
+ gtk_paint_flat_box (tip_window->style, tip_window->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_OUT,
+ NULL, GTK_WIDGET (tip_window), "tooltip",
+ 0, 0, req.width, req.height);
+
+ return FALSE;
+}
+
+static gboolean
+create_tooltip_window (void)
+{
+ tip_window = gtk_window_new (GTK_WINDOW_POPUP);
+
+ gtk_widget_set_app_paintable (tip_window, TRUE);
+ gtk_window_set_resizable (GTK_WINDOW (tip_window), FALSE);
+ gtk_widget_set_name (tip_window, "gtk-tooltips");
+ gtk_container_set_border_width (GTK_CONTAINER (tip_window), 4);
+
+ g_signal_connect_swapped (tip_window,
+ "expose_event",
+ G_CALLBACK (tooltip_paint_window),
+ 0);
+
+ tip_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (tip_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (tip_label), 0.5, 0.5);
+ gtk_widget_show (tip_label);
+
+ gtk_container_add (GTK_CONTAINER (tip_window), tip_label);
+
+ gtk_widget_ensure_style (tip_window);
+
+ return TRUE;
+}
+
+static void
+handle_tooltip_event (WnckWindow *win,
+ XEvent *xevent,
+ guint state,
+ const char *tip)
+{
+ switch (xevent->type) {
+ case ButtonPress:
+ hide_tooltip ();
+ break;
+ case ButtonRelease:
+ break;
+ case EnterNotify:
+ if (!(state & PRESSED_EVENT_WINDOW))
+ {
+ if (wnck_window_is_active (win))
+ tooltip_start_delay (tip);
+ }
+ break;
+ case LeaveNotify:
+ if (xevent->xcrossing.mode != NotifyGrab)
+ hide_tooltip ();
+ break;
+ }
+}
+
+static void
+close_button_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[0];
+
+ handle_tooltip_event (win, xevent, state, "Close Window");
+
+ switch (xevent->type) {
+ case ButtonPress:
+ d->button_states[0] |= PRESSED_EVENT_WINDOW;
+ break;
+ case ButtonRelease:
+ if (d->button_states[0] == (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW))
+ wnck_window_close (win, xevent->xbutton.time);
+
+ d->button_states[0] &= ~PRESSED_EVENT_WINDOW;
+ break;
+ case EnterNotify:
+ d->button_states[0] |= IN_EVENT_WINDOW;
+ break;
+ case LeaveNotify:
+ if (xevent->xcrossing.mode != NotifyGrab)
+ d->button_states[0] &= ~IN_EVENT_WINDOW;
+ break;
+ }
+
+ if (state != d->button_states[0])
+ queue_decor_draw (d);
+}
+
+static void
+max_button_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[1];
+
+ if (wnck_window_is_maximized (win))
+ handle_tooltip_event (win, xevent, state, "Unmaximize Window");
+ else
+ handle_tooltip_event (win, xevent, state, "Maximize Window");
+
+ switch (xevent->type) {
+ case ButtonPress:
+ d->button_states[1] |= PRESSED_EVENT_WINDOW;
+ break;
+ case ButtonRelease:
+ if (d->button_states[1] == (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW))
+ {
+ if (wnck_window_is_maximized (win))
+ wnck_window_unmaximize (win);
+ else
+ wnck_window_maximize (win);
+ }
+
+ d->button_states[1] &= ~PRESSED_EVENT_WINDOW;
+ break;
+ case EnterNotify:
+ d->button_states[1] |= IN_EVENT_WINDOW;
+ break;
+ case LeaveNotify:
+ if (xevent->xcrossing.mode != NotifyGrab)
+ d->button_states[1] &= ~IN_EVENT_WINDOW;
+ break;
+ }
+
+ if (state != d->button_states[1])
+ queue_decor_draw (d);
+}
+
+static void
+min_button_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[2];
+
+ handle_tooltip_event (win, xevent, state, "Minimize Window");
+
+ switch (xevent->type) {
+ case ButtonPress:
+ d->button_states[2] |= PRESSED_EVENT_WINDOW;
+ break;
+ case ButtonRelease:
+ if (d->button_states[2] == (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW))
+ wnck_window_minimize (win);
+
+ d->button_states[2] &= ~PRESSED_EVENT_WINDOW;
+ break;
+ case EnterNotify:
+ d->button_states[2] |= IN_EVENT_WINDOW;
+ if (wnck_window_is_active (win))
+ tooltip_start_delay ("Minimize Window");
+ break;
+ case LeaveNotify:
+ if (xevent->xcrossing.mode != NotifyGrab)
+ d->button_states[2] &= ~IN_EVENT_WINDOW;
+ break;
+ }
+
+ if (state != d->button_states[2])
+ queue_decor_draw (d);
+}
+
+static void
+top_left_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_TOPLEFT, xevent);
+}
+
+static void
+top_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_TOP, xevent);
+}
+
+static void
+top_right_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_TOPRIGHT, xevent);
+}
+
+static void
+left_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_LEFT, xevent);
+}
+
+static void
+action_menu_unmap (GObject *object)
+{
+ action_menu_mapped = FALSE;
+}
+
+static void
+title_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ static int last_button_num = 0;
+ static Window last_button_xwindow = None;
+ static Time last_button_time = 0;
+
+ if (xevent->type != ButtonPress)
+ return;
+
+ if (xevent->xbutton.button == 1)
+ {
+ if (xevent->xbutton.button == last_button_num &&
+ xevent->xbutton.window == last_button_xwindow &&
+ xevent->xbutton.time < last_button_time + double_click_timeout)
+ {
+ if (wnck_window_is_maximized (win))
+ wnck_window_unmaximize (win);
+ else
+ wnck_window_maximize (win);
+
+ last_button_num = 0;
+ last_button_xwindow = None;
+ last_button_time = 0;
+ }
+ else
+ {
+ last_button_num = xevent->xbutton.button;
+ last_button_xwindow = xevent->xbutton.window;
+ last_button_time = xevent->xbutton.time;
+
+ move_resize_window (win, WM_MOVERESIZE_MOVE, xevent);
+ }
+ }
+ else if (xevent->xbutton.button == 3)
+ {
+ GdkDisplay *gdkdisplay;
+ GdkScreen *screen;
+
+ gdkdisplay = gdk_display_get_default ();
+ screen = gdk_display_get_default_screen (gdkdisplay);
+
+ if (action_menu)
+ gtk_object_destroy (GTK_OBJECT (action_menu));
+
+ action_menu = wnck_create_window_action_menu (win);
+
+ gtk_menu_set_screen (GTK_MENU (action_menu), screen);
+
+ g_signal_connect_object (G_OBJECT (action_menu), "unmap",
+ G_CALLBACK (action_menu_unmap),
+ 0, 0);
+
+ gtk_widget_show (action_menu);
+ gtk_menu_popup (GTK_MENU (action_menu),
+ NULL, NULL,
+ NULL, NULL,
+ xevent->xbutton.button,
+ xevent->xbutton.time);
+
+ action_menu_mapped = TRUE;
+ }
+}
+
+static void
+right_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_RIGHT, xevent);
+}
+
+static void
+bottom_left_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_BOTTOMLEFT, xevent);
+}
+
+static void
+bottom_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_BOTTOM, xevent);
+}
+
+static void
+bottom_right_event (WnckWindow *win,
+ XEvent *xevent)
+{
+ if (xevent->xbutton.button == 1)
+ move_resize_window (win, WM_MOVERESIZE_SIZE_BOTTOMRIGHT, xevent);
+}
+
+static GdkFilterReturn
+event_filter_func (GdkXEvent *gdkxevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ Display *xdisplay;
+ GdkDisplay *gdkdisplay;
+ XEvent *xevent = gdkxevent;
+ gulong xid = 0;
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
+
+ switch (xevent->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ xid = (gulong)
+ g_hash_table_lookup (frame_table,
+ GINT_TO_POINTER (xevent->xbutton.window));
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ xid = (gulong)
+ g_hash_table_lookup (frame_table,
+ GINT_TO_POINTER (xevent->xcrossing.window));
+ break;
+ case MotionNotify:
+ xid = (gulong)
+ g_hash_table_lookup (frame_table,
+ GINT_TO_POINTER (xevent->xmotion.window));
+ break;
+ case PropertyNotify:
+ if (xevent->xproperty.atom == frame_window_atom)
+ {
+ WnckWindow *win;
+
+ xid = xevent->xproperty.window;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ Window frame;
+
+ if (get_window_prop (xid, frame_window_atom, &frame))
+ add_frame_window (win, frame);
+ else
+ remove_frame_window (win);
+ }
+ }
+ break;
+ case DestroyNotify:
+ g_hash_table_remove (frame_table,
+ GINT_TO_POINTER (xevent->xproperty.window));
+ default:
+ break;
+ }
+
+ if (xid)
+ {
+ WnckWindow *win;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ static event_callback callback[3][3] = {
+ { top_left_event, top_event, top_right_event },
+ { left_event, title_event, right_event },
+ { bottom_left_event, bottom_event, bottom_right_event }
+ };
+ static event_callback button_callback[3] = {
+ close_button_event,
+ max_button_event,
+ min_button_event
+ };
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ if (d->event_windows[i][j] == xevent->xany.window)
+ (*callback[i][j]) (win, xevent);
+
+ for (i = 0; i < 3; i++)
+ if (d->button_windows[i] == xevent->xany.window)
+ (*button_callback[i]) (win, xevent);
+ }
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+/* from clearlooks theme */
+static void
+rgb_to_hls (gdouble *r,
+ gdouble *g,
+ gdouble *b)
+{
+ gdouble min;
+ gdouble max;
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gdouble h, l, s;
+ gdouble delta;
+
+ red = *r;
+ green = *g;
+ blue = *b;
+
+ if (red > green)
+ {
+ if (red > blue)
+ max = red;
+ else
+ max = blue;
+
+ if (green < blue)
+ min = green;
+ else
+ min = blue;
+ }
+ else
+ {
+ if (green > blue)
+ max = green;
+ else
+ max = blue;
+
+ if (red < blue)
+ min = red;
+ else
+ min = blue;
+ }
+
+ l = (max + min) / 2;
+ s = 0;
+ h = 0;
+
+ if (max != min)
+ {
+ if (l <= 0.5)
+ s = (max - min) / (max + min);
+ else
+ s = (max - min) / (2 - max - min);
+
+ delta = max -min;
+ if (red == max)
+ h = (green - blue) / delta;
+ else if (green == max)
+ h = 2 + (blue - red) / delta;
+ else if (blue == max)
+ h = 4 + (red - green) / delta;
+
+ h *= 60;
+ if (h < 0.0)
+ h += 360;
+ }
+
+ *r = h;
+ *g = l;
+ *b = s;
+}
+
+static void
+hls_to_rgb (gdouble *h,
+ gdouble *l,
+ gdouble *s)
+{
+ gdouble hue;
+ gdouble lightness;
+ gdouble saturation;
+ gdouble m1, m2;
+ gdouble r, g, b;
+
+ lightness = *l;
+ saturation = *s;
+
+ if (lightness <= 0.5)
+ m2 = lightness * (1 + saturation);
+ else
+ m2 = lightness + saturation - lightness * saturation;
+
+ m1 = 2 * lightness - m2;
+
+ if (saturation == 0)
+ {
+ *h = lightness;
+ *l = lightness;
+ *s = lightness;
+ }
+ else
+ {
+ hue = *h + 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ r = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ r = m2;
+ else if (hue < 240)
+ r = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ r = m1;
+
+ hue = *h;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ g = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ g = m2;
+ else if (hue < 240)
+ g = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ g = m1;
+
+ hue = *h - 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ b = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ b = m2;
+ else if (hue < 240)
+ b = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ b = m1;
+
+ *h = r;
+ *l = g;
+ *s = b;
+ }
+}
+
+static void
+shade (const decor_color_t *a,
+ decor_color_t *b,
+ float k)
+{
+ double red;
+ double green;
+ double blue;
+
+ red = a->r;
+ green = a->g;
+ blue = a->b;
+
+ rgb_to_hls (&red, &green, &blue);
+
+ green *= k;
+ if (green > 1.0)
+ green = 1.0;
+ else if (green < 0.0)
+ green = 0.0;
+
+ blue *= k;
+ if (blue > 1.0)
+ blue = 1.0;
+ else if (blue < 0.0)
+ blue = 0.0;
+
+ hls_to_rgb (&red, &green, &blue);
+
+ b->r = red;
+ b->g = green;
+ b->b = blue;
+}
+
+static void
+style_changed (GtkWidget *widget)
+{
+ GdkDisplay *gdkdisplay;
+ GdkScreen *gdkscreen;
+ GtkStyle *style;
+ decor_color_t spot_color;
+ WnckScreen *screen;
+ GList *windows;
+
+ gdkdisplay = gdk_display_get_default ();
+ gdkscreen = gdk_display_get_default_screen (gdkdisplay);
+ screen = wnck_screen_get_default ();
+
+ style = gtk_widget_get_style (widget);
+
+ spot_color.r = style->bg[GTK_STATE_SELECTED].red / 65535.0;
+ spot_color.g = style->bg[GTK_STATE_SELECTED].green / 65535.0;
+ spot_color.b = style->bg[GTK_STATE_SELECTED].blue / 65535.0;
+
+ shade (&spot_color, &_title_color[0], 1.05);
+ shade (&_title_color[0], &_title_color[1], 0.85);
+
+ update_default_decorations (gdkscreen);
+
+ windows = wnck_screen_get_windows (screen);
+ while (windows != NULL)
+ {
+ queue_decor_draw (g_object_get_data (G_OBJECT (windows->data),
+ "decor"));
+ windows = windows->next;
+ }
+}
+
+static gboolean
+init_settings (WnckScreen *screen)
+{
+ PangoFontDescription *desc;
+ GtkSettings *settings;
+
+ style_window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_widget_ensure_style (style_window);
+
+ style_changed (style_window);
+
+ g_signal_connect_object (style_window, "style-set",
+ G_CALLBACK (style_changed),
+ 0, 0);
+
+ settings = gtk_widget_get_settings (style_window);
+
+ g_object_get (G_OBJECT (settings), "gtk-double-click-time",
+ &double_click_timeout, NULL);
+
+ pango_context = gtk_widget_create_pango_context (style_window);
+
+ desc = pango_font_description_from_string ("Sans Bold 10");
+
+ pango_context_set_font_description (pango_context, desc);
+
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GdkDisplay *gdkdisplay;
+ Display *xdisplay;
+ GdkScreen *gdkscreen;
+ WnckScreen *screen;
+ cairo_t *cr;
+ gint i, j;
+
+ gtk_init (&argc, &argv);
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ gdkscreen = gdk_display_get_default_screen (gdkdisplay);
+
+ frame_window_atom = XInternAtom (xdisplay, "_NET_FRAME_WINDOW", FALSE);
+ win_decor_atom = XInternAtom (xdisplay, "_NET_WINDOW_DECOR", FALSE);
+ win_decor_sync_atom = XInternAtom (xdisplay, "_NET_WINDOW_DECOR_SYNC", FALSE);
+ wm_move_resize_atom = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", FALSE);
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (cursor[i][j].shape != XC_left_ptr)
+ cursor[i][j].cursor =
+ XCreateFontCursor (xdisplay, cursor[i][j].shape);
+ }
+ }
+
+ frame_table = g_hash_table_new (NULL, NULL);
+
+ if (check_dm_hint (gdkscreen))
+ {
+ fprintf (stderr, "%s: Another window decorator is already running\n",
+ argv[0]);
+ return 1;
+ }
+
+ shadow_pixmap = pixmap_new_from_inline (_shadow);
+ large_shadow_pixmap = pixmap_new_from_inline (_large_shadow);
+
+ if (!shadow_pixmap || !large_shadow_pixmap)
+ {
+ fprintf (stderr, "%s, Failed to load shadow images\n", argv[0]);
+ return 1;
+ }
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (large_shadow_pixmap));
+ shadow_pattern = cairo_pattern_create_for_surface (cairo_get_target (cr));
+ cairo_destroy (cr);
+
+ if (!create_tooltip_window ())
+ {
+ fprintf (stderr, "%s, Couldn't create tooltip window\n", argv[0]);
+ return 1;
+ }
+
+ screen = wnck_screen_get_default ();
+
+ gdk_window_add_filter (NULL,
+ event_filter_func,
+ NULL);
+
+ connect_screen (screen);
+
+ if (!init_settings (screen))
+ {
+ fprintf (stderr, "%s: Failed to get necessary gtk settings\n", argv[0]);
+ return 1;
+ }
+
+ set_dm_check_hint (gdk_display_get_default_screen (gdkdisplay));
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/images/Makefile.am b/images/Makefile.am
new file mode 100644
index 0000000..f3b7aad
--- /dev/null
+++ b/images/Makefile.am
@@ -0,0 +1,8 @@
+imagesdir = $(imagedir)
+images_DATA = \
+ background.png \
+ window.png
+
+EXTRA_DIST = \
+ background.png \
+ window.png
diff --git a/images/background.png b/images/background.png
new file mode 100644
index 0000000..d2b6231
--- /dev/null
+++ b/images/background.png
Binary files differ
diff --git a/images/window.png b/images/window.png
new file mode 100644
index 0000000..06742e0
--- /dev/null
+++ b/images/window.png
Binary files differ
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..83727aa
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,2 @@
+glxcompincludedir = $(includedir)/compiz
+glxcompinclude_HEADERS = compiz.h
diff --git a/include/compiz.h b/include/compiz.h
new file mode 100644
index 0000000..2840b18
--- /dev/null
+++ b/include/compiz.h
@@ -0,0 +1,1605 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name