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 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>
+ */
+
+#ifndef _COMPIZ_H
+#define _COMPIZ_H
+
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/sync.h>
+#include <X11/Xregion.h>
+
+#define SN_API_NOT_YET_FROZEN
+#include <libsn/sn.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+typedef struct _CompPlugin CompPlugin;
+typedef struct _CompDisplay CompDisplay;
+typedef struct _CompScreen CompScreen;
+typedef struct _CompWindow CompWindow;
+typedef struct _CompTexture CompTexture;
+
+/* virtual modifiers */
+
+#define CompModAlt 0
+#define CompModMeta 1
+#define CompModSuper 2
+#define CompModHyper 3
+#define CompModModeSwitch 4
+#define CompModNumLock 5
+#define CompModScrollLock 6
+#define CompModNum 7
+
+#define CompAltMask (1 << 16)
+#define CompMetaMask (1 << 17)
+#define CompSuperMask (1 << 18)
+#define CompHyperMask (1 << 19)
+#define CompModeSwitchMask (1 << 20)
+#define CompNumLockMask (1 << 21)
+#define CompScrollLockMask (1 << 22)
+
+#define CompPressMask (1 << 23)
+#define CompReleaseMask (1 << 24)
+
+#define CompNoMask (1 << 25)
+
+#define CompWindowProtocolDeleteMask (1 << 0)
+#define CompWindowProtocolTakeFocusMask (1 << 1)
+#define CompWindowProtocolPingMask (1 << 2)
+#define CompWindowProtocolSyncRequestMask (1 << 3)
+
+#define CompWindowTypeDesktopMask (1 << 0)
+#define CompWindowTypeDockMask (1 << 1)
+#define CompWindowTypeToolbarMask (1 << 2)
+#define CompWindowTypeMenuMask (1 << 3)
+#define CompWindowTypeUtilMask (1 << 4)
+#define CompWindowTypeSplashMask (1 << 5)
+#define CompWindowTypeDialogMask (1 << 6)
+#define CompWindowTypeModalDialogMask (1 << 7)
+#define CompWindowTypeNormalMask (1 << 8)
+#define CompWindowTypeFullscreenMask (1 << 9)
+#define CompWindowTypeUnknownMask (1 << 10)
+
+#define CompWindowStateModalMask (1 << 0)
+#define CompWindowStateStickyMask (1 << 1)
+#define CompWindowStateMaximizedVertMask (1 << 2)
+#define CompWindowStateMaximizedHorzMask (1 << 3)
+#define CompWindowStateShadedMask (1 << 4)
+#define CompWindowStateSkipTaskbarMask (1 << 5)
+#define CompWindowStateSkipPagerMask (1 << 6)
+#define CompWindowStateHiddenMask (1 << 7)
+#define CompWindowStateFullscreenMask (1 << 8)
+#define CompWindowStateAboveMask (1 << 9)
+#define CompWindowStateBelowMask (1 << 10)
+#define CompWindowStateDemandsAttentationMask (1 << 11)
+#define CompWindowStateDisplayModalMask (1 << 12)
+
+#define CompWindowActionMoveMask (1 << 0)
+#define CompWindowActionResizeMask (1 << 1)
+#define CompWindowActionStickMask (1 << 2)
+#define CompWindowActionMinimizeMask (1 << 3)
+#define CompWindowActionMaximizeHorzMask (1 << 4)
+#define CompWindowActionMaximizeVertMask (1 << 5)
+#define CompWindowActionFullscreenMask (1 << 6)
+#define CompWindowActionCloseMask (1 << 7)
+
+#define MwmDecorAll (1L << 0)
+#define MwmDecorBorder (1L << 1)
+#define MwmDecorHandle (1L << 2)
+#define MwmDecorTitle (1L << 3)
+#define MwmDecorMenu (1L << 4)
+#define MwmDecorMinimize (1L << 5)
+#define MwmDecorMaximize (1L << 6)
+
+#define WmMoveResizeSizeTopLeft 0
+#define WmMoveResizeSizeTop 1
+#define WmMoveResizeSizeTopRight 2
+#define WmMoveResizeSizeRight 3
+#define WmMoveResizeSizeBottomRight 4
+#define WmMoveResizeSizeBottom 5
+#define WmMoveResizeSizeBottomLeft 6
+#define WmMoveResizeSizeLeft 7
+#define WmMoveResizeMove 8
+#define WmMoveResizeSizeKeyboard 9
+#define WmMoveResizeMoveKeyboard 10
+
+#define OPAQUE 0xffff
+#define COLOR 0xffff
+#define BRIGHT 0xffff
+
+#define RED_SATURATION_WEIGHT 0.30f
+#define GREEN_SATURATION_WEIGHT 0.59f
+#define BLUE_SATURATION_WEIGHT 0.11f
+
+extern char *programName;
+extern char **programArgv;
+extern int programArgc;
+extern char *backgroundImage;
+extern char *windowImage;
+extern REGION emptyRegion;
+extern REGION infiniteRegion;
+extern GLushort defaultColor[4];
+extern Window currentRoot;
+extern Bool testMode;
+extern Bool restartSignal;
+extern CompWindow *lastFoundWindow;
+extern CompWindow *lastDamagedWindow;
+extern Bool replaceCurrentWm;
+
+extern int defaultRefreshRate;
+extern char *defaultTextureFilter;
+
+extern char *windowTypeString[];
+extern int nWindowTypeString;
+
+#define RESTRICT_VALUE(value, min, max) \
+ (((value) < (min)) ? (min): ((value) > (max)) ? (max) : (value))
+
+#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
+
+
+/* privates.h */
+
+#define WRAP(priv, real, func, wrapFunc) \
+ (priv)->func = (real)->func; \
+ (real)->func = (wrapFunc)
+
+#define UNWRAP(priv, real, func) \
+ (real)->func = (priv)->func
+
+typedef union _CompPrivate {
+ void *ptr;
+ long val;
+ unsigned long uval;
+ void *(*fptr) (void);
+} CompPrivate;
+
+typedef int (*ReallocPrivatesProc) (int size, void *closure);
+
+int
+allocatePrivateIndex (int *len,
+ char **indices,
+ ReallocPrivatesProc reallocProc,
+ void *closure);
+
+void
+freePrivateIndex (int len,
+ char *indices,
+ int index);
+
+
+/* readpng.c */
+
+Bool
+readPng (const char *filename,
+ char **data,
+ unsigned int *width,
+ unsigned int *height);
+
+Bool
+readPngBuffer (const unsigned char *buffer,
+ char **data,
+ unsigned int *width,
+ unsigned int *height);
+
+/* option.c */
+
+typedef enum {
+ CompOptionTypeBool,
+ CompOptionTypeInt,
+ CompOptionTypeFloat,
+ CompOptionTypeString,
+ CompOptionTypeColor,
+ CompOptionTypeBinding,
+ CompOptionTypeList
+} CompOptionType;
+
+typedef enum {
+ CompBindingTypeKey,
+ CompBindingTypeButton
+} CompBindingType;
+
+typedef struct _CompKeyBinding {
+ int keycode;
+ unsigned int modifiers;
+} CompKeyBinding;
+
+typedef struct _CompButtonBinding {
+ int button;
+ unsigned int modifiers;
+} CompButtonBinding;
+
+typedef struct {
+ CompBindingType type;
+ union {
+ CompKeyBinding key;
+ CompButtonBinding button;
+ } u;
+} CompBinding;
+
+typedef union _CompOptionValue CompOptionValue;
+
+typedef struct {
+ CompOptionType type;
+ CompOptionValue *value;
+ int nValue;
+} CompListValue;
+
+union _CompOptionValue {
+ Bool b;
+ int i;
+ float f;
+ char *s;
+ unsigned short c[4];
+ CompBinding bind;
+ CompListValue list;
+};
+
+typedef struct _CompOptionIntRestriction {
+ int min;
+ int max;
+} CompOptionIntRestriction;
+
+typedef struct _CompOptionFloatRestriction {
+ float min;
+ float max;
+ float precision;
+} CompOptionFloatRestriction;
+
+typedef struct _CompOptionStringRestriction {
+ char **string;
+ int nString;
+} CompOptionStringRestriction;
+
+typedef union {
+ CompOptionIntRestriction i;
+ CompOptionFloatRestriction f;
+ CompOptionStringRestriction s;
+} CompOptionRestriction;
+
+typedef struct _CompOption {
+ char *name;
+ char *shortDesc;
+ char *longDesc;
+ CompOptionType type;
+ CompOptionValue value;
+ CompOptionRestriction rest;
+} CompOption;
+
+typedef CompOption *(*DisplayOptionsProc) (CompDisplay *display, int *count);
+typedef CompOption *(*ScreenOptionsProc) (CompScreen *screen, int *count);
+
+CompOption *
+compFindOption (CompOption *option,
+ int nOption,
+ char *name,
+ int *index);
+
+Bool
+compSetBoolOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetIntOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetFloatOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetStringOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetColorOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetBindingOption (CompOption *option,
+ CompOptionValue *value);
+
+Bool
+compSetOptionList (CompOption *option,
+ CompOptionValue *value);
+
+unsigned int
+compWindowTypeMaskFromStringList (CompOptionValue *value);
+
+
+/* display.c */
+
+typedef int CompTimeoutHandle;
+
+#define COMP_DISPLAY_OPTION_ACTIVE_PLUGINS 0
+#define COMP_DISPLAY_OPTION_TEXTURE_FILTER 1
+#define COMP_DISPLAY_OPTION_CLICK_TO_FOCUS 2
+#define COMP_DISPLAY_OPTION_AUTORAISE 3
+#define COMP_DISPLAY_OPTION_AUTORAISE_DELAY 4
+#define COMP_DISPLAY_OPTION_NUM 5
+
+typedef CompOption *(*GetDisplayOptionsProc) (CompDisplay *display,
+ int *count);
+typedef Bool (*SetDisplayOptionProc) (CompDisplay *display,
+ char *name,
+ CompOptionValue *value);
+typedef Bool (*SetDisplayOptionForPluginProc) (CompDisplay *display,
+ char *plugin,
+ char *name,
+ CompOptionValue *value);
+
+typedef Bool (*InitPluginForDisplayProc) (CompPlugin *plugin,
+ CompDisplay *display);
+
+typedef void (*FiniPluginForDisplayProc) (CompPlugin *plugin,
+ CompDisplay *display);
+
+typedef void (*HandleEventProc) (CompDisplay *display,
+ XEvent *event);
+
+typedef Bool (*CallBackProc) (void *closure);
+
+typedef void (*ForEachWindowProc) (CompWindow *window,
+ void *closure);
+
+struct _CompDisplay {
+ Display *display;
+ CompScreen *screens;
+
+ char *screenPrivateIndices;
+ int screenPrivateLen;
+
+ int compositeEvent, compositeError, compositeOpcode;
+ int damageEvent, damageError;
+ int randrEvent, randrError;
+ int syncEvent, syncError;
+
+ Bool shapeExtension;
+ int shapeEvent, shapeError;
+
+ SnDisplay *snDisplay;
+
+ Atom supportedAtom;
+ Atom supportingWmCheckAtom;
+
+ Atom utf8StringAtom;
+
+ Atom wmNameAtom;
+
+ Atom winTypeAtom;
+ Atom winTypeDesktopAtom;
+ Atom winTypeDockAtom;
+ Atom winTypeToolbarAtom;
+ Atom winTypeMenuAtom;
+ Atom winTypeUtilAtom;
+ Atom winTypeSplashAtom;
+ Atom winTypeDialogAtom;
+ Atom winTypeNormalAtom;
+
+ Atom winOpacityAtom;
+ Atom winBrightnessAtom;
+ Atom winSaturationAtom;
+ Atom winActiveAtom;
+
+ Atom workareaAtom;
+
+ Atom desktopViewportAtom;
+ Atom desktopGeometryAtom;
+ Atom currentDesktopAtom;
+ Atom numberOfDesktopsAtom;
+
+ Atom winStateAtom;
+ Atom winStateModalAtom;
+ Atom winStateStickyAtom;
+ Atom winStateMaximizedVertAtom;
+ Atom winStateMaximizedHorzAtom;
+ Atom winStateShadedAtom;
+ Atom winStateSkipTaskbarAtom;
+ Atom winStateSkipPagerAtom;
+ Atom winStateHiddenAtom;
+ Atom winStateFullscreenAtom;
+ Atom winStateAboveAtom;
+ Atom winStateBelowAtom;
+ Atom winStateDemandsAttentionAtom;
+ Atom winStateDisplayModalAtom;
+
+ Atom winActionMoveAtom;
+ Atom winActionResizeAtom;
+ Atom winActionStickAtom;
+ Atom winActionMinimizeAtom;
+ Atom winActionMaximizeHorzAtom;
+ Atom winActionMaximizeVertAtom;
+ Atom winActionFullscreenAtom;
+ Atom winActionCloseAtom;
+
+ Atom wmAllowedActionsAtom;
+
+ Atom wmStrutAtom;
+ Atom wmStrutPartialAtom;
+
+ Atom clientListAtom;
+ Atom clientListStackingAtom;
+
+ Atom frameExtentsAtom;
+ Atom frameWindowAtom;
+
+ Atom wmStateAtom;
+ Atom wmChangeStateAtom;
+ Atom wmProtocolsAtom;
+ Atom wmClientLeaderAtom;
+
+ Atom wmDeleteWindowAtom;
+ Atom wmTakeFocusAtom;
+ Atom wmPingAtom;
+ Atom wmSyncRequestAtom;
+
+ Atom wmSyncRequestCounterAtom;
+
+ Atom closeWindowAtom;
+ Atom wmMoveResizeAtom;
+ Atom moveResizeWindowAtom;
+
+ Atom showingDesktopAtom;
+
+ Atom xBackgroundAtom[2];
+
+ Atom panelActionAtom;
+ Atom panelActionMainMenuAtom;
+ Atom panelActionRunDialogAtom;
+
+ Atom mwmHintsAtom;
+
+ Atom managerAtom;
+ Atom targetsAtom;
+ Atom multipleAtom;
+ Atom timestampAtom;
+ Atom versionAtom;
+ Atom atomPairAtom;
+
+ unsigned int lastPing;
+ CompTimeoutHandle pingHandle;
+
+ GLenum textureFilter;
+
+ Window activeWindow;
+
+ Window below;
+ char displayString[256];
+
+ unsigned int modMask[CompModNum];
+ unsigned int ignoredModMask;
+
+ CompOption opt[COMP_DISPLAY_OPTION_NUM];
+
+ CompTimeoutHandle autoRaiseHandle;
+ Window autoRaiseWindow;
+
+ CompOptionValue plugin;
+ Bool dirtyPluginList;
+
+ SetDisplayOptionProc setDisplayOption;
+ SetDisplayOptionForPluginProc setDisplayOptionForPlugin;
+
+ InitPluginForDisplayProc initPluginForDisplay;
+ FiniPluginForDisplayProc finiPluginForDisplay;
+
+ HandleEventProc handleEvent;
+
+ CompPrivate *privates;
+};
+
+extern CompDisplay *compDisplays;
+
+int
+allocateDisplayPrivateIndex (void);
+
+void
+freeDisplayPrivateIndex (int index);
+
+CompOption *
+compGetDisplayOptions (CompDisplay *display,
+ int *count);
+
+CompTimeoutHandle
+compAddTimeout (int time,
+ CallBackProc callBack,
+ void *closure);
+
+void
+compRemoveTimeout (CompTimeoutHandle handle);
+
+int
+compCheckForError (Display *dpy);
+
+Bool
+addDisplay (char *name,
+ char **plugin,
+ int nPlugin);
+
+void
+focusDefaultWindow (CompDisplay *d);
+
+void
+forEachWindowOnDisplay (CompDisplay *display,
+ ForEachWindowProc proc,
+ void *closure);
+
+CompScreen *
+findScreenAtDisplay (CompDisplay *d,
+ Window root);
+
+CompWindow *
+findWindowAtDisplay (CompDisplay *display,
+ Window id);
+
+unsigned int
+virtualToRealModMask (CompDisplay *d,
+ unsigned int modMask);
+
+void
+updateModifierMappings (CompDisplay *d);
+
+void
+eventLoop (void);
+
+void
+handleSelectionRequest (CompDisplay *display,
+ XEvent *event);
+
+void
+handleSelectionClear (CompDisplay *display,
+ XEvent *event);
+
+
+/* event.c */
+
+#define EV_BUTTON(opt, event) \
+ ((opt)->value.bind.type == CompBindingTypeButton && \
+ (opt)->value.bind.u.button.button == (event)->xbutton.button && \
+ ((opt)->value.bind.u.button.modifiers & (event)->xbutton.state) == \
+ (opt)->value.bind.u.button.modifiers)
+
+#define EV_KEY(opt, event) \
+ ((opt)->value.bind.type == CompBindingTypeKey && \
+ (opt)->value.bind.u.key.keycode == (event)->xkey.keycode && \
+ ((opt)->value.bind.u.key.modifiers & (event)->xkey.state) == \
+ (opt)->value.bind.u.key.modifiers)
+
+void
+handleEvent (CompDisplay *display,
+ XEvent *event);
+
+void
+handleSyncAlarm (CompWindow *w);
+
+
+/* paint.c */
+
+#define MULTIPLY_USHORT(us1, us2) \
+ (((GLuint) (us1) * (GLuint) (us2)) / 0xffff)
+
+/* camera distance from screen, 0.5 * tan (FOV) */
+#define DEFAULT_Z_CAMERA 0.866025404f
+
+typedef struct _ScreenPaintAttrib {
+ GLfloat xRotate;
+ GLfloat yRotate;
+ GLfloat vRotate;
+ GLfloat xTranslate;
+ GLfloat yTranslate;
+ GLfloat zTranslate;
+ GLfloat zCamera;
+} ScreenPaintAttrib;
+
+typedef struct _WindowPaintAttrib {
+ GLushort opacity;
+ GLushort brightness;
+ GLushort saturation;
+ GLfloat xScale;
+ GLfloat yScale;
+} WindowPaintAttrib;
+
+extern ScreenPaintAttrib defaultScreenPaintAttrib;
+extern WindowPaintAttrib defaultWindowPaintAttrib;
+
+typedef struct _CompMatrix {
+ float xx; float yx;
+ float xy; float yy;
+ float x0; float y0;
+} CompMatrix;
+
+#define COMP_TEX_COORD_X(m, vx) ((m)->xx * (vx) + (m)->x0)
+#define COMP_TEX_COORD_Y(m, vy) ((m)->yy * (vy) + (m)->y0)
+
+#define COMP_TEX_COORD_XY(m, vx, vy) \
+ ((m)->xx * (vx) + (m)->xy * (vy) + (m)->x0)
+#define COMP_TEX_COORD_YX(m, vx, vy) \
+ ((m)->yx * (vx) + (m)->yy * (vy) + (m)->y0)
+
+
+typedef void (*PreparePaintScreenProc) (CompScreen *screen,
+ int msSinceLastPaint);
+
+typedef void (*DonePaintScreenProc) (CompScreen *screen);
+
+#define PAINT_SCREEN_REGION_MASK (1 << 0)
+#define PAINT_SCREEN_FULL_MASK (1 << 1)
+#define PAINT_SCREEN_TRANSFORMED_MASK (1 << 2)
+#define PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK (1 << 3)
+
+typedef Bool (*PaintScreenProc) (CompScreen *screen,
+ const ScreenPaintAttrib *sAttrib,
+ Region region,
+ unsigned int mask);
+
+typedef void (*PaintTransformedScreenProc) (CompScreen *screen,
+ const ScreenPaintAttrib *sAttrib,
+ unsigned int mask);
+
+
+#define PAINT_WINDOW_SOLID_MASK (1 << 0)
+#define PAINT_WINDOW_TRANSLUCENT_MASK (1 << 1)
+#define PAINT_WINDOW_TRANSFORMED_MASK (1 << 2)
+#define PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK (1 << 3)
+
+typedef Bool (*PaintWindowProc) (CompWindow *window,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask);
+
+typedef void (*AddWindowGeometryProc) (CompWindow *window,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip);
+
+typedef void (*DrawWindowGeometryProc) (CompWindow *window);
+
+#define PAINT_BACKGROUND_ON_TRANSFORMED_SCREEN_MASK (1 << 0)
+#define PAINT_BACKGROUND_WITH_STENCIL_MASK (1 << 1)
+
+typedef void (*PaintBackgroundProc) (CompScreen *screen,
+ Region region,
+ unsigned int mask);
+
+
+void
+preparePaintScreen (CompScreen *screen,
+ int msSinceLastPaint);
+
+void
+donePaintScreen (CompScreen *screen);
+
+void
+translateRotateScreen (const ScreenPaintAttrib *sa);
+
+void
+paintTransformedScreen (CompScreen *screen,
+ const ScreenPaintAttrib *sAttrib,
+ unsigned int mask);
+
+Bool
+paintScreen (CompScreen *screen,
+ const ScreenPaintAttrib *sAttrib,
+ Region region,
+ unsigned int mask);
+
+Bool
+moreWindowVertices (CompWindow *w,
+ int newSize);
+
+Bool
+moreWindowIndices (CompWindow *w,
+ int newSize);
+
+void
+addWindowGeometry (CompWindow *w,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip);
+
+void
+drawWindowGeometry (CompWindow *w);
+
+void
+drawWindowTexture (CompWindow *w,
+ CompTexture *texture,
+ const WindowPaintAttrib *attrib,
+ unsigned int mask);
+
+Bool
+paintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask);
+
+void
+paintBackground (CompScreen *screen,
+ Region region,
+ unsigned int mask);
+
+
+/* texture.c */
+
+#define POWER_OF_TWO(v) ((v & (v - 1)) == 0)
+
+typedef enum {
+ COMP_TEXTURE_FILTER_FAST,
+ COMP_TEXTURE_FILTER_GOOD
+} CompTextureFilter;
+
+struct _CompTexture {
+ GLuint name;
+ GLenum target;
+ GLfloat dx, dy;
+ GLXPixmap pixmap;
+ CompTextureFilter filter;
+ GLenum wrap;
+ CompMatrix matrix;
+};
+
+void
+initTexture (CompScreen *screen,
+ CompTexture *texture);
+
+void
+finiTexture (CompScreen *screen,
+ CompTexture *texture);
+
+Bool
+readImageToTexture (CompScreen *screen,
+ CompTexture *texture,
+ char *imageFileName,
+ unsigned int *width,
+ unsigned int *height);
+
+Bool
+readImageBufferToTexture (CompScreen *screen,
+ CompTexture *texture,
+ const unsigned char *imageBuffer,
+ unsigned int *returnWidth,
+ unsigned int *returnHeight);
+
+Bool
+bindPixmapToTexture (CompScreen *screen,
+ CompTexture *texture,
+ Pixmap pixmap,
+ int width,
+ int height,
+ int depth);
+
+void
+releasePixmapFromTexture (CompScreen *screen,
+ CompTexture *texture);
+
+void
+enableTexture (CompScreen *screen,
+ CompTexture *texture,
+ CompTextureFilter filter);
+
+void
+enableTextureClampToBorder (CompScreen *screen,
+ CompTexture *texture,
+ CompTextureFilter filter);
+
+void
+enableTextureClampToEdge (CompScreen *screen,
+ CompTexture *texture,
+ CompTextureFilter filter);
+
+void
+disableTexture (CompTexture *texture);
+
+
+/* screen.c */
+
+#define COMP_SCREEN_OPTION_DETECT_REFRESH_RATE 0
+#define COMP_SCREEN_OPTION_REFRESH_RATE 1
+#define COMP_SCREEN_OPTION_SIZE 2
+#define COMP_SCREEN_OPTION_CLOSE_WINDOW 3
+#define COMP_SCREEN_OPTION_MAIN_MENU 4
+#define COMP_SCREEN_OPTION_RUN_DIALOG 5
+#define COMP_SCREEN_OPTION_COMMAND0 6
+#define COMP_SCREEN_OPTION_RUN_COMMAND0 7
+#define COMP_SCREEN_OPTION_COMMAND1 8
+#define COMP_SCREEN_OPTION_RUN_COMMAND1 9
+#define COMP_SCREEN_OPTION_NUM 10
+
+typedef void (*FuncPtr) (void);
+typedef FuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
+
+#ifndef GLX_EXT_render_texture
+#define GLX_TEXTURE_TARGET_EXT 0x6001
+#define GLX_TEXTURE_2D_EXT 0x6002
+#define GLX_TEXTURE_RECTANGLE_EXT 0x6003
+#define GLX_NO_TEXTURE_EXT 0x6004
+#define GLX_FRONT_LEFT_EXT 0x6005
+#endif
+
+typedef Bool (*GLXBindTexImageProc) (Display *display,
+ GLXDrawable drawable,
+ int buffer);
+typedef Bool (*GLXReleaseTexImageProc) (Display *display,
+ GLXDrawable drawable,
+ int buffer);
+typedef void (*GLXQueryDrawableProc) (Display *display,
+ GLXDrawable drawable,
+ int attribute,
+ unsigned int *value);
+
+typedef void (*GLActiveTextureProc) (GLenum texture);
+typedef void (*GLClientActiveTextureProc) (GLenum texture);
+
+
+#define MAX_DEPTH 32
+
+typedef CompOption *(*GetScreenOptionsProc) (CompScreen *screen,
+ int *count);
+typedef Bool (*SetScreenOptionProc) (CompScreen *screen,
+ char *name,
+ CompOptionValue *value);
+typedef Bool (*SetScreenOptionForPluginProc) (CompScreen *screen,
+ char *plugin,
+ char *name,
+ CompOptionValue *value);
+
+typedef Bool (*InitPluginForScreenProc) (CompPlugin *plugin,
+ CompScreen *screen);
+
+typedef void (*FiniPluginForScreenProc) (CompPlugin *plugin,
+ CompScreen *screen);
+
+typedef Bool (*DamageWindowRectProc) (CompWindow *w,
+ Bool initial,
+ BoxPtr rect);
+
+typedef Bool (*DamageWindowRegionProc) (CompWindow *w,
+ Region region);
+
+typedef void (*SetWindowScaleProc) (CompWindow *w,
+ float xScale,
+ float yScale);
+
+typedef Bool (*FocusWindowProc) (CompWindow *window);
+
+typedef void (*WindowResizeNotifyProc) (CompWindow *window);
+
+typedef void (*WindowMoveNotifyProc) (CompWindow *window,
+ int dx,
+ int dy);
+
+#define CompWindowGrabKeyMask (1 << 0)
+#define CompWindowGrabButtonMask (1 << 1)
+#define CompWindowGrabMoveMask (1 << 2)
+#define CompWindowGrabResizeMask (1 << 3)
+
+typedef void (*WindowGrabNotifyProc) (CompWindow *window,
+ int x,
+ int y,
+ unsigned int state,
+ unsigned int mask);
+
+typedef void (*WindowUngrabNotifyProc) (CompWindow *window);
+
+#define COMP_SCREEN_DAMAGE_PENDING_MASK (1 << 0)
+#define COMP_SCREEN_DAMAGE_REGION_MASK (1 << 1)
+#define COMP_SCREEN_DAMAGE_ALL_MASK (1 << 2)
+
+typedef struct _CompKeyGrab {
+ int keycode;
+ unsigned int modifiers;
+ int count;
+} CompKeyGrab;
+
+typedef struct _CompButtonGrab {
+ int button;
+ unsigned int modifiers;
+ int count;
+} CompButtonGrab;
+
+typedef struct _CompGrab {
+ Bool active;
+ Cursor cursor;
+} CompGrab;
+
+typedef struct _CompGroup {
+ struct _CompGroup *next;
+ unsigned int refCnt;
+ Window id;
+} CompGroup;
+
+typedef struct _CompStartupSequence {
+ struct _CompStartupSequence *next;
+ SnStartupSequence *sequence;
+} CompStartupSequence;
+
+struct _CompScreen {
+ CompScreen *next;
+ CompDisplay *display;
+ CompWindow *windows;
+ CompWindow *reverseWindows;
+
+ char *windowPrivateIndices;
+ int windowPrivateLen;
+
+ Colormap colormap;
+ int screenNum;
+ int width;
+ int height;
+ int x;
+ int size;
+ REGION region;
+ Region damage;
+ unsigned long damageMask;
+ Window root;
+ Window fake[2];
+ XWindowAttributes attrib;
+ Window grabWindow;
+ XVisualInfo *glxPixmapVisuals[MAX_DEPTH + 1];
+ int textureRectangle;
+ int textureNonPowerOfTwo;
+ int textureEnvCombine;
+ int textureEnvCrossbar;
+ int textureBorderClamp;
+ int maxTextureUnits;
+ Cursor invisibleCursor;
+ XRectangle *exposeRects;
+ int sizeExpose;
+ int nExpose;
+ CompTexture backgroundTexture;
+ unsigned int pendingDestroys;
+ int desktopWindowCount;
+ KeyCode escapeKeyCode;
+ unsigned int mapNum;
+ unsigned int activeNum;
+
+ SnMonitorContext *snContext;
+ CompStartupSequence *startupSequences;
+ unsigned int startupSequenceTimeoutHandle;
+
+ CompGroup *groups;
+
+ Bool canDoSaturated;
+ Bool canDoSlightlySaturated;
+
+ Window wmSnSelectionWindow;
+ Atom wmSnAtom;
+ Time wmSnTimestamp;
+
+ Cursor normalCursor;
+ Cursor busyCursor;
+
+ CompWindow **clientList;
+ int nClientList;
+
+ CompButtonGrab *buttonGrab;
+ int nButtonGrab;
+ CompKeyGrab *keyGrab;
+ int nKeyGrab;
+
+ CompGrab *grabs;
+ int grabSize;
+ int maxGrab;
+
+ int rasterX;
+ int rasterY;
+ struct timeval lastRedraw;
+ int nextRedraw;
+ int redrawTime;
+ int optimalRedrawTime;
+ int frameStatus;
+
+ GLint stencilRef;
+
+ XRectangle workArea;
+
+ unsigned int showingDesktopMask;
+
+ GLXGetProcAddressProc getProcAddress;
+ GLXBindTexImageProc bindTexImage;
+ GLXReleaseTexImageProc releaseTexImage;
+ GLXQueryDrawableProc queryDrawable;
+
+ GLActiveTextureProc activeTexture;
+ GLClientActiveTextureProc clientActiveTexture;
+
+ GLXContext ctx;
+
+ CompOption opt[COMP_SCREEN_OPTION_NUM];
+
+ SetScreenOptionProc setScreenOption;
+ SetScreenOptionForPluginProc setScreenOptionForPlugin;
+
+ InitPluginForScreenProc initPluginForScreen;
+ FiniPluginForScreenProc finiPluginForScreen;
+
+ PreparePaintScreenProc preparePaintScreen;
+ DonePaintScreenProc donePaintScreen;
+ PaintScreenProc paintScreen;
+ PaintTransformedScreenProc paintTransformedScreen;
+ PaintBackgroundProc paintBackground;
+ PaintWindowProc paintWindow;
+ AddWindowGeometryProc addWindowGeometry;
+ DrawWindowGeometryProc drawWindowGeometry;
+ DamageWindowRectProc damageWindowRect;
+ FocusWindowProc focusWindow;
+ SetWindowScaleProc setWindowScale;
+
+ WindowResizeNotifyProc windowResizeNotify;
+ WindowMoveNotifyProc windowMoveNotify;
+ WindowGrabNotifyProc windowGrabNotify;
+ WindowUngrabNotifyProc windowUngrabNotify;
+
+ CompPrivate *privates;
+};
+
+int
+allocateScreenPrivateIndex (CompDisplay *display);
+
+void
+freeScreenPrivateIndex (CompDisplay *display,
+ int index);
+
+CompOption *
+compGetScreenOptions (CompScreen *screen,
+ int *count);
+
+void
+configureScreen (CompScreen *s,
+ XConfigureEvent *ce);
+
+void
+updateScreenBackground (CompScreen *screen,
+ CompTexture *texture);
+
+void
+detectRefreshRateOfScreen (CompScreen *s);
+
+Bool
+addScreen (CompDisplay *display,
+ int screenNum,
+ Window wmSnSelectionWindow,
+ Atom wmSnAtom,
+ Time wmSnTimestamp);
+
+void
+damageScreenRegion (CompScreen *screen,
+ Region region);
+
+void
+damageScreen (CompScreen *screen);
+
+void
+damagePendingOnScreen (CompScreen *s);
+
+void
+insertWindowIntoScreen (CompScreen *s,
+ CompWindow *w,
+ Window aboveId);
+
+void
+unhookWindowFromScreen (CompScreen *s,
+ CompWindow *w);
+
+void
+forEachWindowOnScreen (CompScreen *screen,
+ ForEachWindowProc proc,
+ void *closure);
+
+CompWindow *
+findWindowAtScreen (CompScreen *s,
+ Window id);
+
+CompWindow *
+findTopLevelWindowAtScreen (CompScreen *s,
+ Window id);
+
+int
+pushScreenGrab (CompScreen *s,
+ Cursor cursor);
+
+void
+removeScreenGrab (CompScreen *s,
+ int index,
+ XPoint *restorePointer);
+
+Bool
+addScreenBinding (CompScreen *s,
+ CompBinding *binding);
+
+void
+removeScreenBinding (CompScreen *s,
+ CompBinding *binding);
+
+void
+updatePassiveGrabs (CompScreen *s);
+
+void
+updateWorkareaForScreen (CompScreen *s);
+
+void
+updateClientListForScreen (CompScreen *s);
+
+Window
+getActiveWindow (CompDisplay *display,
+ Window root);
+
+void
+closeActiveWindow (CompScreen *s);
+
+void
+panelAction (CompScreen *s,
+ Atom panelAction);
+
+void
+runCommand (CompScreen *s,
+ const char *command);
+
+void
+moveScreenViewport (CompScreen *s,
+ int tx,
+ Bool sync);
+
+void
+moveWindowToViewportPosition (CompWindow *w,
+ int x,
+ Bool sync);
+
+CompGroup *
+addGroupToScreen (CompScreen *s,
+ Window id);
+void
+removeGroupFromScreen (CompScreen *s,
+ CompGroup *group);
+
+CompGroup *
+findGroupAtScreen (CompScreen *s,
+ Window id);
+
+void
+applyStartupProperties (CompScreen *screen,
+ CompWindow *window);
+
+void
+enterShowDesktopMode (CompScreen *s);
+
+void
+leaveShowDesktopMode (CompScreen *s);
+
+void
+sendWindowActivationRequest (CompScreen *s,
+ Window id);
+
+/* window.c */
+
+#define WINDOW_INVISIBLE(w) \
+ ((w)->attrib.map_state != IsViewable || \
+ (!(w)->damaged) || \
+ (w)->attrib.x + (w)->width + (w)->output.right <= 0 || \
+ (w)->attrib.y + (w)->height + (w)->output.bottom <= 0 || \
+ (w)->attrib.x - (w)->output.left >= (w)->screen->width || \
+ (w)->attrib.y - (w)->output.top >= (w)->screen->height)
+
+typedef Bool (*InitPluginForWindowProc) (CompPlugin *plugin,
+ CompWindow *window);
+typedef void (*FiniPluginForWindowProc) (CompPlugin *plugin,
+ CompWindow *window);
+
+typedef struct _CompWindowExtents {
+ int left;
+ int right;
+ int top;
+ int bottom;
+} CompWindowExtents;
+
+typedef struct _CompStruts {
+ XRectangle left;
+ XRectangle right;
+ XRectangle top;
+ XRectangle bottom;
+} CompStruts;
+
+struct _CompWindow {
+ CompScreen *screen;
+ CompWindow *next;
+ CompWindow *prev;
+
+ int refcnt;
+ Window id;
+ Window frame;
+ unsigned int mapNum;
+ unsigned int activeNum;
+ XWindowAttributes attrib;
+ int serverX;
+ int serverY;
+ Window transientFor;
+ Window clientLeader;
+ XSizeHints sizeHints;
+ Pixmap pixmap;
+ CompTexture texture;
+ CompMatrix matrix;
+ Damage damage;
+ Bool inputHint;
+ Bool alpha;
+ GLint width;
+ GLint height;
+ Region region;
+ Region clip;
+ unsigned int wmType;
+ unsigned int type;
+ unsigned int state;
+ unsigned int actions;
+ unsigned int protocols;
+ unsigned int mwmDecor;
+ Bool invisible;
+ Bool destroyed;
+ Bool damaged;
+ int destroyRefCnt;
+ int unmapRefCnt;
+
+ Bool placed;
+ Bool minimized;
+
+ char *startupId;
+ char *resName;
+ char *resClass;
+
+ CompGroup *group;
+
+ unsigned int lastPong;
+ Bool alive;
+ GLushort saturation;
+
+ WindowPaintAttrib paint;
+ Bool scaled;
+
+ CompWindowExtents input;
+ CompWindowExtents output;
+
+ CompStruts *struts;
+
+ XWindowChanges saveWc;
+ int saveMask;
+
+ XSyncCounter syncCounter;
+ XSyncValue syncValue;
+ XSyncAlarm syncAlarm;
+ unsigned long syncAlarmConnection;
+ unsigned int syncWaitHandle;
+
+ Bool syncWait;
+ int syncX;
+ int syncY;
+ int syncWidth;
+ int syncHeight;
+ int syncBorderWidth;
+
+ XRectangle *damageRects;
+ int sizeDamage;
+ int nDamage;
+
+ GLfloat *vertices;
+ int vertexSize;
+ GLushort *indices;
+ int indexSize;
+ int vCount;
+ int texUnits;
+
+ CompPrivate *privates;
+};
+
+int
+allocateWindowPrivateIndex (CompScreen *screen);
+
+void
+freeWindowPrivateIndex (CompScreen *screen,
+ int index);
+
+unsigned int
+windowStateMask (CompDisplay *display,
+ Atom state);
+
+unsigned int
+getWindowState (CompDisplay *display,
+ Window id);
+
+void
+setWindowState (CompDisplay *display,
+ unsigned int state,
+ Window id);
+
+unsigned int
+getWindowType (CompDisplay *display,
+ Window id);
+
+void
+recalcWindowType (CompWindow *w);
+
+unsigned int
+getMwmDecor (CompDisplay *display,
+ Window id);
+
+unsigned int
+getProtocols (CompDisplay *display,
+ Window id);
+
+unsigned short
+getWindowProp32 (CompDisplay *display,
+ Window id,
+ Atom property,
+ unsigned short defaultValue);
+
+void
+setWindowProp32 (CompDisplay *display,
+ Window id,
+ Atom property,
+ unsigned short value);
+
+void
+updateNormalHints (CompWindow *window);
+
+void
+updateWmHints (CompWindow *w);
+
+void
+updateWindowClassHints (CompWindow *window);
+
+Window
+getClientLeader (CompWindow *w);
+
+int
+getWmState (CompDisplay *display,
+ Window id);
+
+void
+setWmState (CompDisplay *display,
+ int state,
+ Window id);
+
+void
+setWindowFrameExtents (CompWindow *w,
+ CompWindowExtents *input,
+ CompWindowExtents *output);
+
+void
+updateWindowRegion (CompWindow *w);
+
+Bool
+updateWindowStruts (CompWindow *w);
+
+void
+addWindow (CompScreen *screen,
+ Window id,
+ Window aboveId);
+
+void
+removeWindow (CompWindow *w);
+
+void
+destroyWindow (CompWindow *w);
+
+void
+mapWindow (CompWindow *w);
+
+void
+unmapWindow (CompWindow *w);
+
+void
+bindWindow (CompWindow *w);
+
+void
+releaseWindow (CompWindow *w);
+
+void
+moveWindow (CompWindow *w,
+ int dx,
+ int dy,
+ Bool damage);
+
+void
+syncWindowPosition (CompWindow *w);
+
+void
+sendSyncRequest (CompWindow *w);
+
+Bool
+resizeWindow (CompWindow *w,
+ int x,
+ int y,
+ int width,
+ int height,
+ int borderWidth);
+
+void
+configureWindow (CompWindow *w,
+ XConfigureEvent *ce);
+
+void
+circulateWindow (CompWindow *w,
+ XCirculateEvent *ce);
+
+void
+addWindowDamage (CompWindow *w);
+
+void
+damageWindowOutputExtents (CompWindow *w);
+
+Bool
+damageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect);
+
+void
+damageWindowRegion (CompWindow *w,
+ Region region);
+
+void
+setWindowScale (CompWindow *w,
+ float xScale,
+ float yScale);
+
+Bool
+focusWindow (CompWindow *w);
+
+void
+windowResizeNotify (CompWindow *w);
+
+void
+windowMoveNotify (CompWindow *w,
+ int dx,
+ int dy);
+
+void
+windowGrabNotify (CompWindow *w,
+ int x,
+ int y,
+ unsigned int state,
+ unsigned int mask);
+
+void
+windowUngrabNotify (CompWindow *w);
+
+void
+moveInputFocusToWindow (CompWindow *w);
+
+void
+updateWindowAttributes (CompWindow *w);
+
+void
+activateWindow (CompWindow *w);
+
+void
+closeWindow (CompWindow *w);
+
+void
+getOuterRectOfWindow (CompWindow *w,
+ XRectangle *r);
+
+Bool
+constrainNewWindowSize (CompWindow *w,
+ int width,
+ int height,
+ int *newWidth,
+ int *newHeight);
+
+void
+hideWindow (CompWindow *w);
+
+void
+showWindow (CompWindow *w);
+
+void
+minimizeWindow (CompWindow *w);
+
+void
+unminimizeWindow (CompWindow *w);
+
+
+/* plugin.c */
+
+typedef Bool (*InitPluginProc) (CompPlugin *plugin);
+typedef void (*FiniPluginProc) (CompPlugin *plugin);
+
+typedef enum {
+ CompPluginRuleBefore,
+ CompPluginRuleAfter
+} CompPluginRule;
+
+typedef struct _CompPluginDep {
+ CompPluginRule rule;
+ char *plugin;
+} CompPluginDep;
+
+typedef struct _CompPluginVTable {
+ char *name;
+ char *shortDesc;
+ char *longDesc;
+
+ InitPluginProc init;
+ FiniPluginProc fini;
+
+ InitPluginForDisplayProc initDisplay;
+ FiniPluginForDisplayProc finiDisplay;
+
+ InitPluginForScreenProc initScreen;
+ FiniPluginForScreenProc finiScreen;
+
+ InitPluginForWindowProc initWindow;
+ FiniPluginForWindowProc finiWindow;
+
+ GetDisplayOptionsProc getDisplayOptions;
+ SetDisplayOptionProc setDisplayOption;
+ GetScreenOptionsProc getScreenOptions;
+ SetScreenOptionProc setScreenOption;
+
+ CompPluginDep *deps;
+ int nDeps;
+} CompPluginVTable;
+
+typedef CompPluginVTable *(*PluginGetInfoProc) (void);
+
+struct _CompPlugin {
+ CompPlugin *next;
+ void *dlhand;
+ CompPluginVTable *vTable;
+};
+
+CompPluginVTable *
+getCompPluginInfo (void);
+
+void
+screenInitPlugins (CompScreen *s);
+
+void
+screenFiniPlugins (CompScreen *s);
+
+void
+windowInitPlugins (CompWindow *w);
+
+void
+windowFiniPlugins (CompWindow *w);
+
+CompPlugin *
+findActivePlugin (char *name);
+
+CompPlugin *
+loadPlugin (char *plugin);
+
+void
+unloadPlugin (CompPlugin *p);
+
+Bool
+pushPlugin (CompPlugin *p);
+
+CompPlugin *
+popPlugin (void);
+
+#endif
diff --git a/kde/Makefile.am b/kde/Makefile.am
new file mode 100644
index 0000000..d0f733b
--- /dev/null
+++ b/kde/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = window-decorator
diff --git a/kde/window-decorator/Makefile.am b/kde/window-decorator/Makefile.am
new file mode 100644
index 0000000..53908d7
--- /dev/null
+++ b/kde/window-decorator/Makefile.am
@@ -0,0 +1,7 @@
+if USE_KDE
+kde_window_decorator_program =
+endif
+
+INCLUDES = @KDE_WINDOW_DECORATOR_CFLAGS@
+
+bin_PROGRAMS = $(kde_window_decorator_program)
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644
index 0000000..486fefe
--- /dev/null
+++ b/plugins/Makefile.am
@@ -0,0 +1,76 @@
+libfade_la_LDFLAGS = -module -avoid-version -no-undefined
+libfade_la_LIBADD = @COMPIZ_LIBS@
+libfade_la_SOURCES = fade.c
+
+libcube_la_LDFLAGS = -module -avoid-version -no-undefined
+libcube_la_LIBADD = @COMPIZ_LIBS@ @LIBSVG_CAIRO_LIBS@
+libcube_la_SOURCES = cube.c
+
+librotate_la_LDFLAGS = -module -avoid-version -no-undefined
+librotate_la_LIBADD = @COMPIZ_LIBS@
+librotate_la_SOURCES = rotate.c
+
+libzoom_la_LDFLAGS = -module -avoid-version -no-undefined
+libzoom_la_LIBADD = @COMPIZ_LIBS@
+libzoom_la_SOURCES = zoom.c
+
+libscale_la_LDFLAGS = -module -avoid-version -no-undefined
+libscale_la_LIBADD = @COMPIZ_LIBS@
+libscale_la_SOURCES = scale.c
+
+libwobbly_la_LDFLAGS = -module -avoid-version -no-undefined
+libwobbly_la_LIBADD = @COMPIZ_LIBS@
+libwobbly_la_SOURCES = wobbly.c
+
+libminimize_la_LDFLAGS = -module -avoid-version -no-undefined
+libminimize_la_LIBADD = @COMPIZ_LIBS@
+libminimize_la_SOURCES = minimize.c
+
+libmove_la_LDFLAGS = -module -avoid-version -no-undefined
+libmove_la_LIBADD = @COMPIZ_LIBS@
+libmove_la_SOURCES = move.c
+
+libresize_la_LDFLAGS = -module -avoid-version -no-undefined
+libresize_la_LIBADD = @COMPIZ_LIBS@
+libresize_la_SOURCES = resize.c
+
+libdecoration_la_LDFLAGS = -module -avoid-version -no-undefined
+libdecoration_la_LIBADD = @COMPIZ_LIBS@
+libdecoration_la_SOURCES = decoration.c
+
+if GCONF_PLUGIN
+libgconf_la_LDFLAGS = -module -avoid-version -no-undefined
+libgconf_la_LIBADD = @COMPIZ_LIBS@ @GCONF_LIBS@
+libgconf_la_SOURCES = gconf.c
+libgconf_module = libgconf.la
+endif
+
+if PLACE_PLUGIN
+libplace_la_LDFLAGS = -module -avoid-version -no-undefined
+libplace_la_LIBADD = @COMPIZ_LIBS@ @PLACE_LIBS@
+libplace_la_SOURCES = place.c
+libplace_module = libplace.la
+endif
+
+INCLUDES = \
+ @COMPIZ_CFLAGS@ \
+ @LIBSVG_CAIRO_CFLAGS@ \
+ @GCONF_CFLAGS@ \
+ @PLACE_CFLAGS@ \
+ -I$(top_srcdir)/include
+
+moduledir = $(plugindir)
+
+module_LTLIBRARIES = \
+ libfade.la \
+ libcube.la \
+ librotate.la \
+ libzoom.la \
+ libscale.la \
+ libwobbly.la \
+ libminimize.la \
+ libmove.la \
+ libresize.la \
+ libdecoration.la \
+ $(libgconf_module) \
+ $(libplace_module)
diff --git a/plugins/cube.c b/plugins/cube.c
new file mode 100644
index 0000000..381c96e
--- /dev/null
+++ b/plugins/cube.c
@@ -0,0 +1,831 @@
+/*
+ * 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>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/time.h>
+
+#ifdef USE_LIBSVG_CAIRO
+#include <cairo-xlib.h>
+#include <svg-cairo.h>
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+
+#include <compiz.h>
+
+#define CUBE_COLOR_RED_DEFAULT 0xefef
+#define CUBE_COLOR_GREEN_DEFAULT 0xebeb
+#define CUBE_COLOR_BLUE_DEFAULT 0xe7e7
+
+#define CUBE_IN_DEFAULT FALSE
+
+#define CUBE_NEXT_KEY_DEFAULT "space"
+#define CUBE_NEXT_MODIFIERS_DEFAULT CompPressMask
+
+#define CUBE_PREV_KEY_DEFAULT "BackSpace"
+#define CUBE_PREV_MODIFIERS_DEFAULT CompPressMask
+
+static int displayPrivateIndex;
+
+typedef struct _CubeDisplay {
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+} CubeDisplay;
+
+#define CUBE_SCREEN_OPTION_COLOR 0
+#define CUBE_SCREEN_OPTION_IN 1
+#define CUBE_SCREEN_OPTION_SVGS 2
+#define CUBE_SCREEN_OPTION_NEXT 3
+#define CUBE_SCREEN_OPTION_PREV 4
+#define CUBE_SCREEN_OPTION_NUM 5
+
+typedef struct _CubeScreen {
+ PaintTransformedScreenProc paintTransformedScreen;
+ PaintBackgroundProc paintBackground;
+ SetScreenOptionProc setScreenOption;
+
+ CompOption opt[CUBE_SCREEN_OPTION_NUM];
+
+ int invert;
+ int xrotations;
+ GLfloat distance;
+ Bool paintTopBottom;
+ GLushort color[3];
+ GLfloat tc[12];
+
+ GLfloat *vertices;
+ int nvertices;
+
+ Pixmap pixmap;
+ int pw, ph;
+ CompTexture texture;
+
+#ifdef USE_LIBSVG_CAIRO
+ cairo_t *cr;
+ svg_cairo_t *svgc;
+ int svgNFile;
+ int svgCurFile;
+ CompOptionValue *svgFiles;
+#endif
+
+} CubeScreen;
+
+#define GET_CUBE_DISPLAY(d) \
+ ((CubeDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define CUBE_DISPLAY(d) \
+ CubeDisplay *cd = GET_CUBE_DISPLAY (d)
+
+#define GET_CUBE_SCREEN(s, cd) \
+ ((CubeScreen *) (s)->privates[(cd)->screenPrivateIndex].ptr)
+
+#define CUBE_SCREEN(s) \
+ CubeScreen *cs = GET_CUBE_SCREEN (s, GET_CUBE_DISPLAY (s->display))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+#ifdef USE_LIBSVG_CAIRO
+static void
+cubeInitSvg (CompScreen *s)
+
+{
+ CUBE_SCREEN (s);
+
+ cs->pixmap = None;
+ cs->pw = cs->ph = 0;
+ cs->cr = 0;
+ cs->svgc = 0;
+}
+
+static void
+cubeFiniSvg (CompScreen *s)
+
+{
+ CUBE_SCREEN (s);
+
+ if (cs->svgc)
+ svg_cairo_destroy (cs->svgc);
+
+ if (cs->cr)
+ cairo_destroy (cs->cr);
+
+ if (cs->pixmap)
+ XFreePixmap (s->display->display, cs->pixmap);
+}
+
+static void
+cubeLoadSvg (CompScreen *s,
+ int n)
+{
+ unsigned int width, height;
+
+ CUBE_SCREEN (s);
+
+ if (!cs->svgNFile || cs->pw != s->width || cs->ph != s->height)
+ {
+ finiTexture (s, &cs->texture);
+ initTexture (s, &cs->texture);
+ cubeFiniSvg (s);
+ cubeInitSvg (s);
+
+ if (!cs->svgNFile)
+ return;
+ }
+
+ if (!cs->pixmap)
+ {
+ cairo_surface_t *surface;
+ Visual *visual;
+ int depth;
+
+ cs->pw = s->width;
+ cs->ph = s->height;
+
+ depth = DefaultDepth (s->display->display, s->screenNum);
+ cs->pixmap = XCreatePixmap (s->display->display, s->root,
+ s->width, s->height,
+ depth);
+
+ if (!bindPixmapToTexture (s, &cs->texture, cs->pixmap,
+ s->width, s->height, depth))
+ {
+ fprintf (stderr, "%s: Couldn't bind slide pixmap 0x%x to "
+ "texture\n", programName, (int) cs->pixmap);
+ }
+
+ if (cs->texture.target == GL_TEXTURE_RECTANGLE_ARB)
+ {
+ cs->tc[0] = s->width / 2.0f;
+ cs->tc[1] = s->height / 2.0f;
+
+ cs->tc[2] = s->width;
+ cs->tc[3] = s->height;
+
+ cs->tc[4] = 0.0f;
+ cs->tc[5] = s->height;
+
+ cs->tc[6] = 0.0f;
+ cs->tc[7] = 0.0f;
+
+ cs->tc[8] = s->width;
+ cs->tc[9] = 0.0f;
+
+ cs->tc[10] = s->width;
+ cs->tc[11] = s->height;
+ }
+ else
+ {
+ cs->tc[0] = 0.5f;
+ cs->tc[1] = 0.5f;
+
+ cs->tc[2] = 1.0f;
+ cs->tc[3] = 1.0f;
+
+ cs->tc[4] = 0.0f;
+ cs->tc[5] = 1.0f;
+
+ cs->tc[6] = 0.0f;
+ cs->tc[7] = 0.0f;
+
+ cs->tc[8] = 1.0f;
+ cs->tc[9] = 0.0f;
+
+ cs->tc[10] = 1.0;
+ cs->tc[11] = 1.0f;
+ }
+
+ visual = DefaultVisual (s->display->display, s->screenNum);
+ surface = cairo_xlib_surface_create (s->display->display,
+ cs->pixmap, visual,
+ s->width, s->height);
+ cs->cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+ }
+
+ cs->svgCurFile = n % cs->svgNFile;
+
+ if (cs->svgc)
+ svg_cairo_destroy (cs->svgc);
+
+ if (svg_cairo_create (&cs->svgc))
+ {
+ fprintf (stderr, "%s: Failed to create svg_cairo_t.\n",
+ programName);
+ return;
+ }
+
+ svg_cairo_set_viewport_dimension (cs->svgc, s->width, s->height);
+
+ if (svg_cairo_parse (cs->svgc, cs->svgFiles[cs->svgCurFile].s))
+ {
+ fprintf (stderr, "%s: Failed to load svg: %s.\n",
+ programName, cs->svgFiles[cs->svgCurFile].s);
+ return;
+ }
+
+ svg_cairo_get_size (cs->svgc, &width, &height);
+
+ cairo_save (cs->cr);
+ cairo_set_source_rgb (cs->cr,
+ (double) cs->color[0] / 0xffff,
+ (double) cs->color[1] / 0xffff,
+ (double) cs->color[2] / 0xffff);
+ cairo_rectangle (cs->cr, 0, 0, s->width, s->height);
+ cairo_fill (cs->cr);
+
+ cairo_scale (cs->cr,
+ (double) s->width / width,
+ (double) s->height / height);
+
+ svg_cairo_render (cs->svgc, cs->cr);
+ cairo_restore (cs->cr);
+}
+#endif
+
+static Bool
+cubeUpdateGeometry (CompScreen *s,
+ int sides,
+ Bool invert)
+{
+ GLfloat radius, distance;
+ GLfloat *v;
+ int i, n;
+
+ CUBE_SCREEN (s);
+
+ distance = 0.5f / tanf (M_PI / sides);
+ radius = 0.5f / sinf (M_PI / sides);
+
+ n = (sides + 2) * 2;
+
+ if (cs->nvertices != n)
+ {
+ v = realloc (cs->vertices, sizeof (GLfloat) * n * 3);
+ if (!v)
+ return FALSE;
+
+ cs->nvertices = n;
+ cs->vertices = v;
+ }
+ else
+ v = cs->vertices;
+
+ *v++ = 0.0f;
+ *v++ = 0.5 * invert;
+ *v++ = 0.0f;
+
+ for (i = 0; i <= sides; i++)
+ {
+ *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
+ *v++ = 0.5 * invert;
+ *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
+ }
+
+ *v++ = 0.0f;
+ *v++ = -0.5 * invert;
+ *v++ = 0.0f;
+
+ for (i = sides; i >= 0; i--)
+ {
+ *v++ = radius * sinf (i * 2 * M_PI / sides + M_PI / sides);
+ *v++ = -0.5 * invert;
+ *v++ = radius * cosf (i * 2 * M_PI / sides + M_PI / sides);
+ }
+
+ cs->invert = invert;
+ cs->distance = distance;
+
+ return TRUE;
+}
+
+static CompOption *
+cubeGetScreenOptions (CompScreen *screen,
+ int *count)
+{
+ CUBE_SCREEN (screen);
+
+ *count = NUM_OPTIONS (cs);
+ return cs->opt;
+}
+
+static Bool
+cubeSetScreenOption (CompScreen *screen,
+ char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+ int index;
+
+ CUBE_SCREEN (screen);
+
+ o = compFindOption (cs->opt, NUM_OPTIONS (cs), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index) {
+ case CUBE_SCREEN_OPTION_COLOR:
+ if (compSetColorOption (o, value))
+ {
+ memcpy (cs->color, o->value.c, sizeof (cs->color));
+ damageScreen (screen);
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_IN:
+ if (compSetBoolOption (o, value))
+ {
+ if (cubeUpdateGeometry (screen, screen->size, o->value.b ? -1 : 1))
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_SVGS:
+ if (compSetOptionList (o, value))
+ {
+
+#ifdef USE_LIBSVG_CAIRO
+ cs->svgFiles = cs->opt[CUBE_SCREEN_OPTION_SVGS].value.list.value;
+ cs->svgNFile = cs->opt[CUBE_SCREEN_OPTION_SVGS].value.list.nValue;
+
+ cubeLoadSvg (screen, cs->svgCurFile);
+ damageScreen (screen);
+#endif
+
+ return TRUE;
+ }
+ break;
+ case CUBE_SCREEN_OPTION_NEXT:
+ case CUBE_SCREEN_OPTION_PREV:
+ if (compSetBindingOption (o, value))
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+cubeScreenInitOptions (CubeScreen *cs,
+ Display *display)
+{
+ CompOption *o;
+
+ o = &cs->opt[CUBE_SCREEN_OPTION_COLOR];
+ o->name = "color";
+ o->shortDesc = "Cube Color";
+ o->longDesc = "Color of top and bottom sides of the cube";
+ o->type = CompOptionTypeColor;
+ o->value.c[0] = CUBE_COLOR_RED_DEFAULT;
+ o->value.c[1] = CUBE_COLOR_GREEN_DEFAULT;
+ o->value.c[2] = CUBE_COLOR_BLUE_DEFAULT;
+ o->value.c[3] = 0xffff;
+
+ o = &cs->opt[CUBE_SCREEN_OPTION_IN];
+ o->name = "in";
+ o->shortDesc = "Inside Cube";
+ o->longDesc = "Inside cube";
+ o->type = CompOptionTypeBool;
+ o->value.b = CUBE_IN_DEFAULT;
+
+ o = &cs->opt[CUBE_SCREEN_OPTION_SVGS];
+ o->name = "svgs";
+ o->shortDesc = "SVG files";
+ o->longDesc = "List of SVG files rendered on top face of cube";
+ o->type = CompOptionTypeList;
+ o->value.list.type = CompOptionTypeString;
+ o->value.list.nValue = 0;
+ o->value.list.value = 0;
+ o->rest.s.string = 0;
+ o->rest.s.nString = 0;
+
+ o = &cs->opt[CUBE_SCREEN_OPTION_NEXT];
+ o->name = "next_slide";
+ o->shortDesc = "Next Slide";
+ o->longDesc = "Adavence to next slide";
+ o->type = CompOptionTypeBinding;
+ o->value.bind.type = CompBindingTypeKey;
+ o->value.bind.u.key.modifiers = CUBE_NEXT_MODIFIERS_DEFAULT;
+ o->value.bind.u.key.keycode =
+ XKeysymToKeycode (display, XStringToKeysym (CUBE_NEXT_KEY_DEFAULT));
+
+ o = &cs->opt[CUBE_SCREEN_OPTION_PREV];
+ o->name = "prev_slide";
+ o->shortDesc = "Previous Slide";
+ o->longDesc = "Go back to previous slide";
+ o->type = CompOptionTypeBinding;
+ o->value.bind.type = CompBindingTypeKey;
+ o->value.bind.u.key.modifiers = CUBE_PREV_MODIFIERS_DEFAULT;
+ o->value.bind.u.key.keycode =
+ XKeysymToKeycode (display, XStringToKeysym (CUBE_PREV_KEY_DEFAULT));
+}
+
+static void
+cubePaintTransformedScreen (CompScreen *s,
+ const ScreenPaintAttrib *sAttrib,
+ unsigned int mask)
+{
+ ScreenPaintAttrib sa = *sAttrib;
+ int xMove = 0;
+
+ CUBE_SCREEN (s);
+
+ if (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)
+ glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ else
+ glClear (GL_COLOR_BUFFER_BIT);
+
+ if (sa.vRotate > 100.0f)
+ sa.vRotate = 100.0f;
+ else if (sAttrib->vRotate < -100.0f)
+ sa.vRotate = -100.0f;
+ else
+ sa.vRotate = sAttrib->vRotate;
+
+ UNWRAP (cs, s, paintTransformedScreen);
+
+ sa.xTranslate = sAttrib->xTranslate;
+ sa.yTranslate = sAttrib->yTranslate;
+ sa.zTranslate = -cs->invert * cs->distance;
+
+ sa.xRotate = sAttrib->xRotate * cs->invert;
+ if (sa.xRotate > 0.0f)
+ {
+ cs->xrotations = (int) (s->size * sa.xRotate) / 360;
+ sa.xRotate = sa.xRotate - (360.0f * cs->xrotations) / s->size;
+ }
+ else
+ {
+ cs->xrotations = (int) (s->size * sa.xRotate) / 360;
+ sa.xRotate = sa.xRotate -
+ (360.0f * cs->xrotations) / s->size + 360.0f / s->size;
+ cs->xrotations--;
+ }
+
+ if (cs->invert != 1 || sa.vRotate != 0.0f || sa.yTranslate != 0.0f)
+ {
+ glColor3usv (cs->color);
+
+ glPushMatrix ();
+
+ if (sAttrib->xRotate > 0.0f)
+ {
+ sa.yRotate += 360.0f / s->size;
+ translateRotateScreen (&sa);
+ sa.yRotate -= 360.0f / s->size;
+ }
+ else
+ translateRotateScreen (&sa);
+
+ glVertexPointer (3, GL_FLOAT, 0, cs->vertices);
+
+ if (cs->invert == 1 && s->size == 4 && cs->texture.name)
+ {
+ enableTexture (s, &cs->texture, COMP_TEXTURE_FILTER_GOOD);
+ glTexCoordPointer (2, GL_FLOAT, 0, cs->tc);
+ glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
+ disableTexture (&cs->texture);
+ }
+ else
+ glDrawArrays (GL_TRIANGLE_FAN, 0, cs->nvertices >> 1);
+
+ glDrawArrays (GL_TRIANGLE_FAN, cs->nvertices >> 1,
+ cs->nvertices >> 1);
+
+ glPopMatrix ();
+ }
+
+ /* outside 4 side cube */
+ if (s->size == 4 && cs->invert == 1)
+ {
+ if (sAttrib->xRotate != 0.0f)
+ {
+ xMove = cs->xrotations;
+
+ moveScreenViewport (s, xMove, FALSE);
+ (*s->paintTransformedScreen) (s, &sa, mask);
+ moveScreenViewport (s, -xMove, FALSE);
+
+ xMove++;
+
+ moveScreenViewport (s, xMove, FALSE);
+ }
+
+ sa.yRotate -= 360.0f / s->size;
+
+ (*s->paintTransformedScreen) (s, &sa, mask);
+
+ moveScreenViewport (s, -xMove, FALSE);
+ }
+ else
+ {
+ if (sa.xRotate > 180.0f / s->size)
+ {
+ sa.yRotate -= 360.0f / s->size;
+ cs->xrotations++;
+ }
+
+ sa.yRotate -= 360.0f / s->size;
+ xMove = -1 - cs->xrotations;
+
+ moveScreenViewport (s, xMove, FALSE);
+ (*s->paintTransformedScreen) (s, &sa, mask);
+ moveScreenViewport (s, -xMove, FALSE);
+
+ sa.yRotate += 360.0f / s->size;
+ xMove = -cs->xrotations;
+
+ moveScreenViewport (s, xMove, FALSE);
+ (*s->paintTransformedScreen) (s, &sa, mask);
+ moveScreenViewport (s, -xMove, FALSE);
+
+ sa.yRotate += 360.0f / s->size;
+ xMove = 1 - cs->xrotations;
+
+ moveScreenViewport (s, xMove, FALSE);
+ (*s->paintTransformedScreen) (s, &sa, mask);
+ moveScreenViewport (s, -xMove, FALSE);
+ }
+
+ WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
+}
+
+static void
+cubePaintBackground (CompScreen *s,
+ Region region,
+ unsigned int mask)
+{
+ CUBE_SCREEN (s);
+
+ s->stencilRef++;
+
+ UNWRAP (cs, s, paintBackground);
+ (*s->paintBackground) (s, region, mask);
+ WRAP (cs, s, paintBackground, cubePaintBackground);
+}
+
+#ifdef USE_LIBSVG_CAIRO
+static void
+cubeHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ CompScreen *s;
+
+ CUBE_DISPLAY (d);
+
+ switch (event->type) {
+ case KeyPress:
+ case KeyRelease:
+ s = findScreenAtDisplay (d, event->xkey.root);
+ if (s)
+ {
+ CUBE_SCREEN (s);
+
+ if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
+ {
+ cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
+ damageScreen (s);
+ }
+
+ if (EV_KEY (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
+ {
+ cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
+ cs->svgNFile);
+ damageScreen (s);
+ }
+ }
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ s = findScreenAtDisplay (d, event->xbutton.root);
+ if (s)
+ {
+ CUBE_SCREEN (s);
+
+ if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_NEXT], event))
+ {
+ cubeLoadSvg (s, (cs->svgCurFile + 1) % cs->svgNFile);
+ damageScreen (s);
+ }
+
+ if (EV_BUTTON (&cs->opt[CUBE_SCREEN_OPTION_PREV], event))
+ {
+ cubeLoadSvg (s, (cs->svgCurFile - 1 + cs->svgNFile) %
+ cs->svgNFile);
+ damageScreen (s);
+ }
+ }
+ default:
+ break;
+ }
+
+ UNWRAP (cd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (cd, d, handleEvent, cubeHandleEvent);
+}
+#endif
+
+static Bool
+cubeSetGlobalScreenOption (CompScreen *s,
+ char *name,
+ CompOptionValue *value)
+{
+ Bool status;
+
+ CUBE_SCREEN (s);
+
+ UNWRAP (cs, s, setScreenOption);
+ status = (*s->setScreenOption) (s, name, value);
+ WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
+
+ if (status && strcmp (name, "size") == 0)
+ cubeUpdateGeometry (s, s->size, cs->invert);
+
+ return status;
+}
+
+static Bool
+cubeInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CubeDisplay *cd;
+
+ cd = malloc (sizeof (CubeDisplay));
+ if (!cd)
+ return FALSE;
+
+ cd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (cd->screenPrivateIndex < 0)
+ {
+ free (cd);
+ return FALSE;
+ }
+
+#ifdef USE_LIBSVG_CAIRO
+ WRAP (cd, d, handleEvent, cubeHandleEvent);
+#endif
+
+ d->privates[displayPrivateIndex].ptr = cd;
+
+ return TRUE;
+}
+
+static void
+cubeFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ CUBE_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, cd->screenPrivateIndex);
+
+#ifdef USE_LIBSVG_CAIRO
+ UNWRAP (cd, d, handleEvent);
+#endif
+
+ free (cd);
+}
+
+static Bool
+cubeInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ CubeScreen *cs;
+
+ CUBE_DISPLAY (s->display);
+
+ cs = malloc (sizeof (CubeScreen));
+ if (!cs)
+ return FALSE;
+
+ cs->invert = 1;
+
+ cs->tc[0] = cs->tc[1] = cs->tc[2] = cs->tc[3] = 0.0f;
+ cs->tc[4] = cs->tc[5] = cs->tc[6] = cs->tc[7] = 0.0f;
+
+ cs->color[0] = CUBE_COLOR_RED_DEFAULT;
+ cs->color[1] = CUBE_COLOR_GREEN_DEFAULT;
+ cs->color[2] = CUBE_COLOR_BLUE_DEFAULT;
+
+ cs->nvertices = 0;
+ cs->vertices = NULL;
+
+ s->privates[cd->screenPrivateIndex].ptr = cs;
+
+ cs->paintTopBottom = FALSE;
+
+ initTexture (s, &cs->texture);
+
+#ifdef USE_LIBSVG_CAIRO
+ cubeInitSvg (s);
+
+ cs->svgFiles = 0;
+ cs->svgNFile = 0;
+ cs->svgCurFile = 0;
+#endif
+
+ cubeScreenInitOptions (cs, s->display->display);
+
+ WRAP (cs, s, paintTransformedScreen, cubePaintTransformedScreen);
+ WRAP (cs, s, paintBackground, cubePaintBackground);
+ WRAP (cs, s, setScreenOption, cubeSetGlobalScreenOption);
+
+ if (!cubeUpdateGeometry (s, s->size, cs->invert))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+cubeFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ CUBE_SCREEN (s);
+
+ UNWRAP (cs, s, paintTransformedScreen);
+ UNWRAP (cs, s, paintBackground);
+ UNWRAP (cs, s, setScreenOption);
+
+ finiTexture (s, &cs->texture);
+
+#ifdef USE_LIBSVG_CAIRO
+ cubeFiniSvg (s);
+#endif
+
+ free (cs);
+}
+
+static Bool
+cubeInit (CompPlugin *p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+cubeFini (CompPlugin *p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+CompPluginDep cubeDeps[] = {
+ { CompPluginRuleBefore, "expose" }
+};
+
+CompPluginVTable cubeVTable = {
+ "cube",
+ "Desktop Cube",
+ "Place windows on cube",
+ cubeInit,
+ cubeFini,
+ cubeInitDisplay,
+ cubeFiniDisplay,
+ cubeInitScreen,
+ cubeFiniScreen,
+ 0, /* InitWindow */
+ 0, /* FiniWindow */
+ 0, /* GetDisplayOptions */
+ 0, /* SetDisplayOption */
+ cubeGetScreenOptions,
+ cubeSetScreenOption,
+ cubeDeps,
+ sizeof (cubeDeps) / sizeof (cubeDeps[0])
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &cubeVTable;
+}
diff --git a/plugins/decoration.c b/plugins/decoration.c
new file mode 100644
index 0000000..a0e2704
--- /dev/null
+++ b/plugins/decoration.c
@@ -0,0 +1,1321 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+
+#include <compiz.h>
+
+#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)
+
+typedef struct _Point {
+ int x;
+ int y;
+ int gravity;
+} Point;
+
+typedef struct _Vector {
+ int dx;
+ int dy;
+ int x0;
+ int y0;
+} Vector;
+
+typedef struct _Quad {
+ Point p1;
+ Point p2;
+ int maxWidth;
+ int maxHeight;
+ int align;
+ CompMatrix m;
+} Quad;
+
+#define DECOR_BARE 0
+#define DECOR_NORMAL 1
+#define DECOR_ACTIVE 2
+#define DECOR_NUM 3
+
+typedef struct _DecorTexture {
+ struct _DecorTexture *next;
+ int refCount;
+ Pixmap pixmap;
+ Damage damage;
+ CompTexture texture;
+
+ XRectangle *damageRects;
+ int sizeDamage;
+ int nDamage;
+} DecorTexture;
+
+typedef struct _Decoration {
+ int refCount;
+ DecorTexture *texture;
+ CompWindowExtents output;
+ CompWindowExtents input;
+ Quad *quad;
+ int nQuad;
+} Decoration;
+
+typedef struct _ScaledQuad {
+ CompMatrix matrix;
+ BoxRec box;
+} ScaledQuad;
+
+typedef struct _WindowDecoration {
+ Decoration *decor;
+ ScaledQuad *quad;
+ int nQuad;
+} WindowDecoration;
+
+static int displayPrivateIndex;
+
+typedef struct _DecorDisplay {
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+ DecorTexture *textures;
+ Atom supportingDmCheckAtom;
+ Atom winDecorAtom;
+ Atom winDecorBareAtom;
+ Atom winDecorNormalAtom;
+ Atom winDecorActiveAtom;
+ Atom winDecorSyncAtom;
+} DecorDisplay;
+
+typedef struct _DecorScreen {
+ int windowPrivateIndex;
+
+ Window dmWin;
+
+ Decoration *decor[DECOR_NUM];
+
+ PaintWindowProc paintWindow;
+ DamageWindowRectProc damageWindowRect;
+
+ WindowMoveNotifyProc windowMoveNotify;
+ WindowResizeNotifyProc windowResizeNotify;
+} DecorScreen;
+
+typedef struct _DecorWindow {
+ WindowDecoration *wd;
+ Decoration *decor;
+} DecorWindow;
+
+#define GET_DECOR_DISPLAY(d) \
+ ((DecorDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define DECOR_DISPLAY(d) \
+ DecorDisplay *dd = GET_DECOR_DISPLAY (d)
+
+#define GET_DECOR_SCREEN(s, dd) \
+ ((DecorScreen *) (s)->privates[(dd)->screenPrivateIndex].ptr)
+
+#define DECOR_SCREEN(s) \
+ DecorScreen *ds = GET_DECOR_SCREEN (s, GET_DECOR_DISPLAY (s->display))
+
+#define GET_DECOR_WINDOW(w, ds) \
+ ((DecorWindow *) (w)->privates[(ds)->windowPrivateIndex].ptr)
+
+#define DECOR_WINDOW(w) \
+ DecorWindow *dw = GET_DECOR_WINDOW (w, \
+ GET_DECOR_SCREEN (w->screen, \
+ GET_DECOR_DISPLAY (w->screen->display)))
+
+
+static Bool
+decorPaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ Bool status;
+
+ DECOR_SCREEN (w->screen);
+
+ if (!(mask & PAINT_WINDOW_SOLID_MASK))
+ {
+ DECOR_WINDOW (w);
+
+ if (dw->wd)
+ {
+ WindowDecoration *wd = dw->wd;
+ REGION box;
+ int i;
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ region = &infiniteRegion;
+
+ box.rects = &box.extents;
+ box.numRects = 1;
+
+ if (w->alpha && wd->decor == ds->decor[DECOR_BARE])
+ {
+ if (attrib->saturation == COLOR)
+ {
+ CompMatrix matrix[2];
+
+ if (!w->texture.pixmap)
+ bindWindow (w);
+
+ matrix[1] = w->texture.matrix;
+
+ w->vCount = 0;
+
+ for (i = 0; i < wd->nQuad; i++)
+ {
+ box.extents = wd->quad[i].box;
+
+ if (box.extents.x1 < box.extents.x2 &&
+ box.extents.y1 < box.extents.y2)
+ {
+ matrix[0] = wd->quad[i].matrix;
+
+ (*w->screen->addWindowGeometry) (w,
+ matrix, 2,
+ &box,
+ region);
+ }
+ }
+
+ if (w->vCount)
+ {
+ int filter;
+
+ if ((mask & PAINT_WINDOW_TRANSFORMED_MASK) ||
+ (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK))
+ filter = COMP_TEXTURE_FILTER_GOOD;
+ else
+ filter = COMP_TEXTURE_FILTER_FAST;
+
+ glEnable (GL_BLEND);
+
+ glPushMatrix ();
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ {
+ glTranslatef (w->attrib.x, w->attrib.y, 0.0f);
+ glScalef (attrib->xScale, attrib->yScale, 0.0f);
+ glTranslatef (-w->attrib.x, -w->attrib.y, 0.0f);
+ }
+
+ enableTexture (w->screen, &wd->decor->texture->texture,
+ filter);
+
+ if (attrib->opacity != OPAQUE ||
+ attrib->brightness != BRIGHT)
+ {
+ GLushort color;
+
+ color = (attrib->opacity * attrib->brightness) >> 16;
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
+ GL_MODULATE);
+ glColor4us (color, color, color, attrib->opacity);
+ }
+
+ w->screen->activeTexture (GL_TEXTURE1_ARB);
+
+ enableTexture (w->screen, &w->texture, filter);
+
+ glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
+ GL_MODULATE);
+
+ w->screen->clientActiveTexture (GL_TEXTURE1_ARB);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ w->screen->clientActiveTexture (GL_TEXTURE0_ARB);
+
+ (*w->screen->drawWindowGeometry) (w);
+
+ disableTexture (&w->texture);
+ w->screen->activeTexture (GL_TEXTURE0_ARB);
+
+ w->screen->clientActiveTexture (GL_TEXTURE1_ARB);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ w->screen->clientActiveTexture (GL_TEXTURE0_ARB);
+
+ disableTexture (&wd->decor->texture->texture);
+
+ glPopMatrix ();
+
+ if (attrib->opacity != OPAQUE ||
+ attrib->brightness != BRIGHT)
+ {
+ glColor4usv (defaultColor);
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,
+ GL_REPLACE);
+ }
+
+ glDisable (GL_BLEND);
+ }
+ }
+ }
+ else
+ {
+ w->vCount = 0;
+
+ for (i = 0; i < wd->nQuad; i++)
+ {
+ box.extents = wd->quad[i].box;
+
+ if (box.extents.x1 < box.extents.x2 &&
+ box.extents.y1 < box.extents.y2)
+ {
+ (*w->screen->addWindowGeometry) (w,
+ &wd->quad[i].matrix, 1,
+ &box,
+ region);
+ }
+ }
+
+ if (w->vCount)
+ drawWindowTexture (w, &wd->decor->texture->texture, attrib,
+ mask | PAINT_WINDOW_TRANSLUCENT_MASK);
+ }
+ }
+ }
+
+ UNWRAP (ds, w->screen, paintWindow);
+ status = (*w->screen->paintWindow) (w, attrib, region, mask);
+ WRAP (ds, w->screen, paintWindow, decorPaintWindow);
+
+ return status;
+}
+
+static DecorTexture *
+decorGetTexture (CompScreen *screen,
+ Pixmap pixmap)
+{
+ DecorTexture *texture;
+ unsigned int width, height, depth, ui;
+ Window root;
+ int i;
+
+ DECOR_DISPLAY (screen->display);
+
+ for (texture = dd->textures; texture; texture = texture->next)
+ {
+ if (texture->pixmap == pixmap)
+ {
+ texture->refCount++;
+ return texture;
+ }
+ }
+
+ texture = malloc (sizeof (DecorTexture));
+ if (!texture)
+ return NULL;
+
+ initTexture (screen, &texture->texture);
+
+ if (!XGetGeometry (screen->display->display, pixmap, &root,
+ &i, &i, &width, &height, &ui, &depth))
+ {
+ finiTexture (screen, &texture->texture);
+ free (texture);
+ return NULL;
+ }
+
+ if (!bindPixmapToTexture (screen, &texture->texture, pixmap,
+ width, height, depth))
+ {
+ finiTexture (screen, &texture->texture);
+ free (texture);
+ return NULL;
+ }
+
+ texture->damage = XDamageCreate (screen->display->display, pixmap,
+ XDamageReportRawRectangles);
+
+ texture->refCount = 1;
+ texture->pixmap = pixmap;
+ texture->next = dd->textures;
+
+ texture->damageRects = 0;
+ texture->sizeDamage = 0;
+ texture->nDamage = 0;
+
+ dd->textures = texture;
+
+ return texture;
+}
+
+static void
+decorReleaseTexture (CompScreen *screen,
+ DecorTexture *texture)
+{
+ DECOR_DISPLAY (screen->display);
+
+ texture->refCount--;
+ if (texture->refCount)
+ return;
+
+ if (texture == dd->textures)
+ {
+ dd->textures = texture->next;
+ }
+ else
+ {
+ DecorTexture *t;
+
+ for (t = dd->textures; t; t = t->next)
+ {
+ if (t->next == texture)
+ {
+ t->next = texture->next;
+ break;
+ }
+ }
+ }
+
+ finiTexture (screen, &texture->texture);
+ free (texture);
+}
+
+/*
+ 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 Decoration *
+decorCreateDecoration (CompScreen *screen,
+ Window id,
+ Atom decorAtom)
+{
+ Decoration *decoration;
+ Atom actual;
+ int result, format;
+ unsigned long n, nleft;
+ unsigned char *data;
+ long *prop;
+ Pixmap pixmap;
+ Quad *quad;
+ int nQuad;
+ int left, right, top, bottom;
+ int flags;
+
+ result = XGetWindowProperty (screen->display->display, id,
+ decorAtom, 0L, 1024L, FALSE,
+ XA_INTEGER, &actual, &format,
+ &n, &nleft, &data);
+
+ if (result != Success || !n || !data)
+ return NULL;
+
+ if (n < 9 + 14)
+ {
+ XFree (data);
+ return NULL;
+ }
+
+ decoration = malloc (sizeof (Decoration));
+ if (!decoration)
+ {
+ XFree (data);
+ return NULL;
+ }
+
+ prop = (long *) data;
+
+ memcpy (&pixmap, prop++, sizeof (Pixmap));
+
+ decoration->texture = decorGetTexture (screen, pixmap);
+ if (!decoration->texture)
+ {
+ free (decoration);
+ XFree (data);
+ return NULL;
+ }
+
+ decoration->input.left = *prop++;
+ decoration->input.right = *prop++;
+ decoration->input.top = *prop++;
+ decoration->input.bottom = *prop++;
+
+ nQuad = (n - 5) / 9;
+
+ quad = malloc (sizeof (Quad) * nQuad);
+ if (!quad)
+ {
+ decorReleaseTexture (screen, decoration->texture);
+ free (decoration);
+ XFree (data);
+ return NULL;
+ }
+
+ decoration->quad = quad;
+ decoration->nQuad = nQuad;
+
+ left = right = top = bottom = 0;
+
+ while (nQuad--)
+ {
+ flags = *prop++;
+
+ quad->p1.gravity = (flags >> 0) & 0x3;
+ quad->p2.gravity = (flags >> 2) & 0x3;
+
+ quad->align = (flags >> 4) & 0x3;
+
+ quad->m.xx = (flags & XX_MASK) ? 1.0f : 0.0f;
+ quad->m.xy = (flags & XY_MASK) ? 1.0f : 0.0f;
+ quad->m.yx = (flags & YX_MASK) ? 1.0f : 0.0f;
+ quad->m.yy = (flags & YY_MASK) ? 1.0f : 0.0f;
+
+ quad->p1.x = *prop++;
+ quad->p1.y = *prop++;
+ quad->p2.x = *prop++;
+ quad->p2.y = *prop++;
+
+ quad->maxWidth = *prop++;
+ quad->maxHeight = *prop++;
+
+ quad->m.x0 = *prop++;
+ quad->m.y0 = *prop++;
+
+ if (quad->p1.x < left)
+ left = quad->p1.x;
+ if (quad->p1.y < top)
+ top = quad->p1.y;
+ if (quad->p2.x > right)
+ right = quad->p2.x;
+ if (quad->p2.y > bottom)
+ bottom = quad->p2.y;
+
+ quad++;
+ }
+
+ XFree (data);
+
+ decoration->output.left = -left;
+ decoration->output.right = right;
+ decoration->output.top = -top;
+ decoration->output.bottom = bottom;
+
+ decoration->refCount = 1;
+
+ return decoration;
+}
+
+static void
+decorReleaseDecoration (CompScreen *screen,
+ Decoration *decoration)
+{
+ decoration->refCount--;
+ if (decoration->refCount)
+ return;
+
+ decorReleaseTexture (screen, decoration->texture);
+ free (decoration->quad);
+}
+
+static void
+decorWindowUpdateDecoration (CompWindow *w)
+{
+ Decoration *decoration;
+
+ DECOR_DISPLAY (w->screen->display);
+ DECOR_WINDOW (w);
+
+ decoration = decorCreateDecoration (w->screen, w->id, dd->winDecorAtom);
+
+ if (dw->decor)
+ decorReleaseDecoration (w->screen, dw->decor);
+
+ dw->decor = decoration;
+}
+
+static WindowDecoration *
+createWindowDecoration (Decoration *d)
+{
+ WindowDecoration *wd;
+
+ wd = malloc (sizeof (WindowDecoration) +
+ sizeof (ScaledQuad) * d->nQuad);
+ if (!wd)
+ return NULL;
+
+ wd->decor = d;
+ wd->quad = (ScaledQuad *) (wd + 1);
+ wd->nQuad = d->nQuad;
+
+ return wd;
+}
+
+static void
+destroyWindowDecoration (WindowDecoration *wd)
+{
+ free (wd);
+}
+
+static void
+setDecorationMatrices (CompWindow *w)
+{
+ WindowDecoration *wd;
+ int i;
+
+ DECOR_WINDOW (w);
+
+ wd = dw->wd;
+ if (!wd)
+ return;
+
+ for (i = 0; i < wd->nQuad; i++)
+ {
+ wd->quad[i].matrix = wd->decor->texture->texture.matrix;
+
+ wd->quad[i].matrix.x0 += wd->decor->quad[i].m.x0 * wd->quad[i].matrix.xx;
+ wd->quad[i].matrix.y0 += wd->decor->quad[i].m.y0 * wd->quad[i].matrix.yy;
+
+ wd->quad[i].matrix.xx *= wd->decor->quad[i].m.xx;
+ wd->quad[i].matrix.yy *= wd->decor->quad[i].m.yy;
+ wd->quad[i].matrix.xy *= wd->decor->quad[i].m.xy;
+ wd->quad[i].matrix.yx *= wd->decor->quad[i].m.yx;
+
+ wd->quad[i].matrix.x0 -=
+ wd->quad[i].box.x1 * wd->quad[i].matrix.xx +
+ wd->quad[i].box.y1 * wd->quad[i].matrix.xy;
+
+ wd->quad[i].matrix.y0 -=
+ wd->quad[i].box.y1 * wd->quad[i].matrix.yy +
+ wd->quad[i].box.x1 * wd->quad[i].matrix.yx;
+ }
+}
+
+static void
+applyGravity (int gravity,
+ int x,
+ int y,
+ int width,
+ int height,
+ int *return_x,
+ int *return_y)
+{
+ if (gravity & GRAVITY_EAST)
+ *return_x = x + width;
+ else
+ *return_x = x;
+
+ if (gravity & GRAVITY_SOUTH)
+ *return_y = y + height;
+ else
+ *return_y = y;
+}
+
+static void
+updateWindowDecorationScale (CompWindow *w)
+{
+ WindowDecoration *wd;
+ int x1, y1, x2, y2;
+ int maxWidth, maxHeight;
+ int align;
+ int i;
+
+ DECOR_WINDOW (w);
+
+ wd = dw->wd;
+ if (!wd)
+ return;
+
+ for (i = 0; i < wd->nQuad; i++)
+ {
+ applyGravity (wd->decor->quad[i].p1.gravity,
+ wd->decor->quad[i].p1.x, wd->decor->quad[i].p1.y,
+ w->width, w->height,
+ &x1, &y1);
+
+ applyGravity (wd->decor->quad[i].p2.gravity,
+ wd->decor->quad[i].p2.x, wd->decor->quad[i].p2.y,
+ w->width, w->height,
+ &x2, &y2);
+
+ maxWidth = wd->decor->quad[i].maxWidth;
+ maxHeight = wd->decor->quad[i].maxHeight;
+ align = wd->decor->quad[i].align;
+
+ if (maxWidth < x2 - x1)
+ {
+ if (align & ALIGN_RIGHT)
+ x1 = x2 - maxWidth;
+ else
+ x2 = x1 + maxWidth;
+ }
+
+ if (maxHeight < y2 - y1)
+ {
+ if (align & ALIGN_BOTTOM)
+ y1 = y2 - maxHeight;
+ else
+ y2 = y1 + maxHeight;
+ }
+
+ wd->quad[i].box.x1 = x1 + w->attrib.x;
+ wd->quad[i].box.y1 = y1 + w->attrib.y;
+ wd->quad[i].box.x2 = x2 + w->attrib.x;
+ wd->quad[i].box.y2 = y2 + w->attrib.y;
+ }
+
+ setDecorationMatrices (w);
+}
+
+static Bool
+decorWindowUpdate (CompWindow *w,
+ Bool move)
+{
+ WindowDecoration *wd;
+ Decoration *old, *decor = NULL;
+ int dx, dy;
+
+ DECOR_SCREEN (w->screen);
+ DECOR_WINDOW (w);
+
+ wd = dw->wd;
+ old = (wd) ? wd->decor : NULL;
+
+ if (dw->decor)
+ {
+ decor = dw->decor;
+ }
+ else
+ {
+ if (w->attrib.override_redirect)
+ {
+ if (w->region->numRects == 1)
+ decor = ds->decor[DECOR_BARE];
+ }
+ else
+ {
+ switch (w->type) {
+ case CompWindowTypeDialogMask:
+ case CompWindowTypeModalDialogMask:
+ case CompWindowTypeUtilMask:
+ case CompWindowTypeNormalMask:
+ if (w->mwmDecor & MwmDecorAll)
+ {
+ if (w->id == w->screen->display->activeWindow)
+ decor = ds->decor[DECOR_ACTIVE];
+ else
+ decor = ds->decor[DECOR_NORMAL];
+
+ break;
+ }
+ /* fall-through */
+ case CompWindowTypeSplashMask:
+ case CompWindowTypeToolbarMask:
+ case CompWindowTypeMenuMask:
+ case CompWindowTypeUnknownMask:
+ case CompWindowTypeDockMask:
+ if (w->region->numRects == 1)
+ decor = ds->decor[DECOR_BARE];
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!ds->dmWin)
+ decor = NULL;
+
+ if (decor == old)
+ return FALSE;
+
+ if (old)
+ {
+ damageWindowOutputExtents (w);
+
+ if (wd->decor == dw->decor)
+ {
+ decorReleaseDecoration (w->screen, dw->decor);
+ dw->decor = NULL;
+ }
+
+ destroyWindowDecoration (wd);
+ }
+
+ if (decor)
+ {
+ dx = decor->input.left;
+ dy = decor->input.top;
+ }
+ else
+ dx = dy = 0;
+
+ dx -= w->input.left;
+ dy -= w->input.top;
+
+ /* if (dx == 0 && dy == 0) */
+ move = FALSE;
+
+ if (decor)
+ {
+ dw->wd = createWindowDecoration (decor);
+ if (!dw->wd)
+ return FALSE;
+
+ setWindowFrameExtents (w, &decor->input, &decor->output);
+
+ if (!move)
+ damageWindowOutputExtents (w);
+
+ updateWindowDecorationScale (w);
+ }
+ else
+ {
+ dw->wd = NULL;
+ }
+
+ if (move)
+ moveWindow (w, dx, dy, TRUE);
+
+ return TRUE;
+}
+
+static void
+decorCheckForDmOnScreen (CompScreen *s,
+ Bool updateWindows)
+{
+ CompDisplay *d = s->display;
+ Atom actual;
+ int result, format;
+ unsigned long n, left;
+ unsigned char *data;
+ Window dmWin = None;
+
+ DECOR_DISPLAY (s->display);
+ DECOR_SCREEN (s);
+
+ result = XGetWindowProperty (d->display, s->root,
+ dd->supportingDmCheckAtom, 0L, 1L, FALSE,
+ XA_WINDOW, &actual, &format,
+ &n, &left, &data);
+
+ if (result == Success && n && data)
+ {
+ XWindowAttributes attr;
+
+ memcpy (&dmWin, data, sizeof (Window));
+ XFree (data);
+
+ compCheckForError (d->display);
+
+ XGetWindowAttributes (d->display, dmWin, &attr);
+
+ if (compCheckForError (d->display))
+ dmWin = None;
+ }
+
+ if (dmWin != ds->dmWin)
+ {
+ CompWindow *w;
+
+ if (dmWin)
+ {
+ ds->decor[DECOR_BARE] =
+ decorCreateDecoration (s, s->root, dd->winDecorBareAtom);
+
+ ds->decor[DECOR_NORMAL] =
+ decorCreateDecoration (s, s->root, dd->winDecorNormalAtom);
+
+ ds->decor[DECOR_ACTIVE] =
+ decorCreateDecoration (s, s->root, dd->winDecorActiveAtom);
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < DECOR_NUM; i++)
+ {
+ if (ds->decor[i])
+ {
+ decorReleaseDecoration (s, ds->decor[i]);
+ ds->decor[i] = 0;
+ }
+ }
+ }
+
+ ds->dmWin = dmWin;
+
+ if (updateWindows)
+ {
+ for (w = s->windows; w; w = w->next)
+ decorWindowUpdate (w, TRUE);
+ }
+ }
+}
+
+static void
+decorHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ Window activeWindow = 0;
+ CompWindow *w;
+
+ DECOR_DISPLAY (d);
+
+ switch (event->type) {
+ case PropertyNotify:
+ if (event->xproperty.atom == d->winActiveAtom)
+ activeWindow = d->activeWindow;
+ break;
+ case DestroyNotify:
+ w = findWindowAtDisplay (d, event->xdestroywindow.window);
+ if (w)
+ {
+ DECOR_SCREEN (w->screen);
+
+ if (w->id == ds->dmWin)
+ decorCheckForDmOnScreen (w->screen, TRUE);
+ }
+ default:
+ if (event->type == d->damageEvent + XDamageNotify)
+ {
+ XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
+ DecorTexture *t;
+
+ for (t = dd->textures; t; t = t->next)
+ {
+ if (t->pixmap == de->drawable)
+ {
+ if (t->nDamage == t->sizeDamage)
+ {
+ if (t->damageRects)
+ {
+ t->damageRects = realloc (t->damageRects,
+ (t->sizeDamage + 1) *
+ sizeof (XRectangle));
+ t->sizeDamage += 1;
+ }
+ else
+ {
+ t->damageRects = malloc (sizeof (XRectangle));
+ t->sizeDamage = 1;
+ }
+ }
+
+ t->damageRects[t->nDamage].x = de->area.x;
+ t->damageRects[t->nDamage].y = de->area.y;
+ t->damageRects[t->nDamage].width = de->area.width;
+ t->damageRects[t->nDamage].height = de->area.height;
+ t->nDamage++;
+
+ return;
+ }
+ }
+ }
+ break;
+ }
+
+ UNWRAP (dd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (dd, d, handleEvent, decorHandleEvent);
+
+ switch (event->type) {
+ case PropertyNotify:
+ if (event->xproperty.atom == d->winActiveAtom)
+ {
+ if (d->activeWindow != activeWindow)
+ {
+ w = findWindowAtDisplay (d, activeWindow);
+ if (w)
+ decorWindowUpdate (w, FALSE);
+
+ w = findWindowAtDisplay (d, d->activeWindow);
+ if (w)
+ decorWindowUpdate (w, FALSE);
+ }
+ }
+ else if (event->xproperty.atom == dd->winDecorAtom)
+ {
+ w = findWindowAtDisplay (d, event->xproperty.window);
+ if (w)
+ {
+ decorWindowUpdateDecoration (w);
+ decorWindowUpdate (w, TRUE);
+ }
+ }
+ else if (event->xproperty.atom == d->mwmHintsAtom)
+ {
+ w = findWindowAtDisplay (d, event->xproperty.window);
+ if (w)
+ decorWindowUpdate (w, TRUE);
+ }
+ else if (event->xproperty.atom == dd->supportingDmCheckAtom)
+ {
+ CompScreen *s;
+
+ s = findScreenAtDisplay (d, event->xproperty.window);
+ if (s)
+ decorCheckForDmOnScreen (s, TRUE);
+ }
+ break;
+ case ClientMessage:
+ if (event->xclient.message_type == dd->winDecorSyncAtom)
+ {
+ DecorTexture *t;
+
+ for (t = dd->textures; t; t = t->next)
+ if (t->pixmap == event->xclient.data.l[0])
+ break;
+
+ if (t)
+ {
+ DecorWindow *dw;
+ DecorScreen *ds;
+ CompScreen *s;
+
+ if (!t->nDamage)
+ return;
+
+ for (s = d->screens; s; s = s->next)
+ {
+ ds = GET_DECOR_SCREEN (s, dd);
+
+ for (w = s->windows; w; w = w->next)
+ {
+ if (!w->attrib.override_redirect && w->mapNum)
+ {
+ dw = GET_DECOR_WINDOW (w, ds);
+
+ if (dw->wd && dw->wd->decor->texture == t)
+ damageWindowOutputExtents (w);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case MapRequest:
+ w = findWindowAtDisplay (d, event->xmaprequest.window);
+ if (w)
+ decorWindowUpdate (w, TRUE);
+ break;
+ default:
+ if (d->shapeExtension && event->type == d->shapeEvent + ShapeNotify)
+ {
+ w = findWindowAtDisplay (d, ((XShapeEvent *) event)->window);
+ if (w)
+ decorWindowUpdate (w, TRUE);
+ }
+ break;
+ }
+}
+
+static Bool
+decorDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ DECOR_SCREEN (w->screen);
+
+ if (initial)
+ decorWindowUpdate (w, FALSE);
+
+ UNWRAP (ds, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (ds, w->screen, damageWindowRect, decorDamageWindowRect);
+
+ return status;
+}
+
+static void
+decorWindowMoveNotify (CompWindow *w,
+ int dx,
+ int dy)
+{
+ DECOR_SCREEN (w->screen);
+ DECOR_WINDOW (w);
+
+ if (dw->wd)
+ {
+ WindowDecoration *wd = dw->wd;
+ int i;
+
+ for (i = 0; i < wd->nQuad; i++)
+ {
+ wd->quad[i].box.x1 += dx;
+ wd->quad[i].box.y1 += dy;
+ wd->quad[i].box.x2 += dx;
+ wd->quad[i].box.y2 += dy;
+ }
+
+ setDecorationMatrices (w);
+ }
+
+ UNWRAP (ds, w->screen, windowMoveNotify);
+ (*w->screen->windowMoveNotify) (w, dx, dy);
+ WRAP (ds, w->screen, windowMoveNotify, decorWindowMoveNotify);
+}
+
+static void
+decorWindowResizeNotify (CompWindow *w)
+{
+ DECOR_SCREEN (w->screen);
+
+ if (!decorWindowUpdate (w, FALSE))
+ updateWindowDecorationScale (w);
+
+ UNWRAP (ds, w->screen, windowResizeNotify);
+ (*w->screen->windowResizeNotify) (w);
+ WRAP (ds, w->screen, windowResizeNotify, decorWindowResizeNotify);
+}
+
+static Bool
+decorInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ DecorDisplay *dd;
+
+ dd = malloc (sizeof (DecorDisplay));
+ if (!dd)
+ return FALSE;
+
+ dd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (dd->screenPrivateIndex < 0)
+ {
+ free (dd);
+ return FALSE;
+ }
+
+ dd->textures = 0;
+
+ dd->supportingDmCheckAtom =
+ XInternAtom (d->display, "_NET_SUPPORTING_DM_CHECK", 0);
+ dd->winDecorAtom = XInternAtom (d->display, "_NET_WINDOW_DECOR", 0);
+ dd->winDecorBareAtom =
+ XInternAtom (d->display, "_NET_WINDOW_DECOR_BARE", 0);
+ dd->winDecorNormalAtom =
+ XInternAtom (d->display, "_NET_WINDOW_DECOR_NORMAL", 0);
+ dd->winDecorActiveAtom =
+ XInternAtom (d->display, "_NET_WINDOW_DECOR_ACTIVE", 0);
+ dd->winDecorSyncAtom =
+ XInternAtom (d->display, "_NET_WINDOW_DECOR_SYNC", 0);
+
+ WRAP (dd, d, handleEvent, decorHandleEvent);
+
+ d->privates[displayPrivateIndex].ptr = dd;
+
+ return TRUE;
+}
+
+static void
+decorFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ DECOR_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, dd->screenPrivateIndex);
+
+ UNWRAP (dd, d, handleEvent);
+
+ free (dd);
+}
+
+static Bool
+decorInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ DecorScreen *ds;
+
+ DECOR_DISPLAY (s->display);
+
+ ds = malloc (sizeof (DecorScreen));
+ if (!ds)
+ return FALSE;
+
+ ds->windowPrivateIndex = allocateWindowPrivateIndex (s);
+ if (ds->windowPrivateIndex < 0)
+ {
+ free (ds);
+ return FALSE;
+ }
+
+ memset (ds->decor, 0, sizeof (ds->decor));
+
+ ds->dmWin = None;
+
+ WRAP (ds, s, paintWindow, decorPaintWindow);
+ WRAP (ds, s, damageWindowRect, decorDamageWindowRect);
+ WRAP (ds, s, windowMoveNotify, decorWindowMoveNotify);
+ WRAP (ds, s, windowResizeNotify, decorWindowResizeNotify);
+
+ s->privates[dd->screenPrivateIndex].ptr = ds;
+
+ decorCheckForDmOnScreen (s, FALSE);
+
+ return TRUE;
+}
+
+static void
+decorFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ int i;
+
+ DECOR_SCREEN (s);
+
+ for (i = 0; i < DECOR_NUM; i++)
+ if (ds->decor[i])
+ decorReleaseDecoration (s, ds->decor[i]);
+
+ UNWRAP (ds, s, paintWindow);
+ UNWRAP (ds, s, damageWindowRect);
+ UNWRAP (ds, s, windowMoveNotify);
+ UNWRAP (ds, s, windowResizeNotify);
+
+ free (ds);
+}
+
+static Bool
+decorInitWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ DecorWindow *dw;
+
+ DECOR_SCREEN (w->screen);
+
+ dw = malloc (sizeof (DecorWindow));
+ if (!dw)
+ return FALSE;
+
+ dw->wd = NULL;
+ dw->decor = NULL;
+
+ w->privates[ds->windowPrivateIndex].ptr = dw;
+
+ if (w->attrib.map_state == IsViewable)
+ {
+ if (!w->attrib.override_redirect)
+ decorWindowUpdateDecoration (w);
+
+ decorWindowUpdate (w, FALSE);
+ }
+
+ return TRUE;
+}
+
+static void
+decorFiniWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ DECOR_WINDOW (w);
+
+ if (dw->wd)
+ destroyWindowDecoration (dw->wd);
+
+ if (dw->decor)
+ decorReleaseDecoration (w->screen, dw->decor);
+
+ free (dw);
+}
+
+static Bool
+decorInit (CompPlugin *p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+decorFini (CompPlugin *p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+CompPluginDep decorDeps[] = {
+ { CompPluginRuleBefore, "wobbly" },
+ { CompPluginRuleBefore, "fade" },
+ { CompPluginRuleBefore, "cube" },
+ { CompPluginRuleBefore, "expose" }
+};
+
+static CompPluginVTable decorVTable = {
+ "decoration",
+ "Window Decoration",
+ "Window decorations",
+ decorInit,
+ decorFini,
+ decorInitDisplay,
+ decorFiniDisplay,
+ decorInitScreen,
+ decorFiniScreen,
+ decorInitWindow,
+ decorFiniWindow,
+ 0, /* GetDisplayOptions */
+ 0, /* SetDisplayOption */
+ 0, /* GetScreenOptions */
+ 0, /* SetScreenOption */
+ decorDeps,
+ sizeof (decorDeps) / sizeof (decorDeps[0])
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &decorVTable;
+}
diff --git a/plugins/fade.c b/plugins/fade.c
new file mode 100644
index 0000000..6162acb
--- /dev/null
+++ b/plugins/fade.c
@@ -0,0 +1,720 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <compiz.h>
+
+#define FADE_SPEED_DEFAULT 5.0f
+#define FADE_SPEED_MIN 0.1f
+#define FADE_SPEED_MAX 10.0f
+#define FADE_SPEED_PRECISION 0.1f
+
+static char *winType[] = {
+ "Dock",
+ "Toolbar",
+ "Menu",
+ "Utility",
+ "Splash",
+ "Normal",
+ "Dialog",
+ "ModalDialog",
+ "Unknown"
+};
+#define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0]))
+
+static int displayPrivateIndex;
+
+typedef struct _FadeDisplay {
+ int screenPrivateIndex;
+ HandleEventProc handleEvent;
+ int displayModals;
+} FadeDisplay;
+
+#define FADE_SCREEN_OPTION_FADE_SPEED 0
+#define FADE_SCREEN_OPTION_WINDOW_TYPE 1
+#define FADE_SCREEN_OPTION_NUM 2
+
+typedef struct _FadeScreen {
+ int windowPrivateIndex;
+ int fadeTime;
+ int steps;
+
+ CompOption opt[FADE_SCREEN_OPTION_NUM];
+
+ PreparePaintScreenProc preparePaintScreen;
+ PaintWindowProc paintWindow;
+ DamageWindowRectProc damageWindowRect;
+ FocusWindowProc focusWindow;
+
+ int wMask;
+} FadeScreen;
+
+typedef struct _FadeWindow {
+ GLushort opacity;
+ GLushort brightness;
+ GLushort saturation;
+
+ int dModal;
+
+ int destroyCnt;
+ int unmapCnt;
+} FadeWindow;
+
+#define GET_FADE_DISPLAY(d) \
+ ((FadeDisplay *) (d)->privates[displayPrivateIndex].ptr)
+
+#define FADE_DISPLAY(d) \
+ FadeDisplay *fd = GET_FADE_DISPLAY (d)
+
+#define GET_FADE_SCREEN(s, fd) \
+ ((FadeScreen *) (s)->privates[(fd)->screenPrivateIndex].ptr)
+
+#define FADE_SCREEN(s) \
+ FadeScreen *fs = GET_FADE_SCREEN (s, GET_FADE_DISPLAY (s->display))
+
+#define GET_FADE_WINDOW(w, fs) \
+ ((FadeWindow *) (w)->privates[(fs)->windowPrivateIndex].ptr)
+
+#define FADE_WINDOW(w) \
+ FadeWindow *fw = GET_FADE_WINDOW (w, \
+ GET_FADE_SCREEN (w->screen, \
+ GET_FADE_DISPLAY (w->screen->display)))
+
+#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
+
+static CompOption *
+fadeGetScreenOptions (CompScreen *screen,
+ int *count)
+{
+ FADE_SCREEN (screen);
+
+ *count = NUM_OPTIONS (fs);
+ return fs->opt;
+}
+
+static Bool
+fadeSetScreenOption (CompScreen *screen,
+ char *name,
+ CompOptionValue *value)
+{
+ CompOption *o;
+ int index;
+
+ FADE_SCREEN (screen);
+
+ o = compFindOption (fs->opt, NUM_OPTIONS (fs), name, &index);
+ if (!o)
+ return FALSE;
+
+ switch (index) {
+ case FADE_SCREEN_OPTION_FADE_SPEED:
+ if (compSetFloatOption (o, value))
+ {
+ fs->fadeTime = 1000.0f / o->value.f;
+ return TRUE;
+ }
+ break;
+ case FADE_SCREEN_OPTION_WINDOW_TYPE:
+ if (compSetOptionList (o, value))
+ {
+ fs->wMask = compWindowTypeMaskFromStringList (&o->value);
+ fs->wMask &= ~CompWindowTypeDesktopMask;
+ return TRUE;
+ }
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static void
+fadeScreenInitOptions (FadeScreen *fs)
+{
+ CompOption *o;
+ int i;
+
+ o = &fs->opt[FADE_SCREEN_OPTION_FADE_SPEED];
+ o->name = "fade_speed";
+ o->shortDesc = "Fade Speed";
+ o->longDesc = "Window fade speed";
+ o->type = CompOptionTypeFloat;
+ o->value.f = FADE_SPEED_DEFAULT;
+ o->rest.f.min = FADE_SPEED_MIN;
+ o->rest.f.max = FADE_SPEED_MAX;
+ o->rest.f.precision = FADE_SPEED_PRECISION;
+
+ o = &fs->opt[FADE_SCREEN_OPTION_WINDOW_TYPE];
+ o->name = "window_types";
+ o->shortDesc = "Window Types";
+ o->longDesc = "Window types that should be fading";
+ o->type = CompOptionTypeList;
+ o->value.list.type = CompOptionTypeString;
+ o->value.list.nValue = N_WIN_TYPE;
+ o->value.list.value = malloc (sizeof (CompOptionValue) * N_WIN_TYPE);
+ for (i = 0; i < N_WIN_TYPE; i++)
+ o->value.list.value[i].s = strdup (winType[i]);
+ o->rest.s.string = windowTypeString;
+ o->rest.s.nString = nWindowTypeString;
+
+ fs->wMask = compWindowTypeMaskFromStringList (&o->value);
+}
+
+static void
+fadePreparePaintScreen (CompScreen *s,
+ int msSinceLastPaint)
+{
+ FADE_SCREEN (s);
+
+ fs->steps = (msSinceLastPaint * OPAQUE) / fs->fadeTime;
+ if (fs->steps < 12)
+ fs->steps = 12;
+
+ UNWRAP (fs, s, preparePaintScreen);
+ (*s->preparePaintScreen) (s, msSinceLastPaint);
+ WRAP (fs, s, preparePaintScreen, fadePreparePaintScreen);
+}
+
+static Bool
+fadePaintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ CompScreen *s = w->screen;
+ Bool status;
+
+ FADE_SCREEN (s);
+ FADE_WINDOW (w);
+
+ if (!w->screen->canDoSlightlySaturated)
+ fw->saturation = attrib->saturation;
+
+ if (fw->opacity != attrib->opacity ||
+ fw->brightness != attrib->brightness ||
+ fw->saturation != attrib->saturation)
+ {
+ GLint opacity;
+ GLint brightness;
+ GLint saturation;
+
+ opacity = fw->opacity;
+ if (attrib->opacity > fw->opacity)
+ {
+ opacity = fw->opacity + fs->steps;
+ if (opacity > attrib->opacity)
+ opacity = attrib->opacity;
+ }
+ else if (attrib->opacity < fw->opacity)
+ {
+ if (w->type & CompWindowTypeUnknownMask)
+ opacity = fw->opacity - (fs->steps >> 1);
+ else
+ opacity = fw->opacity - fs->steps;
+
+ if (opacity < attrib->opacity)
+ opacity = attrib->opacity;
+ }
+
+ brightness = fw->brightness;
+ if (attrib->brightness > fw->brightness)
+ {
+ brightness = fw->brightness + fs->steps;
+ if (brightness > attrib->brightness)
+ brightness = attrib->brightness;
+ }
+ else if (attrib->brightness < fw->brightness)
+ {
+ brightness = fw->brightness - fs->steps;
+ if (brightness < attrib->brightness)
+ brightness = attrib->brightness;
+ }
+
+ saturation = fw->saturation;
+ if (attrib->saturation > fw->saturation)
+ {
+ saturation = fw->saturation + (fs->steps / 6);
+ if (saturation > attrib->saturation)
+ saturation = attrib->saturation;
+ }
+ else if (attrib->saturation < fw->saturation)
+ {
+ saturation = fw->saturation - (fs->steps / 12);
+ if (saturation < attrib->saturation)
+ saturation = attrib->saturation;
+ }
+
+ if (opacity > 0)
+ {
+ WindowPaintAttrib fAttrib = *attrib;
+
+ fAttrib.opacity = opacity;
+ fAttrib.brightness = brightness;
+ fAttrib.saturation = saturation;
+
+ UNWRAP (fs, s, paintWindow);
+ status = (*s->paintWindow) (w, &fAttrib, region, mask);
+ WRAP (fs, s, paintWindow, fadePaintWindow);
+
+ if (status)
+ {
+ fw->opacity = opacity;
+ fw->brightness = brightness;
+ fw->saturation = saturation;
+
+ if (opacity != attrib->opacity ||
+ brightness != attrib->brightness ||
+ saturation != attrib->saturation)
+ addWindowDamage (w);
+ }
+ }
+ else
+ {
+ fw->opacity = 0;
+
+ while (fw->unmapCnt)
+ {
+ unmapWindow (w);
+ fw->unmapCnt--;
+ }
+
+ while (fw->destroyCnt)
+ {
+ destroyWindow (w);
+ fw->destroyCnt--;
+ }
+
+ return (mask & PAINT_WINDOW_SOLID_MASK) ? FALSE : TRUE;
+ }
+ }
+ else
+ {
+ UNWRAP (fs, s, paintWindow);
+ status = (*s->paintWindow) (w, attrib, region, mask);
+ WRAP (fs, s, paintWindow, fadePaintWindow);
+ }
+
+ return status;
+}
+
+static void
+fadeAddDisplayModal (CompDisplay *d,
+ CompWindow *w)
+{
+ FADE_DISPLAY (d);
+ FADE_WINDOW (w);
+
+ if (!(w->state & CompWindowStateDisplayModalMask))
+ return;
+
+ if (fw->dModal)
+ return;
+
+ fw->dModal = 1;
+
+ fd->displayModals++;
+ if (fd->displayModals == 1)
+ {
+ CompScreen *s;
+
+ for (s = d->screens; s; s = s->next)
+ {
+ for (w = s->windows; w; w = w->next)
+ {
+ FADE_WINDOW (w);
+
+ if (fw->dModal)
+ continue;
+
+ w->paint.saturation = 0;
+ }
+
+ damageScreen (s);
+ }
+ }
+}
+
+static void
+fadeRemoveDisplayModal (CompDisplay *d,
+ CompWindow *w)
+{
+ FADE_DISPLAY (d);
+ FADE_WINDOW (w);
+
+ if (!fw->dModal)
+ return;
+
+ fw->dModal = 0;
+
+ fd->displayModals--;
+ if (fd->displayModals == 0)
+ {
+ CompScreen *s;
+
+ for (s = d->screens; s; s = s->next)
+ {
+ for (w = s->windows; w; w = w->next)
+ {
+ FADE_WINDOW (w);
+
+ if (fw->dModal)
+ continue;
+
+ if (w->alive)
+ w->paint.saturation = w->saturation;
+ }
+
+ damageScreen (s);
+ }
+ }
+}
+
+static void
+fadeHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ CompWindow *w;
+
+ FADE_DISPLAY (d);
+
+ switch (event->type) {
+ case DestroyNotify:
+ w = findWindowAtDisplay (d, event->xdestroywindow.window);
+ if (w)
+ {
+ FADE_SCREEN (w->screen);
+
+ if (w->texture.pixmap && (fs->wMask & w->type))
+ {
+ FADE_WINDOW (w);
+
+ w->paint.opacity = 0;
+
+ fw->destroyCnt++;
+ w->destroyRefCnt++;
+
+ addWindowDamage (w);
+ }
+
+ fadeRemoveDisplayModal (d, w);
+ }
+ break;
+ case UnmapNotify:
+ w = findWindowAtDisplay (d, event->xunmap.window);
+ if (w)
+ {
+ FADE_SCREEN (w->screen);
+
+ if (w->texture.pixmap && (fs->wMask & w->type))
+ {
+ FADE_WINDOW (w);
+
+ w->paint.opacity = 0;
+
+ fw->unmapCnt++;
+ w->unmapRefCnt++;
+
+ addWindowDamage (w);
+ }
+
+ fadeRemoveDisplayModal (d, w);
+ }
+ break;
+ case MapNotify:
+ w = findWindowAtDisplay (d, event->xunmap.window);
+ if (w)
+ {
+ FADE_WINDOW (w);
+
+ if (!(w->type & CompWindowTypeDesktopMask))
+ w->paint.opacity = getWindowProp32 (d, w->id,
+ d->winOpacityAtom,
+ OPAQUE);
+
+ while (fw->unmapCnt)
+ {
+ unmapWindow (w);
+ fw->unmapCnt--;
+ }
+
+ if (w->state & CompWindowStateDisplayModalMask)
+ fadeAddDisplayModal (d, w);
+ }
+ default:
+ break;
+ }
+
+ UNWRAP (fd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (fd, d, handleEvent, fadeHandleEvent);
+
+ switch (event->type) {
+ case PropertyNotify:
+ if (event->xproperty.atom == d->winStateAtom)
+ {
+ w = findWindowAtDisplay (d, event->xproperty.window);
+ if (w && w->attrib.map_state == IsViewable)
+ {
+ if (w->state & CompWindowStateDisplayModalMask)
+ fadeAddDisplayModal (d, w);
+ else
+ fadeRemoveDisplayModal (d, w);
+ }
+ }
+ break;
+ }
+}
+
+static Bool
+fadeDamageWindowRect (CompWindow *w,
+ Bool initial,
+ BoxPtr rect)
+{
+ Bool status;
+
+ FADE_SCREEN (w->screen);
+
+ if (initial)
+ {
+ FADE_WINDOW (w);
+
+ if (fs->wMask & w->type)
+ fw->opacity = 0;
+ else
+ fw->opacity = w->paint.opacity;
+ }
+
+ UNWRAP (fs, w->screen, damageWindowRect);
+ status = (*w->screen->damageWindowRect) (w, initial, rect);
+ WRAP (fs, w->screen, damageWindowRect, fadeDamageWindowRect);
+
+ return status;
+}
+
+static Bool
+fadeFocusWindow (CompWindow *w)
+{
+ Bool status;
+
+ FADE_SCREEN (w->screen);
+ FADE_WINDOW (w);
+
+ if (fw->destroyCnt || fw->unmapCnt)
+ return FALSE;
+
+ UNWRAP (fs, w->screen, focusWindow);
+ status = (*w->screen->focusWindow) (w);
+ WRAP (fs, w->screen, focusWindow, fadeFocusWindow);
+
+ return status;
+}
+
+static Bool
+fadeInitDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ FadeDisplay *fd;
+
+ fd = malloc (sizeof (FadeDisplay));
+ if (!fd)
+ return FALSE;
+
+ fd->screenPrivateIndex = allocateScreenPrivateIndex (d);
+ if (fd->screenPrivateIndex < 0)
+ {
+ free (fd);
+ return FALSE;
+ }
+
+ fd->displayModals = 0;
+
+ WRAP (fd, d, handleEvent, fadeHandleEvent);
+
+ d->privates[displayPrivateIndex].ptr = fd;
+
+ return TRUE;
+}
+
+static void
+fadeFiniDisplay (CompPlugin *p,
+ CompDisplay *d)
+{
+ FADE_DISPLAY (d);
+
+ freeScreenPrivateIndex (d, fd->screenPrivateIndex);
+
+ UNWRAP (fd, d, handleEvent);
+
+ free (fd);
+}
+
+static Bool
+fadeInitScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ FadeScreen *fs;
+
+ FADE_DISPLAY (s->display);
+
+ fs = malloc (sizeof (FadeScreen));
+ if (!fs)
+ return FALSE;
+
+ fs->windowPrivateIndex = allocateWindowPrivateIndex (s);
+ if (fs->windowPrivateIndex < 0)
+ {
+ free (fs);
+ return FALSE;
+ }
+
+ fs->steps = 0;
+ fs->fadeTime = 1000.0f / FADE_SPEED_DEFAULT;
+
+ fadeScreenInitOptions (fs);
+
+ WRAP (fs, s, preparePaintScreen, fadePreparePaintScreen);
+ WRAP (fs, s, paintWindow, fadePaintWindow);
+ WRAP (fs, s, damageWindowRect, fadeDamageWindowRect);
+ WRAP (fs, s, focusWindow, fadeFocusWindow);
+
+ s->privates[fd->screenPrivateIndex].ptr = fs;
+
+ return TRUE;
+}
+
+static void
+fadeFiniScreen (CompPlugin *p,
+ CompScreen *s)
+{
+ FADE_SCREEN (s);
+
+ freeWindowPrivateIndex (s, fs->windowPrivateIndex);
+
+ UNWRAP (fs, s, preparePaintScreen);
+ UNWRAP (fs, s, paintWindow);
+ UNWRAP (fs, s, damageWindowRect);
+ UNWRAP (fs, s, focusWindow);
+
+ free (fs);
+}
+
+static Bool
+fadeInitWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ FadeWindow *fw;
+
+ FADE_SCREEN (w->screen);
+
+ fw = malloc (sizeof (FadeWindow));
+ if (!fw)
+ return FALSE;
+
+ fw->opacity = w->paint.opacity;
+ fw->brightness = w->paint.brightness;
+ fw->saturation = w->paint.saturation;
+
+ fw->dModal = 0;
+
+ fw->destroyCnt = 0;
+ fw->unmapCnt = 0;
+
+ w->privates[fs->windowPrivateIndex].ptr = fw;
+
+ if (w->attrib.map_state == IsViewable)
+ {
+ if (w->state & CompWindowStateDisplayModalMask)
+ fadeAddDisplayModal (w->screen->display, w);
+ }
+
+ return TRUE;
+}
+
+static void
+fadeFiniWindow (CompPlugin *p,
+ CompWindow *w)
+{
+ FADE_WINDOW (w);
+
+ fadeRemoveDisplayModal (w->screen->display, w);
+
+ while (fw->unmapCnt--)
+ unmapWindow (w);
+
+ while (fw->destroyCnt--)
+ destroyWindow (w);
+
+ free (fw);
+}
+
+static Bool
+fadeInit (CompPlugin *p)
+{
+ displayPrivateIndex = allocateDisplayPrivateIndex ();
+ if (displayPrivateIndex < 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+fadeFini (CompPlugin *p)
+{
+ if (displayPrivateIndex >= 0)
+ freeDisplayPrivateIndex (displayPrivateIndex);
+}
+
+CompPluginDep fadeDeps[] = {
+ { CompPluginRuleBefore, "cube" },
+ { CompPluginRuleBefore, "expose" }
+};
+
+static CompPluginVTable fadeVTable = {
+ "fade",
+ "Fading Windows",
+ "Fade in windows when mapped and fade out windows when unmapped",
+ fadeInit,
+ fadeFini,
+ fadeInitDisplay,
+ fadeFiniDisplay,
+ fadeInitScreen,
+ fadeFiniScreen,
+ fadeInitWindow,
+ fadeFiniWindow,
+ 0, /* GetDisplayOptions */
+ 0, /* SetDisplayOption */
+ fadeGetScreenOptions,
+ fadeSetScreenOption,
+ fadeDeps,
+ sizeof (fadeDeps) / sizeof (fadeDeps[0])
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ return &fadeVTable;
+}
diff --git a/plugins/gconf.c b/plugins/gconf.c
new file mode 100644
index 0000000..0e8083c
--- /dev/null
+++ b/plugins/gconf.c
@@ -0,0 +1,1036 @@
+/*
+ * 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 o