summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--AUTHORS29
-rw-r--r--CMakeLists.txt125
-rw-r--r--COPYING6
-rw-r--r--COPYING.GPL340
-rw-r--r--COPYING.LGPL510
-rw-r--r--COPYING.MIT21
-rw-r--r--ChangeLog1795
-rw-r--r--Doxyfile1514
-rw-r--r--INSTALL12
-rw-r--r--NEWS457
-rw-r--r--README8
-rw-r--r--RELEASING75
-rw-r--r--TODO22
-rw-r--r--cmake/CMakeLists.txt21
-rw-r--r--cmake/CompizBcop.cmake41
-rw-r--r--cmake/CompizCommon.cmake273
-rw-r--r--cmake/CompizDefaults.cmake15
-rw-r--r--cmake/CompizDefaults.cmake.in5
-rw-r--r--cmake/CompizGconf.cmake52
-rw-r--r--cmake/CompizPackage.cmake101
-rw-r--r--cmake/CompizPlugin.cmake451
-rw-r--r--cmake/FindCompiz.cmake89
-rw-r--r--cmake/all_plugins_in_folder_example-CMakeLists.txt10
-rw-r--r--cmake/base.cmake63
-rw-r--r--compiz.pc.in12
-rw-r--r--config.h.core.in5
-rw-r--r--gtk/CMakeLists.txt88
-rw-r--r--gtk/config.h.gtk.in25
-rw-r--r--gtk/gnome/50-compiz-desktop-key.xml.in16
-rw-r--r--gtk/gnome/50-compiz-key.xml.in36
-rw-r--r--gtk/gnome/CMakeLists.txt84
-rw-r--r--gtk/gnome/compiz-window-manager.c505
-rw-r--r--gtk/gnome/compiz-window-manager.h39
-rw-r--r--gtk/gnome/compiz-wm.desktop.in17
-rw-r--r--gtk/gnome/compiz.desktop.in15
-rw-r--r--gtk/window-decorator/CMakeLists.txt65
-rw-r--r--gtk/window-decorator/TODO6
-rw-r--r--gtk/window-decorator/gtk-window-decorator.c8045
-rw-r--r--gtk/window-decorator/gwd.schemas.in81
-rw-r--r--images/CMakeLists.txt10
-rw-r--r--images/freedesktop.pngbin0 -> 30453 bytes
-rw-r--r--images/icon.pngbin0 -> 529 bytes
-rw-r--r--include/CMakeLists.txt11
-rw-r--r--include/compiz-common.h.in9
-rw-r--r--include/compiz.h92
-rw-r--r--include/core/CMakeLists.txt30
-rw-r--r--include/core/action.h174
-rw-r--r--include/core/atoms.h162
-rw-r--r--include/core/core.h85
-rw-r--r--include/core/countedlist.h114
-rw-r--r--include/core/icon.h53
-rw-r--r--include/core/match.h95
-rw-r--r--include/core/modifierhandler.h114
-rw-r--r--include/core/option.h240
-rw-r--r--include/core/output.h70
-rw-r--r--include/core/plugin.h332
-rw-r--r--include/core/pluginclasses.h70
-rw-r--r--include/core/pluginclasshandler.h167
-rw-r--r--include/core/point.h110
-rw-r--r--include/core/propertywriter.h54
-rw-r--r--include/core/rect.h227
-rw-r--r--include/core/region.h190
-rw-r--r--include/core/screen.h455
-rw-r--r--include/core/serialization.h152
-rw-r--r--include/core/session.h53
-rw-r--r--include/core/size.h69
-rw-r--r--include/core/timer.h108
-rw-r--r--include/core/window.h557
-rw-r--r--include/core/wrapsystem.h184
-rw-r--r--include/decoration.h428
-rw-r--r--kde/CMakeLists.txt1
-rw-r--r--kde/window-decorator-kde4/CMakeLists.txt76
-rw-r--r--kde/window-decorator-kde4/Makefile.am49
-rw-r--r--kde/window-decorator-kde4/decorator.cpp918
-rw-r--r--kde/window-decorator-kde4/decorator.h167
-rw-r--r--kde/window-decorator-kde4/kdecoration_plugins.cpp212
-rw-r--r--kde/window-decorator-kde4/kdecoration_plugins.h90
-rw-r--r--kde/window-decorator-kde4/main.cpp136
-rw-r--r--kde/window-decorator-kde4/options.cpp186
-rw-r--r--kde/window-decorator-kde4/options.h140
-rw-r--r--kde/window-decorator-kde4/org.kde.KWin.xml10
-rw-r--r--kde/window-decorator-kde4/paintredirector.cpp124
-rw-r--r--kde/window-decorator-kde4/paintredirector.h60
-rw-r--r--kde/window-decorator-kde4/switcher.cpp324
-rw-r--r--kde/window-decorator-kde4/switcher.h86
-rw-r--r--kde/window-decorator-kde4/utils.cpp213
-rw-r--r--kde/window-decorator-kde4/utils.h72
-rw-r--r--kde/window-decorator-kde4/window.cpp1943
-rw-r--r--kde/window-decorator-kde4/window.h276
-rw-r--r--legacy/compiz-cube.h230
-rw-r--r--legacy/compiz-cube.pc.in13
-rw-r--r--legacy/fs.xml.in13
-rw-r--r--legacy/fuse.cpp1442
-rw-r--r--legacy/gconf.cpp848
-rw-r--r--legacy/gconf.xml.in18
-rw-r--r--legacy/metadata.cpp1160
-rw-r--r--legacy/metadata.h106
-rw-r--r--legacy/minimize.cpp1059
-rw-r--r--legacy/minimize.xml.in43
-rw-r--r--legacy/privatemetadata.h40
-rw-r--r--legacy/video.cpp1329
-rw-r--r--legacy/video.xml.in14
-rw-r--r--libdecoration/CMakeLists.txt59
-rw-r--r--libdecoration/config.h.libdecoration.in4
-rw-r--r--libdecoration/decoration.c2953
-rw-r--r--libdecoration/libdecoration.pc.in12
-rw-r--r--metadata/CMakeLists.txt56
-rw-r--r--metadata/core.xml.in268
-rw-r--r--plugins/CMakeLists.txt9
-rw-r--r--plugins/annotate/CMakeLists.txt5
-rw-r--r--plugins/annotate/annotate.xml.in92
-rw-r--r--plugins/annotate/src/annotate.cpp980
-rw-r--r--plugins/annotate/src/annotate.h213
-rw-r--r--plugins/blur/CMakeLists.txt16
-rw-r--r--plugins/blur/blur.xml.in112
-rw-r--r--plugins/blur/src/blur.cpp2335
-rw-r--r--plugins/blur/src/blur.h241
-rw-r--r--plugins/clone/CMakeLists.txt5
-rw-r--r--plugins/clone/clone.xml.in22
-rw-r--r--plugins/clone/src/clone.cpp595
-rw-r--r--plugins/clone/src/clone.h147
-rw-r--r--plugins/commands/CMakeLists.txt5
-rw-r--r--plugins/commands/commands.xml.in385
-rw-r--r--plugins/commands/src/commands.cpp132
-rw-r--r--plugins/commands/src/commands.h50
-rw-r--r--plugins/compiztoolbox/CMakeLists.txt5
-rw-r--r--plugins/compiztoolbox/compiz-compiztoolbox.pc.in12
-rw-r--r--plugins/compiztoolbox/compiztoolbox.xml.in13
-rw-r--r--plugins/compiztoolbox/include/compiztoolbox/compiztoolbox.h168
-rw-r--r--plugins/compiztoolbox/src/compiztoolbox.cpp737
-rw-r--r--plugins/composite/CMakeLists.txt5
-rw-r--r--plugins/composite/compiz-composite.pc.in12
-rw-r--r--plugins/composite/composite.xml.in35
-rw-r--r--plugins/composite/include/composite/composite.h408
-rw-r--r--plugins/composite/src/composite.cpp103
-rw-r--r--plugins/composite/src/privates.h156
-rw-r--r--plugins/composite/src/screen.cpp998
-rw-r--r--plugins/composite/src/window.cpp630
-rw-r--r--plugins/copytex/CMakeLists.txt5
-rw-r--r--plugins/copytex/copytex.xml.in12
-rw-r--r--plugins/copytex/src/copytex.cpp341
-rw-r--r--plugins/copytex/src/copytex.h114
-rw-r--r--plugins/cube/CMakeLists.txt5
-rw-r--r--plugins/cube/compiz-cube.pc.in12
-rw-r--r--plugins/cube/cube.xml.in188
-rw-r--r--plugins/cube/include/cube/cube.h179
-rw-r--r--plugins/cube/src/cube.cpp1897
-rw-r--r--plugins/cube/src/privates.h196
-rw-r--r--plugins/dbus/CMakeLists.txt37
-rw-r--r--plugins/dbus/dbus.xml.in14
-rw-r--r--plugins/dbus/src/dbus.cpp2044
-rw-r--r--plugins/dbus/src/dbus.h185
-rw-r--r--plugins/decor/CMakeLists.txt14
-rw-r--r--plugins/decor/decor.xml.in75
-rw-r--r--plugins/decor/src/decor.cpp1746
-rw-r--r--plugins/decor/src/decor.h234
-rw-r--r--plugins/fade/CMakeLists.txt5
-rw-r--r--plugins/fade/fade.xml.in85
-rw-r--r--plugins/fade/src/fade.cpp398
-rw-r--r--plugins/fade/src/fade.h102
-rw-r--r--plugins/glib/CMakeLists.txt5
-rw-r--r--plugins/glib/glib.xml.in14
-rw-r--r--plugins/glib/src/glib.cpp177
-rw-r--r--plugins/glib/src/private.h77
-rw-r--r--plugins/gnomecompat/CMakeLists.txt5
-rw-r--r--plugins/gnomecompat/gnomecompat.xml.in59
-rw-r--r--plugins/gnomecompat/src/gnomecompat.cpp131
-rw-r--r--plugins/gnomecompat/src/gnomecompat.h53
-rw-r--r--plugins/imgpng/CMakeLists.txt5
-rw-r--r--plugins/imgpng/imgpng.xml.in16
-rw-r--r--plugins/imgpng/src/imgpng.cpp358
-rw-r--r--plugins/imgpng/src/imgpng.h69
-rw-r--r--plugins/imgsvg/CMakeLists.txt5
-rw-r--r--plugins/imgsvg/imgsvg.xml.in24
-rw-r--r--plugins/imgsvg/src/imgsvg.cpp637
-rw-r--r--plugins/imgsvg/src/imgsvg.h136
-rw-r--r--plugins/ini/CMakeLists.txt5
-rw-r--r--plugins/ini/ini.xml.in13
-rw-r--r--plugins/ini/src/ini.cpp611
-rw-r--r--plugins/ini/src/ini.h106
-rw-r--r--plugins/inotify/CMakeLists.txt10
-rw-r--r--plugins/inotify/inotify.xml.in14
-rw-r--r--plugins/inotify/src/inotify.cpp169
-rw-r--r--plugins/inotify/src/inotify.h66
-rw-r--r--plugins/kde/CMakeLists.txt22
-rw-r--r--plugins/kde/kde.xml.in15
-rw-r--r--plugins/kde/src/dispatcher.cpp262
-rw-r--r--plugins/kde/src/dispatcher.h79
-rw-r--r--plugins/kde/src/kde.cpp68
-rw-r--r--plugins/kde/src/kde.h60
-rw-r--r--plugins/kde/src/socket.cpp67
-rw-r--r--plugins/kde/src/socket.h44
-rw-r--r--plugins/kde/src/timer.cpp69
-rw-r--r--plugins/kde/src/timer.h55
-rw-r--r--plugins/move/CMakeLists.txt5
-rw-r--r--plugins/move/move.xml.in48
-rw-r--r--plugins/move/src/move.cpp730
-rw-r--r--plugins/move/src/move.h129
-rw-r--r--plugins/obs/CMakeLists.txt5
-rw-r--r--plugins/obs/obs.xml.in161
-rw-r--r--plugins/obs/src/obs.cpp332
-rw-r--r--plugins/obs/src/obs.h102
-rw-r--r--plugins/opengl/CMakeLists.txt8
-rw-r--r--plugins/opengl/compiz-opengl.pc.in12
-rw-r--r--plugins/opengl/include/opengl/fragment.h124
-rw-r--r--plugins/opengl/include/opengl/matrix.h66
-rw-r--r--plugins/opengl/include/opengl/opengl.h590
-rw-r--r--plugins/opengl/include/opengl/texture.h220
-rw-r--r--plugins/opengl/include/opengl/vector.h127
-rw-r--r--plugins/opengl/opengl.xml.in48
-rw-r--r--plugins/opengl/src/fragment.cpp1105
-rw-r--r--plugins/opengl/src/matrix.cpp439
-rw-r--r--plugins/opengl/src/opengl.cpp101
-rw-r--r--plugins/opengl/src/paint.cpp1262
-rw-r--r--plugins/opengl/src/privatefragment.h54
-rw-r--r--plugins/opengl/src/privates.h172
-rw-r--r--plugins/opengl/src/privatetexture.h85
-rw-r--r--plugins/opengl/src/screen.cpp1193
-rw-r--r--plugins/opengl/src/texture.cpp615
-rw-r--r--plugins/opengl/src/vector.cpp276
-rw-r--r--plugins/opengl/src/window.cpp363
-rw-r--r--plugins/place/CMakeLists.txt5
-rw-r--r--plugins/place/place.xml.in168
-rw-r--r--plugins/place/src/place.cpp1680
-rw-r--r--plugins/place/src/place.h140
-rw-r--r--plugins/regex/CMakeLists.txt5
-rw-r--r--plugins/regex/regex.xml.in14
-rw-r--r--plugins/regex/src/regex.cpp309
-rw-r--r--plugins/regex/src/regexplugin.h74
-rw-r--r--plugins/resize/CMakeLists.txt5
-rw-r--r--plugins/resize/resize.xml.in115
-rw-r--r--plugins/resize/src/resize.cpp1414
-rw-r--r--plugins/resize/src/resize.h174
-rw-r--r--plugins/rotate/CMakeLists.txt5
-rw-r--r--plugins/rotate/rotate.xml.in278
-rw-r--r--plugins/rotate/src/rotate.cpp1080
-rw-r--r--plugins/rotate/src/rotate.h173
-rw-r--r--plugins/scale/CMakeLists.txt5
-rw-r--r--plugins/scale/compiz-scale.pc.in12
-rw-r--r--plugins/scale/include/scale/scale.h166
-rw-r--r--plugins/scale/scale.xml.in179
-rw-r--r--plugins/scale/src/privates.h187
-rw-r--r--plugins/scale/src/scale.cpp1782
-rw-r--r--plugins/screenshot/CMakeLists.txt5
-rw-r--r--plugins/screenshot/screenshot.xml.in36
-rw-r--r--plugins/screenshot/src/screenshot.cpp362
-rw-r--r--plugins/screenshot/src/screenshot.h83
-rw-r--r--plugins/switcher/CMakeLists.txt5
-rw-r--r--plugins/switcher/src/switcher.cpp1186
-rw-r--r--plugins/switcher/src/switcher.h175
-rw-r--r--plugins/switcher/switcher.xml.in167
-rw-r--r--plugins/water/CMakeLists.txt5
-rw-r--r--plugins/water/src/water.cpp1356
-rw-r--r--plugins/water/src/water.h179
-rw-r--r--plugins/water/water.xml.in64
-rw-r--r--plugins/wobbly/CMakeLists.txt5
-rw-r--r--plugins/wobbly/src/wobbly.cpp2380
-rw-r--r--plugins/wobbly/src/wobbly.h369
-rw-r--r--plugins/wobbly/wobbly.xml.in126
-rw-r--r--plugins/zoom/CMakeLists.txt5
-rw-r--r--plugins/zoom/src/zoom.cpp742
-rw-r--r--plugins/zoom/src/zoom.h112
-rw-r--r--plugins/zoom/zoom.xml.in66
-rw-r--r--po/CMakeLists.txt56
-rw-r--r--po/ChangeLog25
-rw-r--r--po/POTFILES.in28
-rw-r--r--po/af.po3123
-rw-r--r--po/ar.po3009
-rw-r--r--po/as.po2624
-rw-r--r--po/be.po2738
-rw-r--r--po/bg.po3776
-rw-r--r--po/bn.po3576
-rw-r--r--po/bn_IN.po3566
-rw-r--r--po/bs.po3251
-rw-r--r--po/ca.po4148
-rw-r--r--po/cs.po4706
-rw-r--r--po/cy.po3267
-rw-r--r--po/da.po4135
-rw-r--r--po/de.po4823
-rw-r--r--po/el.po3334
-rw-r--r--po/en_GB.po3713
-rw-r--r--po/en_US.po2766
-rw-r--r--po/es.po4751
-rw-r--r--po/et.po3726
-rw-r--r--po/eu.po3222
-rw-r--r--po/fa.po2634
-rw-r--r--po/fi.po4724
-rw-r--r--po/fr.po3378
-rw-r--r--po/gl.po3329
-rw-r--r--po/gu.po3345
-rw-r--r--po/he.po3550
-rw-r--r--po/hi.po3799
-rw-r--r--po/hr.po3652
-rw-r--r--po/hu.po3218
-rw-r--r--po/id.po3178
-rw-r--r--po/it.po3436
-rw-r--r--po/ja.po2974
-rw-r--r--po/ka.po2999
-rw-r--r--po/km.po3751
-rw-r--r--po/ko.po3177
-rw-r--r--po/lo.po2997
-rw-r--r--po/lt.po3754
-rw-r--r--po/mk.po3017
-rw-r--r--po/ml_IN.po3000
-rw-r--r--po/mr.po2780
-rw-r--r--po/nb.po3358
-rw-r--r--po/nl.po3457
-rw-r--r--po/or.po3439
-rw-r--r--po/pa.po3861
-rw-r--r--po/pl.po3753
-rw-r--r--po/pt.po3309
-rw-r--r--po/pt_BR.po3363
-rw-r--r--po/ro.po3628
-rw-r--r--po/ru.po3258
-rw-r--r--po/sk.po3295
-rw-r--r--po/sl.po3772
-rw-r--r--po/sr.po3965
-rw-r--r--po/sv.po3389
-rw-r--r--po/ta.po3068
-rw-r--r--po/tr.po3558
-rw-r--r--po/uk.po3501
-rw-r--r--po/vi.po3000
-rw-r--r--po/xh.po3115
-rw-r--r--po/zh_CN.po4367
-rw-r--r--po/zh_TW.po4366
-rw-r--r--po/zu.po3115
-rw-r--r--src/CMakeLists.txt62
-rw-r--r--src/action.cpp644
-rw-r--r--src/actions.cpp289
-rw-r--r--src/atoms.cpp324
-rw-r--r--src/event.cpp1759
-rw-r--r--src/icon.cpp46
-rw-r--r--src/main.cpp242
-rw-r--r--src/match.cpp744
-rw-r--r--src/modifierhandler.cpp204
-rw-r--r--src/option.cpp964
-rw-r--r--src/output.cpp90
-rw-r--r--src/plugin.cpp700
-rw-r--r--src/pluginclasses.cpp74
-rw-r--r--src/point.cpp100
-rw-r--r--src/privateaction.h53
-rw-r--r--src/privatematch.h88
-rw-r--r--src/privateoption.h95
-rw-r--r--src/privateregion.h44
-rw-r--r--src/privatescreen.h427
-rw-r--r--src/privatewindow.h296
-rw-r--r--src/propertywriter.cpp227
-rw-r--r--src/rect.cpp285
-rw-r--r--src/region.cpp449
-rw-r--r--src/screen.cpp4636
-rw-r--r--src/session.cpp427
-rw-r--r--src/size.cpp50
-rw-r--r--src/string.cpp88
-rw-r--r--src/timer.cpp140
-rw-r--r--src/window.cpp5615
-rw-r--r--src/windowgeometry.cpp206
-rw-r--r--xslt/CMakeLists.txt13
-rw-r--r--xslt/bcop.xslt1581
-rw-r--r--xslt/compiz_gconf_schemas.xslt409
-rw-r--r--xslt/default_plugins.xslt76
361 files changed, 308469 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b9739d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+po/compiz.pot
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..1500f90
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,29 @@
+compiz and the standard set of plugins are designed and written by
+
+David Reveman <davidr@novell.com>
+
+with additional functionality by
+
+Radek Doulik <rodo@novell.com> IO multiplexing
+Mirco Müller <macslow@bangang.de> Skydome support in cube plugin
+Søren Sandmann <sandmann@redhat.com> plane plugin
+Dan Winship <danw@novell.com> gconf-dump plugin
+Brian Paul <brian.paul@tungstengraphics.com> Matrix functions
+
+and other contributions by
+
+Mike Cook <mcook@novell.com>
+Mike Dransfield <mike@blueroot.co.uk>
+Diogo Ferreira <diogo@underdev.org>
+gandalfn <gandalfn@club-internet.fr>
+Guillaume <ixcemix@gmail.com>
+Kristian Høgsberg <krh@redhat.com>
+Dennis Kasprzyk <onestone@beryl-project.org>
+Gerd Kohlberger <lowfi@chello.at>
+Volker Krause <vkrause@kde.org>
+moppsy <moppsy@comcast.net>
+Jeremy C. Reed <reed@reedmedia.net>
+Thierry Reding <thierry@gilfi.de>
+Julian Sikorski <lordzanon@poczta.onet.pl>
+Quinn Storm <livinglatexkali@gmail.com>
+Erkin Bahceci <erkinbah@gmail.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..92ca824
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,125 @@
+project (compiz)
+
+set (CMAKE_MODULE_PATH_ORIG ${CMAKE_MODULE_PATH})
+set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
+include (CompizCommon)
+include (CompizPackage)
+include (cmake/base.cmake)
+include (CheckFunctionExists)
+
+
+set (CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRe" CACHE INTERNAL "" FORCE)
+if (NOT CMAKE_BUILD_TYPE)
+ set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type (Debug/Release/RelWithDebInfo/MinSizeRe)" FORCE)
+endif (NOT CMAKE_BUILD_TYPE)
+
+# compiz package version number
+# An odd micro number indicates in-progress development.
+# An even micro number indicates a released version.
+set (COMPIZ_VERSION_MAJOR 0)
+set (COMPIZ_VERSION_MINOR 9)
+set (COMPIZ_VERSION_MICRO 0)
+set (VERSION ${COMPIZ_VERSION_MAJOR}.${COMPIZ_VERSION_MINOR}.${COMPIZ_VERSION_MICRO})
+
+set (DECOR_INTERFACE_VERSION 20080901)
+
+if (COMPIZ_PACKAGING_ENABLED)
+ set (prefix ${CMAKE_INSTALL_PREFIX} CACHE PATH "prefix")
+ set (exec_prefix ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "bindir")
+ set (libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "libdir")
+ set (includedir ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "includedir")
+ set (datadir ${CMAKE_INSTALL_PREFIX}/share CACHE PATH "datadir")
+else (COMPIZ_PACKAGING_ENABLED)
+ set (prefix ${CMAKE_INSTALL_PREFIX} )
+ set (exec_prefix ${CMAKE_INSTALL_PREFIX}/bin )
+ set (libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
+ set (includedir ${CMAKE_INSTALL_PREFIX}/include )
+ set (datadir ${CMAKE_INSTALL_PREFIX}/share )
+endif (COMPIZ_PACKAGING_ENABLED)
+
+set (compiz_plugindir ${libdir}/compiz)
+set (compiz_imagedir ${datadir}/compiz/images)
+set (compiz_metadatadir ${datadir}/compiz)
+set (COMPIZ_I18N_DIR ${CMAKE_SOURCE_DIR}/po)
+
+set (ALL_LINGUAS af ar bg bn bn_IN bs ca cs cy da de el en_GB en_US es eu et fi fr gl gu he hi hr hu id it ja ka km ko lo lt mk mr nb nl or pa pl pt pt_BR ro ru sk sl sr sv ta tr uk vi xh zh_CN zh_TW zu)
+set (GETTEXT_PACKAGE compiz)
+
+find_package (Boost 1.34.0 REQUIRED COMPONENTS serialization)
+
+set (COMPIZ_REQUIRES
+ x11
+ xext
+ xdamage
+ xcomposite
+ x11-xcb
+ xrandr
+ xinerama
+ xext
+ ice
+ sm
+ libxml-2.0
+ libxslt
+ "libstartup-notification-1.0 >= 0.7"
+)
+
+set (DECORATION_REQUIRES xrender)
+
+compiz_pkg_check_modules (COMPIZ REQUIRED ${COMPIZ_REQUIRES})
+compiz_pkg_check_modules (LIBDECORATION REQUIRED ${DECORATION_REQUIRES})
+
+list (APPEND COMPIZ_LIBRARIES ${Boost_LIBRARIES})
+
+include (CompizDefaults)
+
+set (COMPIZ_CFLAGS "${COMPIZ_CFLAGS} -I${Boost_INCLUDE_DIR}")
+
+set (_compiz_package_string "Compiz ${VERSION}")
+set (_compiz_package "Compiz")
+
+compiz_configure_file (${compiz_SOURCE_DIR}/config.h.core.in ${compiz_BINARY_DIR}/generated/config.h)
+
+compiz_configure_file (
+ ${CMAKE_SOURCE_DIR}/include/compiz-common.h.in
+ ${CMAKE_BINARY_DIR}/generated/compiz-common.h
+)
+
+install (
+ FILES ${CMAKE_BINARY_DIR}/generated/compiz-common.h
+ DESTINATION ${COMPIZ_DESTDIR}${includedir}/compiz
+)
+
+compiz_configure_file (
+ ${CMAKE_SOURCE_DIR}/compiz.pc.in
+ ${CMAKE_BINARY_DIR}/compiz.pc
+ COMPIZ_REQUIRES
+ COMPIZ_CFLAGS
+)
+
+install (
+ FILES ${CMAKE_BINARY_DIR}/compiz.pc
+ DESTINATION ${COMPIZ_DESTDIR}${libdir}/pkgconfig
+)
+
+add_subdirectory (cmake)
+add_subdirectory (include)
+add_subdirectory (images)
+add_subdirectory (libdecoration)
+add_subdirectory (gtk)
+add_subdirectory (kde)
+add_subdirectory (po)
+add_subdirectory (metadata)
+add_subdirectory (src)
+add_subdirectory (xslt)
+add_subdirectory (plugins)
+
+compiz_ensure_linkage ()
+compiz_package_generation ("Compiz")
+compiz_add_uninstall ()
+compiz_add_git_dist ()
+
+_print_configure_results ()
+
+_check_compiz_cmake_macro (${CMAKE_MODULE_PATH_ORIG})
+
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..988ebf2
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,6 @@
+Most of the code is MIT licensed, some code is instead licensed
+under the LGPL and some under the GPL. Each source code file
+contain a header that describes the license for the code in that
+specific file.
+
+For More information see COPYING.GPL, COPYING.LGPL 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.LGPL b/COPYING.LGPL
new file mode 100644
index 0000000..b124cf5
--- /dev/null
+++ b/COPYING.LGPL
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.1 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
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
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..bbfa473
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1795 @@
+2006-06-21 David Reveman <davidr@novell.com>
+
+ * src/window.c: Add updateTransientHint to protect against circular
+ transient dependencies. (bnc 186825)
+
+2006-06-20 David Reveman <davidr@novell.com>
+
+ * src/window.c (addWindowSizeChanges): Constrain window
+ dimensions if they are too large.
+
+ * gnome/window-decorator/gnome-window-decorator.c (get_mwm_prop):
+ Trap X errors.
+
+2006-06-20 Dan Winship <danw@novell.com>
+
+ * configure.ac (ALL_LINGUAS): Add pl
+
+2006-06-16 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * plugins/switcher.c:
+ * plugins/scale.c: Add modal dialogs and fullscreen windows
+ to default window types. (bnc 185749)
+
+ * gnome/window-decorator/gnome-window-decorator.c: Track motif
+ WM hints and disable decorations when application wants no
+ titlebar. (bnc 185852)
+
+2006-06-15 David Reveman <davidr@novell.com>
+
+ * plugins/cube.c (cubePaintTransformedScreen): Remove
+ PAINT_SCREEN_CLEAR_MASK from mask.
+
+ * plugins/switcher.c (switchPaintScreen): Add PAINT_SCREEN_CLEAR_MASK
+ when zooming. (bnc 183676)
+
+ * src/paint.c (paintTransformedScreen): Clear color buffer if
+ PAINT_SCREEN_CLEAR_MASK is present.
+
+ * include/compiz.h: Add PAINT_SCREEN_CLEAR_MASK.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Add DM selection
+ support and --repalce option so it's possible to replace an
+ existing window decorator in the same way as it's possible to replace
+ a window manager. (bnc 185296)
+ (close_button_event):
+ (max_button_event):
+ (min_button_event): De-highlight on NotifyGrab. (bnc 185293)
+
+2006-06-12 Dan Winship <danw@novell.com>
+
+ * plugins/cube.c:
+ * plugins/switcher.c: Mark cube as needing to load before switcher
+ rather than marking switcher as requiring cube. bnc #183676.
+
+ * plugins/gconf-dump.c (dumpPluginOptions): Output load_before and
+ requires for all plugins, even if the list is empty, to ensure
+ that an empty value in a new release overrides a non-empty value
+ in an older release.
+
+ * plugins/compiz.schemas.in.in: regen
+
+2006-06-09 Dan Winship <danw@novell.com>
+
+ * configure.ac: add translations
+
+2006-06-09 David Reveman <davidr@novell.com>
+
+ * plugins/move.c (moveHandleMotionEvent): Handle shaded windows
+ better.
+
+ * src/window.c (maximizeWindow):
+ * src/event.c (handleEvent): Allow windows to be both maximized
+ and shaded.
+
+ * src/window.c: Update addWindowSizeChanges so it can be used by
+ moveResizeWindow.
+ (updateWindowAttributes): Add missing sendSyncRequest call.
+ (addWindowSizeChanges): Make maximized window placement a bit better.
+ (moveResizeWindow): Adjust window geometry using
+ addWindowSizeChanges. (bnc 183121)
+
+ * src/window.c: Only allow shading on windows with top decoration.
+
+ * src/event.c (handleEvent): Check that shade action is allowed
+ before shading a window.
+
+2006-06-08 David Reveman <davidr@novell.com>
+
+ * plugins/decoration.c (decorInitWindow):
+ * plugins/minimize.c (minInitWindow):
+ * src/window.c (addWindow): Handle initially shaded windows
+ correctly.
+
+ * plugins/switcher.c (switchTerminate): Only use hideWindow
+ if switcher window is managed and mapped.
+ (switchInitiate): Only use showWindow if switcher window is
+ hidden. (bnc 182519)
+
+ * plugins/minimize.c (minHandleEvent): Make sure we adjust the window
+ region correctly when it's being unshaded.
+
+2006-06-07 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.13.
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * src/window.c: Add window shading support.
+
+ * src/screen.c:
+ * src/paint.c:
+ * src/event.c: Adjust for window shading support.
+ (handleEvent): Handle RESTACK client messages with sibling None
+ correctly.
+
+ * src/event.c:
+ * src/display.c: Add toggle window shade binding.
+
+ * plugins/minimize.c: Add window shading animation support.
+
+ * plugins/fade.c:
+ * plugins/place.c:
+ * plugins/resize.c:
+ * plugins/scale.c:
+ * plugins/switcher.c:
+ * plugins/decoration.c: Adjust for window shading support.
+
+ * include/compiz.h: Add window shading support.
+
+ * gnome/window-decorator/gnome-window-decorator.c: lower_window ->
+ restack_window and change it so it can be used for both
+ raising and lowering a window.
+ Add support for double_click_titlebar setting.
+ (title_event): Don't activate window on titlebar click only
+ raise it. Use double_click_action to determine what should be
+ done when titlebar is double clicked.
+ (update_event_windows): Remove vertical resize event windows
+ when top level window is shaded.
+ (window_state_changed): Update event windows when window state
+ changed.
+
+ * gnome/window-decorator/gnome-window-decorator.c:
+ * gnome/compiz-window-manager.c: Add support for shade double click
+ setting.
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * plugins/cube.c (cubePaintTransformedScreen):
+ * plugins/wobbly.c (wobblyDrawWindowGeometry):
+ * plugins/switcher.c (switchPaintWindow):
+ * src/paint.c (drawWindowGeometry): Disable client-side texture
+ coordinate arrays that are not used. (bnc #182430)
+
+ * plugins/compiz.schemas.in.in:
+ * plugins/resize.c:
+ * plugins/move.c: Add initiate_keyboard binding which is more
+ appropriate for key-binding as it moves the cursor to middle of
+ window.
+
+2006-06-06 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c: Track thumbnail damage correctly.
+ (switchPaintScreen): Only intercept paintScreen when screen is
+ grabbed or we're zooming and ss->translate > 0.001.
+ (switchPaintScreen): Paint switcher window correctly when we're
+ not zooming.
+ Add cube as a dependency to make sure background is rendered
+ correctly when zooming.
+ (bnc #181909)
+
+ * src/window.c (moveResizeWindow, ensureWindowVisibility):
+ Don't make sure fullscreen windows are in workarea.
+ (fdo #7115) (bnc #181907)
+
+ * src/event.c (handleEvent): Track XA_WM_CLASS property changes.
+
+ * src/window.c:
+ * include/compiz.h: remove updateWindowClass and update
+ updateWindowClassHints.
+
+2006-06-02 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.12.
+
+ * src/event.c (handleEvent): Fix typo.
+
+ * gnome/window-decorator/gnome-window-decorator.c:
+ Hide tooltips on NotifyGrab. (bnc #180692)
+
+2006-06-01 Dan Winship <danw@novell.com>
+
+ * src/event.c (handleEvent): If we receive a _NET_SHOWING_DESKTOP
+ request with no window set, set the flag on all screens. (Fixes
+ the KDE "show desktop" applet.) Also, don't allow a client to
+ change its _NET_WM_DESKTOP.
+
+ * src/window.c (addWindow): Set _NET_WM_DESKTOP on all windows to
+ 0; KDE's pager and tasklist require this to be set. (bnc 178320)
+
+2006-06-01 David Reveman <davidr@novell.com>
+
+ * include/compiz.h:
+ * src/window.c: Add updateWindowClass.
+
+2006-05-31 David Reveman <davidr@novell.com>
+
+ * include/compiz.h:
+ * src/screen.c:
+ * src/display.c: Add hide_skip_taskbar_windows option. (bnc 180055)
+
+ * include/compiz.h:
+ * src/window.c: Add getStartupId.
+
+ * src/screen.c: Save initial viewport when startup notification
+ is received. Fix implementation of applyStartupProperties.
+ (bnc 180224)
+
+ * src/event.c (handleEvent): Handle startup ID property changes.
+
+ * plugins/place.c: Adjust work area to initial viewport.
+
+ * plugins/cube.c (cubePaintTransformedScreen): Disable skydome
+ animation while cube is unfolded. (bnc 179833)
+
+ * plugins/switcher.c (switchPaintWindow): Make sure selected window is
+ not clipped incorrectly when some window is transformed. (bnc 179828)
+
+ * plugins/move.c (moveHandleEvent): Initialize xRoot and yRoot.
+ (bnc 179902)
+
+ * src/Makefile.am (INCLUDES): Add @GL_CFLAGS@. (Eric Work)
+
+2006-05-30 Dan Winship <danw@novell.com>
+
+ * configure.ac: Check libwnck for wnck_window_has_name (new in
+ HEAD).
+
+ * gnome/window-decorator/gnome-window-decorator.c
+ (wnck_window_get_real_name): #if HAVE_WNCK_WINDOW_HAS_NAME,
+ redefine wnck_window_get_name to return NULL if the window only
+ has a fallback name. bnc 173059.
+
+ * src/event.c (handleEvent): call moveInputFocusToOtherWindow()
+ before destroyWindow() when processing a DestroyNotify, or else
+ the input focus can get stranded.
+
+2006-05-26 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * plugins/scale.c (SCALE_SLOPPY_FOCUS_DEFAULT): TRUE.
+
+ * plugins/decoration.c (decorWindowUpdate): No drop-shadow decoration
+ on windows with below state.
+
+ * src/window.c (recalcWindowType): Treat dock windows with below state
+ as normal windows. (bnc #178316)
+
+ * plugins/cube.c (cubePaintTransformedScreen): Avoid optimized case
+ when more than 4 cube sides.
+
+2006-05-25 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * src/window.c (moveResizeWindow): Don't adjust position for NorthWest
+ gravity. (bnc 178765) (fdo #6992)
+
+ * plugins/compiz.schemas.in.in:
+ * include/compiz.h:
+ * src/event.c (handleEvent):
+ * src/display.c: Add maximize_window_horizontally,
+ maximize_window_vertically, toggle_window_maximized,
+ toggle_window_maximized_horizontally,
+ toggle_window_maximized_vertically.
+
+ * src/event.c (handleEvent): Track changes to maximizeWindow function.
+
+ * plugins/move.c (moveHandleMotionEvent): Make sure we have a saved
+ width before we use it. Track changes to maximizeWindow function.
+
+ * plugins/wobbly.c (wobblyHandleEvent): Handle the case where
+ window is not both vertically and horizontally maximized better.
+
+ * include/compiz.h: Add MAXIMIZE_STATE macro.
+
+ * include/compiz.h:
+ * src/window.c: Remove unmaximizeWindow and make maximizeWindow
+ take a state mask so it can be used for both maximizing and
+ unmaximizing.
+
+ * plugins/switcher.c: Don't add windows that appear after the switcher
+ is popped up. (bnc 178350)
+ (switchWindowRemove): Don't create a new list. Instead remove
+ window from the existing list and make sure we're positioned
+ correctly.
+
+2006-05-24 David Reveman <davidr@novell.com>
+
+ * plugins/scale.c (scaleMoveFocusWindow): When moving to window on
+ left, make sure the window we're moving to is completely left of
+ currently selected window. And same thing when moving to window on
+ right, top, bottom.
+ (layoutThumbs): Set slot->x2 and slot->y2 correctly. (bnc 178216)
+
+2006-05-23 David Reveman <davidr@novell.com>
+
+ * plugins/water.c: GL_UNSIGNED_INT_8_8_8_8_REV as pixel data type on
+ MSBFirst machines.
+
+ * src/texture.c: Include config.h before compiz.h so that
+ IMAGE_BYTE_ORDER is defined correctly. (bnc 178171)
+
+ * include/compiz.h: Define LSBFirst, MSBFirst, IMAGE_BYTE_ORDER,
+ BITMAP_BIT_ORDER. (bnc 178171)
+
+2006-05-23 Dan Winship <danw@novell.com>
+
+ * plugins/switcher.c (switchToWindow): use ss->windows here as
+ well so that multiple activeNum==0 windows don't get skipped.
+ (switchTerminate): Remove the screen grab right away so that
+ keystrokes don't get dropped. bnc 177650
+ (switchPreparePaintScreen, switchPaintScreen,
+ switchDonePaintScreen): update for that
+
+2006-05-22 Dan Winship <danw@novell.com>
+
+ * src/window.c (moveResizeWindow): deal with both vertical and
+ horizontal struts; but not when moving a dock window
+
+ * plugins/switcher.c (switchHandleEvent): Check init_all binding
+ before init, so you can bind "<Alt>" to init_all and so end up
+ with "<Alt>Tab" being init_all rather than init (but with no way
+ to get "init"...). bnc 173376
+
+2006-05-21 David Reveman <davidr@novell.com>
+
+ * src/display.c (addDisplay): Select for button events on root windows.
+
+ * configure.ac: Bump version to 0.0.11.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Fix shadow
+ performance by separating the convolution filter into one vertical and
+ one horizontal pass.
+
+ * src/window.c (mapWindow): Give sync request on map another try, it
+ seems to be working now.
+
+ * src/window.c (addWindow): Allow XGetWindowAttributes to fail.
+ (bnc 173416).
+
+ * src/window.c (addWindow): Initialize managed to false. Set managed
+ to true if widows is viewable.
+
+ * src/event.c (handleEvent): Set managed to false when window
+ transitions to withdrawn state.
+ (handleEvent): Set managed to true when we get MapRequest.
+ (handleEvent): Constrain configure request if window is managed.
+
+ * include/compiz.h: Add "managed" variable that is true while
+ windows is managed.
+
+2006-05-19 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c (ICON_SIZE): Allow use of larger window icons.
+
+2006-05-18 Dan Winship <danw@novell.com>
+
+ * plugins/wobbly.c (WOBBLY_FOCUS_DEFAULT): Set this to "None" to
+ match wobblyInitScreen() so that it actually works right.
+
+ * plugins/compiz.schemas.in.in: regen
+
+2006-05-18 Dan Winship <danw@novell.com>
+
+ * src/session.c (saveYourselfCallback): if we have a
+ RestartCommand registered with the session manager, update the
+ --sm-client-id in it to match the id we were assigned. bnc 176746
+
+ * src/main.c (main, usage): remove unused --sm-save-file arg and
+ fix documentation of --sm-client-id.
+
+2006-05-17 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas.in.in: Regen (Overlay Icon).
+
+ * plugins/switcher.c (switchPaintScreen): Don't remove switcher
+ from window list, just temporarily mark it as destroyed. This fixes
+ issue with switcher decorations disappearing when some window is
+ unmapped.
+
+ * src/screen.c (updateDefaultIcon): width and height should be
+ unsigned.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Add minimal
+ option that can be used to run g-w-d with drop-shadows but without full
+ window decorations.
+
+ * plugins/minimize.c (minHandleEvent): Restore window position
+ when transitioning to withdrawn state.
+
+ * plugins/scale.c: Remove next_window binding and fix so that arrow
+ keys can be used to select window.
+ Focus new window when pointer enter window decorations and sloppy focus
+ is used.
+ Remove scaleSelectWindow.
+
+ * plugins/scale.c: Icon support (Nat Friedman).
+
+2006-05-17 Dan Winship <danw@novell.com>
+
+ * src/display.c (handleSelectionClear, eventLoop): don't process
+ exit-on-selection-clear until the event queue is empty, or else
+ MapRequest and ConfigureRequest events could get lost. bnc 175558
+
+2006-05-14 David Reveman <davidr@novell.com>
+
+ * src/event.c (handleEvent): mapNum might be 0 if we found the window
+ unmapped when trying to bind it to a texture.
+
+2006-05-12 David Reveman <davidr@novell.com>
+
+ * src/screen.c (enterShowDesktopMode): Only go into show desktop mode
+ when some window is being hidden.
+
+ * src/event.c (handleWindowDamageRect): Make sure placed is set to true
+ when no plugin is doing placement.
+ (handleEvent): Don't set WM_STATE on override redirect windows.
+
+ * plugins/switcher.c (isSwitchWin): Don't show windows that ask not to
+ be in tasklists.
+
+ * plugins/rotate.c (rotateHandleEvent): Only adjust viewport if window
+ has been placed.
+
+ * plugins/minimize.c (minHandleEvent): Reset everything when going
+ into withdrawn state.
+
+ * src/window.c (moveResizeWindow): Handle west and north gravity
+ correctly.
+
+2006-05-11 David Reveman <davidr@novell.com>
+
+ * src/display.c (addDisplay):
+ * src/screen.c (addScreen): Move server grab to addDisplay to make
+ sure that no windows are created between XSelectInput and XQueryTree
+ as that would result in them being added two times.
+
+ * src/window.c (moveResizeWindow): Fix typo, CWY should be CWX.
+ (moveResizeWindow): Constrain Y position so that window titlebar is
+ visible.
+ (restoreWindowGeometry): Fix issue with going from maximized state
+ to non-maximized state without changing the window size.
+
+ * gnome/window-decorator/gnome-window-decorator.c
+ (max_window_name_width): Make sure title text fit in titlebar.
+
+2006-05-11 Dan Winship <danw@novell.com>
+
+ * plugins/gconf-compiz-utils.c (gconfStringToBinding): Treat "" as
+ meaning "disabled"
+
+2006-05-11 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c (action_menu_map):
+ Don't show window action menu on desktop and dock windows.
+
+ * src/event.c (handleEvent): Allow click on window decorations
+ to trigger window action menu.
+
+ * plugins/place.c (placeWindow): Place fullscreen and maximized
+ windows correctly.
+ (placeWindow): Only clip dialog position to screen if parent is
+ visible in current viewport.
+
+2006-05-09 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c (switchPaintThumb): Rearrange code so we handle
+ the case when bindWindow fails.
+
+ * src/paint.c (paintWindow): Bail out if window is not mapped.
+
+ * src/window.c (bindWindow): Make sure window is mapped when
+ getting the window pixmap. (bnc 173248)
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * plugins/cube.c (CUBE_MIPMAP_DEFAULT): Enable by default as
+ performance seem to be OK now when new mipmaps are only generated
+ when necessary.
+
+ * src/texture.c (enableTexture): Don't generate new mipmaps
+ every time the texture is used.
+
+2006-05-08 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c: Allow switcher to be initiated with prev
+ bindings. (Quinn Storm)
+
+2006-05-07 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas.in.in: Regen.
+
+ * plugins/switcher.c: Add icon support, minimized windows support
+ and allow switcher to show up when only one selectable window exist.
+
+ * images/Makefile.am: Add default icon image.
+
+ * include/compiz.h:
+ * src/texture.c:
+ * src/event.c (handleEvent):
+ * src/screen.c:
+ * src/display.c:
+ * src/window.c: Add WM icon interface.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Compute
+ switcher title text width correctly.
+
+ * src/event.c (handleEvent): Insert windows correctly when
+ reparenting.
+
+2006-05-07 Dan Winship <danw@novell.com>
+
+ * configure.ac: Add --with-scale-corner option and make
+ compiz.schemas reflect it; the best corner to use depends on where
+ the panels are and what's on them, so distros will want to
+ override this to match their default panel layout.
+
+ * src/event.c (eventMatches): Fix the the "water plugin gets
+ mysteriously activated when activating some other keybinding" bug.
+
+2006-05-05 Dan Winship <danw@novell.com>
+
+ * Makefile.am:
+ * autogen.sh:
+ * configure.ac: require intltool for option-description
+ translation
+
+ * plugins/Makefile.am: translate compiz.schemas.in into
+ compiz.schemas
+
+2006-05-05 Dan Winship <danw@novell.com>
+
+ * src/display.c (COMMAND_OPTION): Put numbers into the shortDescs
+ of the command and run_command options
+
+ * plugins/wobbly.c (WOBBLY_SNAP_MODIFIERS_DEFAULT): Use Shift
+ rather than Control, for consistency with Metacity, and to remove
+ the ambiguity about whether Ctrl+Alt+Button1 should be "grab cube"
+ or "move with snapping". (bnc 169402)
+
+ * plugins/compiz.schemas: regen
+
+2006-05-05 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas: Regen.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Forward
+ metacity's bell settings to compiz.
+
+ * plugins/water.c:
+ * plugins/wobbly.c:
+ * plugins/fade.c: Add visual bell.
+
+ * include/compiz.h:
+ * src/display.c: Add audible bell option.
+
+2006-05-04 David Reveman <davidr@novell.com>
+
+ * src/window.c (getModalTransient): Avoid infinite recursion when more
+ than one group transient got modal state.
+
+2006-05-03 David Reveman <davidr@novell.com>
+
+ * plugins/move.c:
+ * plugins/resize.c (resizeHandleMotionEvent): Don't constrain the
+ cursor.
+
+ * plugins/rotate.c (rotateHandleEvent): Use defaultViewportForWindow
+ to figure out which viewport we should move to. (bnc 152677)
+
+ * src/window.c (addWindowSizeChanges): Offset x coordinate with
+ default viewport coordinate. (bnc 171465)
+ (updateWindowAttributes): Always add windows size changes. (bnc 171465)
+
+ * include/compiz.h:
+ * src/window.c (defaultViewportForWindow): Add defaultViewportForWindow
+ function that computes the default viewport for a window.
+
+2006-05-02 David Reveman <davidr@novell.com>
+
+ * plugins/cube.c (cubePaintTransformedScreen): Bump up size a bit more
+ to make sure the cube unfolds completely.
+
+ * src/event.c (handleEvent): Not constraints should be applied to
+ ConfigureRequests for withdrawn windows. (bnc 171143)
+
+ * src/window.c (syncWindowPosition): We never need to send synthetic
+ ConfigureNotify events as we're not reparenting windows.
+
+2006-05-02 Dan Winship <danw@novell.com>
+
+ * plugins/gconf-dump.c: rewrite to make compiz.schema regeneration
+ a little easier, and to make it possible to generate schema files
+ for third-party plugins. Include plugin descriptions and
+ dependency information in the schema.
+
+ * plugins/Makefile.am: add a rule to generate compiz.schemas
+
+ * plugins/compiz.schemas: regen
+
+ * plugins/cube.c, plugins/decoration.c, plugins/fade.c,
+ plugins/gconf.c, plugins/minimize.c, plugins/wobbly.c:
+ s/expose/scale/ in dependencies
+
+2006-05-02 David Reveman <davidr@novell.com>
+
+ * include/compiz.h:
+ * configure.ac: Don't require glproto, include necessary enums in
+ compiz.h.
+
+ * src/texture.c:
+ * include/compiz.h: Update to latest EXT_tfp spec. Requires an
+ X server that has also been updated.
+
+ * configure.ac: Require glproto >= 1.4.7 with final EXT_tfp tokens.
+
+2006-05-01 David Reveman <davidr@novell.com>
+
+ * src/window.c (circulateWindow):
+ * src/event.c (handleEvent): Use getTopWindow instead of
+ reverseWindows->id as reverseWindows might be a destroyed window.
+
+ * include/compiz.h:
+ * src/screen.c: Add getTopWindow function that returns top window.
+
+2006-04-30 David Reveman <davidr@novell.com>
+
+ * plugins/compiz.schemas: Regen.
+
+ * plugins/decoration.c (decorWindowUpdate): Don't decorate fullscreen
+ windows.
+
+ * plugins/cube.c: Add initial support for unfolding the cube. Default
+ key-binding is <Control><Alt>Down.
+
+ * plugins/rotate.c (rotateHandleEvent): Fix absolute rotation.
+
+ * plugins/switcher.c: Fix so that bring-to-front doesn't change
+ the actual stacking order.
+ Add zoom option, enable it by default so it gets some testing.
+ Made bring-to-front enabled by default as it makes zoom functionality
+ more useful.
+ Made switcher window always rendered above all other windows and
+ not affected by screen transformations.
+
+ * src/event.c (handleEvent): Send configure notify before mapping
+ window if PPosition or USPosition is set.
+
+ * src/screen.c (insertWindowIntoScreen): Sibling above doesn't have to
+ be mapped. This change seem to currently by causing the
+ stacking order of some override-redirect windows to be incorrect.
+ Don't insert window when aboveId doesn't match an existing window.
+ (removeScreenGrab): ifdef DEBUG around abort.
+
+ * src/event.c (handleEvent): Only update active window property
+ when it's changing.
+
+ * src/window.c (sendConfigureNotify): Make sure the latest
+ window attributes are put in the ConfigureNotify.
+ (moveResizeWindow): Only send sync request if window is mapped.
+
+ * plugins/rotate.c: Add support for edge-flipping when using
+ drag-and-drop. Remove edge_flip and flip_move options and add
+ edge_flip_pointer, edge_flip_move, edge_flip_dnd.
+
+ * src/screen.c:
+ * src/display.c:
+ * include/compiz.h:
+ Make screen edges drag-and-drop aware.
+
+ * plugins/zoom.c:
+ * plugins/water.c:
+ * plugins/switcher.c:
+ * plugins/scale.c:
+ * plugins/rotate.c:
+ * plugins/resize.c:
+ * plugins/move.c:
+ * src/scren.c:
+ * include/compiz.h:
+ Variable argument list to otherScreenGrabExist, last argument must
+ be 0.
+
+ * src/event.c:
+ * src/display.c:
+ * include/compiz.h: Add raise-on-click option.
+
+ * gnome/window-decorator/gnome-window-decorator.c (title_event):
+ Activate window when clicking titlebar.
+
+2006-04-28 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c: Back out last change
+ as it clearly didn't fix anything. XFixed being defined as "int"
+ is perfectly fine of course. libXrender is currently broken on 64bit.
+ See Bug #6774 for a fix.
+ (XRenderSetPictureFilter_wrapper): Add workaround for 64bit
+ issue in libXrender. (Dan Winship)
+
+ * src/event.c (handleEvent):
+ * src/display.c:
+ * include/compiz.h:
+ Add show desktop binding. (Martin Szulecki)
+
+ * plugins/rotate.c: Reset timout handle correctly.
+
+ * plugins/move.c:
+ * plugins/resize.c:
+ * plugins/rotate.c:
+ * plugins/scale.c:
+ * plugins/switcher.c:
+ * plugins/water.c:
+ * plugins/zoom.c: Track screen grab changes changes.
+
+ * src/screen.c:
+ * include/compiz.h: Associate all screen grabs with a name. Add
+ otherScreenGrabExist function which can be used to check if screen
+ is grabbed by other plugins.
+
+2006-04-28 Dan Winship <danw@novell.com>
+
+ * src/event.c (eventMatches): new method that replaces EV_KEY and
+ EV_BUTTON. Tests if an event matches a binding, being more precise
+ about modifier state than EV_KEY and EV_BUTTON were.
+ (eventTerminates): Tests if an event is "the opposite" of a
+ binding. (Eg, button or modifier key release.) Replaces
+ CompReleaseMask and "terminate" bindings.
+ (handleEvent): Use eventMatches
+
+ * src/screen.c (addPassiveKeyGrab, removePassiveKeyGrab,
+ updatePassiveKeyGrabs): When passed a keybinding containing just
+ modifiers, grab/ungrab every keypress event that would result in
+ that modifier state (eg, both left and right modifier keys, and
+ allow them to be pressed in any order).
+
+ * src/display.c: Remove CompPressMask from default bindings.
+ (eventLoop): don't add virtual modifiers to event state.
+ (updateModifierMappings): store the XModifierKeymap for later
+ use.
+
+ * plugins/*.c: Use eventMatches and eventTerminates. Remove
+ CompPressMask and "terminate" bindings (except from scale, which
+ is different from the others).
+
+ * plugins/switcher.c: Make initiate_all be just the modifier key
+ used in addition to the initiate binding ("<Control>"). Remove
+ next_window since it doesn't make a lot of sense to have it be
+ different from initiate_all, and make prev_window be just a
+ modifier key as well. ("<Shift>").
+ (SwitchScreen): add extra options to store the fully-composed
+ initiate_all, prev, and prev_all bindings.
+ (switchScreenInitOptions, switchSetScreenOption): Generate and
+ regenerate initiate_all, prev, and prev_all bindings as needed.
+ (switchHandleEvent): update
+
+ * plugins/gconf-compiz-utils.c: Remove "<Release>" handling.
+
+ * plugins/compiz.schemas: regen, dropping the terminate bindings
+ and updating a few others.
+
+ * include/compiz.h: remove CompPressMask, CompReleaseMask,
+ EV_BUTTON, and EV_KEY. Add eventMatches, eventTerminates, and
+ keycodeToModifiers. Add modMap field to CompDisplay.
+
+2006-04-28 David Reveman <davidr@novell.com>
+
+ * plugins/water.c: Handle enter/leave notify events.
+
+ * plugins/decoration.c (decorInitWindow): Check for window specific
+ decoration on both mapped and unmapped windows so that initially
+ minimized windows get properly decorated. (Dan Winship)
+
+ * gnome/window-decorator/gnome-window-decorator.c: Use xfixed_16_16_t
+ instead of XFixed to avoid 64bit issue with XFixed being defined as
+ "int".
+
+ * configure.ac: xrender 0.8.4 is good enough.
+
+2006-04-27 Dan Winship <danw@novell.com>
+
+ * plugins/rotate.c (rotateHandleEvent): for the
+ rotate-to-specific-face keys, rotate counterclockwise when that's
+ faster. (bnc 169427)
+
+ * plugins/scale.c (scaleHandleEvent): Make the corners toggle
+ scale mode rather than only activating it. (bnc 169408)
+
+2006-04-27 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.10.
+
+ * plugins/decoration.c: Remove debug variable.
+
+ * src/window.c (addWindow): Check if window is minimized. (Dan Winship)
+
+ * plugins/compiz.schemas: Regen (snapoff and maximize_effect).
+
+ * plugins/wobbly.c: Add maximize effect.
+
+ * plugins/zoom.c:
+ * plugins/water.c:
+ * plugins/rotate.c:
+ * plugins/resize.c:
+ * plugins/move.c:
+ * src/event.c:
+ * src/screen.c:
+ * src/display.c:
+ * include/compiz.h: Add proper warp pointer interface and update
+ all plugins to use it.
+
+2006-04-26 Dan Winship <danw@novell.com>
+
+ * src/event.c (handleEvent): activate window on Button2 click in
+ addition to Button1 and Button3.
+
+ * plugins/gconf.c (gconfSetOption): gconf_value_compare against
+ the old value for list-type options too.
+ (gconfInitOption): Change the call to gconf_client_get_entry to
+ request the default value again; the fix to gconfSetOption will
+ prevent the infinite loops that happened before.
+
+2006-04-26 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c (update_shadow):
+ Remove comment that is no longer valid.
+
+ * plugins/move.c: Support for maximized windows snap-off. Based on
+ patch by Colin Guthrie.
+
+ * plugins/rotate.c (rotateHandleEvent): Don't do edge flipping
+ when a horizontally maximized or fullscreen window is grabbed.
+
+ * plugins/zoom.c:
+ * plugins/rotate.c:
+ * plugins/resize.c:
+ * plugins/move.c:
+ * src/screen.c:
+ * include/compiz.h: Add warpPointerToScreenPos and use it everywhere
+ we want to invisibly warp the pointer.
+
+2006-04-25 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c:
+ * plugins/decoration.c: Add clamp and min size.
+
+ * plugins/decoration.c (decorReleaseDecoration): Fix memory leak.
+
+ * plugins/scale.c: Click on background leaves scale mode and enters
+ show desktop mode. (Dan Winship)
+
+ * plugins/minimize.c (minHandleEvent): Initialize scale and
+ translate properly.
+
+ * src/window.c (activateWindow):
+ * src/event.c (handleEvent):
+ * src/screen.c: Add window parameter to leaveShowDesktopMode and
+ use this function for making one window leave show desktop mode.
+ Fixes so that we're leaving show desktop mode when no windows
+ are longer hidden.
+
+ * plugins/scale.c (scaleSetScreenOption): Add missing break statement.
+
+ * plugins/rotate.c (rotateInitScreen): Initialize rotateHandle.
+
+ * src/paint.c (paintScreen): Only paint windows that have been
+ damaged.
+
+2006-04-24 Dan Winship <danw@novell.com>
+
+ * plugins/scale.c:
+ * plugins/switcher.c: clarify the "initiate" descriptions
+
+ * plugins/compiz.schemas: regen
+
+2006-04-24 David Reveman <davidr@novell.com>
+
+ * src/paint.c (paintScreen): Always call paintWindow when window
+ is visible. Fixes so that window animations (fade, minimize...) aren't
+ paused when if window becomes invisible.
+ (paintWindow): Return early if region is empty.
+
+ * plugins/switcher.c: Use hideWindow and showWindow so that the
+ decoration doesn't have to be redrawn every time the switcher window
+ is mapped.
+
+ * src/window.c:
+ * include/compiz.h: Add hidden flag, that can be used to hide windows
+ without minimizing them.
+
+ * plugins/compiz.schemas: Regen (drop-shadow options).
+
+ * configure.ac: xrender 0.9, required for g-w-d.
+
+ * gnome/window-decorator/gnome-window-decorator.c:
+ * plugins/decoration.c: Add configurable drop-shadows. A minor issue is
+ that shadows around "tiny" windows are not rendered correctly when
+ large shadow offsets are used. Solution is to have the decorator set
+ a minimum size for which a decoration can be used so that no shadows
+ are rendered around "tiny" windows.
+
+2006-04-20 Dan Winship <danw@novell.com>
+
+ * plugins/rotate.c: add 12 go-directly-to-cube-face and 12
+ go-directly-to-cube-face-with-window bindings.
+
+ * src/display.c (compDisplayInitOptions): fix the binding type on
+ WINDOW_MENU.
+
+ * plugins/compiz.schemas: Regen. (lower_window, window_menu,
+ scale_image, images, resize, flip_move, move_window_types, and the
+ new rotate bindings)
+
+2006-04-20 David Reveman <davidr@novell.com>
+
+ * src/window.c:
+ * src/event.c (handleEvent):
+ * src/display.c:
+ * include/compiz.h:
+ * gnome/window-decorator/gnome-window-decorator.c: Add force quit
+ dialog.
+
+ * plugins/resize.c: Changed default binding to Button2.
+
+ * src/display.c (LOWER_WINDOW_BUTTON_DEFAULT): Button2 -> 6.
+
+ * gnome/window-decorator/gnome-window-decorator.c:
+ * include/compiz.h:
+ * src/event.c (handleEvent):
+ * src/display.c: Add window menu binding.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Pick up toolkit
+ actions from compiz and send gnome panel actions for "main menu" and
+ "run dialog" actions.
+
+ * src/event.c (handleEvent):
+ * src/screen.c:
+ * include/compiz.h:
+ * src/display.c (addDisplay): panel action -> toolkit action.
+
+ * src/window.c (getModalTransient): Group transient must not be an
+ ancestor to the window we've currently found as the window to focus.
+ (getModalTransient): Check for child modal transient.
+
+2006-04-19 David Reveman <davidr@novell.com>
+
+ * gnome/compiz-window-manager.c: Be nice to gnome-theme-manager
+ and return a theme even though we currently don't support it.
+
+ * include/compiz.h:
+ * src/main.c: Remove window-image option.
+
+ * include/compiz.h:
+ * plugins/water.c:
+ * plugins/cube.c:
+ * src/texture.c:
+ * src/paint.c:
+ * src/main.c: Add strict-binding option.
+
+2006-04-18 Dan Winship <danw@novell.com>
+
+ * src/event.c (handleEvent): Fix a crasher in the screenshot
+ binding code (and rename some of the #defines to make them not so
+ ridiculously long). Also temporarily hack around a bug in EV_KEY
+ by putting the check for WINDOW_SCREENSHOT before the check for
+ SCREENSHOT.
+
+ * plugins/scale.c: Change the keybinding again, now to "Pause".
+ (F11 is the "fullscreen mode" binding for many apps.)
+
+ * plugins/compiz.schemas: update
+
+ * plugins/gconf.c:
+ * plugins/gconf-compiz-utils.c:
+ * plugins/gconf-dump.c: Rearrange #includes to prevent warning
+ about TRUE and FALSE being redefined
+
+2006-04-18 David Reveman <davidr@novell.com>
+
+ * plugins/rotate.c (ROTATE_FLIPMOVE_DEFAULT): Changed to TRUE.
+
+ * src/window.c (recalcWindowActions): Remove maximize and fullscreen
+ actions when resizing isn't allowed.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Dynamic positioning
+ of window buttons.
+
+ * plugins/cube.c (readSvgToTexture): Fix typo.
+
+ * plugins/resize.c: Constrain cursor movement to min/max window size.
+
+ * src/window.c (constrainNewWindowSize): Fix aspect ratio calculations.
+
+2006-04-17 David Reveman <davidr@novell.com>
+
+ * plugins/cube.c: Put PNG on top face by default.
+
+ * images/Makefile.am: Remove window.png.
+ Add novell.png.
+
+ * include/compiz.h:
+ * src/readpng.c: Add openImageFile.
+
+ * plugins/cube.c: Support for PNGs on top face.
+ Add scale image option which is used to determine if top face
+ image should be scaled or not.
+
+2006-04-15 David Reveman <davidr@novell.com>
+
+ * plugins/wobbly.c: Add modal dialog type to default list of windows
+ that should be wobbly when moved.
+
+ * plugins/water.c (SET): +1 for border.
+
+2006-04-14 Dan Winship <danw@novell.com>
+
+ * plugins/gconf-dump.c: add "water" to gconfDeps
+
+ * plugins/compiz.schemas: regen including the water options
+
+2006-04-14 David Reveman <davidr@novell.com>
+
+ * src/event.c (handleWindowDamageRect): Ignore damage from windows
+ that aren't redirected.
+
+ * include/compiz.h:
+ * src/window.c:
+ * src/display.c (eventLoop):
+ * src/screen.c: Add support for automatic unredirecting of fullscreen
+ windows.
+
+ * plugins/scale.c (scaleInitiate): Layout thumbnails before we
+ grab the screen to make sure some window exist.
+
+ * plugins/resize.c: Allow 4-way resize. (Mike Hearn)
+
+2006-04-13 Dan Winship <danw@novell.com>
+
+ * src/screen.c (panelAction): take a timestamp and pass that to
+ the panel rather than using CurrentTime
+
+ * src/event.c (handleEvent): update for that
+
+ * src/window.c (moveResizeWindow): fix the gravity handling so
+ self-resizing windows don't dance (although I'm pretty sure this
+ is a symptom of mishandling gravity somewhere else).
+
+ * plugins/gconf.c (gconfInitOption): Request the default value of
+ the key from gconf, rather than initializing the key to the
+ internal default value if it hasn't yet been set by the user.
+ Notably, this makes it so that "compiz gconf" on a new account
+ will use the default value of active_plugins rather than the
+ (effectively empty) list of plugins on the command line. (It also
+ makes it so that the sysadmin can override defaults via sabayon or
+ whatever.)
+
+2006-04-13 David Reveman <davidr@novell.com>
+
+ * src/window.c (mapWindow): Maybe not, disable it again. :(
+
+ * src/window.c (mapWindow): Enable draw synchronization on map
+ again. Should be working correctly with CVS version of X server.
+
+2006-04-12 Dan Winship <danw@novell.com>
+
+ * src/window.c (moveResizeWindow): move duplicated code from
+ _NET_MOVERESIZE_WINDOW and ConfigureRequest handlers in event.c to
+ here, and handle gravity as well. (Fixes bnc 163058.)
+ (updateWindowAttributes): Do nothing if the window is
+ override_redirect (and remove a few now-redundant checks of that
+ elsewhere). Previously we were forgetting to check
+ !override_redirect in the case where the motif hints changed. (bnc
+ 163931)
+ (getWindowUserTime): fix a cut-and-paste-o that caused a crash on
+ 64bit machines.
+
+ * src/event.c (handleEvent): fix the _NET_MOVERESIZE_WINDOW bit
+ manipulation to correspond to what the EWMH means rather than what
+ it says, and use moveResizeWindow for that and for
+ ConfigureRequest.
+
+ * plugins/gconf-compiz-utils.c (gconfBindingToString): DTRT with
+ "None" bindings.
+
+ * gnome/window-decorator/gnome-window-decorator.c (title_event):
+ if the user right-clicks on the titlebar while the context menu is
+ popped up, just pop it down and eat the click, like all other
+ GNOME context menus do.
+ (style_changed, value_changed): Don't add decorations to
+ previously-undecorated windows. (bnc 165393)
+
+2006-04-11 David Reveman <davidr@novell.com>
+
+ * src/screen.c (addScreen): Fix typo.
+
+2006-04-10 Dan Winship <danw@novell.com>
+
+ * src/window.c (focusWindowOnMap): new function to decide whether
+ or not to focus a newly-mapped window. In addition to the old
+ checks, this also checks that _NET_WM_USER_TIME isn't 0, to allow
+ a window to explicitly request to not get focus.
+
+ * src/event.c (handleEvent): use focusWindowOnMap when processing
+ MapRequest.
+
+ * plugins/rotate.c (rotateHandleEvent): fix _NET_ACTIVE_WINDOW
+ handling so this doesn't interfere with focusable panel applets.
+
+ * plugins/compiz.schemas: regen (fixing cube top/bottom color)
+
+ * plugins/gconf-dump.c: Handle CompOptionTypeColor.
+
+ * configure.ac: Add --enable-gconf-dump so that the gconf-dump
+ plugin doesn't get built in normal builds
+
+ * plugins/Makefile.am: make gconf-dump optional.
+
+2006-04-09 Dan Winship <danw@novell.com>
+
+ * plugins/gconf-dump.c: add plugin options, and add information
+ about restrictions (numeric ranges, specific string values) to the
+ long description. Make gconf-dump refuse to run if gconf is
+ running (since you want the defaults it writes out to be coming
+ from the defaults in the source code, not from any gconf
+ overrides).
+
+ * plugins/compiz.schemas: regen
+
+ * plugins/gconf.c (gconfGetOptionValue): don't call gconfSetOption
+ from here, or we'll get an infinite loop when anything changes
+
+2006-04-09 David Reveman <davidr@novell.com>
+
+ * include/compiz.h:
+ * src/display.c:
+ * src/main.c:
+ * src/screen.c:
+ * src/texture.c:
+ * src/window.c: Remove test mode.
+
+ * plugins/Makefile.am: Remove schema from CLEANFILES.
+
+ * plugins/compiz.schemas:
+ * src/display.c:
+ Improve documentation for runcommand keys slightly. (Mike Hearn)
+
+ * include/compiz.h:
+ * src/texture.c:
+ * src/screen.c (addScreen): Switch to using GLX 1.3 functions.
+ (James Jones)
+
+ * src/main.c: Indirect rendering option. (James Jones)
+
+2006-04-08 David Reveman <davidr@novell.com>
+
+ * plugins/water.c: Add rain delay option. (Emilie Roberts)
+
+2006-04-07 David Reveman <davidr@novell.com>
+
+ * plugins/gconf-dump.c: Dump list options correctly.
+
+ * plugins/rotate.c: Add flip_move option, edge flipping is only
+ used when moving windows if this option is enabled.
+ (rotateHandleEvent): Make we don't rotate when some other plugin
+ has grabbed the screen.
+
+ * plugins/scale.c: Change default key-binding to F11.
+ (scaleInitiate): Make sure screen isn't grabbed by some other plugin.
+ (scaleInitScreen): Initialize darkenBack properly.
+
+ * configure.ac: Bump version to 0.0.9.
+
+ * plugins/Makefile.am (CLEANFILES, EXTRA_DIST): Fix.
+
+ * plugins/rotate.c (ROTATE_SPEED_DEFAULT): 1.5.
+
+2006-04-07 Dan Winship <danw@novell.com>
+
+ (Much of this patch was written by Radek Doulik
+ <rodo@novell.com>.)
+
+ * src/display.c:
+ * src/event.c:
+ * src/screen.c: Move keybinding stuff to CompDisplay, making it no
+ longer settable per-screen. Add bindings for screenshots (for
+ compatibility with metacity, which handles that keybinding in
+ GNOME for historical reasons).
+
+ * include/compiz.h: add an explicit CompBindingTypeNone rather
+ than relying on modifiers==0 to mean none. Update bindings stuff.
+
+ * src/screen.c (removePassiveKeyGrab, removePassiveButtonGrab):
+ Fix these to remove the right grab rather than always removing the
+ most-recently-added one.
+ (addScreenBinding): deal with CompBindingTypeNone
+
+ * plugins/gconf-dump.c: hacky plugin to dump information about the
+ other plugins to a gconf schemas file (used to regenerate
+ compiz.schemas)
+
+ * plugins/gconf-compiz-utils.c: shared code between gconf.c and
+ gconf-dump.c
+
+ * plugins/Makefile.am: add gconf-dump plugin and compiz.schemas,
+ and code to install compiz.schemas.
+
+ * configure.ac: Update gconf test to set macros needed for schema
+ install.
+
+2006-04-07 David Reveman <davidr@novell.com>
+
+ * plugins/rotate.c: Add edge flipping support.
+
+ * plugins/scale.c: Allow corner screen edges to be used for
+ initiating scale mode.
+
+ * src/option.c (compSetBoolOption): Only return TRUE if value changed.
+
+ * src/screen.c:
+ * src/window.c:
+ * plugins/minimize.c:
+ * plugins/decoration.c:
+ * include/compiz.h: Add immediate argument to MoveNotify, immediate
+ means that any animations should be avoided.
+
+ * src/screen.c:
+ * plugins/water.c:
+ * plugins/resize.c:
+ * plugins/place.c:
+ * plugins/move.c:
+ * plugins/zoom.c:
+ * plugins/rotate.c:
+ * plugins/scale.c:
+ * src/event.c:
+ * include/compiz.h:
+ Add previous pointer position that can be shared between multiple
+ plugins.
+
+2006-04-06 David Reveman <davidr@novell.com>
+
+ * include/compiz.h:
+ * src/screen.c: Add screen edges and simple interface for enabling
+ and disabling them.
+
+ * plugins/switcher.c (switchDamageWindowRect)
+ (switchWindowRemove): Update switcher list even when screen isn't
+ grabbed.
+
+ * plugins/switcher.c (switchDamageWindowRect):
+ * include/compiz.h:
+ * src/event.c (handleEvent):
+ * src/window.c: Made it possible to select if window should be
+ stacked above fullscreen windows or not.
+
+ * src/window.c (findSiblingBelow): Only find a fullscreen sibling
+ if aboveFs is TRUE.
+ (activateWindow): Allow stacking of window above fullscreen windows
+ when being activated.
+
+2006-04-05 David Reveman <davidr@novell.com>
+
+ * plugins/water.c (fboEpilogue): Reset raster position. Avoids
+ an FBO/raster-position issue found in newer nvidia drivers.
+
+ * plugins/move.c: Add constrain_y option that constrains window
+ movement so that top of window is always visible (on by default).
+
+ * src/event.c (handleEvent): Change active window property even though
+ it's not different than the window we currently have as active.
+
+ * src/window.c (moveInputFocusToWindow): Set focus even though
+ the window is considered the active window.
+
+2006-04-03 David Reveman <davidr@novell.com>
+
+ * plugins/water.c: Use char everywhere instead.
+ Fix offset direction (P-a Bäckström).
+ Add offset scale option.
+
+ * plugins/water.c: (loadFragmentProgram): GLubyte -> const GLbyte.
+ (loadWaterProgram): char -> GLbyte.
+ (loadBumpMapProgram): char -> GLbyte.
+ Use char everywhere.
+
+ * configure.ac: Bump version to 0.0.8.
+
+ * plugins/water.c: Add simple rain effect.
+ (loadFragmentProgram): Clear any previous error.
+
+ * src/display.c: Change so that timeouts are not only triggered
+ when we're idle.
+
+2006-04-02 David Reveman <davidr@novell.com>
+
+ * plugins/water.c: Add scale and bias to normal so that light can be
+ computed correclty. Offset texture coordinates for nice refraction
+ effect. (P-a Bäckström)
+ (waterDrawWindowTexture): Add scaling after setting up texture
+ coordinate generation.
+ Fix up loading of bump map programs.
+ (softwareUpdate): Improve performance of software fall-back code a bit.
+ (waterDrawWindowTexture): Always use filter for when window is
+ transformed.
+
+ * plugins/gconf.c (gconfGetValue): Fix typo that caused color
+ parsing to be incomplete (Quinn Storm).
+
+2006-04-01 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c: Add "initiate all" binding which brings up the
+ switcher window with all mapped windows and "initiate" binding will
+ now bring up the switcher window with only the visible windows.
+
+2006-03-31 David Reveman <davidr@novell.com>
+
+ * plugins/minimize.c (minDamageWindowRect): Never leave windows
+ in scaled state.
+
+ * src/screen.c (moveScreenViewport): Move hidden windows as well.
+
+ * src/window.c (addWindow, activateWindow, hideWindow)
+ (showWindow):
+ * src/screen.c (enterShowDesktopMode, leaveShowDesktopMode):
+ * src/event.c (handleEvent):
+ * include/compiz.h: Fix up show desktop mode.
+
+ * plugins/water.c (fboVertices): return 1.
+
+2006-03-30 David Reveman <davidr@novell.com>
+
+ * src/texture.c (enableTexture): Always make sure mipmaps are up to
+ date when using GL_LINEAR_MIPMAP_LINEAR filter.
+
+2006-03-29 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c: Draw outline around
+ window title text and buttons instead of small shadow.
+
+ * src/event.c (handleEvent):
+ * include/compiz.h:
+ * src/window.c: Set allowed window actions more correctly.
+
+ * plugins/move.c: Add opacity option.
+
+ * plugins/Makefile.am: Add water plugin. It's not very useful yet
+ and it needs more work but it's a good example of how to use
+ GL_ARB_fragment_program and GL_EXT_framebuffer_object for visual
+ effects.
+
+ * src/screen.c (addScreen): Fix light position.
+
+ * src/paint.c (paintWindow):
+ * plugins/switcher.c (switchPaintThumb):
+ * plugins/decoration.c (decorPaintWindow):
+ * include/compiz.h: Make drawWindowTexture a screen function so that
+ plugins can wrap it.
+
+ * src/texture.c (enableTexture):
+ * src/screen.c (addScreen):
+ * include/compiz.h: GL_EXT_framebuffer_object and
+ GL_ARB_fragment_program support.
+
+2006-03-21 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c (lower_window): Don't
+ try to lower a window below hidden windows or desktop windows.
+
+2006-03-20 David Reveman <davidr@novell.com>
+
+ * plugins/wobbly.c (wobblyHandleEvent):
+ xunmap -> xmap (François Ingelrest).
+
+ * src/screen.c (isClientListWindow): All type of windows should go into
+ the client lists (Thanks to Quinn Storm).
+
+ * src/window.c (freeWindow): Destroy frame window.
+ (mapWindow): Fix so the sync requests are sent correctly when a window
+ is mapped but disable it for now as it seems to be causing problems
+ with some applications.
+ (recalcWindowActions): Allow dialog window actions on util and
+ toolbar windows.
+
+ * src/event.c (handleEvent): Remove event mask and button grabs
+ when window is reparented.
+ (handleEvent): Update client list when window type changes.
+ (handleEvent): Use constrainNewWindowSize on move/resize client
+ messages and configure requests.
+
+ * gnome/window-decorator/gnome-window-decorator.c (window_closed):
+ Delete decor property when window is closed.
+
+2006-03-17 Jeremy C. Reed <reed@reedmedia.net>
+
+ reviewed by: David Reveman
+
+ * autogen.sh:
+ Be consistent with rest of modular xorg by using same
+ autogen.sh. This allows it to be run using a different
+ work directory.
+
+2006-03-17 Jeremy C. Reed <reed@reedmedia.net>
+
+ reviewed by: David Reveman
+
+ * INSTALL:
+ Mention startup-notification requirement.
+
+2006-03-17 David Reveman <davidr@novell.com>
+
+ * plugins/scale.c: Add opacity option.
+
+ * configure.ac: Bump version to 0.0.7.
+
+2006-03-17 Radek Doulik <rodo@novell.com>
+
+ * src/session.c: added all mandatory SM client callbacks, handle
+ ICE connection and process ICE messages
+
+ * src/display.c (compAddWatchFd): new function, adds new fd watch
+ - for poll io multiplexing
+ (compRemoveWatchFd): new function, remove fd watch added by
+ compAddWatchFd
+ (doPoll): new helper function, does call poll and calls callbacks
+ for watch fd's. returns the value of poll call
+ (eventLoop): use doPoll, we use NULL for display fd watch so that
+ it doesn't call anything and just use return value from poll as
+ before
+
+2006-03-17 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c (switchDamageWindowRect): Update window
+ attributes for popup window. We never get a MapRequest for this
+ window so it most be done here.
+ Add "bring to front" option. (Greg)
+
+ * src/window.c (stackAncestors): Never raise desktop windows.
+ Made restackWindowAbove and restackWindowBelow smarter.
+
+2006-03-16 David Reveman <davidr@novell.com>
+
+ * plugins/minimize.c:
+ * src/event.c (handleEvent):
+ * src/window.c:
+ Handle window state changes correctly.
+ (maximizeWindow): Use actions to determine if we're allowed maximize
+ window.
+
+ * src/event.c (handleEvent):
+ * src/window.c: Send configure notifies correctly.
+
+2006-03-15 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c (switchPaintWindow): Fix paint attribute
+ calculations.
+
+ * include/compiz.h:
+ * src/event.c (handleEvent):
+ * src/window.c: Add restackWindowBelow.
+
+2006-03-14 David Reveman <davidr@novell.com>
+
+ * plugins/switcher.c: Opacity, brightness and saturation as adjustable
+ options. (Greg)
+
+ * src/window.c (syncWindowPosition): Move frame window now instead of
+ waiting for client window to change before moving it.
+
+ * plugins/move.c (moveTerminate): Sync window position before
+ releasing pointer grab so that the EnterNotify event from the release
+ go to the correct window.
+
+ * src/window.c (unmapWindow): Put window in withdrawn state when
+ being unmapped. Should make it work better with KDE. (Tim Northover)
+
+ * src/screen.c (addScreen): Fix ambient and diffuse light.
+
+ * src/main.c (main): Add --version command line option.
+
+ * src/event.c:
+ * src/screen.c:
+ * include/compiz.h: Add bindings for changing window opacity.
+
+2006-03-14 Radek Doulik <rodo@novell.com>
+
+ * src/event.c (handleEvent): handle minimize/maximize/unmaximize
+ window keybindings
+
+ * src/screen.c: added minimize/maximize/unmaximize window
+ options/keybindings
+
+ * src/window.c (maximizeWindow): new helper function
+ (unmaximizeWindow): ditto
+
+2006-03-14 David Reveman <davidr@novell.com>
+
+ * plugins/scale.c: Add darken background option (Daniel G. Taylor).
+
+2006-03-13 David Reveman <davidr@novell.com>
+
+ * src/display.c (eventLoop):
+ * include/compiz.h:
+ * src/screen.c (addScreen): CopySubBufferMESA support.
+
+2006-03-07 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c (lower_window):
+ Remove unused variable tmp.
+
+ * src/event.c:
+ * src/display.c:
+ * src/window.c:
+ * src/screen.c:
+ * include/compiz.h: Better window stacking support.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Lower window
+ when clicking button 2 on titlebar.
+
+ * src/window.c (ensureWindowVisibility): Only ensure that window is
+ visible if it isn't a override redirect window, dock window or
+ window with struts.
+
+2006-03-06 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.6.
+
+ * plugins/cube.c: Skydome update. (MacSlow)
+
+ * src/window.c: Ensure window visibility when activating window.
+
+2006-03-05 David Reveman <davidr@novell.com>
+
+ * src/window.c (closeWindow): Use protocol mask to determine if
+ Client Message should be send or if we should kill the client.
+
+ * plugins/decoration.c: Don't draw shadow only decorations around
+ windows with alpha channel.
+
+2006-03-03 David Reveman <davidr@novell.com>
+
+ * src/texture.c (readImageBufferToTexture):
+ (readImageToTexture): Check that returnWidth and returnHeight are
+ not NULL.
+
+ * plugins/cube.c: Skydome support. Thanks to MacSlow.
+
+ * plugins/fade.c (fadeHandleEvent): Make sure opacity isn't opaque
+ when fading out.
+ Stop fading if window is resized.
+
+ * src/window.c (resizeWindow): Only verify pixmap size if window is
+ mapped.
+ (resizeWindow): Check XGetGeometry result.
+
+ * plugins/switcher.c: Make sure switcher is correctly updated
+ even though the previously selected window isn't selectable by
+ switcher.
+
+ * src/event.c (handleEvent): Avoid panel actions when screen is
+ grabbed.
+
+2006-03-03 Radek Doulik <rodo@novell.com>
+
+ * src/main.c (main): init and close session when sm is not
+ disabled. Enable sm by default.
+
+ * src/session.c: added minimal session support so that compiz at
+ least register with session manager to avoid registering timeouts
+
+2006-03-03 David Reveman <davidr@novell.com>
+
+ * src/screen.c (removeScreenGrab): Use correct cursor when changing
+ actvie pointer grab.
+
+2006-03-02 David Reveman <davidr@novell.com>
+
+ * plugins/rotate.c (rotateHandleEvent):
+ * plugins/zoom.c (zoomHandleEvent): Make sure no pending motion
+ notify events exists when warping the pointer.
+
+ * plugins/rotate.c (rotateHandleEvent): Reset movement.
+
+ * plugins/switcher.c: Always send activate request when selecting a
+ window.
+
+ * plugins/cube.c (cubePaintTransformedScreen): Reset color.
+
+ * plugins/switcher.c (switchPaintThumb): PAINT_WINDOW_TRANSLUCENT_MASK
+ if opacity isn't opaque.
+ (switchPaintWindow): Reset color.
+
+2006-03-01 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.5.
+
+ * plugins/fade.c (fadeAddDisplayModal): Higher brightness when showing
+ display modal dialogs.
+
+ * plugins/switcher.c (switchPreparePaintScreen): Continue adjusting
+ window selection even though we're not grabbing the screen.
+ (switchPaintWindow): Use last used paint attributes for thumbnails.
+ (switchPaintWindow): Use blending when drawing selection rectangle.
+
+ * plugins/fade.c (fadeHandleEvent): unmap. -> map.
+ (fadeDamageWindowRect): Only zero opacity if we're not already
+ fading the window.
+
+ * src/window.c (unmapWindow): 'placed' variable should be reset on
+ first call to unmapWindow.
+
+ * src/screen.c:
+ * src/event.c (handleEvent):
+ * src/display.c (eventLoop):
+ * include/compiz.h: Add slow animation option.
+
+ * src/window.c (recalcNormalHints): Constrain window dimensions to
+ max texture size.
+
+ * src/screen.c (addScreen): Get max texture size.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Nicer drop shadow
+ on windows without decorations.
+
+ * src/window.c (addWindow): Move initialization of sync alarm.
+
+ * plugins/cube.c:
+ * plugins/decoration.c:
+ (decorCreateDecoration): Fix minimum size check.
+
+ * src/main.c:
+ * include/compiz.h:
+ * src/paint.c:
+ * src/screen.c: Ligthing support.
+
+ * compiz.pc.in: Fix.
+
+2006-02-23 David Reveman <davidr@novell.com>
+
+ * src/window.c (unmapWindow): Not minimized and not part of showing
+ desktop mode.
+
+ * plugins/wobbly.c: Fix handling of scaled windows.
+ Update options so that user gets more control over which windows
+ that should wobble and when.
+
+ * configure.ac: Bump version to 0.0.4.
+
+ * gnome/window-decorator/gnome-window-decorator.c (window_opened): Make
+ sure decoration property for switcher window is set.
+
+ * plugins/decoration.c (decorHandleEvent):
+ * src/event.c (handleEvent):
+ * plugins/switcher.c:
+ * src/screen.c (addScreen, setScreenOption)
+ (compScreenInitOptions):
+ * src/texture.c:
+ * include/compiz.h: Mipmap support. Add more RUN_COMMAND options.
+
+2006-02-22 David Reveman <davidr@novell.com>
+
+ * src/display.c (realToVirtualModMask): Remove modifiers that should
+ be ignored.
+ (addDisplay): Select ButtonPress and ButtonRelease events on root
+ window.
+
+ * include/compiz.h (EV_KEY):
+ (EV_BUTTON): Modifiers should match exactly.
+
+ * plugins/switcher.c: Add binding for selecting previous window.
+
+ * plugins/decoration.c: Remove sync hack.
+
+ * gnome/window-decorator/gnome-window-decorator.c
+ (draw_shadow_background): Fix drawing of bottom and bottom right
+ shadow rectangle.
+ Add switcher window decorations.
+ Remove sync hack.
+ Always use double buffering.
+
+ * plugins/switcher.c: Remove background color option.
+ Use property instead of client message to indicate change of selected
+ window.
+
+2006-02-21 David Reveman <davidr@novell.com>
+
+ * plugins/cube.c (cubeHandleEvent): Only load new SVG when available.
+
+2006-02-20 David Reveman <davidr@novell.com>
+
+ * plugins/decoration.c (decorWindowUpdate): Decorate window
+ MwmDecorTitle is present.
+
+ * src/window.c (focusWindow):
+ (moveInputFocusToWindow):
+ Allow focusing windows with input hint set to false.
+ (activateWindow): Fix so that dock windows can be active.
+
+ * src/screen.c (isClientListWindow): Don't put destroyed windows in
+ client lists.
+
+ * src/event.c (handleEvent): Fix so that dock windows can be active.
+ (handleEvent): Avoid focusing windows with input hint set to false
+ when mapped.
+
+2006-02-18 David Reveman <davidr@novell.com>
+
+ * src/window.c (unmapWindow): Windows not being minimized should be
+ placed again at next map.
+
+ * plugins/wobbly.c (wobblyDonePaintScreen): Also add pending damage
+ if any window is in initial wobbly state.
+
+2006-02-17 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.3.
+
+ * plugins/zoom.c (zoomIn): Translate less.
+ (zoomPaintScreen): Use selected filter.
+ (adjustZoomVelocity): Made zoom animation nicer.
+ (zoomPreparePaintScreen): Don't zoom to much.
+ ADd filter selection option.
+
+ * plugins/decoration.c (decorPaintWindow):
+ * src/paint.c (drawWindowTexture): Use screen filters.
+
+ * include/compiz.h: Add support for adjusting filters.
+
+ * plugins/scale.c (scaleHandleEvent): Only button 1.
+
+ * plugins/cube.c (cubePaintTransformedScreen): Fix drawing with size
+ greater than 4.
+
+2006-02-16 David Reveman <davidr@novell.com>
+
+ * configure.ac: Remove menu.
+
+ * plugins/switcher.c (switchNextWindow): Damage new and previously
+ selected window.
+ (switchInitiate): Damage screen initiating switching.
+ (switchTerminate): Damage screen terminating switching.
+ (switchPaintThumb): Draw thumbnail without calling any function that
+ can be wrapped.
+
+ * gnome/window-decorator/gnome-window-decorator.c
+ (update_window_decoration_size): Make sure title isn't rendered
+ when it doesn't fit.
+
+2006-02-14 David Reveman <davidr@novell.com>
+
+ * gnome/window-decorator/gnome-window-decorator.c
+ (draw_window_decoration): Make sure complete icon is visible.
+
+ * src/display.c (eventLoop):
+ (getTimeToNextRedraw): Handle clock rollback.
+
+2006-02-13 David Reveman <davidr@novell.com>
+
+ * configure.ac: Remove menu plugin check.
+ Require version 2.8.0 or greater of gtk+.
+
+2006-02-11 David Reveman <davidr@novell.com>
+
+ * configure.ac: Bump version to 0.0.2.
+
+ * src/window.c:
+ * src/event.c:
+ * plugins/fade.c:
+ * src/display.c:
+ * include/compiz.h: Lower brightness of windows that are not responding
+ and all windows when showing logout dialog.
+
+ * gnome/window-decorator/gnome-window-decorator.c: Use metacity
+ titlebar font settings.
+
+ * gnome/compiz-window-manager.c: Add titlebar font setting.
+
+ * plugins/Makefile.am:
+ * plugins/switcher.c: Add switcher plugin.
+
+ * plugins/gconf.c: Add alpha to color options.
+
+2006-02-10 David Reveman <davidr@novell.com>
+
+ * src/screen.c:
+ * src/display.c: Do not include X11/extensions/Xevie.h.
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..6280c80
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1514 @@
+# Doxyfile 1.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Compiz
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 0.9
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = include/ src/
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = private*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS = _* *Private* *Wrap*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX = _,Private
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP)
+# there is already a search function so this one should typically
+# be disabled.
+
+SEARCHENGINE = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..fe1619a
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,12 @@
+compiz uses libstartup-notification which is available at
+ftp://ftp.gnome.org/pub/GNOME/sources/startup-notification/
+
+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/NEWS b/NEWS
new file mode 100644
index 0000000..40b06ec
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,457 @@
+Release 0.9.0 (2010-07-03 Sam Spilsbury <smspillaz@gmail.com>)
+==============================================================
+Development release.
+
+Rewritten core in C++.
+
+Rewritten plugin APIs.
+
+Rewritten buildsystem in CMake, supports option code autogeneration,
+plugin build dependency handling, amongst other things.
+
+Smart wrappable functions, enables saving on otherwise useless CPU cycles.
+
+Reparenting window decorations.
+
+Support for tiled textures and screen sizes larger than max_texture_size
+through the use of the copytex plugin.
+
+Composite and OpenGL based rendering dropped from core, split into the
+opengl and composite plugins, which represent a step towards pluggable
+rendering backends.
+
+Ability to run in non composited mode added to gtk-window-decorator
+and kde4-window-decorator.
+
+kde-window-decorator dropped.
+
+Added KDE plugin to integrate with the QT main loop and create a KApplication
+for KCrash support on KDE.
+
+dbus plugin now uses screen number to identify compiz instance.
+
+Dropped multi-screen mode, launch compiz on individual screens instead.
+
+Shape drawing mode added to annotate plugin.
+
+Fixed screen updates issue in annotate plugin.
+
+Added serialization interface, which allows plugins to save/restore activity
+states between plugin and compiz reloads. Serialization info is stored in
+X11 window properties and is automatically dropped by the X Server when
+the window is destroyed.
+
+Added compiztoolbox library plugin used by switchers and screenshot, which
+provide a simple interface for accessing XDG and drawing thumbnails.
+
+Release 0.8.6 (2010-03-28 Danny Baumann <dannybaumann@web.de>)
+==============================================================
+Maintenance release.
+
+Various focus and window placement fixes.
+
+Fixed handling of windows that have a (server-drawn) border.
+
+Fixed handling of window icons that have a colour depth of 1 bit.
+
+Added KDE 4.4 support to KDE4 window decorator.
+
+Release 0.8.4 (2009-10-14 Erkin Bahceci <erkinbah@gmail.com>)
+=============================================================
+Maintenance release.
+
+Fixed many crashes (including doPoll/eventLoop ones).
+
+Various memory leak fixes.
+
+Fixed lost window issues with windows that are visible on all workspaces.
+
+Fixed lost window issue when reducing the number of workspaces.
+
+Fixed placing of dialogs (e.g. PolicyKit) behind currently focused window.
+
+Fixed placing of new windows behind fullscreen window.
+
+Fixed and improved screen resolution change handling (Compiz now remembers
+original window size and position).
+
+Lowering a window now activates the topmost window when click-to-focus is on.
+
+Fixed wobbly title bar hiding and bouncing near panel edges.
+
+Screenshot plugin now saves to the correct desktop directory by default.
+
+Fixed inconsistent icon sizes in switcher plugin.
+
+Improved constraining of window size and position in move, resize, and wobbly.
+
+Ported KDE4 window decorator to KDE 4.3.
+
+Added support for _NET_REQUEST_FRAME_EXTENTS and _NET_SUPPORT_FULL_PLACEMENT
+EWMH hints.
+
+Release 0.8.2 (2009-03-01 Danny Baumann <dannybaumann@web.de>)
+==============================================================
+Maintenance release.
+
+Fixed issue in strut handling that could lead to struts being ignored
+for certain monitor configurations.
+
+Fixed window position constraining logic.
+
+Fixed kconfig xslt files missing from 0.8.0 tarball.
+
+Release 0.8.0 (2009-02-20 Danny Baumann <dannybaumann@web.de>)
+==============================================================
+Fourth stable release of compiz.
+
+New plugin "commands" that handles the bindings for arbitrary commands that
+previously were handled in core. In addition to the previously present key
+bindings button and edge bindings were added as well.
+
+New plugin "gnomecompat" which handles bindings that are exclusively used
+in the Gnome desktop environment and removed the corresponding bindings
+from core. This change fixes main menu and run dialog bindings for KDE users
+as those previously were conflicting between compiz and KDE. Gnome users
+upgrading should make sure to enable this plugin.
+
+Added support for _NET_WM_FULLSCREEN_MONITORS EWMH hint.
+
+Added support for reading the icon hint from the WM_HINTS property if
+_NET_WM_ICON is not available.
+
+Update Gnome support for Gnome 2.24.
+
+Added options to scale plugin that allow "toggle type" behaviour for
+key and button bindings.
+
+Several memory leak fixes.
+
+Adjusted gtk-window-decorator for newer libmetacity-private versions.
+
+Fixed gtk-window-decorator display for RTL languages.
+
+Adjusted kde4-window-decorator for KDE 4.2 API.
+
+Large number of minor bug fixes, especially in resize handling and
+stacking code.
+
+Translation updates
+
+Release 0.7.8 (2008-09-17 Danny Baumann <dannybaumann@web.de>)
+==============================================================
+Development release.
+
+New plugin "obs" that handles opacity, brightness and saturation bindings
+and matches.
+
+Put unresponsive window greyout, including options to configure it, to
+fade plugin.
+
+Add "constant fade time" fade mode to fade plugin.
+
+Removed opacity bindings and matches from core. Users that entered opacity
+matches should enable the obs plugin and enter the matches there.
+
+Enhanced timer infrastructure to allow synchronization of execution of
+multiple timer callbacks.
+
+Added matching for window's alpha channel (match type rgba=[0|1]).
+
+Reflect new Metacity "spacer" button type in gtk-window-decorator.
+
+Various bugfixes.
+
+Translation updates.
+
+Release 0.7.6 (2008-05-29 Dennis Kasprzyk <onestone@opencompositing.org>)
+=========================================================================
+Development release.
+
+Rewrite of place plugin, which significantly improves multi-output
+behaviour.
+
+Configurable multi-output behaviour in place.
+
+Removed plane plugin. Former plane plugin users are encouraged to use
+the wall plugin of Compiz Fusion.
+
+Removed cube wallpaper painting. Users are encouraged to use the Compiz
+Fusion wallpaper plugin instead.
+
+Place plugin viewport placement viewport numbers are now 1-based.
+
+Panel and desktop selection mode in switcher plugin.
+
+Improved painting behaviour when using overlapping outputs.
+
+Gtk-window-decorator now emits accessibility events when switching.
+
+Gtk-window-decorator behaviour when using Metacity themes has been
+improved to match Metacity better.
+
+KDE4-window-decorator has been adapted to current KDE4 API.
+
+Various bugfixes.
+
+Release 0.7.4 (2008-03-04 Dennis Kasprzyk <onestone@opencompositing.org>)
+=========================================================================
+Development release.
+
+Configurable handling of overlapping output devices.
+
+Enhanced focus stealing prevention with configurable amount of focus
+stealing prevention.
+
+Added configurable, optional delay for edge actions to prevent
+accidential invocation.
+
+Generalized vertex system to improve plugin compatibility.
+
+Optimized gaussian blur shaders to support more hardware.
+
+Improved unredirection of fullscreen windows.
+
+Several bugfixes.
+
+Translation updates.
+
+Release 0.7.2 (2008-03-06 Dennis Kasprzyk <onestone@opencompositing.org>)
+=========================================================================
+Development release.
+
+Several bugfixes
+
+Translation support in gtk-window-decorator.
+
+Updated translations.
+
+Added wrapable session functions to core. This allows to provide a full session save/restore in a plugin.
+
+Release 0.7.0 (2008-02-07 Dennis Kasprzyk <onestone@opencompositing.org>)
+=========================================================================
+Development release.
+
+A core plugin has been added that allows handling certain core APIs, such as
+querying the ABI version, similarly to plugin APIs, allowing sharing more
+code.
+
+Added a simple object system, which generalize the privates mechanism and the plugin system. It allows to share more code between display, screen and window objects. It also makes it possible to properly introduce new object types without changing the plugin interface or breaking the API.
+
+Multi-display support.
+
+Various fixes in ICCCM compliance, window stacking and focus handling.
+
+Validity checking of ConfigureRequest events.
+
+Fixes to transient children placement in place plugin.
+
+Hooks have been added to the cube plugin which allow better control of
+viewport drawing.
+
+Middle and right click actions have been made configurable in
+gtk-window-decorator.
+
+Gtk-window-decorator now optionally allows mouse wheel title bar actions, such
+as shading.
+
+A KDE4 port of the kde-window-decorator has been added.
+
+Frequent crashes of kde-window-decorator for some people have been fixed.
+
+
+Release 0.5.4 (2007-08-20 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+XCB is now required.
+
+Major improvements to option system that makes
+configuration backend integration much less complex.
+
+Kconfig plugin that provides proper KDE configuration
+support.
+
+Kcfg files are generated from the meta-data and they can
+be used to generate C++ source code that will provide an
+API for applications to access all compiz configuration
+data used by the kconfig plugin.
+
+
+Release 0.5.2 (2007-08-03 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+Better support for multiple X-screens.
+
+XML-based meta-data system for handling of various kinds
+for meta-data like plugin descriptions, default option
+values, etc.
+
+Major improvements to option initialization based on the
+new meta-data system.
+
+Logging framework.
+
+Support for configurable button layout in metacity themes
+has been added to gtk-window-decorator.
+
+Glib plugin that allows plugins that use the glib main
+loop to integrate properly with the compiz main loop
+without waking up periodically to check for pending
+events.
+
+Plugin plugins that make it possible to adjust and extend
+the behavior of existing plugins through new plugins.
+
+More dynamic handling of output devices, which allows the
+output device configuration used when rendering to be
+changed between frames.
+
+Transparency support in cube plugin.
+
+Introspection support in dbus plugin.
+
+
+Release 0.5.0 (2007-04-02 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+Remove stencil buffer requirement.
+
+Focus stealing prevention support.
+
+Blur plugin that provide support for blurring windows and
+contents behind translucent windows.
+
+Fragment attribute interface that allow plugins
+to perform more advanced fragment shading effects and
+integrate properly with other plugins.
+
+Extensible window matching interface and new option type
+that provide advanced window selection functionality.
+
+Plugin that provide a composited video interface for
+efficient video playback.
+
+FUSE plugin that maps compiz options to a file-system and
+allow efficient manipulation of options by reading and
+writing files.
+
+Better occlusion detection and more efficient rendering.
+
+Flat file configuration backend.
+
+
+Release 0.3.6 (2006-12-31 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+Add support for unredirect of fullscreen windows when using
+the composite overlay window and make usage of the
+composite overlay window for output default.
+
+Add file notification API.
+
+Add inotify plugin that implements file notification API.
+
+A "GetPlugins" method has been added to dbus plugin
+and it can be used to retrieve a list of available plugins.
+
+A 'GetPluginMetadata' method has been added to dbus plugin
+and it returns metadata for available plugins.
+
+Add support for switching between windows without having
+the thumbnail window show up.
+
+Switcher thumbnails now include decorations and shadows.
+
+Basic drag and drop support has been added to scale plugin.
+
+It's now possible to initiate scale plugin for specific window
+groups.
+
+Window menu icon support has been added to gtk window decorator.
+
+Improved support for metacity themes.
+
+Add KDE window decorator with support for shadows and opacity
+has been added.
+
+
+Release 0.3.4 (2006-11-21 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+Edge button, which can be used to require a button press
+for edge actions to be triggered.
+
+Basic compiz event support.
+
+Zoom plugin now works without "largedesktop" feature.
+
+Cube plugin now handles desktop width less than 4 times
+the screen better.
+
+Support for multiple desktops (workspaces).
+
+Handling of _NET_DESKTOP_GEOMETRY client messages has
+been fixed.
+
+Much better multi-head support.
+
+Annotate plugin has been added.
+
+Clone plugin which can be used to clone outputs in a
+convenient way has been added. Currently more of a
+prototype as we need randr++ and input transformation
+in the server to do this properly.
+
+Shadow color option has been added.
+
+initiate_all option has been added to scale plugin.
+
+Zoom factor option has been added to zoom plugin.
+
+Support for new metacity theme version and support for
+metacity versions < 2.15.21.
+
+Event window placement when using some metacity
+themes has been fixed.
+
+Fix a number of issues related to minimizing windows
+with transients.
+
+
+Release 0.3.2 (2006-10-20 David Reveman <davidr@novell.com>)
+============================================================
+Development release.
+
+snap_inverted option has been added to wobbly plugin.
+
+Configuration support has been added to dbus plugin.
+
+Add 'command' option has been added to decoration plugin,
+which can be used to automatically launch a decorator
+when one isn't already running.
+
+Opacity support for metacity themes.
+
+A raise_window option has been added.
+
+Decorations on maximized windows are now rendered
+correctly when using metacity themes.
+
+An ignore_hints_when_maximized option, which makes compiz
+ignore size increment and aspect hints for maximized
+windows has been added and made default.
+
+Better default option values for rotate plugin.
+
+and much more...
+
+
+Release 0.2.0 (2006-10-02 David Reveman <davidr@novell.com>)
+============================================================
+First official release of compiz.
+
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/RELEASING b/RELEASING
new file mode 100644
index 0000000..0c278c6
--- /dev/null
+++ b/RELEASING
@@ -0,0 +1,75 @@
+Here are the steps to follow to create a new compiz release:
+
+1) Ensure that there are no local, uncommitted modifications.
+ It's probably good enough if "git diff HEAD" doesn't output
+ anything and your "master" and "origin" branches are at the
+ current revision.
+
+2) Verify that the code passes "make distcheck"
+
+ Running "make distcheck" should result in no warnings or
+ errors and end with a message of the form:
+
+ ==============================================
+ compiz-X.Y.Z archives ready for distribution:
+ compiz-X.Y.Z.tar.gz
+ ==============================================
+
+ (But the tar file isn't actually ready yet, as we still have
+ some more steps to follow).
+
+3) Fill out an entry in the NEWS file
+
+ Shift through the logs since the last release. This is most
+ easily done with a comand such as:
+
+ git log --stat compiz-X.Y.Z..
+
+ where X.Y.Z is the previous release version.
+
+ Summarize major changes briefly in a style similar to other
+ entries in NEWS.
+
+4) Increment version number in configure.ac:
+
+ Increment to the micro version number to the next larger
+ (even) number.
+
+5) Commit the changes to NEWS and configure.ac
+
+ It's especially important to mention the new version number in your
+ commit log.
+
+6) Run "make release-publish" which will perform the following steps
+ for you:
+
+ * Check that the version number ends with an even micro component
+ * Check that no release exists with the current version
+ * Verify that make distcheck completes successfully
+ * Generate the final tar file
+ * Generate an sha1sum file
+ * Sign the sha1sum using your GPG setup (asks for your GPG password)
+ * scp the three files to appear on
+ http://xorg.freedesktop.org/archive/individual/app
+ * Place local copies of the three files in the releases directory
+ * Tag the entire source tree with a tag of the form compiz-X.Y.Z, and
+ sign the tag with your GPG key (asks for your GPG password, and you
+ may need to set GIT_COMMITTER_NAME and GIT_COMMITTER_EMAIL to match
+ your public-key's setting or this fails.)
+ * Provide some text for the release announcement (see below).
+ If for some reason you lost this message,
+ "make release-publish-message" prints it for you.
+
+7) Increment compiz_version_micro to the next larger (odd) number in
+ configure, commit, and push.
+
+8) Push the newly created tag out to the central tree with a command
+ something like:
+
+ git push compiz-X.Y.Z
+
+9) Send a message to compiz@list.freedesktop.org to announce the
+ new release using the text provided from "make release-publish",
+ adding the excerpt from NEWS, your signature, followed by
+ tacking on the detailed changelog-ish thing that gets mailed
+ out when you push the tag (but not the diffstat thing).
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/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
new file mode 100644
index 0000000..be750f3
--- /dev/null
+++ b/cmake/CMakeLists.txt
@@ -0,0 +1,21 @@
+compiz_configure_file (
+ ${CMAKE_CURRENT_SOURCE_DIR}/CompizDefaults.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/CompizDefaults.cmake
+)
+
+set (_files
+ CompizCommon.cmake
+ CompizPlugin.cmake
+ CompizPackage.cmake
+ CompizBcop.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/CompizDefaults.cmake
+)
+
+if (USE_GCONF)
+ list (APPEND _files CompizGconf.cmake)
+endif ()
+
+install (
+ FILES ${_files}
+ DESTINATION ${COMPIZ_DESTDIR}${CMAKE_INSTALL_PREFIX}/share/compiz/cmake
+)
diff --git a/cmake/CompizBcop.cmake b/cmake/CompizBcop.cmake
new file mode 100644
index 0000000..0d00a95
--- /dev/null
+++ b/cmake/CompizBcop.cmake
@@ -0,0 +1,41 @@
+find_program (XSLTPROC_EXECUTABLE xsltproc)
+mark_as_advanced (FORCE XSLTPROC_EXECUTABLE)
+
+if (NOT XSLTPROC_EXECUTABLE)
+ message (FATAL_ERROR "xsltproc not found.")
+endif ()
+
+# does the plugin require bcop
+function (compiz_plugin_needs_bcop _file _return)
+ file (READ ${_file} _xml_content)
+ if ("${_xml_content}" MATCHES "useBcop=\"true\"")
+ set (${_return} TRUE PARENT_SCOPE)
+ else ()
+ set (${_return} FALSE PARENT_SCOPE)
+ endif ()
+endfunction ()
+
+# prepare bcop build
+function (compiz_add_bcop_targets _plugin _file _sources)
+
+ add_custom_command (
+ OUTPUT ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.h
+ COMMAND ${XSLTPROC_EXECUTABLE}
+ -o ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.h
+ --stringparam "file" "header" ${COMPIZ_BCOP_XSLT}
+ ${_file}
+ DEPENDS ${_file}
+ )
+ add_custom_command (
+ OUTPUT ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.cpp
+ COMMAND ${XSLTPROC_EXECUTABLE}
+ -o ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.cpp
+ --stringparam "file" "source" ${COMPIZ_BCOP_XSLT}
+ ${_file} > ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.cpp
+ DEPENDS ${_file}
+ ${CMAKE_BINARY_DIR}/generated/${_plugin}_options.h
+ )
+ set (${_sources} "${CMAKE_BINARY_DIR}/generated/${_plugin}_options.h;${CMAKE_BINARY_DIR}/generated/${_plugin}_options.cpp" PARENT_SCOPE)
+
+
+endfunction () \ No newline at end of file
diff --git a/cmake/CompizCommon.cmake b/cmake/CompizCommon.cmake
new file mode 100644
index 0000000..1ad6900
--- /dev/null
+++ b/cmake/CompizCommon.cmake
@@ -0,0 +1,273 @@
+cmake_minimum_required (VERSION 2.6)
+
+if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+ message (SEND_ERROR "Building in the source directory is not supported.")
+ message (FATAL_ERROR "Please remove the created \"CMakeCache.txt\" file, the \"CMakeFiles\" directory and create a build directory and call \"${CMAKE_COMMAND} <path to the sources>\".")
+endif ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
+
+#### policies
+
+cmake_policy (SET CMP0000 OLD)
+cmake_policy (SET CMP0002 OLD)
+cmake_policy (SET CMP0003 NEW)
+cmake_policy (SET CMP0005 OLD)
+cmake_policy (SET CMP0011 OLD)
+
+set (CMAKE_SKIP_RPATH FALSE)
+
+option (COMPIZ_BUILD_WITH_RPATH "Leave as ON unless building packages" ON)
+option (COMPIZ_RUN_LDCONFIG "Leave OFF unless you need to run ldconfig after install")
+option (COMPIZ_PACKAGING_ENABLED "Enable to manually set prefix, exec_prefix, libdir, includedir, datadir" OFF)
+set (COMPIZ_DESTDIR ${COMPIZ_DESTDIR} CACHE STRING "Leave blank unless building packages")
+
+set (COMPIZ_DATADIR ${CMAKE_INSTALL_PREFIX}/share)
+set (COMPIZ_METADATADIR ${CMAKE_INSTALL_PREFIX}/share/compiz)
+set (COMPIZ_IMAGEDIR ${CMAKE_INSTALL_PREFIX}/share/compiz/images)
+set (COMPIZ_PLUGINDIR ${libdir}/compiz)
+set (COMPIZ_SYSCONFDIR ${sysconfdir})
+
+set (
+ VERSION ${VERSION} CACHE STRING
+ "Package version that is added to a plugin pkg-version file"
+)
+
+set (
+ COMPIZ_I18N_DIR ${COMPIZ_I18N_DIR} CACHE PATH "Translation file directory"
+)
+
+option (COMPIZ_SIGN_WARNINGS "Should compiz use -Wsign-conversion during compilation." OFF)
+
+if (COMPIZ_SIGN_WARNINGS)
+ set (CMAKE_CXX_FLAGS "-Wall -Wsign-conversion")
+ set (CMAKE_C_FLAGS "-Wall -Wsign-conversion")
+else ()
+ set (CMAKE_CXX_FLAGS "-Wall")
+ set (CMAKE_C_FLAGS "-Wall")
+endif ()
+
+function (compiz_ensure_linkage)
+ find_program (LDCONFIG_EXECUTABLE ldconfig)
+ mark_as_advanced (FORCE LDCONFIG_EXECUTABLE)
+
+ if (LDCONFIG_EXECUTABLE AND ${COMPIZ_RUN_LDCONFIG})
+
+ install (
+ CODE "message (\"Running \" ${LDCONFIG_EXECUTABLE} \" \" ${CMAKE_INSTALL_PREFIX} \"/lib\")
+ exec_program (${LDCONFIG_EXECUTABLE} ARGS \"-v\" ${CMAKE_INSTALL_PREFIX}/lib)"
+ )
+
+ endif (LDCONFIG_EXECUTABLE AND ${COMPIZ_RUN_LDCONFIG})
+endfunction ()
+
+macro (compiz_add_git_dist)
+ set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${VERSION})
+ add_custom_target(dist
+ COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD
+ | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+endmacro ()
+
+# unsets the given variable
+macro (compiz_unset var)
+ set (${var} "" CACHE INTERNAL "")
+endmacro ()
+
+# sets the given variable
+macro (compiz_set var value)
+ set (${var} ${value} CACHE INTERNAL "")
+endmacro ()
+
+
+macro (compiz_format_string str length return)
+ string (LENGTH "${str}" _str_len)
+ math (EXPR _add_chr "${length} - ${_str_len}")
+ set (${return} "${str}")
+ while (_add_chr GREATER 0)
+ set (${return} "${${return}} ")
+ math (EXPR _add_chr "${_add_chr} - 1")
+ endwhile ()
+endmacro ()
+
+string (ASCII 27 _escape)
+function (compiz_color_message _str)
+ if (CMAKE_COLOR_MAKEFILE)
+ message (${_str})
+ else ()
+ string (REGEX REPLACE "${_escape}.[0123456789;]*m" "" __str ${_str})
+ message (${__str})
+ endif ()
+endfunction ()
+
+function (compiz_configure_file _src _dst)
+ foreach (_val ${ARGN})
+ set (_${_val}_sav ${${_val}})
+ set (${_val} "")
+ foreach (_word ${_${_val}_sav})
+ set (${_val} "${${_val}}${_word} ")
+ endforeach (_word ${_${_val}_sav})
+ endforeach (_val ${ARGN})
+
+ configure_file (${_src} ${_dst} @ONLY)
+
+ foreach (_val ${ARGN})
+ set (${_val} ${_${_val}_sav})
+ set (_${_val}_sav "")
+ endforeach (_val ${ARGN})
+endfunction ()
+
+function (compiz_add_plugins_in_folder folder)
+ file (
+ GLOB _plugins_in
+ RELATIVE "${folder}"
+ "${folder}/*/CMakeLists.txt"
+ )
+
+ foreach (_plugin ${_plugins_in})
+ get_filename_component (_plugin_dir ${_plugin} PATH)
+ add_subdirectory (${folder}/${_plugin_dir})
+ endforeach ()
+endfunction ()
+
+#### pkg-config handling
+
+include (FindPkgConfig)
+
+function (compiz_pkg_check_modules _var _req)
+ if (NOT ${_var})
+ pkg_check_modules (${_var} ${_req} ${ARGN})
+ if (${_var}_FOUND)
+ set (${_var} 1 CACHE INTERNAL "" FORCE)
+ endif ()
+ set(__pkg_config_checked_${_var} 0 CACHE INTERNAL "" FORCE)
+ endif ()
+endfunction ()
+
+#### translations
+
+# translate metadata file
+function (compiz_translate_xml _src _dst)
+ find_program (INTLTOOL_MERGE_EXECUTABLE intltool-merge)
+ mark_as_advanced (FORCE INTLTOOL_MERGE_EXECUTABLE)
+
+ if (INTLTOOL_MERGE_EXECUTABLE
+ AND COMPIZ_I18N_DIR
+ AND EXISTS ${COMPIZ_I18N_DIR})
+ add_custom_command (
+ OUTPUT ${_dst}
+ COMMAND ${INTLTOOL_MERGE_EXECUTABLE} -x -u -c
+ ${CMAKE_BINARY_DIR}/.intltool-merge-cache
+ ${COMPIZ_I18N_DIR}
+ ${_src}
+ ${_dst}
+ DEPENDS ${_src}
+ )
+ else ()
+ add_custom_command (
+ OUTPUT ${_dst}
+ COMMAND cat ${_src} |
+ sed -e 's;<_;<;g' -e 's;</_;</;g' >
+ ${_dst}
+ DEPENDS ${_src}
+ )
+ endif ()
+endfunction ()
+
+function (compiz_translate_desktop_file _src _dst)
+ find_program (INTLTOOL_MERGE_EXECUTABLE intltool-merge)
+ mark_as_advanced (FORCE INTLTOOL_MERGE_EXECUTABLE)
+
+ if (INTLTOOL_MERGE_EXECUTABLE
+ AND COMPIZ_I18N_DIR
+ AND EXISTS ${COMPIZ_I18N_DIR})
+ add_custom_command (
+ OUTPUT ${_dst}
+ COMMAND ${INTLTOOL_MERGE_EXECUTABLE} -d -u -c
+ ${CMAKE_BINARY_DIR}/.intltool-merge-cache
+ ${COMPIZ_I18N_DIR}
+ ${_src}
+ ${_dst}
+ DEPENDS ${_src}
+ )
+ else ()
+ add_custom_command (
+ OUTPUT ${_dst}
+ COMMAND cat ${_src} |
+ sed -e 's;^_;;g' >
+ ${_dst}
+ DEPENDS ${_src}
+ )
+ endif ()
+endfunction ()
+
+#### optional file install
+
+function (compiz_opt_install_file _src _dst)
+ install (CODE
+ "message (\"-- Installing: ${_dst}\")
+ execute_process (
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different \"${_src}\" \"${COMPIZ_DESTDIR}${_dst}\"
+ RESULT_VARIABLE _result
+ OUTPUT_QUIET ERROR_QUIET
+ )
+ if (_result)
+ message (\"-- Failed to install: ${_dst}\")
+ endif ()
+ "
+ )
+endfunction ()
+
+#### uninstall
+
+macro (compiz_add_uninstall)
+ if (NOT _compiz_uninstall_rule_created)
+ compiz_set(_compiz_uninstall_rule_created TRUE)
+
+ set (_file "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake")
+
+ file (WRITE ${_file} "if (NOT EXISTS \"${CMAKE_BINARY_DIR}/install_manifest.txt\")\n")
+ file (APPEND ${_file} " message (FATAL_ERROR \"Cannot find install manifest: \\\"${CMAKE_BINARY_DIR}/install_manifest.txt\\\"\")\n")
+ file (APPEND ${_file} "endif (NOT EXISTS \"${CMAKE_BINARY_DIR}/install_manifest.txt\")\n\n")
+ file (APPEND ${_file} "file (READ \"${CMAKE_BINARY_DIR}/install_manifest.txt\" files)\n")
+ file (APPEND ${_file} "string (REGEX REPLACE \"\\n\" \";\" files \"\${files}\")\n")
+ file (APPEND ${_file} "foreach (file \${files})\n")
+ file (APPEND ${_file} " message (STATUS \"Uninstalling \\\"\${file}\\\"\")\n")
+ file (APPEND ${_file} " if (EXISTS \"\${file}\")\n")
+ file (APPEND ${_file} " exec_program(\n")
+ file (APPEND ${_file} " \"${CMAKE_COMMAND}\" ARGS \"-E remove \\\"\${file}\\\"\"\n")
+ file (APPEND ${_file} " OUTPUT_VARIABLE rm_out\n")
+ file (APPEND ${_file} " RETURN_VALUE rm_retval\n")
+ file (APPEND ${_file} " )\n")
+ file (APPEND ${_file} " if (\"\${rm_retval}\" STREQUAL 0)\n")
+ file (APPEND ${_file} " else (\"\${rm_retval}\" STREQUAL 0)\n")
+ file (APPEND ${_file} " message (FATAL_ERROR \"Problem when removing \\\"\${file}\\\"\")\n")
+ file (APPEND ${_file} " endif (\"\${rm_retval}\" STREQUAL 0)\n")
+ file (APPEND ${_file} " else (EXISTS \"\${file}\")\n")
+ file (APPEND ${_file} " message (STATUS \"File \\\"\${file}\\\" does not exist.\")\n")
+ file (APPEND ${_file} " endif (EXISTS \"\${file}\")\n")
+ file (APPEND ${_file} "endforeach (file)\n")
+
+ add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake")
+
+ endif ()
+endmacro ()
+
+#posix 2008 scandir check
+include (CheckCXXSourceCompiles)
+CHECK_CXX_SOURCE_COMPILES (
+ "# include <dirent.h>
+ int func (const char *d, dirent ***list, void *sort)
+ {
+ int n = scandir(d, list, 0, (int(*)(const dirent **, const dirent **))sort);
+ return n;
+ }
+
+ int main (int, char **)
+ {
+ return 0;
+ }
+ "
+ HAVE_SCANDIR_POSIX)
+
+if (HAVE_SCANDIR_POSIX)
+ add_definitions (-DHAVE_SCANDIR_POSIX)
+endif ()
diff --git a/cmake/CompizDefaults.cmake b/cmake/CompizDefaults.cmake
new file mode 100644
index 0000000..aad551c
--- /dev/null
+++ b/cmake/CompizDefaults.cmake
@@ -0,0 +1,15 @@
+set (COMPIZ_PREFIX ${CMAKE_INSTALL_PREFIX})
+set (COMPIZ_INCLUDEDIR ${includedir})
+set (COMPIZ_LIBDIR ${libdir})
+
+list (APPEND COMPIZ_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include)
+list (APPEND COMPIZ_INCLUDE_DIRS ${CMAKE_BINARY_DIR})
+
+set (COMPIZ_BCOP_XSLT ${CMAKE_SOURCE_DIR}/xslt/bcop.xslt)
+
+set (COMPIZ_GCONF_SCHEMAS_SUPPORT ${USE_GCONF})
+set (COMPIZ_GCONF_SCHEMAS_XSLT ${CMAKE_SOURCE_DIR}/xslt/compiz_gconf_schemas.xslt)
+
+set (COMPIZ_PLUGIN_INSTALL_TYPE "package")
+
+set (_COMPIZ_INTERNAL 1)
diff --git a/cmake/CompizDefaults.cmake.in b/cmake/CompizDefaults.cmake.in
new file mode 100644
index 0000000..e3f1ea4
--- /dev/null
+++ b/cmake/CompizDefaults.cmake.in
@@ -0,0 +1,5 @@
+
+set (COMPIZ_BCOP_XSLT @CMAKE_INSTALL_PREFIX@/share/compiz/xslt/bcop.xslt)
+
+set (COMPIZ_GCONF_SCHEMAS_SUPPORT @USE_GCONF@)
+set (COMPIZ_GCONF_SCHEMAS_XSLT @CMAKE_INSTALL_PREFIX@/share/compiz/xslt/compiz_gconf_schemas.xslt) \ No newline at end of file
diff --git a/cmake/CompizGconf.cmake b/cmake/CompizGconf.cmake
new file mode 100644
index 0000000..4d82020
--- /dev/null
+++ b/cmake/CompizGconf.cmake
@@ -0,0 +1,52 @@
+option (
+ COMPIZ_DISABLE_SCHEMAS_INSTALL
+ "Disables gconf schema installation with gconftool"
+ OFF
+)
+
+set (
+ COMPIZ_INSTALL_GCONF_SCHEMA_DIR ${COMPIZ_INSTALL_GCONF_SCHEMA_DIR} CACHE PATH
+ "Installation path of the gconf schema file"
+)
+
+function (compiz_install_gconf_schema _src _dst)
+ find_program (GCONFTOOL_EXECUTABLE gconftool-2)
+ mark_as_advanced (FORCE GCONFTOOL_EXECUTABLE)
+
+ if (GCONFTOOL_EXECUTABLE AND NOT COMPIZ_DISABLE_SCHEMAS_INSTALL)
+ install (CODE "
+ if (\"\$ENV{USER}\" STREQUAL \"root\")
+ exec_program (${GCONFTOOL_EXECUTABLE}
+ ARGS \"--get-default-source\"
+ OUTPUT_VARIABLE ENV{GCONF_CONFIG_SOURCE})
+ exec_program (${GCONFTOOL_EXECUTABLE}
+ ARGS \"--makefile-install-rule ${_src} > /dev/null\")
+ else (\"\$ENV{USER}\" STREQUAL \"root\")
+ exec_program (${GCONFTOOL_EXECUTABLE}
+ ARGS \"--install-schema-file=${_src} > /dev/null\")
+ endif (\"\$ENV{USER}\" STREQUAL \"root\")
+ ")
+ endif ()
+ install (
+ FILES "${_src}"
+ DESTINATION "${COMPIZ_DESTDIR}${_dst}"
+ )
+endfunction ()
+
+# generate gconf schema
+function (compiz_gconf_schema _src _dst _inst)
+ find_program (XSLTPROC_EXECUTABLE xsltproc)
+ mark_as_advanced (FORCE XSLTPROC_EXECUTABLE)
+
+ if (XSLTPROC_EXECUTABLE)
+ add_custom_command (
+ OUTPUT ${_dst}
+ COMMAND ${XSLTPROC_EXECUTABLE}
+ -o ${_dst}
+ ${COMPIZ_GCONF_SCHEMAS_XSLT}
+ ${_src}
+ DEPENDS ${_src}
+ )
+ compiz_install_gconf_schema (${_dst} ${_inst})
+ endif ()
+endfunction ()
diff --git a/cmake/CompizPackage.cmake b/cmake/CompizPackage.cmake
new file mode 100644
index 0000000..aae7c54
--- /dev/null
+++ b/cmake/CompizPackage.cmake
@@ -0,0 +1,101 @@
+include (CompizCommon)
+
+function (compiz_package_generation _name)
+ include(InstallRequiredSystemLibraries)
+
+ set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "${_name}")
+ set (CPACK_PACKAGE_VENDOR "Compiz")
+ set (CPACK_PACKAGE_VERSION "${VERSION}")
+ set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${VERSION}")
+
+ set (CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_DESCRIPTION_SUMMARY})
+ set (CPACK_RPM_PACKAGE_NAME ${CPACK_PACKAGE_NAME})
+ set (CPACK_RPM_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
+ set (CPACK_RPM_PACKAGE_RELEASE 1)
+ set (CPACK_RPM_PACKAGE_LICENCE "GPL")
+ set (CPACK_RPM_PACKAGE_GROUP "unknown")
+ set (CPACK_RPM_PACKAGE_VENDOR ${CPACK_PACKAGE_VENDOR})
+ set (CPACK_RPM_PACKAGE_DESCRIPTION "The blingiest window manager in the world")
+ set (CPACK_SOURCE_GENERATOR "TGZ;TBZ2")
+ set (CPACK_SOURCE_IGNORE_FILES "\\\\.#;/#;.*~")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "/\\\\.git")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "legacy/")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.intltool-merge-cache")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "/po/POTFILES$")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "CMakeCache.txt")
+ list (APPEND CPACK_SOURCE_IGNORE_FILES "CMakeFiles")
+ include(CPack)
+
+ #file (REMOVE "${CMAKE_BINARY_DIR}/CPackConfig.cmake")
+endfunction ()
+
+function (compiz_print_configure_header _name)
+ compiz_format_string ("${_name}" 40 _project)
+ compiz_format_string ("${VERSION}" 40 _version)
+ compiz_color_message ("\n${_escape}[40;37m************************************************************${_escape}[0m")
+ compiz_color_message ("${_escape}[40;37m* ${_escape}[1;31mCompiz ${_escape}[0;40;34mBuildsystem${_escape}[0m${_escape}[40;37m *${_escape}[0m")
+ compiz_color_message ("${_escape}[40;37m* *${_escape}[0m")
+ compiz_color_message ("${_escape}[40;37m* Package : ${_escape}[32m${_project} ${_escape}[37m *${_escape}[0m")
+ compiz_color_message ("${_escape}[40;37m* Version : ${_escape}[32m${_version} ${_escape}[37m *${_escape}[0m")
+ compiz_color_message ("${_escape}[40;37m************************************************************${_escape}[0m")
+endfunction ()
+
+function (compiz_print_configure_footer)
+ compiz_color_message ("${_escape}[40;37m************************************************************${_escape}[0m\n")
+endfunction ()
+
+function (compiz_print_plugin_stats _folder)
+ compiz_color_message ("\n${_escape}[4mPlugin configure check results:${_escape}[0m\n")
+ file (
+ GLOB _plugins_in
+ RELATIVE "${_folder}"
+ "${_folder}/*/CMakeLists.txt"
+ )
+ foreach (_plugin ${_plugins_in})
+ file (READ "${_folder}/${_plugin}" _file)
+ if (_file MATCHES "^.*compiz_plugin ?\\(([^\\) ]*).*$")
+ string (
+ REGEX REPLACE
+ "^.*compiz_plugin ?\\(([^\\) ]*).*$" "\\1"
+ _plugin_name ${_file}
+ )
+ else ()
+ get_filename_component (_plugin_name ${_plugin} PATH)
+ endif ()
+
+ string (TOUPPER ${_plugin_name} _PLUGIN)
+ compiz_format_string (${_plugin_name} 14 _plugin_name)
+
+ if (COMPIZ_DISABLE_PLUGIN_${_PLUGIN})
+ compiz_color_message (" ${_plugin_name}: ${_escape}[1;34mDisabled${_escape}[0m")
+ else ()
+ if (COMPIZ_${_PLUGIN}_BUILD)
+ compiz_color_message (" ${_plugin_name}: ${_escape}[1;32mYes${_escape}[0m")
+ else ()
+ compiz_color_message (" ${_plugin_name}: ${_escape}[1;31mNo${_escape}[0m (Missing dependencies :${COMPIZ_${_PLUGIN}_MISSING_DEPS})")
+ endif ()
+ endif ()
+ endforeach ()
+ message ("")
+endfunction ()
+
+function (compiz_print_result_message _name _var)
+ compiz_format_string ("${_name}" 30 __name)
+ if (${_var})
+ set (_result "${_escape}[1;32mYes${_escape}[0m")
+ else (${_var})
+ set (_result "${_escape}[1;31mNo${_escape}[0m")
+ endif (${_var})
+ compiz_color_message (" ${__name} : ${_result}")
+endfunction (compiz_print_result_message)
+
+function (compiz_get_version_from_file)
+ file (READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" _file)
+ string (
+ REGEX REPLACE
+ "^.*VERSION=([^\n]*).*$" "\\1"
+ _version ${_file}
+ )
+ set (VERSION ${_version} PARENT_SCOPE)
+endfunction ()
diff --git a/cmake/CompizPlugin.cmake b/cmake/CompizPlugin.cmake
new file mode 100644
index 0000000..60551d6
--- /dev/null
+++ b/cmake/CompizPlugin.cmake
@@ -0,0 +1,451 @@
+#######################################################################
+#
+# Generic Compiz Fusion plugin cmake module
+#
+# Copyright : (C) 2008 by Dennis Kasprzyk
+# E-mail : onestone@opencompositing.org
+#
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# 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.
+#
+#######################################################################
+#
+# This module provides the following macro:
+#
+# compiz_plugin (<plugin name>
+# [PKGDEPS dep1 dep2 ...]
+# [PLUGINDEPS plugin1 plugin2 ...]
+# [LDFLAGSADD flag1 flag2 ...]
+# [CFLAGSADD flag1 flag2 ...]
+# [LIBRARIES lib1 lib2 ...]
+# [LIBDIRS dir1 dir2 ...]
+# [INCDIRS dir1 dir2 ...])
+#
+# PKGDEPS = pkgconfig dependencies
+# PLUGINDEPS = compiz plugin dependencies
+# LDFLAGSADD = flags added to the link command
+# CFLAGSADD = flags added to the compile command
+# LIBRARIES = libraries added to link command
+# LIBDIRS = additional link directories
+# INCDIRS = additional include directories
+#
+# The following variables will be used by this macro:
+#
+# BUILD_GLOBAL=true Environment variable to install a plugin
+# into the compiz directories
+#
+# COMPIZ_PLUGIN_INSTALL_TYPE = (package | compiz | local (default))
+# package = Install into ${CMAKE_INSTALL_PREFIX}
+# compiz = Install into compiz prefix (BUILD_GLOBAL=true)
+# local = Install into home directory
+#
+# COMPIZ_I18N_DIR = Translation file directory
+#
+# COMPIZ_DISABLE_SCHEMAS_INSTALL = Disables gconf schema installation with gconftool
+# COMPIZ_INSTALL_GCONF_SCHEMA_DIR = Installation path of the gconf schema file
+#
+# VERSION = package version that is added to a plugin pkg-version file
+#
+#######################################################################
+
+include (CompizCommon)
+include (CompizBcop)
+
+if (COMPIZ_GCONF_SCHEMAS_SUPPORT)
+ include (CompizGconf)
+endif ()
+
+if (COMPIZ_PACKAGING_ENABLED)
+ set (prefix ${CMAKE_INSTALL_PREFIX} CACHE PATH "prefix")
+ set (exec_prefix ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "bindir")
+ set (libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "libdir")
+ set (includedir ${CMAKE_INSTALL_PREFIX}/include CACHE PATH "includedir")
+ set (datadir ${CMAKE_INSTALL_PREFIX}/share CACHE PATH "datadir")
+else (COMPIZ_PACKAGING_ENABLED)
+ set (prefix ${CMAKE_INSTALL_PREFIX} )
+ set (exec_prefix ${CMAKE_INSTALL_PREFIX}/bin )
+ set (libdir ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
+ set (includedir ${CMAKE_INSTALL_PREFIX}/include )
+ set (datadir ${CMAKE_INSTALL_PREFIX}/share )
+endif (COMPIZ_PACKAGING_ENABLED)
+
+# determinate installation directories
+macro (_prepare_directories)
+ set (CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRe" CACHE INTERNAL "" FORCE)
+ if ("${COMPIZ_PLUGIN_INSTALL_TYPE}" STREQUAL "package")
+ set (PLUGIN_BUILDTYPE global)
+ set (PLUGIN_PREFIX ${CMAKE_INSTALL_PREFIX})
+ set (PLUGIN_LIBDIR ${libdir}/compiz)
+ set (PLUGIN_INCDIR ${includedir})
+ set (PLUGIN_PKGDIR ${libdir}/pkgconfig)
+ set (PLUGIN_XMLDIR ${datadir}/compiz)
+ set (PLUGIN_IMAGEDIR ${datadir}/compiz)
+ set (PLUGIN_DATADIR ${datadir}/compiz)
+ if (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "${datadir}/gconf/schemas")
+ else (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "${COMPIZ_INSTALL_GCONF_SCHEMA_DIR}")
+ endif (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+
+ elseif ("${COMPIZ_PLUGIN_INSTALL_TYPE}" STREQUAL "compiz" OR
+ "$ENV{BUILD_GLOBAL}" STREQUAL "true")
+ set (PLUGIN_BUILDTYPE global)
+ set (PLUGIN_PREFIX ${COMPIZ_PREFIX})
+ set (PLUGIN_LIBDIR ${COMPIZ_LIBDIR}/compiz)
+ set (PLUGIN_INCDIR ${COMPIZ_INCLUDEDIR})
+ set (PLUGIN_PKGDIR ${COMPIZ_LIBDIR}/pkgconfig)
+ set (PLUGIN_XMLDIR ${COMPIZ_PREFIX}/share/compiz)
+ set (PLUGIN_IMAGEDIR ${COMPIZ_PREFIX}/share/compiz)
+ set (PLUGIN_DATADIR ${COMPIZ_PREFIX}/share/compiz)
+ if (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "${COMPIZ_PREFIX}/share/gconf/schemas")
+ else (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "${COMPIZ_INSTALL_GCONF_SCHEMA_DIR}")
+ endif (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+
+ if (NOT "${CMAKE_BUILD_TYPE}")
+ set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type (Debug/Release/RelWithDebInfo/MinSizeRe)" FORCE)
+ endif (NOT "${CMAKE_BUILD_TYPE}")
+ else ("${COMPIZ_PLUGIN_INSTALL_TYPE}" STREQUAL "compiz" OR
+ "$ENV{BUILD_GLOBAL}" STREQUAL "true")
+ set (PLUGIN_BUILDTYPE local)
+ set (PLUGIN_PREFIX $ENV{HOME}/.compiz-1)
+ set (PLUGIN_LIBDIR $ENV{HOME}/.compiz-1/plugins)
+ set (PLUGIN_XMLDIR $ENV{HOME}/.compiz-1/metadata)
+ set (PLUGIN_IMAGEDIR $ENV{HOME}/.compiz-1)
+ set (PLUGIN_DATADIR $ENV{HOME}/.compiz-1)
+
+ if (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "$ENV{HOME}/.gconf/schemas")
+ else (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (PLUGIN_SCHEMADIR "${COMPIZ_INSTALL_GCONF_SCHEMA_DIR}")
+ endif (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+
+ if (NOT "${CMAKE_BUILD_TYPE}")
+ set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type (Debug/Release/RelWithDebInfo/MinSizeRe)" FORCE)
+ endif (NOT "${CMAKE_BUILD_TYPE}")
+ endif ("${COMPIZ_PLUGIN_INSTALL_TYPE}" STREQUAL "package")
+endmacro (_prepare_directories)
+
+# parse plugin macro parameter
+macro (_get_plugin_parameters _prefix)
+ set (_current_var _foo)
+ set (_supported_var PKGDEPS PLUGINDEPS LDFLAGSADD CFLAGSADD LIBRARIES LIBDIRS INCDIRS)
+ foreach (_val ${_supported_var})
+ set (${_prefix}_${_val})
+ endforeach (_val)
+ foreach (_val ${ARGN})
+ set (_found FALSE)
+ foreach (_find ${_supported_var})
+ if ("${_find}" STREQUAL "${_val}")
+ set (_found TRUE)
+ endif ("${_find}" STREQUAL "${_val}")
+ endforeach (_find)
+
+ if (_found)
+ set (_current_var ${_prefix}_${_val})
+ else (_found)
+ list (APPEND ${_current_var} ${_val})
+ endif (_found)
+ endforeach (_val)
+endmacro (_get_plugin_parameters)
+
+# check pkgconfig dependencies
+macro (_check_plugin_pkg_deps _prefix)
+ set (${_prefix}_HAS_PKG_DEPS TRUE)
+ foreach (_val ${ARGN})
+ string (REGEX REPLACE "[<>=\\.]" "_" _name ${_val})
+ string (TOUPPER ${_name} _name)
+
+ compiz_pkg_check_modules (_${_name} ${_val})
+
+ if (_${_name}_FOUND)
+ list (APPEND ${_prefix}_PKG_LIBDIRS "${_${_name}_LIBRARY_DIRS}")
+ list (APPEND ${_prefix}_PKG_LIBRARIES "${_${_name}_LIBRARIES}")
+ list (APPEND ${_prefix}_PKG_INCDIRS "${_${_name}_INCLUDE_DIRS}")
+ else ()
+ set (${_prefix}_HAS_PKG_DEPS FALSE)
+ compiz_set (COMPIZ_${_prefix}_MISSING_DEPS "${COMPIZ_${_prefix}_MISSING_DEPS} ${_val}")
+ set(__pkg_config_checked__${_name} 0 CACHE INTERNAL "" FORCE)
+ endif ()
+ endforeach ()
+endmacro ()
+
+# check plugin dependencies
+macro (_check_plugin_plugin_deps _prefix)
+ set (${_prefix}_HAS_PLUGIN_DEPS TRUE)
+ foreach (_val ${ARGN})
+ string (TOUPPER ${_val} _name)
+
+ find_file (
+ _plugin_dep_${_val}
+ compiz-${_val}.pc.in
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../${_val}
+ NO_DEFAULT_PATH
+ )
+
+ if (_plugin_dep_${_val})
+ file (RELATIVE_PATH _relative ${CMAKE_CURRENT_SOURCE_DIR} ${_plugin_dep_${_val}})
+ get_filename_component (_plugin_inc_dir ${_relative} PATH)
+ list (APPEND ${_prefix}_LOCAL_INCDIRS "${_plugin_inc_dir}/include")
+ list (APPEND ${_prefix}_LOCAL_LIBRARIES ${_val})
+ else ()
+ # fallback to pkgconfig
+ compiz_pkg_check_modules (_${_name} compiz-${_val})
+ if (_${_name}_FOUND)
+ list (APPEND ${_prefix}_PKG_LIBDIRS "${_${_name}_LIBRARY_DIRS}")
+ list (APPEND ${_prefix}_PKG_LIBRARIES "${_${_name}_LIBRARIES}")
+ list (APPEND ${_prefix}_PKG_INCDIRS "${_${_name}_INCLUDE_DIRS}")
+ else ()
+ set (${_prefix}_HAS_PLUGIN_DEPS FALSE)
+ compiz_set (COMPIZ_${_prefix}_MISSING_DEPS "${COMPIZ_${_prefix}_MISSING_DEPS} compiz-${_val}")
+ endif ()
+ endif ()
+
+ compiz_set (_plugin_dep_${_val} "${_plugin_dep_${_val}}")
+
+ endforeach ()
+endmacro ()
+
+
+
+
+# main function
+function (_build_compiz_plugin plugin)
+ string (TOUPPER ${plugin} _PLUGIN)
+
+ if (COMPIZ_PLUGIN_INSTALL_TYPE)
+ set (
+ COMPIZ_PLUGIN_INSTALL_TYPE ${COMPIZ_PLUGIN_INSTALL_TYPE} CACHE STRING
+ "Where a plugin should be installed \(package | compiz | local\)"
+ )
+ else (COMPIZ_PLUGIN_INSTALL_TYPE)
+ set (
+ COMPIZ_PLUGIN_INSTALL_TYPE "local" CACHE STRING
+ "Where a plugin should be installed \(package | compiz | local\)"
+ )
+ endif (COMPIZ_PLUGIN_INSTALL_TYPE)
+
+ _get_plugin_parameters (${_PLUGIN} ${ARGN})
+ _prepare_directories ()
+
+ find_file (
+ _${plugin}_xml_in ${plugin}.xml.in
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}
+ NO_DEFAULT_PATH
+ )
+ if (_${plugin}_xml_in)
+ set (_${plugin}_xml ${_${plugin}_xml_in})
+ else ()
+ find_file (
+ _${plugin}_xml ${plugin}.xml
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR} }
+ NO_DEFAULT_PATH
+ )
+ endif ()
+
+ set (${_PLUGIN}_HAS_PKG_DEPS)
+ set (${_PLUGIN}_HAS_PLUGIN_DEPS)
+
+ # check dependencies
+ compiz_unset (COMPIZ_${_PLUGIN}_MISSING_DEPS)
+ _check_plugin_plugin_deps (${_PLUGIN} ${${_PLUGIN}_PLUGINDEPS})
+ _check_plugin_pkg_deps (${_PLUGIN} ${${_PLUGIN}_PKGDEPS})
+
+ if (${_PLUGIN}_HAS_PKG_DEPS AND ${_PLUGIN}_HAS_PLUGIN_DEPS)
+
+ compiz_set (COMPIZ_${_PLUGIN}_BUILD TRUE PARENT_SCOPE)
+
+ if (NOT EXISTS ${CMAKE_BINARY_DIR}/generated)
+ file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated)
+ endif (NOT EXISTS ${CMAKE_BINARY_DIR}/generated)
+
+ if (_${plugin}_xml_in)
+ # translate xml
+ compiz_translate_xml ( ${_${plugin}_xml_in} "${CMAKE_BINARY_DIR}/generated/${plugin}.xml")
+ set (_translation_sources "${CMAKE_BINARY_DIR}/generated/${plugin}.xml")
+ set (_translated_xml ${CMAKE_BINARY_DIR}/generated/${plugin}.xml)
+ else ()
+ if (_${plugin}_xml)
+ set (_translated_xml ${_${plugin}_xml})
+ endif ()
+ endif ()
+
+ if (_${plugin}_xml)
+ # do we need bcop for our plugin
+ compiz_plugin_needs_bcop (${_${plugin}_xml} _needs_bcop)
+ if (_needs_bcop)
+ # initialize everything we need for bcop
+ compiz_add_bcop_targets (${plugin} ${_${plugin}_xml} _bcop_sources)
+ endif ()
+ endif ()
+
+ if (_translated_xml)
+ if (COMPIZ_GCONF_SCHEMAS_SUPPORT)
+ # generate gconf schema
+ compiz_gconf_schema (${_translated_xml} "${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.schemas" ${PLUGIN_SCHEMADIR})
+ set (_schema_sources "${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.schemas")
+ endif ()
+
+ # install xml
+ install (
+ FILES ${_translated_xml}
+ DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_XMLDIR}
+ )
+ endif (_translated_xml)
+
+ find_file (
+ _${plugin}_pkg compiz-${plugin}.pc.in
+ PATHS ${CMAKE_CURRENT_SOURCE_DIR}
+ NO_DEFAULT_PATH
+ )
+
+ # generate pkgconfig file and install it and the plugin header file
+ if (_${plugin}_pkg AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin})
+ if ("${PLUGIN_BUILDTYPE}" STREQUAL "local")
+ message (STATUS "[WARNING] The plugin ${plugin} might be needed by other plugins. Install it systemwide.")
+ else ()
+ set (prefix ${PLUGIN_PREFIX})
+ set (libdir ${PLUGIN_LIBDIR})
+ set (includedir ${PLUGIN_INCDIR})
+ if (NOT VERSION)
+ set (VERSION 0.0.1-git)
+ endif (NOT VERSION)
+
+ compiz_configure_file (
+ ${_${plugin}_pkg}
+ ${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.pc
+ COMPIZ_REQUIRES
+ COMPIZ_CFLAGS
+ )
+
+ install (
+ FILES ${CMAKE_BINARY_DIR}/generated/compiz-${plugin}.pc
+ DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_PKGDIR}
+ )
+ install (
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin}
+ DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_INCDIR}/compiz
+ )
+ endif ()
+ endif ()
+
+ # install plugin data files
+ if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/data)
+ install (
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
+ DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_DATADIR}
+ )
+ endif ()
+
+ # install plugin image files
+ if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/images)
+ install (
+ DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/images
+ DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_IMAGEDIR}
+ )
+ endif ()
+
+ # find files for build
+ file (GLOB _h_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
+ file (GLOB _h_ins_files "${CMAKE_CURRENT_SOURCE_DIR}/include/${plugin}/*.h")
+ file (GLOB _cpp_files "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
+
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs")
+
+# set (_cflags "-Wall -Wpointer-arith -fno-strict-aliasing")
+
+
+ add_definitions (-DPREFIX='\"${PLUGIN_PREFIX}\"'
+ -DIMAGEDIR='\"${PLUGIN_IMAGEDIR}\"'
+ -DDATADIR='\"${PLUGIN_DATADIR}\"')
+
+ include_directories (
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/generated
+ ${${_PLUGIN}_LOCAL_INCDIRS}
+ ${${_PLUGIN}_PKG_INCDIRS}
+ ${${_PLUGIN}_INCDIRS}
+ ${COMPIZ_INCLUDE_DIRS}
+ )
+
+ link_directories (
+ ${COMPIZ_LINK_DIRS}
+ ${${_PLUGIN}_PKG_LIBDIRS}
+ ${${_PLUGIN}_LIBDIRS}
+ ${PLUGIN_LIBDIR}
+ ${COMPIZ_LIBDIR}/compiz
+ )
+
+ add_library (
+ ${plugin} SHARED ${_cpp_files}
+ ${_h_files}
+ ${_h_ins_files}
+ ${_bcop_sources}
+ ${_translation_sources}
+ ${_schema_sources}
+ )
+
+ if (COMPIZ_BUILD_WITH_RPATH)
+ set_target_properties (
+ ${plugin} PROPERTIES
+ INSTALL_RPATH_USE_LINK_PATH 1
+ BUILD_WITH_INSTALL_RPATH 1
+ SKIP_BUILD_RPATH 0
+ COMPILE_FLAGS "${${_PLUGIN}_CFLAGSADD}"
+ LINK_FLAGS "${${_PLUGIN}_LDFLAGSADD}"
+ )
+ else (COMPIZ_BUILD_WITH_RPATH)
+ set_target_properties (
+ ${plugin} PROPERTIES
+ INSTALL_RPATH_USE_LINK_PATH 0
+ SKIP_BUILD_RPATH 1
+ INSTALL_RPATH "${COMPIZ_LIBDIR}/compiz"
+ COMPILE_FLAGS "${${_PLUGIN}_CFLAGSADD}"
+ LINK_FLAGS "${${_PLUGIN}_LDFLAGSADD}"
+ )
+ endif (COMPIZ_BUILD_WITH_RPATH)
+
+ target_link_libraries (
+ ${plugin} ${COMPIZ_LIBRARIES}
+ ${${_PLUGIN}_LOCAL_LIBRARIES}
+ ${${_PLUGIN}_PKG_LIBRARIES}
+ ${${_PLUGIN}_LIBRARIES}
+ )
+
+ install (
+ TARGETS ${plugin}
+ LIBRARY DESTINATION ${COMPIZ_DESTDIR}${PLUGIN_LIBDIR}
+ )
+
+ compiz_add_uninstall ()
+
+ else ()
+ message (STATUS "[WARNING] One or more dependencies for compiz plugin ${plugin} not found. Skipping plugin.")
+ message (STATUS "Missing dependencies :${COMPIZ_${_PLUGIN}_MISSING_DEPS}")
+ compiz_set (COMPIZ_${_PLUGIN}_BUILD FALSE)
+ endif ()
+endfunction ()
+
+macro (compiz_plugin plugin)
+ string (TOUPPER ${plugin} _PLUGIN)
+
+ option (
+ COMPIZ_DISABLE_PLUGIN_${_PLUGIN}
+ "Disable building of plugin \"${plugin}\""
+ OFF
+ )
+
+ if (NOT COMPIZ_DISABLE_PLUGIN_${_PLUGIN})
+ _build_compiz_plugin (${plugin} ${ARGN})
+ endif (NOT COMPIZ_DISABLE_PLUGIN_${_PLUGIN})
+endmacro ()
diff --git a/cmake/FindCompiz.cmake b/cmake/FindCompiz.cmake
new file mode 100644
index 0000000..3aafc5d
--- /dev/null
+++ b/cmake/FindCompiz.cmake
@@ -0,0 +1,89 @@
+
+
+
+################################################################################
+#
+# FindCompiz
+#
+# This module finds Compiz (www.compiz.org). It uses the FindPkgConfig to
+# locate Compiz and adds the Compiz CMake module path to the CMake module path.
+# It also loads the CompizDefaults that sets all variables to compile Compiz
+# modules.
+#
+# This module sets the following variables:
+# COMPIZ_FOUND ... set to true if compiz and its CompizDefaults macro
+# is found
+#
+# Variables set by the FindPkgConfig macro for compiz
+# COMPIZ_LIBRARY_DIRS ... the paths of the libraries (w/o the '-L')
+# COMPIZ_LDFLAGS ... all required linker flags
+# COMPIZ_LDFLAGS_OTHER ... all other linker flags
+# COMPIZ_INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I')
+# COMPIZ_CFLAGS ... all required cflags
+# COMPIZ_CFLAGS_OTHER ... the other compiler flags
+# COMPIZ_VERSION ... version of the module
+# COMPIZ_PREFIX ... prefix-directory of the module
+# COMPIZ_INCLUDEDIR ... include-dir of the module
+# COMPIZ_LIBDIR ... lib-dir of the module
+#
+# If the _COMPIZ_INTERNAL variable is set to true, then this module will do
+# nothing. This is required for the Compiz core package build system.
+#
+# Author: Dennis Kasprzyk <onestone@compiz.org>
+#
+################################################################################
+
+if (NOT _COMPIZ_INTERNAL)
+
+ if (Compiz_FIND_REQUIRED)
+ set (_req REQUIRED)
+ endif ()
+
+ # look for pkg-config
+ find_package (PkgConfig ${_req})
+
+ if (PKG_CONFIG_FOUND)
+
+ # do we need to look for a specified version?
+ set (_comp_ver)
+ if (Compiz_FIND_VERSION)
+ if (Compiz_FIND_VERSION_EXACT)
+ set (_comp_ver "=${Compiz_FIND_VERSION}")
+ else ()
+ set (_comp_ver ">=${Compiz_FIND_VERSION}")
+ endif ()
+ endif ()
+
+ # add install prefix to pkgconfig search path if needed
+ string (REGEX REPLACE "([\\+\\(\\)\\^\\\$\\.\\-\\*\\?\\|])" "\\\\\\1" PKGCONFIG_REGEX ${CMAKE_INSTALL_PREFIX})
+ set (PKGCONFIG_REGEX ".*${PKGCONFIG_REGEX}/lib/pkgconfig:${PKGCONFIG_REGEX}/share/pkgconfig.*")
+
+ if (NOT "$ENV{PKG_CONFIG_PATH}" MATCHES "${PKGCONFIG_REGEX}")
+ if ("" STREQUAL "$ENV{PKG_CONFIG_PATH}")
+ set (ENV{PKG_CONFIG_PATH} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig:${CMAKE_INSTALL_PREFIX}/share/pkgconfig")
+ else ()
+ set (ENV{PKG_CONFIG_PATH}
+ "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig:${CMAKE_INSTALL_PREFIX}/share/pkgconfig:$ENV{PKG_CONFIG_PATH}")
+ endif ()
+ endif ()
+
+ # look for compiz
+ pkg_check_modules (COMPIZ ${_req} "compiz${_comp_ver}")
+
+ # is the CompizDefaults module installed?
+ find_path(_compiz_def_macro CompizDefaults.cmake ${COMPIZ_PREFIX}/share/compiz/cmake)
+
+ if (COMPIZ_FOUND AND _compiz_def_macro)
+ # everything found. Set module path and include defaults module
+ set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${COMPIZ_PREFIX}/share/compiz/cmake)
+ include (CompizDefaults)
+ else ()
+ set (COMPIZ_FOUND 0)
+ endif ()
+
+ if (Compiz_FIND_REQUIRED AND NOT COMPIZ_FOUND)
+ message (FATAL_ERROR "Unable to find Compiz ${_comp_ver}")
+ endif ()
+ endif ()
+endif ()
+
diff --git a/cmake/all_plugins_in_folder_example-CMakeLists.txt b/cmake/all_plugins_in_folder_example-CMakeLists.txt
new file mode 100644
index 0000000..6ba885a
--- /dev/null
+++ b/cmake/all_plugins_in_folder_example-CMakeLists.txt
@@ -0,0 +1,10 @@
+find_package (Compiz REQUIRED)
+
+include (CompizCommon)
+include (CompizPackage)
+
+compiz_add_plugins_in_folder ("${CMAKE_SOURCE_DIR}")
+
+compiz_print_configure_header ("Compiz")
+compiz_print_plugin_stats ("${CMAKE_SOURCE_DIR}")
+compiz_print_configure_footer () \ No newline at end of file
diff --git a/cmake/base.cmake b/cmake/base.cmake
new file mode 100644
index 0000000..05493d9
--- /dev/null
+++ b/cmake/base.cmake
@@ -0,0 +1,63 @@
+set (USE_GCONF 1 CACHE BOOL "Install GConf schemas")
+
+if (USE_GCONF)
+ pkg_check_modules (GCONF gconf-2.0)
+
+ find_program (GCONFTOOL_EXECUTABLE gconftool-2)
+ mark_as_advanced (FORCE GCONFTOOL_EXECUTABLE)
+
+ if (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (SCHEMADIR "${CMAKE_INSTALL_PREFIX}/share/gconf/schemas")
+ else (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+ set (SCHEMADIR "${COMPIZ_INSTALL_GCONF_SCHEMA_DIR}")
+ endif (NOT COMPIZ_INSTALL_GCONF_SCHEMA_DIR)
+
+ if (NOT GCONF_FOUND OR NOT GCONFTOOL_EXECUTABLE)
+ set (USE_GCONF 0)
+ else ()
+ include (CompizGconf)
+ endif ()
+endif ()
+
+function (_print_configure_results)
+ compiz_print_configure_header ("Compiz")
+ compiz_color_message ("\n${_escape}[4mOptional features:${_escape}[0m\n")
+
+ compiz_print_result_message ("gtk window decorator" USE_GTK)
+ compiz_print_result_message ("metacity theme support" USE_METACITY)
+ compiz_print_result_message ("gconf schemas" USE_GCONF)
+ compiz_print_result_message ("gnome" USE_GNOME)
+ compiz_print_result_message ("kde4 window decorator" USE_KDE4)
+
+ compiz_print_configure_footer ()
+ compiz_print_plugin_stats ("${CMAKE_SOURCE_DIR}/plugins")
+ compiz_print_configure_footer ()
+endfunction ()
+
+function (_check_compiz_cmake_macro)
+ find_file (_find_compiz FindCompiz.cmake PATHS ${CMAKE_ROOT}/Modules ${ARGN})
+ if (NOT _find_compiz)
+ compiz_color_message ("${_escape}[1;31mWARNING:${_escape}[0m")
+ message ("\"FindCompiz.cmake\" file not found in cmake module directories.")
+ message ("It should be installed to allow building of external compiz packages.")
+ message ("Call \"sudo make findcompiz_install\" to install it.\n")
+ compiz_print_configure_footer ()
+ endif ()
+ add_custom_target (
+ findcompiz_install
+ ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/cmake/FindCompiz.cmake ${COMPIZ_DESTDIR}${CMAKE_ROOT}/Modules
+ )
+endfunction ()
+
+# add install prefix to pkgconfig search path if needed
+string (REGEX REPLACE "([\\+\\(\\)\\^\\\$\\.\\-\\*\\?\\|])" "\\\\\\1" PKGCONFIG_REGEX ${CMAKE_INSTALL_PREFIX})
+set (PKGCONFIG_REGEX ".*${PKGCONFIG_REGEX}/lib/pkgconfig:${PKGCONFIG_REGEX}/share/pkgconfig.*")
+
+if (NOT "$ENV{PKG_CONFIG_PATH}" MATCHES "${PKGCONFIG_REGEX}")
+ if ("" STREQUAL "$ENV{PKG_CONFIG_PATH}")
+ set (ENV{PKG_CONFIG_PATH} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig:${CMAKE_INSTALL_PREFIX}/share/pkgconfig")
+ else ()
+ set (ENV{PKG_CONFIG_PATH}
+ "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig:${CMAKE_INSTALL_PREFIX}/share/pkgconfig:$ENV{PKG_CONFIG_PATH}")
+ endif ()
+endif ()
diff --git a/compiz.pc.in b/compiz.pc.in
new file mode 100644
index 0000000..6ae4240
--- /dev/null
+++ b/compiz.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: compiz
+Description: OpenGL compositing manager
+Version: @VERSION@
+
+Requires: @COMPIZ_REQUIRES@
+Libs:
+Cflags: @COMPIZ_CFLAGS@ -I${includedir}/compiz
diff --git a/config.h.core.in b/config.h.core.in
new file mode 100644
index 0000000..4d66815
--- /dev/null
+++ b/config.h.core.in
@@ -0,0 +1,5 @@
+#define PACKAGE_STRING "@_compiz_package_string@"
+
+#define PACKAGE "@_compiz_package@"
+
+#define GETTEXT_PACKAGE "@GETTEXT_PACKAGE@"
diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt
new file mode 100644
index 0000000..6cb008f
--- /dev/null
+++ b/gtk/CMakeLists.txt
@@ -0,0 +1,88 @@
+option (BUILD_GTK "Build gtk-window-decorator and Gnome related toold" 1)
+option (BUILD_METACITY "Gtk-window-decorator metacity theme support" 1)
+option (BUILD_GNOME "Gnome settings module" 1)
+option (BUILD_GNOME_KEYBINDINGS "Gnome keybindings" 1)
+
+compiz_set (USE_GTK ${BUILD_GTK})
+compiz_set (USE_METACITY ${BUILD_METACITY})
+compiz_set (USE_GNOME ${BUILD_GNOME})
+compiz_set (USE_GNOME_KEYBINDINGS ${BUILD_GNOME_KEYBINDINGS})
+
+if (USE_GTK)
+ pkg_check_modules (GTK_WINDOW_DECORATOR
+ xrender>=0.8.4
+ gtk+-2.0>=2.8.0
+ libwnck-1.0
+ pangocairo
+ )
+ if (GTK_WINDOW_DECORATOR_FOUND)
+ set (CMAKE_REQUIRED_FLAGS ${GTK_WINDOW_DECORATOR_CFLAGS})
+ set (CMAKE_REQUIRED_LIBRARIES ${GTK_WINDOW_DECORATOR_LIBRARIES})
+ check_function_exists (wnck_window_has_name HAVE_WNCK_WINDOW_HAS_NAME)
+ set (CMAKE_REQUIRED_FLAGS "")
+ set (CMAKE_REQUIRED_LIBRARIES "")
+
+ compiz_pkg_check_modules (HAVE_LIBWNCK_2_18_1 libwnck-1.0>=2.18.1)
+ compiz_pkg_check_modules (HAVE_LIBWNCK_2_19_4 libwnck-1.0>=2.19.4)
+
+ if (USE_METACITY)
+ pkg_check_modules (METACITY libmetacity-private)
+ if (METACITY_FOUND)
+ compiz_pkg_check_modules (HAVE_METACITY_2_15_21 libmetacity-private>=2.15.21)
+ compiz_pkg_check_modules (HAVE_METACITY_2_17_0 libmetacity-private>=2.17.0)
+ compiz_pkg_check_modules (HAVE_METACITY_2_23_2 libmetacity-private>=2.23.2)
+ else (METACITY_FOUND)
+ compiz_set (USE_METACITY 0)
+ endif (METACITY_FOUND)
+ endif (USE_METACITY)
+
+ if (USE_GNOME)
+ compiz_pkg_check_modules (GNOME_WINDOW_SETTINGS
+ gnome-window-settings-2.0
+ gnome-desktop-2.0
+ )
+
+ if (GNOME_WINDOW_SETTINGS_FOUND)
+ exec_program (${PKG_CONFIG_EXECUTABLE}
+ ARGS "--variable=prefix gnome-window-settings-2.0"
+ OUTPUT_VARIABLE windowsettingsdatadir
+ )
+ set (windowsettingsdatadir ${windowsettingsdatadir}/share)
+ exec_program (${PKG_CONFIG_EXECUTABLE}
+ ARGS "--variable=libdir gnome-window-settings-2.0"
+ OUTPUT_VARIABLE windowsettingslibdir
+ )
+ else (GNOME_WINDOW_SETTINGS_FOUND)
+ compiz_set (USE_GNOME 0)
+ endif (GNOME_WINDOW_SETTINGS_FOUND)
+ endif (USE_GNOME)
+
+ if (USE_GNOME_KEYBINDINGS)
+ compiz_pkg_check_modules (GNOME_KEY_BINDINGS gnome-keybindings)
+ if (GNOME_KEY_BINDINGS_FOUND)
+ exec_program (${PKG_CONFIG_EXECUTABLE}
+ ARGS "--variable=keysdir gnome-keybindings"
+ OUTPUT_VARIABLE keybindingsdir
+ )
+ else (GNOME_KEY_BINDINGS_FOUND)
+ compiz_set (USE_GNOME_KEYBINDINGS 0)
+ endif (GNOME_KEY_BINDINGS_FOUND)
+ endif (USE_GNOME_KEYBINDINGS)
+ else (GTK_WINDOW_DECORATOR_FOUND)
+ compiz_set (USE_GTK 0)
+ endif (GTK_WINDOW_DECORATOR_FOUND)
+endif (USE_GTK)
+
+if (NOT USE_GTK)
+ compiz_set (USE_METACITY 0)
+ compiz_set (USE_GNOME 0)
+ compiz_set (USE_GNOME_KEYBINDINGS 0)
+endif (NOT USE_GTK)
+
+configure_file (
+ ${CMAKE_CURRENT_SOURCE_DIR}/config.h.gtk.in
+ ${CMAKE_CURRENT_BINARY_DIR}/config.h
+)
+
+add_subdirectory (window-decorator)
+add_subdirectory (gnome)
diff --git a/gtk/config.h.gtk.in b/gtk/config.h.gtk.in
new file mode 100644
index 0000000..ff0f14d
--- /dev/null
+++ b/gtk/config.h.gtk.in
@@ -0,0 +1,25 @@
+/* Define to 1 if Metacity support is enabled */
+#cmakedefine USE_METACITY 1
+
+/* Define to 1 if Gconf support is enabled */
+#cmakedefine USE_GCONF 1
+
+/* Define to 1 if you have the `wnck_window_has_name' function. */
+#cmakedefine HAVE_WNCK_WINDOW_HAS_NAME 1
+
+/* Define to 1 if libwnck version >= 2_18_1 */
+#cmakedefine HAVE_LIBWNCK_2_18_1 1
+
+/* Define to 1 if libwnck version >= 2_19_4 */
+#cmakedefine HAVE_LIBWNCK_2_19_4 1
+
+/* Define to 1 if metacity version >= 2.15.21 */
+#cmakedefine HAVE_METACITY_2_15_21 1
+
+/* Define to 1 if metacity version >= 2.17.0 */
+#cmakedefine HAVE_METACITY_2_17_0 1
+
+/* Define to 1 if metacity version >= 2.23.2 */
+#cmakedefine HAVE_METACITY_2_23_2 1
+
+#define GETTEXT_PACKAGE "${GETTEXT_PACKAGE}"
diff --git a/gtk/gnome/50-compiz-desktop-key.xml.in b/gtk/gnome/50-compiz-desktop-key.xml.in
new file mode 100644
index 0000000..083d5e1
--- /dev/null
+++ b/gtk/gnome/50-compiz-desktop-key.xml.in
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<KeyListEntries _name="Desktop" wm_name="compiz" package="compiz">
+
+ <KeyListEntry name="/apps/compiz/plugins/gnomecompat/options/run_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/gnomecompat/options/main_menu_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/gnomecompat/allscreens/options/run_command_screenshot_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/gnomecompat/allscreens/options/run_command_window_screenshot_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/show_desktop_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/gnomecompat/allscreens/options/run_command_terminal_key"/>
+
+</KeyListEntries>
diff --git a/gtk/gnome/50-compiz-key.xml.in b/gtk/gnome/50-compiz-key.xml.in
new file mode 100644
index 0000000..c063f11
--- /dev/null
+++ b/gtk/gnome/50-compiz-key.xml.in
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<KeyListEntries _name="Window Management" wm_name="compiz" package="compiz">
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/close_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/raise_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/lower_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/maximize_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/maximize_window_horizontally_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/maximize_window_vertically_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/minimize_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/obs/allscreens/options/opacity_decrease_key"/>
+
+ <KeyListEntry name="/apps/compiz/plugins/obs/allscreens/options/opacity_increase_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/show_desktop_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/toggle_window_maximized_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/toggle_window_maximized_horizontally_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/toggle_window_maximized_vertically_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/toggle_window_shaded_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/unmaximize_window_key"/>
+
+ <KeyListEntry name="/apps/compiz/general/allscreens/options/window_menu_key"/>
+
+</KeyListEntries>
diff --git a/gtk/gnome/CMakeLists.txt b/gtk/gnome/CMakeLists.txt
new file mode 100644
index 0000000..662979d
--- /dev/null
+++ b/gtk/gnome/CMakeLists.txt
@@ -0,0 +1,84 @@
+if (USE_GNOME)
+
+ include_directories (
+ ${CMAKE_BINARY_DIR}/gtk
+ ${GNOME_WINDOW_SETTINGS_INCLUDE_DIRS}
+ ${GCONF_INCLUDE_DIRS}
+ )
+
+ add_definitions (
+ -DHAVE_CONFIG_H
+ -DMETACITY_THEME_DIR=\\\"${windowsettingsdatadir}/themes\\\"
+ )
+
+ link_directories (
+ ${COMPIZ_LINK_DIRS}
+ )
+
+ set (desktop_file ${CMAKE_CURRENT_BINARY_DIR}/compiz.desktop)
+ compiz_translate_desktop_file (
+ ${CMAKE_CURRENT_SOURCE_DIR}/compiz.desktop.in
+ ${desktop_file}
+ )
+ install (
+ FILES ${desktop_file}
+ DESTINATION ${COMPIZ_DESTDIR}${datadir}/applications
+ )
+
+ set (wmproperties_file ${CMAKE_CURRENT_BINARY_DIR}/compiz-wm.desktop)
+ compiz_translate_desktop_file (
+ ${CMAKE_CURRENT_SOURCE_DIR}/compiz-wm.desktop.in
+ ${wmproperties_file}
+ )
+ compiz_opt_install_file (
+ ${wmproperties_file}
+ ${windowsettingsdatadir}/gnome/wm-properties/compiz-wm.desktop
+ )
+
+
+ if (USE_GNOME_KEYBINDINGS)
+ compiz_translate_xml (
+ ${CMAKE_CURRENT_SOURCE_DIR}/50-compiz-desktop-key.xml.in
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-desktop-key.xml
+ )
+ compiz_translate_xml (
+ ${CMAKE_CURRENT_SOURCE_DIR}/50-compiz-key.xml.in
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-key.xml
+ )
+ set (key_xml
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-desktop-key.xml
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-key.xml
+ )
+ compiz_opt_install_file (
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-desktop-key.xml
+ ${keybindingsdir}/50-compiz-desktop-key.xml
+ )
+ compiz_opt_install_file (
+ ${CMAKE_CURRENT_BINARY_DIR}/50-compiz-key.xml
+ ${keybindingsdir}/50-compiz-key.xml
+ )
+ endif (USE_GNOME_KEYBINDINGS)
+
+ add_library (gnome-compiz MODULE
+ compiz-window-manager.c
+ compiz-window-manager.h
+ ${key_xml}
+ ${desktop_file}
+ ${wmproperties_file}
+ )
+
+
+ set_target_properties (gnome-compiz
+ PROPERTIES OUTPUT_NAME compiz
+ SKIP_BUILD_RPATH 1
+ )
+
+ target_link_libraries (
+ gnome-compiz ${GNOME_WINDOW_SETTINGS_LIBRARIES}
+ )
+
+ compiz_opt_install_file (
+ ${CMAKE_CURRENT_BINARY_DIR}/libcompiz.so
+ ${windowsettingslibdir}/window-manager-settings/libcompiz.so
+ )
+endif (USE_GNOME)
diff --git a/gtk/gnome/compiz-window-manager.c b/gtk/gnome/compiz-window-manager.c
new file mode 100644
index 0000000..c8011fb
--- /dev/null
+++ b/gtk/gnome/compiz-window-manager.c
@@ -0,0 +1,505 @@
+/*
+ * 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/allscreens/options/initiate_button"
+
+#define GCONF_DIR "/apps/metacity/general"
+
+#define COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY \
+ GCONF_DIR "/action_double_click_titlebar"
+
+#define COMPIZ_USE_SYSTEM_FONT_KEY \
+ GCONF_DIR "/titlebar_uses_system_font"
+
+#define COMPIZ_TITLEBAR_FONT_KEY \
+ GCONF_DIR "/titlebar_font"
+
+#define COMPIZ_THEME_KEY \
+ GCONF_DIR "/theme"
+
+enum {
+ DOUBLE_CLICK_SHADE,
+ DOUBLE_CLICK_MAXIMIZE
+};
+
+static GnomeWindowManagerClass *parent_class;
+
+struct _CompizWindowManagerPrivate {
+ GConfClient *gconf;
+ gchar *font;
+ gchar *theme;
+ gchar *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_FONT)
+ gconf_client_set_string (cwm->p->gconf,
+ COMPIZ_TITLEBAR_FONT_KEY,
+ settings->font, NULL);
+
+ 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_THEME)
+ gconf_client_set_string (cwm->p->gconf,
+ COMPIZ_THEME_KEY,
+ settings->theme, NULL);
+
+ 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 (cwm->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_FONT)
+ {
+ char *str;
+
+ str = gconf_client_get_string (cwm->p->gconf,
+ COMPIZ_TITLEBAR_FONT_KEY,
+ NULL);
+
+ if (!str)
+ str = g_strdup ("Sans Bold 12");
+
+ if (cwm->p->font)
+ g_free (cwm->p->font);
+
+ cwm->p->font = str;
+
+ settings->font = cwm->p->font;
+
+ settings->flags |= GNOME_WM_SETTING_FONT;
+ }
+
+ 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 = 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 (cwm->p->mouse_modifier)
+ 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_THEME)
+ {
+ char *str;
+
+ str = gconf_client_get_string (cwm->p->gconf,
+ COMPIZ_THEME_KEY,
+ NULL);
+
+ if (str == NULL)
+ str = g_strdup ("Atlanta");
+
+ g_free (cwm->p->theme);
+ cwm->p->theme = str;
+ settings->theme = cwm->p->theme;
+
+ settings->flags |= GNOME_WM_SETTING_THEME;
+ }
+
+ if (to_get & GNOME_WM_SETTING_DOUBLE_CLICK_ACTION)
+ {
+ char *str;
+
+ settings->double_click_action = DOUBLE_CLICK_MAXIMIZE;
+
+ str = gconf_client_get_string (cwm->p->gconf,
+ COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY,
+ NULL);
+
+ if (str)
+ {
+ 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;
+ }
+
+ settings->flags |= GNOME_WM_SETTING_DOUBLE_CLICK_ACTION;
+ }
+}
+
+static int
+compiz_get_settings_mask (GnomeWindowManager *wm)
+{
+ return GNOME_WM_SETTING_MASK;
+}
+
+static GList *
+add_themes_from_dir (GList *current_list,
+ const char *path)
+{
+ DIR *theme_dir;
+ struct dirent *entry;
+ char *theme_file_path;
+ GList *node;
+ gboolean found = FALSE;
+
+ if (!(g_file_test (path, G_FILE_TEST_EXISTS) &&
+ g_file_test (path, G_FILE_TEST_IS_DIR)))
+ {
+ return current_list;
+ }
+
+ theme_dir = opendir (path);
+
+ /* If this is NULL, then we couldn't open ~/.themes. The test above
+ * only checks existence, not wether we can really read it.*/
+ if (theme_dir == NULL)
+ return current_list;
+
+ for (entry = readdir (theme_dir); entry; entry = readdir (theme_dir))
+ {
+ theme_file_path =
+ g_build_filename (path, entry->d_name,
+ "metacity-1/metacity-theme-1.xml", NULL);
+
+ if (g_file_test (theme_file_path, G_FILE_TEST_EXISTS))
+ {
+
+ for (node = current_list; node && !found; node = node->next)
+ found = strcmp (node->data, entry->d_name) == 0;
+
+ if (!found)
+ current_list = g_list_prepend (current_list,
+ g_strdup (entry->d_name));
+ }
+
+ found = FALSE;
+
+ g_free (theme_file_path);
+ }
+
+ closedir (theme_dir);
+
+ return current_list;
+}
+
+static GList *
+compiz_get_theme_list (GnomeWindowManager *wm)
+{
+ GList *themes = NULL;
+ char *home_dir_themes;
+
+ home_dir_themes = g_build_filename (g_get_home_dir (), ".themes", NULL);
+
+ themes = add_themes_from_dir (themes, METACITY_THEME_DIR);
+ themes = add_themes_from_dir (themes, "/usr/share/themes");
+ themes = add_themes_from_dir (themes, home_dir_themes);
+
+ g_free (home_dir_themes);
+
+ return themes;
+}
+
+static char *
+compiz_get_user_theme_folder (GnomeWindowManager *wm)
+{
+ return g_build_filename (g_get_home_dir (), ".themes", NULL);
+}
+
+static void
+compiz_get_double_click_actions (GnomeWindowManager *wm,
+ const GnomeWMDoubleClickAction **actions_p,
+ int *n_actions_p)
+{
+ static GnomeWMDoubleClickAction actions[] = {
+ { DOUBLE_CLICK_SHADE, "Shade" },
+ { DOUBLE_CLICK_MAXIMIZE, "Maximize" }
+ };
+
+ *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;
+ cwm->p->font = NULL;
+ cwm->p->theme = NULL;
+
+ gconf_client_add_dir (cwm->p->gconf,
+ "/apps/compiz",
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ gconf_client_add_dir (cwm->p->gconf,
+ GCONF_DIR,
+ 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);
+
+ if (cwm->p->mouse_modifier)
+ g_free (cwm->p->mouse_modifier);
+
+ if (cwm->p->font)
+ g_free (cwm->p->font);
+
+ if (cwm->p->theme)
+ g_free (cwm->p->theme);
+
+ 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_user_theme_folder = compiz_get_user_theme_folder;
+ wm_class->get_theme_list = compiz_get_theme_list;
+ 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/gtk/gnome/compiz-window-manager.h b/gtk/gnome/compiz-window-manager.h
new file mode 100644
index 0000000..5506e63
--- /dev/null
+++ b/gtk/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/gtk/gnome/compiz-wm.desktop.in b/gtk/gnome/compiz-wm.desktop.in
new file mode 100644
index 0000000..bb3967a
--- /dev/null
+++ b/gtk/gnome/compiz-wm.desktop.in
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Type=Application
+Encoding=UTF-8
+_Name=Compiz
+Exec=compiz
+# name of loadable control center module
+X-GNOME-WMSettingsModule=compiz
+# autostart phase
+X-GNOME-Autostart-Phase=WindowManager
+X-GNOME-Provides=windowmanager
+# 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/gtk/gnome/compiz.desktop.in b/gtk/gnome/compiz.desktop.in
new file mode 100644
index 0000000..fce1407
--- /dev/null
+++ b/gtk/gnome/compiz.desktop.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Type=Application
+Encoding=UTF-8
+_Name=Compiz
+Exec=compiz
+NoDisplay=true
+# name of loadable control center module
+X-GNOME-WMSettingsModule=compiz
+# autostart phase
+X-GNOME-Autostart-Phase=WindowManager
+X-GNOME-Provides=windowmanager
+# name we put on the WM spec check window
+X-GNOME-WMName=compiz
+# back compat only
+X-GnomeWMSettingsLibrary=compiz
diff --git a/gtk/window-decorator/CMakeLists.txt b/gtk/window-decorator/CMakeLists.txt
new file mode 100644
index 0000000..5182b3a
--- /dev/null
+++ b/gtk/window-decorator/CMakeLists.txt
@@ -0,0 +1,65 @@
+if (USE_GTK)
+
+ if (COMPIZ_BUILD_WITH_RPATH)
+ set (CMAKE_INSTALL_RPATH ${libdir})
+ endif (COMPIZ_BUILD_WITH_RPATH)
+
+ include_directories (
+ ${compiz_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/gtk
+ ${GTK_WINDOW_DECORATOR_INCLUDE_DIRS}
+ ${METACITY_INCLUDE_DIRS}
+ ${GCONF_INCLUDE_DIRS}
+ ${DBUS_GLIB_INCLUDE_DIRS}
+ )
+
+ add_definitions (
+ -DHAVE_CONFIG_H
+ -DALL_LINGUAS=\"${ALL_LINGUAS}\"
+ -DLOCALEDIR=\\\"${datadir}/locale\\\"
+ )
+
+ link_directories (
+ ${COMPIZ_LINK_DIRS}
+ )
+
+ if (USE_GCONF)
+ set (gwd_schema ${CMAKE_CURRENT_BINARY_DIR}/gwd.schemas)
+ compiz_translate_xml (
+ ${CMAKE_CURRENT_SOURCE_DIR}/gwd.schemas.in
+ ${gwd_schema}
+ )
+ compiz_install_gconf_schema (${CMAKE_CURRENT_BINARY_DIR}/gwd.schemas ${SCHEMADIR})
+ endif (USE_GCONF)
+
+ add_executable (gtk-window-decorator
+ gtk-window-decorator.c
+ ${gwd_schema}
+ )
+
+ add_dependencies (gtk-window-decorator decoration)
+
+ if (USE_METACITY)
+ set (metacitylibs ${METACITY_LIBRARIES})
+ endif (USE_METACITY)
+
+
+ target_link_libraries (
+ gtk-window-decorator
+ decoration
+ ${GTK_WINDOW_DECORATOR_LIBRARIES}
+ ${GCONF_LIBRARIES}
+ ${DBUS_GLIB_LIBRARIES}
+ ${metacitylibs}
+ )
+
+ install (
+ TARGETS gtk-window-decorator
+ DESTINATION ${COMPIZ_DESTDIR}${exec_prefix}
+ )
+
+
+endif (USE_GTK)
+
+
+
diff --git a/gtk/window-decorator/TODO b/gtk/window-decorator/TODO
new file mode 100644
index 0000000..d1b8e93
--- /dev/null
+++ b/gtk/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/gtk/window-decorator/gtk-window-decorator.c b/gtk/window-decorator/gtk-window-decorator.c
new file mode 100644
index 0000000..254f5c1
--- /dev/null
+++ b/gtk/window-decorator/gtk-window-decorator.c
@@ -0,0 +1,8045 @@
+/*
+ * 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "decoration.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/cursorfont.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/Xregion.h>
+
+#ifndef GDK_DISABLE_DEPRECATED
+#define GDK_DISABLE_DEPRECATED
+#endif
+
+#ifndef GTK_DISABLE_DEPRECATED
+#define GTK_DISABLE_DEPRECATED
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#ifdef USE_GCONF
+#include <gconf/gconf-client.h>
+#endif
+
+#ifdef USE_DBUS_GLIB
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#endif
+
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include <libwnck/libwnck.h>
+#include <libwnck/window-action-menu.h>
+
+#ifndef HAVE_LIBWNCK_2_19_4
+#define wnck_window_get_client_window_geometry wnck_window_get_geometry
+#endif
+
+#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>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <libintl.h>
+#define _(x) gettext (x)
+#define N_(x) x
+
+#ifdef USE_METACITY
+#include <metacity-private/theme.h>
+#endif
+
+#define METACITY_GCONF_DIR "/apps/metacity/general"
+
+#define COMPIZ_USE_SYSTEM_FONT_KEY \
+ METACITY_GCONF_DIR "/titlebar_uses_system_font"
+
+#define COMPIZ_TITLEBAR_FONT_KEY \
+ METACITY_GCONF_DIR "/titlebar_font"
+
+#define COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY \
+ METACITY_GCONF_DIR "/action_double_click_titlebar"
+
+#define COMPIZ_MIDDLE_CLICK_TITLEBAR_KEY \
+ METACITY_GCONF_DIR "/action_middle_click_titlebar"
+
+#define COMPIZ_RIGHT_CLICK_TITLEBAR_KEY \
+ METACITY_GCONF_DIR "/action_right_click_titlebar"
+
+#define COMPIZ_GCONF_DIR1 "/apps/compiz/plugins/decoration/allscreens/options"
+
+#define COMPIZ_SHADOW_RADIUS_KEY \
+ COMPIZ_GCONF_DIR1 "/shadow_radius"
+
+#define COMPIZ_SHADOW_OPACITY_KEY \
+ COMPIZ_GCONF_DIR1 "/shadow_opacity"
+
+#define COMPIZ_SHADOW_COLOR_KEY \
+ COMPIZ_GCONF_DIR1 "/shadow_color"
+
+#define COMPIZ_SHADOW_OFFSET_X_KEY \
+ COMPIZ_GCONF_DIR1 "/shadow_x_offset"
+
+#define COMPIZ_SHADOW_OFFSET_Y_KEY \
+ COMPIZ_GCONF_DIR1 "/shadow_y_offset"
+
+#define META_THEME_KEY \
+ METACITY_GCONF_DIR "/theme"
+
+#define META_BUTTON_LAYOUT_KEY \
+ METACITY_GCONF_DIR "/button_layout"
+
+#define GCONF_DIR "/apps/gwd"
+
+#define USE_META_THEME_KEY \
+ GCONF_DIR "/use_metacity_theme"
+
+#define META_THEME_OPACITY_KEY \
+ GCONF_DIR "/metacity_theme_opacity"
+
+#define META_THEME_SHADE_OPACITY_KEY \
+ GCONF_DIR "/metacity_theme_shade_opacity"
+
+#define META_THEME_ACTIVE_OPACITY_KEY \
+ GCONF_DIR "/metacity_theme_active_opacity"
+
+#define META_THEME_ACTIVE_SHADE_OPACITY_KEY \
+ GCONF_DIR "/metacity_theme_active_shade_opacity"
+
+#define BLUR_TYPE_KEY \
+ GCONF_DIR "/blur_type"
+
+#define WHEEL_ACTION_KEY \
+ GCONF_DIR "/mouse_wheel_action"
+
+#define DBUS_DEST "org.freedesktop.compiz"
+#define DBUS_PATH "/org/freedesktop/compiz/decoration/allscreens"
+#define DBUS_INTERFACE "org.freedesktop.compiz"
+#define DBUS_METHOD_GET "get"
+
+#define STROKE_ALPHA 0.6
+
+#define ICON_SPACE 20
+
+#define DOUBLE_CLICK_DISTANCE 8.0
+
+#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
+
+#define SHADOW_RADIUS 8.0
+#define SHADOW_OPACITY 0.5
+#define SHADOW_OFFSET_X 1
+#define SHADOW_OFFSET_Y 1
+#define SHADOW_COLOR_RED 0x0000
+#define SHADOW_COLOR_GREEN 0x0000
+#define SHADOW_COLOR_BLUE 0x0000
+
+#define META_OPACITY 0.75
+#define META_SHADE_OPACITY TRUE
+#define META_ACTIVE_OPACITY 1.0
+#define META_ACTIVE_SHADE_OPACITY TRUE
+
+#define META_MAXIMIZED (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY | \
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY)
+
+#define CMDLINE_OPACITY (1 << 0)
+#define CMDLINE_OPACITY_SHADE (1 << 1)
+#define CMDLINE_ACTIVE_OPACITY (1 << 2)
+#define CMDLINE_ACTIVE_OPACITY_SHADE (1 << 3)
+#define CMDLINE_BLUR (1 << 4)
+#define CMDLINE_THEME (1 << 5)
+
+#define MWM_HINTS_DECORATIONS (1L << 1)
+
+#define MWM_DECOR_ALL (1L << 0)
+#define MWM_DECOR_BORDER (1L << 1)
+#define MWM_DECOR_HANDLE (1L << 2)
+#define MWM_DECOR_TITLE (1L << 3)
+#define MWM_DECOR_MENU (1L << 4)
+#define MWM_DECOR_MINIMIZE (1L << 5)
+#define MWM_DECOR_MAXIMIZE (1L << 6)
+
+#define PROP_MOTIF_WM_HINT_ELEMENTS 3
+
+typedef struct {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+} MwmHints;
+
+enum {
+ CLICK_ACTION_NONE,
+ CLICK_ACTION_SHADE,
+ CLICK_ACTION_MAXIMIZE,
+ CLICK_ACTION_MINIMIZE,
+ CLICK_ACTION_RAISE,
+ CLICK_ACTION_LOWER,
+ CLICK_ACTION_MENU
+};
+
+enum {
+ WHEEL_ACTION_NONE,
+ WHEEL_ACTION_SHADE
+};
+
+#define DOUBLE_CLICK_ACTION_DEFAULT CLICK_ACTION_MAXIMIZE
+#define MIDDLE_CLICK_ACTION_DEFAULT CLICK_ACTION_LOWER
+#define RIGHT_CLICK_ACTION_DEFAULT CLICK_ACTION_MENU
+#define WHEEL_ACTION_DEFAULT WHEEL_ACTION_NONE
+
+int double_click_action = DOUBLE_CLICK_ACTION_DEFAULT;
+int middle_click_action = MIDDLE_CLICK_ACTION_DEFAULT;
+int right_click_action = RIGHT_CLICK_ACTION_DEFAULT;
+int wheel_action = WHEEL_ACTION_DEFAULT;
+
+static gboolean minimal = FALSE;
+
+static double decoration_alpha = 0.5;
+
+#define SWITCHER_SPACE 40
+
+static decor_extents_t _shadow_extents = { 0, 0, 0, 0 };
+static decor_extents_t _win_extents = { 6, 6, 6, 6 };
+static decor_extents_t _max_win_extents = { 6, 6, 4, 6 };
+static decor_extents_t _default_win_extents = { 6, 6, 6, 6 };
+static decor_extents_t _switcher_extents = { 6, 6, 6, 6 + SWITCHER_SPACE };
+
+static int titlebar_height = 17;
+static int max_titlebar_height = 17;
+
+static decor_context_t window_context = {
+ { 0, 0, 0, 0 },
+ 6, 6, 4, 6,
+ 0, 0, 0, 0
+};
+
+static decor_context_t max_window_context = {
+ { 0, 0, 0, 0 },
+ 6, 6, 4, 6,
+ 0, 0, 0, 0
+};
+
+static decor_context_t switcher_context = {
+ { 0, 0, 0, 0 },
+ 6, 6, 6, 6 + SWITCHER_SPACE,
+ 0, 0, 0, 0
+};
+
+static decor_context_t shadow_context = {
+ { 0, 0, 0, 0 },
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+
+static gdouble shadow_radius = SHADOW_RADIUS;
+static gdouble shadow_opacity = SHADOW_OPACITY;
+static gushort shadow_color[3] = {
+ SHADOW_COLOR_RED,
+ SHADOW_COLOR_GREEN,
+ SHADOW_COLOR_BLUE
+};
+static gint shadow_offset_x = SHADOW_OFFSET_X;
+static gint shadow_offset_y = SHADOW_OFFSET_Y;
+
+#ifdef USE_METACITY
+static double meta_opacity = META_OPACITY;
+static gboolean meta_shade_opacity = META_SHADE_OPACITY;
+static double meta_active_opacity = META_ACTIVE_OPACITY;
+static gboolean meta_active_shade_opacity = META_ACTIVE_SHADE_OPACITY;
+
+static gboolean meta_button_layout_set = FALSE;
+static MetaButtonLayout meta_button_layout;
+#endif
+
+static guint cmdline_options = 0;
+
+static decor_shadow_t *no_border_shadow = NULL;
+static decor_shadow_t *border_shadow = NULL;
+static decor_shadow_t *max_border_shadow = NULL;
+static decor_shadow_t *switcher_shadow = NULL;
+
+static GdkPixmap *decor_normal_pixmap = NULL;
+static GdkPixmap *decor_active_pixmap = NULL;
+
+static Atom frame_input_window_atom;
+static Atom frame_output_window_atom;
+static Atom win_decor_atom;
+static Atom win_blur_decor_atom;
+static Atom wm_move_resize_atom;
+static Atom restack_window_atom;
+static Atom select_window_atom;
+static Atom mwm_hints_atom;
+static Atom switcher_fg_atom;
+
+static Atom toolkit_action_atom;
+static Atom toolkit_action_window_menu_atom;
+static Atom toolkit_action_force_quit_dialog_atom;
+
+static Time dm_sn_timestamp;
+
+#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) }
+};
+
+#define BUTTON_CLOSE 0
+#define BUTTON_MAX 1
+#define BUTTON_MIN 2
+#define BUTTON_MENU 3
+#define BUTTON_SHADE 4
+#define BUTTON_ABOVE 5
+#define BUTTON_STICK 6
+#define BUTTON_UNSHADE 7
+#define BUTTON_UNABOVE 8
+#define BUTTON_UNSTICK 9
+#define BUTTON_NUM 10
+
+static struct _pos {
+ int x, y, w, h;
+ int xw, yh, ww, hh, yth, hth;
+} pos[3][3] = {
+ {
+ { 0, 0, 10, 21, 0, 0, 0, 0, 0, 1 },
+ { 10, 0, -8, 6, 0, 0, 1, 0, 0, 1 },
+ { 2, 0, 10, 21, 1, 0, 0, 0, 0, 1 }
+ }, {
+ { 0, 10, 6, 11, 0, 0, 0, 1, 1, 0 },
+ { 6, 6, 0, 15, 0, 0, 1, 0, 0, 1 },
+ { 6, 10, 6, 11, 1, 0, 0, 1, 1, 0 }
+ }, {
+ { 0, 17, 10, 10, 0, 1, 0, 0, 1, 0 },
+ { 10, 21, -8, 6, 0, 1, 1, 0, 1, 0 },
+ { 2, 17, 10, 10, 1, 1, 0, 0, 1, 0 }
+ }
+}, bpos[] = {
+ { 0, 6, 16, 16, 1, 0, 0, 0, 0, 0 },
+ { 0, 6, 16, 16, 1, 0, 0, 0, 0, 0 },
+ { 0, 6, 16, 16, 1, 0, 0, 0, 0, 0 },
+ { 6, 2, 16, 16, 0, 0, 0, 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_event {
+ guint time;
+ guint window;
+ guint x;
+ guint y;
+ guint x_root;
+ guint y_root;
+ guint button;
+} decor_event;
+
+typedef enum _decor_event_type {
+ GButtonPress = 1,
+ GButtonRelease,
+ GEnterNotify,
+ GLeaveNotify,
+ GMotionNotify
+} decor_event_type;
+
+typedef void (*event_callback) (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type);
+
+typedef struct {
+ Window window;
+ Box pos;
+ event_callback callback;
+} event_window;
+
+typedef struct _decor {
+ WnckWindow *win;
+ event_window event_windows[3][3];
+ event_window button_windows[BUTTON_NUM];
+ Box *last_pos_entered;
+ guint button_states[BUTTON_NUM];
+ GdkPixmap *pixmap;
+ GdkPixmap *buffer_pixmap;
+ GdkWindow *frame_window;
+ GtkWidget *decor_window;
+ GtkWidget *decor_event_box;
+ GtkWidget *decor_image;
+ GdkGC *gc;
+ decor_layout_t border_layout;
+ decor_context_t *context;
+ decor_shadow_t *shadow;
+ Picture picture;
+ gint button_width;
+ gint width;
+ gint height;
+ gint client_width;
+ gint client_height;
+ gboolean decorated;
+ gboolean active;
+ PangoLayout *layout;
+ gchar *name;
+ cairo_pattern_t *icon;
+ GdkPixmap *icon_pixmap;
+ GdkPixbuf *icon_pixbuf;
+ WnckWindowState state;
+ WnckWindowActions actions;
+ XID prop_xid;
+ GtkWidget *force_quit_dialog;
+ Bool created;
+ void (*draw) (struct _decor *d);
+} decor_t;
+
+void (*theme_draw_window_decoration) (decor_t *d);
+gboolean (*theme_calc_decoration_size) (decor_t *d,
+ int client_width,
+ int client_height,
+ int text_width,
+ int *width,
+ int *height);
+void (*theme_update_border_extents) (gint text_height);
+void (*theme_get_event_window_position) (decor_t *d,
+ gint i,
+ gint j,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
+gboolean (*theme_get_button_position) (decor_t *d,
+ gint i,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h);
+
+static char *program_name;
+
+static GtkWidget *style_window_rgba;
+static GtkWidget *style_window_rgb;
+static GtkWidget *switcher_label;
+
+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 = { 0, 0 };
+static gint tooltip_timer_tag = 0;
+
+static GSList *draw_list = NULL;
+static guint draw_idle_id = 0;
+
+static PangoFontDescription *titlebar_font = NULL;
+static gboolean use_system_font = FALSE;
+static gint text_height;
+
+#define BLUR_TYPE_NONE 0
+#define BLUR_TYPE_TITLEBAR 1
+#define BLUR_TYPE_ALL 2
+
+static gint blur_type = BLUR_TYPE_NONE;
+
+static GdkPixmap *switcher_pixmap = NULL;
+static GdkPixmap *switcher_buffer_pixmap = NULL;
+static gint switcher_width;
+static gint switcher_height;
+static Window switcher_selected_window = None;
+
+static XRenderPictFormat *xformat_rgba;
+static XRenderPictFormat *xformat_rgb;
+
+static void
+decor_update_blur_property (decor_t *d,
+ int width,
+ int height,
+ Region top_region,
+ int top_offset,
+ Region bottom_region,
+ int bottom_offset,
+ Region left_region,
+ int left_offset,
+ Region right_region,
+ int right_offset)
+{
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ long *data = NULL;
+ int size = 0;
+
+ if (blur_type != BLUR_TYPE_ALL)
+ {
+ bottom_region = NULL;
+ left_region = NULL;
+ right_region = NULL;
+
+ if (blur_type != BLUR_TYPE_TITLEBAR)
+ top_region = NULL;
+ }
+
+ if (top_region)
+ size += top_region->numRects;
+ if (bottom_region)
+ size += bottom_region->numRects;
+ if (left_region)
+ size += left_region->numRects;
+ if (right_region)
+ size += right_region->numRects;
+
+ if (size)
+ data = malloc (sizeof (long) * (2 + size * 6));
+
+ if (data)
+ {
+ decor_region_to_blur_property (data, 4, 0, width, height,
+ top_region, top_offset,
+ bottom_region, bottom_offset,
+ left_region, left_offset,
+ right_region, right_offset);
+
+ gdk_error_trap_push ();
+ XChangeProperty (xdisplay, d->prop_xid,
+ win_blur_decor_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ 2 + size * 6);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+
+ free (data);
+ }
+ else
+ {
+ gdk_error_trap_push ();
+ XDeleteProperty (xdisplay, d->prop_xid, win_blur_decor_atom);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+ }
+}
+
+static void
+decor_update_window_property (decor_t *d)
+{
+ long data[256];
+ Display *xdisplay =
+ GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ decor_extents_t extents = _win_extents;
+ gint nQuad;
+ decor_quad_t quads[N_QUADS_MAX];
+ int w, h;
+ gint stretch_offset;
+ REGION top, bottom, left, right;
+
+ w = d->border_layout.top.x2 - d->border_layout.top.x1 -
+ d->context->left_space - d->context->right_space;
+
+ if (d->border_layout.rotation)
+ h = d->border_layout.left.x2 - d->border_layout.left.x1;
+ else
+ h = d->border_layout.left.y2 - d->border_layout.left.y1;
+
+ stretch_offset = w - d->button_width - 1;
+
+ nQuad = decor_set_lSrStXbS_window_quads (quads, d->context,
+ &d->border_layout,
+ stretch_offset);
+
+ extents.top += titlebar_height;
+
+ if (d->frame_window)
+ {
+ decor_gen_window_property (data, &extents, &extents, 20, 20);
+ }
+ else
+ {
+ decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap),
+ &extents, &extents,
+ ICON_SPACE + d->button_width,
+ 0,
+ quads, nQuad);
+ }
+
+ gdk_error_trap_push ();
+ XChangeProperty (xdisplay, d->prop_xid,
+ win_decor_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+
+ top.rects = &top.extents;
+ top.numRects = top.size = 1;
+
+ top.extents.x1 = -extents.left;
+ top.extents.y1 = -extents.top;
+ top.extents.x2 = w + extents.right;
+ top.extents.y2 = 0;
+
+ bottom.rects = &bottom.extents;
+ bottom.numRects = bottom.size = 1;
+
+ bottom.extents.x1 = -extents.left;
+ bottom.extents.y1 = 0;
+ bottom.extents.x2 = w + extents.right;
+ bottom.extents.y2 = extents.bottom;
+
+ left.rects = &left.extents;
+ left.numRects = left.size = 1;
+
+ left.extents.x1 = -extents.left;
+ left.extents.y1 = 0;
+ left.extents.x2 = 0;
+ left.extents.y2 = h;
+
+ right.rects = &right.extents;
+ right.numRects = right.size = 1;
+
+ right.extents.x1 = 0;
+ right.extents.y1 = 0;
+ right.extents.x2 = extents.right;
+ right.extents.y2 = h;
+
+ decor_update_blur_property (d,
+ w, h,
+ &top, stretch_offset,
+ &bottom, w / 2,
+ &left, h / 2,
+ &right, h / 2);
+}
+
+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);
+}
+
+static inline GdkWindow *
+create_gdk_window (Window xframe)
+{
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkScreen *screen = gdk_display_get_default_screen (display);
+ GdkWindow *window = gdk_window_foreign_new (xframe);
+ GdkColormap *cmap = gdk_screen_get_rgb_colormap (screen);
+
+ gdk_drawable_set_colormap (GDK_DRAWABLE (window), cmap);
+
+ return window;
+}
+
+static GdkColormap *
+get_colormap_for_drawable (GdkDrawable *d)
+{
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkScreen *screen = gdk_display_get_default_screen (display);
+
+ if (gdk_drawable_get_depth (d) == 32)
+ return gdk_screen_get_rgba_colormap (screen);
+
+ return gdk_screen_get_rgb_colormap (screen);
+}
+
+static XRenderPictFormat *
+get_format_for_drawable (decor_t *d, GdkDrawable *drawable)
+{
+ if (!d->frame_window || gdk_drawable_get_depth (drawable) == 32)
+ return xformat_rgba;
+
+ return xformat_rgb;
+}
+
+static GdkPixmap *
+create_pixmap (int w,
+ int h,
+ int depth)
+{
+ GtkWidget *widget;
+ GdkWindow *window;
+
+ if (w == 0 || h == 0)
+ abort ();
+
+ widget = (depth > 24) ? style_window_rgba : style_window_rgb;
+ window = gtk_widget_get_window (widget);
+ return gdk_pixmap_new (GDK_DRAWABLE (window), w, h, depth);
+}
+
+#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,
+ decor_shadow_t *s,
+ decor_context_t *c)
+{
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ if (!s || !s->picture ||!d->picture)
+ {
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
+ cairo_paint (cr);
+ }
+ else
+ {
+ decor_fill_picture_extents_with_shadow (xdisplay,
+ s, c,
+ d->picture,
+ &d->border_layout);
+ }
+}
+
+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);
+}
+
+typedef void (*draw_proc) (cairo_t *cr);
+
+static void
+button_state_offsets (gdouble x,
+ gdouble y,
+ guint state,
+ gdouble *return_x,
+ gdouble *return_y)
+{
+ static double off[] = { 0.0, 0.0, 0.0, 0.5 };
+
+ *return_x = x + off[state];
+ *return_y = y + off[state];
+}
+
+static void
+button_state_paint (cairo_t *cr,
+ GtkStyle *style,
+ decor_color_t *color,
+ guint state)
+{
+
+#define IN_STATE (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)
+
+ if ((state & IN_STATE) == IN_STATE)
+ {
+ if (state & 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_fill_preserve (cr);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ STROKE_ALPHA);
+
+ cairo_set_line_width (cr, 1.0);
+ cairo_stroke (cr);
+ cairo_set_line_width (cr, 2.0);
+ }
+ else
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ STROKE_ALPHA);
+ cairo_stroke_preserve (cr);
+
+ if (state & 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_fill (cr);
+ }
+}
+
+static void
+draw_window_decoration (decor_t *d)
+{
+ cairo_t *cr;
+ GtkStyle *style;
+ GdkDrawable *drawable;
+ decor_color_t color;
+ double alpha;
+ double x1, y1, x2, y2, x, y, h;
+ int corners = SHADE_LEFT | SHADE_RIGHT | SHADE_TOP | SHADE_BOTTOM;
+ int top;
+ int button_x;
+
+ if (!d->pixmap)
+ return;
+
+ style = gtk_widget_get_style (style_window_rgba);
+
+ 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->frame_window)
+ {
+ GdkColormap *cmap;
+
+ cmap = get_colormap_for_drawable (GDK_DRAWABLE (d->pixmap));
+ gdk_drawable_set_colormap (GDK_DRAWABLE (d->pixmap), cmap);
+ gdk_drawable_set_colormap (GDK_DRAWABLE (d->buffer_pixmap), cmap);
+ drawable = GDK_DRAWABLE (d->buffer_pixmap);
+ }
+ else if (d->buffer_pixmap)
+ drawable = GDK_DRAWABLE (d->buffer_pixmap);
+ else
+ drawable = GDK_DRAWABLE (d->pixmap);
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (drawable));
+ if (!cr)
+ return;
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ top = _win_extents.top + titlebar_height;
+
+ x1 = d->context->left_space - _win_extents.left;
+ y1 = d->context->top_space - _win_extents.top - titlebar_height;
+ x2 = d->width - d->context->right_space + _win_extents.right;
+ y2 = d->height - d->context->bottom_space + _win_extents.bottom;
+
+ h = d->height - d->context->top_space - d->context->bottom_space;
+
+ cairo_set_line_width (cr, 1.0);
+
+ if (!d->frame_window)
+ draw_shadow_background (d, cr, d->shadow, d->context);
+
+ if (d->active)
+ {
+ decor_color_t *title_color = _title_color;
+
+ alpha = decoration_alpha + 0.3;
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + 0.5,
+ _win_extents.left - 0.5,
+ 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,
+ 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,
+ top - 0.5,
+ 5.0, CORNER_TOPRIGHT & corners,
+ &title_color[0], 1.0, &title_color[1], alpha,
+ SHADE_TOP | SHADE_RIGHT);
+ }
+ else
+ {
+ alpha = decoration_alpha;
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + 0.5,
+ _win_extents.left - 0.5,
+ 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,
+ 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,
+ 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 + top,
+ _win_extents.left - 0.5,
+ h,
+ 5.0, 0,
+ &color, 1.0, &color, alpha,
+ SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x2 - _win_extents.right,
+ y1 + top,
+ _win_extents.right - 0.5,
+ h,
+ 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,
+ d->context->left_space,
+ d->context->top_space,
+ d->width - d->context->left_space -
+ d->context->right_space,
+ h);
+ 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 + 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);
+
+ cairo_set_line_width (cr, 2.0);
+
+ button_x = d->width - d->context->right_space - 13;
+
+ if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
+ {
+ button_state_offsets (button_x,
+ y1 - 3.0 + titlebar_height / 2,
+ d->button_states[BUTTON_CLOSE], &x, &y);
+
+ button_x -= 17;
+
+ if (d->active)
+ {
+ cairo_move_to (cr, x, y);
+ draw_close_button (d, cr, 3.0);
+ button_state_paint (cr, style, &color,
+ d->button_states[BUTTON_CLOSE]);
+ }
+ 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 (button_x,
+ y1 - 3.0 + titlebar_height / 2,
+ d->button_states[BUTTON_MAX], &x, &y);
+
+ button_x -= 17;
+
+ 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],
+ STROKE_ALPHA);
+
+ 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);
+
+ button_state_paint (cr, style, &color,
+ d->button_states[BUTTON_MAX]);
+ }
+ 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 (button_x,
+ y1 - 3.0 + titlebar_height / 2,
+ d->button_states[BUTTON_MIN], &x, &y);
+
+ button_x -= 17;
+
+ if (d->active)
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ STROKE_ALPHA);
+
+
+ cairo_move_to (cr, x, y);
+ draw_min_button (d, cr, 4.0);
+ button_state_paint (cr, style, &color,
+ d->button_states[BUTTON_MIN]);
+ }
+ 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)
+ {
+ if (d->active)
+ {
+ cairo_move_to (cr,
+ d->context->left_space + 21.0,
+ y1 + 2.0 + (titlebar_height - text_height) / 2.0);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ STROKE_ALPHA);
+
+ pango_cairo_layout_path (cr, d->layout);
+ cairo_stroke (cr);
+
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ }
+ else
+ {
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+ }
+
+ cairo_move_to (cr,
+ d->context->left_space + 21.0,
+ y1 + 2.0 + (titlebar_height - text_height) / 2.0);
+
+ pango_cairo_show_layout (cr, d->layout);
+ }
+
+ if (d->icon)
+ {
+ cairo_translate (cr, d->context->left_space + 1,
+ y1 - 5.0 + titlebar_height / 2);
+ 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->frame_window)
+ {
+ GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window);
+
+ gtk_image_set_from_pixmap (GTK_IMAGE (d->decor_image), d->pixmap, NULL);
+ gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height);
+ gdk_window_reparent (gdk_frame_window, d->frame_window,
+ -_win_extents.left - 2, -_win_extents.top - 2);
+ gdk_window_lower (gdk_frame_window);
+ }
+
+ if (d->prop_xid)
+ {
+ decor_update_window_property (d);
+ d->prop_xid = 0;
+ }
+}
+
+#ifdef USE_METACITY
+static void
+decor_update_meta_window_property (decor_t *d,
+ MetaTheme *theme,
+ MetaFrameFlags flags,
+ Region top,
+ Region bottom,
+ Region left,
+ Region right)
+{
+ long data[256];
+ Display *xdisplay =
+ GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ gint nQuad;
+ decor_extents_t extents, max_extents;
+ decor_quad_t quads[N_QUADS_MAX];
+ gint w, lh, rh;
+ gint top_stretch_offset;
+ gint bottom_stretch_offset;
+ gint left_stretch_offset;
+ gint right_stretch_offset;
+
+ w = d->border_layout.top.x2 - d->border_layout.top.x1 -
+ d->context->left_space - d->context->right_space;
+
+ if (d->border_layout.rotation)
+ lh = d->border_layout.left.x2 - d->border_layout.left.x1;
+ else
+ lh = d->border_layout.left.y2 - d->border_layout.left.y1;
+
+ if (d->border_layout.rotation)
+ rh = d->border_layout.right.x2 - d->border_layout.right.x1;
+ else
+ rh = d->border_layout.right.y2 - d->border_layout.right.y1;
+
+ left_stretch_offset = lh / 2;
+ right_stretch_offset = rh / 2;
+ top_stretch_offset = w - d->button_width - 1;
+ bottom_stretch_offset = (d->border_layout.bottom.x2 -
+ d->border_layout.bottom.x1 -
+ d->context->left_space -
+ d->context->right_space) / 2;
+
+ nQuad = decor_set_lXrXtXbX_window_quads (quads, d->context,
+ &d->border_layout,
+ left_stretch_offset,
+ right_stretch_offset,
+ top_stretch_offset,
+ bottom_stretch_offset);
+
+ extents = _win_extents;
+ max_extents = _max_win_extents;
+
+ extents.top += titlebar_height;
+ max_extents.top += max_titlebar_height;
+
+ if (d->frame_window)
+ decor_gen_window_property (data, &extents, &max_extents, 20, 20);
+ else
+ decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap),
+ &extents, &max_extents,
+ ICON_SPACE + d->button_width,
+ 0,
+ quads, nQuad);
+
+ gdk_error_trap_push ();
+ XChangeProperty (xdisplay, d->prop_xid,
+ win_decor_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+
+ decor_update_blur_property (d,
+ w, lh,
+ top, top_stretch_offset,
+ bottom, bottom_stretch_offset,
+ left, left_stretch_offset,
+ right, right_stretch_offset);
+}
+
+static void
+meta_get_corner_radius (const MetaFrameGeometry *fgeom,
+ int *top_left_radius,
+ int *top_right_radius,
+ int *bottom_left_radius,
+ int *bottom_right_radius)
+{
+
+#ifdef HAVE_METACITY_2_17_0
+ *top_left_radius = fgeom->top_left_corner_rounded_radius;
+ *top_right_radius = fgeom->top_right_corner_rounded_radius;
+ *bottom_left_radius = fgeom->bottom_left_corner_rounded_radius;
+ *bottom_right_radius = fgeom->bottom_right_corner_rounded_radius;
+#else
+ *top_left_radius = fgeom->top_left_corner_rounded ? 5 : 0;
+ *top_right_radius = fgeom->top_right_corner_rounded ? 5 : 0;
+ *bottom_left_radius = fgeom->bottom_left_corner_rounded ? 5 : 0;
+ *bottom_right_radius = fgeom->bottom_right_corner_rounded ? 5 : 0;
+#endif
+
+}
+
+static int
+radius_to_width (int radius,
+ int i)
+{
+ float r1 = sqrt (radius) + radius;
+ float r2 = r1 * r1 - (r1 - (i + 0.5)) * (r1 - (i + 0.5));
+
+ return floor (0.5f + r1 - sqrt (r2));
+}
+
+static Region
+meta_get_top_border_region (const MetaFrameGeometry *fgeom,
+ int width)
+{
+ Region corners_xregion, border_xregion;
+ XRectangle xrect;
+ int top_left_radius;
+ int top_right_radius;
+ int bottom_left_radius;
+ int bottom_right_radius;
+ int w, i;
+
+ corners_xregion = XCreateRegion ();
+
+ meta_get_corner_radius (fgeom,
+ &top_left_radius,
+ &top_right_radius,
+ &bottom_left_radius,
+ &bottom_right_radius);
+
+ if (top_left_radius)
+ {
+ for (i = 0; i < top_left_radius; i++)
+ {
+ w = radius_to_width (top_left_radius, i);
+
+ xrect.x = 0;
+ xrect.y = i;
+ xrect.width = w;
+ xrect.height = 1;
+
+ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
+ }
+ }
+
+ if (top_right_radius)
+ {
+ for (i = 0; i < top_right_radius; i++)
+ {
+ w = radius_to_width (top_right_radius, i);
+
+ xrect.x = width - w;
+ xrect.y = i;
+ xrect.width = w;
+ xrect.height = 1;
+
+ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
+ }
+ }
+
+ border_xregion = XCreateRegion ();
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = width;
+ xrect.height = fgeom->top_height;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+ XSubtractRegion (border_xregion, corners_xregion, border_xregion);
+
+ XDestroyRegion (corners_xregion);
+
+ return border_xregion;
+}
+
+static Region
+meta_get_bottom_border_region (const MetaFrameGeometry *fgeom,
+ int width)
+{
+ Region corners_xregion, border_xregion;
+ XRectangle xrect;
+ int top_left_radius;
+ int top_right_radius;
+ int bottom_left_radius;
+ int bottom_right_radius;
+ int w, i;
+
+ corners_xregion = XCreateRegion ();
+
+ meta_get_corner_radius (fgeom,
+ &top_left_radius,
+ &top_right_radius,
+ &bottom_left_radius,
+ &bottom_right_radius);
+
+ if (bottom_left_radius)
+ {
+ for (i = 0; i < bottom_left_radius; i++)
+ {
+ w = radius_to_width (bottom_left_radius, i);
+
+ xrect.x = 0;
+ xrect.y = fgeom->bottom_height - i - 1;
+ xrect.width = w;
+ xrect.height = 1;
+
+ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
+ }
+ }
+
+ if (bottom_right_radius)
+ {
+ for (i = 0; i < bottom_right_radius; i++)
+ {
+ w = radius_to_width (bottom_right_radius, i);
+
+ xrect.x = width - w;
+ xrect.y = fgeom->bottom_height - i - 1;
+ xrect.width = w;
+ xrect.height = 1;
+
+ XUnionRectWithRegion (&xrect, corners_xregion, corners_xregion);
+ }
+ }
+
+ border_xregion = XCreateRegion ();
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = width;
+ xrect.height = fgeom->bottom_height;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+ XSubtractRegion (border_xregion, corners_xregion, border_xregion);
+
+ XDestroyRegion (corners_xregion);
+
+ return border_xregion;
+}
+
+static Region
+meta_get_left_border_region (const MetaFrameGeometry *fgeom,
+ int height)
+{
+ Region border_xregion;
+ XRectangle xrect;
+
+ border_xregion = XCreateRegion ();
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = fgeom->left_width;
+ xrect.height = height - fgeom->top_height - fgeom->bottom_height;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+ return border_xregion;
+}
+
+static Region
+meta_get_right_border_region (const MetaFrameGeometry *fgeom,
+ int height)
+{
+ Region border_xregion;
+ XRectangle xrect;
+
+ border_xregion = XCreateRegion ();
+
+ xrect.x = 0;
+ xrect.y = 0;
+ xrect.width = fgeom->right_width;
+ xrect.height = height - fgeom->top_height - fgeom->bottom_height;
+
+ XUnionRectWithRegion (&xrect, border_xregion, border_xregion);
+
+ return border_xregion;
+}
+
+static MetaButtonState
+meta_button_state (int state)
+{
+ if (state & IN_EVENT_WINDOW)
+ {
+ if (state & PRESSED_EVENT_WINDOW)
+ return META_BUTTON_STATE_PRESSED;
+
+ return META_BUTTON_STATE_PRELIGHT;
+ }
+
+ return META_BUTTON_STATE_NORMAL;
+}
+
+static MetaButtonType
+meta_function_to_type (MetaButtonFunction function)
+{
+ switch (function) {
+ case META_BUTTON_FUNCTION_MENU:
+ return META_BUTTON_TYPE_MENU;
+ case META_BUTTON_FUNCTION_MINIMIZE:
+ return META_BUTTON_TYPE_MINIMIZE;
+ case META_BUTTON_FUNCTION_MAXIMIZE:
+ return META_BUTTON_TYPE_MAXIMIZE;
+ case META_BUTTON_FUNCTION_CLOSE:
+ return META_BUTTON_TYPE_CLOSE;
+
+#ifdef HAVE_METACITY_2_17_0
+ case META_BUTTON_FUNCTION_SHADE:
+ return META_BUTTON_TYPE_SHADE;
+ case META_BUTTON_FUNCTION_ABOVE:
+ return META_BUTTON_TYPE_ABOVE;
+ case META_BUTTON_FUNCTION_STICK:
+ return META_BUTTON_TYPE_STICK;
+ case META_BUTTON_FUNCTION_UNSHADE:
+ return META_BUTTON_TYPE_UNSHADE;
+ case META_BUTTON_FUNCTION_UNABOVE:
+ return META_BUTTON_TYPE_UNABOVE;
+ case META_BUTTON_FUNCTION_UNSTICK:
+ return META_BUTTON_TYPE_UNSTICK;
+#endif
+
+ default:
+ break;
+ }
+
+ return META_BUTTON_TYPE_LAST;
+}
+
+static MetaButtonState
+meta_button_state_for_button_type (decor_t *d,
+ MetaButtonType type)
+{
+ switch (type) {
+ case META_BUTTON_TYPE_LEFT_LEFT_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.left_buttons[0]);
+ break;
+ case META_BUTTON_TYPE_LEFT_MIDDLE_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.left_buttons[1]);
+ break;
+ case META_BUTTON_TYPE_LEFT_RIGHT_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.left_buttons[2]);
+ break;
+ case META_BUTTON_TYPE_RIGHT_LEFT_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.right_buttons[0]);
+ break;
+ case META_BUTTON_TYPE_RIGHT_MIDDLE_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.right_buttons[1]);
+ break;
+ case META_BUTTON_TYPE_RIGHT_RIGHT_BACKGROUND:
+ type = meta_function_to_type (meta_button_layout.right_buttons[2]);
+ default:
+ break;
+ }
+
+ switch (type) {
+ case META_BUTTON_TYPE_CLOSE:
+ return meta_button_state (d->button_states[BUTTON_CLOSE]);
+ case META_BUTTON_TYPE_MAXIMIZE:
+ return meta_button_state (d->button_states[BUTTON_MAX]);
+ case META_BUTTON_TYPE_MINIMIZE:
+ return meta_button_state (d->button_states[BUTTON_MIN]);
+ case META_BUTTON_TYPE_MENU:
+ return meta_button_state (d->button_states[BUTTON_MENU]);
+
+#ifdef HAVE_METACITY_2_17_0
+ case META_BUTTON_TYPE_SHADE:
+ return meta_button_state (d->button_states[BUTTON_SHADE]);
+ case META_BUTTON_TYPE_ABOVE:
+ return meta_button_state (d->button_states[BUTTON_ABOVE]);
+ case META_BUTTON_TYPE_STICK:
+ return meta_button_state (d->button_states[BUTTON_STICK]);
+ case META_BUTTON_TYPE_UNSHADE:
+ return meta_button_state (d->button_states[BUTTON_UNSHADE]);
+ case META_BUTTON_TYPE_UNABOVE:
+ return meta_button_state (d->button_states[BUTTON_UNABOVE]);
+ case META_BUTTON_TYPE_UNSTICK:
+ return meta_button_state (d->button_states[BUTTON_UNSTICK]);
+#endif
+
+ default:
+ break;
+ }
+
+ return META_BUTTON_STATE_NORMAL;
+}
+
+static void
+meta_get_decoration_geometry (decor_t *d,
+ MetaTheme *theme,
+ MetaFrameFlags *flags,
+ MetaFrameGeometry *fgeom,
+ MetaButtonLayout *button_layout,
+ GdkRectangle *clip)
+{
+ gint left_width, right_width, top_height, bottom_height;
+
+ if (meta_button_layout_set)
+ {
+ *button_layout = meta_button_layout;
+ }
+ else
+ {
+ gint i;
+
+ button_layout->left_buttons[0] = META_BUTTON_FUNCTION_MENU;
+
+ for (i = 1; i < MAX_BUTTONS_PER_CORNER; i++)
+ button_layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
+
+ button_layout->right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
+ button_layout->right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
+ button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
+
+ for (i = 3; i < MAX_BUTTONS_PER_CORNER; i++)
+ button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
+ }
+
+ *flags = 0;
+
+ if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
+ *flags |= META_FRAME_ALLOWS_DELETE;
+
+ if (d->actions & WNCK_WINDOW_ACTION_MINIMIZE)
+ *flags |= META_FRAME_ALLOWS_MINIMIZE;
+
+ if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
+ *flags |= META_FRAME_ALLOWS_MAXIMIZE;
+
+ *flags |= META_FRAME_ALLOWS_MENU;
+
+ if (d->actions & WNCK_WINDOW_ACTION_RESIZE)
+ {
+ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ *flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
+ if (!(d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY))
+ *flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE;
+ }
+
+ if (d->actions & WNCK_WINDOW_ACTION_MOVE)
+ *flags |= META_FRAME_ALLOWS_MOVE;
+
+ if (d->actions & WNCK_WINDOW_ACTION_MAXIMIZE)
+ *flags |= META_FRAME_ALLOWS_MAXIMIZE;
+
+ if (d->actions & WNCK_WINDOW_ACTION_SHADE)
+ *flags |= META_FRAME_ALLOWS_SHADE;
+
+ if (d->active)
+ *flags |= META_FRAME_HAS_FOCUS;
+
+ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
+ *flags |= META_FRAME_MAXIMIZED;
+
+ if (d->state & WNCK_WINDOW_STATE_STICKY)
+ *flags |= META_FRAME_STUCK;
+
+ if (d->state & WNCK_WINDOW_STATE_FULLSCREEN)
+ *flags |= META_FRAME_FULLSCREEN;
+
+ if (d->state & WNCK_WINDOW_STATE_SHADED)
+ *flags |= META_FRAME_SHADED;
+
+#ifdef HAVE_METACITY_2_17_0
+ if (d->state & WNCK_WINDOW_STATE_ABOVE)
+ *flags |= META_FRAME_ABOVE;
+#endif
+
+ meta_theme_get_frame_borders (theme,
+ META_FRAME_TYPE_NORMAL,
+ text_height,
+ *flags,
+ &top_height,
+ &bottom_height,
+ &left_width,
+ &right_width);
+
+ clip->x = d->context->left_space - left_width;
+ clip->y = d->context->top_space - top_height;
+
+ clip->width = d->border_layout.top.x2 - d->border_layout.top.x1;
+ clip->width -= d->context->right_space + d->context->left_space;
+
+ if (d->border_layout.rotation)
+ clip->height = d->border_layout.left.x2 - d->border_layout.left.x1;
+ else
+ clip->height = d->border_layout.left.y2 - d->border_layout.left.y1;
+
+ meta_theme_calc_geometry (theme,
+ META_FRAME_TYPE_NORMAL,
+ text_height,
+ *flags,
+ clip->width,
+ clip->height,
+ button_layout,
+ fgeom);
+
+ clip->width += left_width + right_width;
+ clip->height += top_height + bottom_height;
+}
+
+static void
+meta_draw_window_decoration (decor_t *d)
+{
+ Display *xdisplay =
+ GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ GdkPixmap *pixmap;
+ Picture src;
+ MetaButtonState button_states[META_BUTTON_TYPE_LAST];
+ MetaButtonLayout button_layout;
+ MetaFrameGeometry fgeom;
+ MetaFrameFlags flags;
+ MetaTheme *theme;
+ GtkStyle *style;
+ cairo_t *cr;
+ gint size, i;
+ GdkRectangle clip, rect;
+ GdkDrawable *drawable;
+ Region top_region = NULL;
+ Region bottom_region = NULL;
+ Region left_region = NULL;
+ Region right_region = NULL;
+ double alpha = (d->active) ? meta_active_opacity : meta_opacity;
+ gboolean shade_alpha = (d->active) ? meta_active_shade_opacity :
+ meta_shade_opacity;
+ MetaFrameStyle *frame_style;
+ GtkWidget *style_window;
+ GdkColor bg_color;
+ double bg_alpha;
+ int x1, x2, y1, y2;
+
+ x1 = d->context->left_space - _win_extents.left;
+ y1 = d->context->top_space - _win_extents.top - titlebar_height;
+ x2 = d->width - d->context->right_space + _win_extents.right;
+ y2 = d->height - d->context->bottom_space + _win_extents.bottom;
+
+ if (!d->pixmap || !d->picture)
+ return;
+
+ if (d->frame_window)
+ {
+ GdkColormap *cmap;
+
+ cmap = get_colormap_for_drawable (GDK_DRAWABLE (d->pixmap));
+ gdk_drawable_set_colormap (GDK_DRAWABLE (d->pixmap), cmap);
+ gdk_drawable_set_colormap (GDK_DRAWABLE (d->buffer_pixmap), cmap);
+ }
+
+ if (decoration_alpha == 1.0)
+ alpha = 1.0;
+
+ if (gdk_drawable_get_depth (GDK_DRAWABLE (d->pixmap)) == 32)
+ {
+ style = gtk_widget_get_style (style_window_rgba);
+ style_window = style_window_rgba;
+ }
+ else
+ {
+ style = gtk_widget_get_style (style_window_rgb);
+ style_window = style_window_rgb;
+ }
+
+ drawable = d->buffer_pixmap ? d->buffer_pixmap : d->pixmap;
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (drawable));
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ theme = meta_theme_get_current ();
+
+ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
+ &clip);
+
+ /* we only have to redraw the shadow background when decoration
+ changed size */
+ if ((d->prop_xid || !d->buffer_pixmap) && !d->frame_window)
+ draw_shadow_background (d, cr, d->shadow, d->context);
+
+ for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
+ button_states[i] = meta_button_state_for_button_type (d, i);
+
+ frame_style = meta_theme_get_frame_style (theme,
+ META_FRAME_TYPE_NORMAL,
+ flags);
+
+ bg_color = style->bg[GTK_STATE_NORMAL];
+ bg_alpha = 1.0;
+
+#ifdef HAVE_METACITY_2_17_0
+ if (frame_style->window_background_color)
+ {
+ meta_color_spec_render (frame_style->window_background_color,
+ GTK_WIDGET (style_window),
+ &bg_color);
+
+ bg_alpha = frame_style->window_background_alpha / 255.0;
+ }
+#endif
+
+ cairo_destroy (cr);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = clip.width;
+
+ size = MAX (fgeom.top_height, fgeom.bottom_height);
+
+ if (rect.width && size)
+ {
+ XRenderPictFormat *format;
+
+ if (d->frame_window)
+ {
+ int depth;
+ GdkColormap *cmap;
+
+ cmap = get_colormap_for_drawable (GDK_DRAWABLE (d->pixmap));
+ depth = gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window));
+ pixmap = create_pixmap (rect.width, size, depth);
+ gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), cmap);
+ }
+ else
+ pixmap = create_pixmap (rect.width, size, 32);
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
+ gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ format = get_format_for_drawable (d, GDK_DRAWABLE (pixmap));
+ src = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (pixmap),
+ format, 0, NULL);
+
+ if (fgeom.top_height)
+ {
+ rect.height = fgeom.top_height;
+
+ cairo_paint (cr);
+
+ meta_theme_draw_frame (theme,
+ style_window,
+ pixmap,
+ &rect,
+ 0, 0,
+ META_FRAME_TYPE_NORMAL,
+ flags,
+ clip.width - fgeom.left_width -
+ fgeom.right_width,
+ clip.height - fgeom.top_height -
+ fgeom.bottom_height,
+ d->layout,
+ text_height,
+ &button_layout,
+ button_states,
+ d->icon_pixbuf,
+ NULL);
+
+ top_region = meta_get_top_border_region (&fgeom, clip.width);
+
+ decor_blend_border_picture (xdisplay,
+ d->context,
+ src,
+ 0, 0,
+ d->picture,
+ &d->border_layout,
+ BORDER_TOP,
+ top_region,
+ alpha * 0xffff,
+ shade_alpha,
+ 0);
+ }
+
+ if (fgeom.bottom_height)
+ {
+ rect.height = fgeom.bottom_height;
+
+ cairo_paint (cr);
+
+ meta_theme_draw_frame (theme,
+ style_window,
+ pixmap,
+ &rect,
+ 0,
+ -(clip.height - fgeom.bottom_height),
+ META_FRAME_TYPE_NORMAL,
+ flags,
+ clip.width - fgeom.left_width -
+ fgeom.right_width,
+ clip.height - fgeom.top_height -
+ fgeom.bottom_height,
+ d->layout,
+ text_height,
+ &button_layout,
+ button_states,
+ d->icon_pixbuf,
+ NULL);
+
+ bottom_region = meta_get_bottom_border_region (&fgeom, clip.width);
+
+ decor_blend_border_picture (xdisplay,
+ d->context,
+ src,
+ 0, 0,
+ d->picture,
+ &d->border_layout,
+ BORDER_BOTTOM,
+ bottom_region,
+ alpha * 0xffff,
+ shade_alpha,
+ 0);
+
+ }
+
+ cairo_destroy (cr);
+
+ g_object_unref (G_OBJECT (pixmap));
+
+ XRenderFreePicture (xdisplay, src);
+ }
+
+ rect.height = clip.height - fgeom.top_height - fgeom.bottom_height;
+
+ size = MAX (fgeom.left_width, fgeom.right_width);
+
+ if (size && rect.height)
+ {
+ XRenderPictFormat *format;
+
+ if (d->frame_window)
+ {
+ int depth;
+ GdkColormap *cmap;
+
+ cmap = get_colormap_for_drawable (GDK_DRAWABLE (d->pixmap));
+ depth = gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window));
+ pixmap = create_pixmap (size, rect.height, depth);
+ gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), cmap);
+ }
+ else
+ pixmap = create_pixmap (size, rect.height, 32);
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (pixmap));
+ gdk_cairo_set_source_color_alpha (cr, &bg_color, bg_alpha);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ format = get_format_for_drawable (d, GDK_DRAWABLE (pixmap));
+ src = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (pixmap),
+ format, 0, NULL);
+
+ if (fgeom.left_width)
+ {
+ rect.width = fgeom.left_width;
+
+ cairo_paint (cr);
+
+ meta_theme_draw_frame (theme,
+ style_window,
+ pixmap,
+ &rect,
+ 0,
+ -fgeom.top_height,
+ META_FRAME_TYPE_NORMAL,
+ flags,
+ clip.width - fgeom.left_width -
+ fgeom.right_width,
+ clip.height - fgeom.top_height -
+ fgeom.bottom_height,
+ d->layout,
+ text_height,
+ &button_layout,
+ button_states,
+ d->icon_pixbuf,
+ NULL);
+
+ left_region = meta_get_left_border_region (&fgeom, clip.height);
+
+ decor_blend_border_picture (xdisplay,
+ d->context,
+ src,
+ 0, 0,
+ d->picture,
+ &d->border_layout,
+ BORDER_LEFT,
+ left_region,
+ alpha * 0xffff,
+ shade_alpha,
+ 0);
+ }
+
+ if (fgeom.right_width)
+ {
+ rect.width = fgeom.right_width;
+
+ cairo_paint (cr);
+
+ meta_theme_draw_frame (theme,
+ style_window,
+ pixmap,
+ &rect,
+ -(clip.width - fgeom.right_width),
+ -fgeom.top_height,
+ META_FRAME_TYPE_NORMAL,
+ flags,
+ clip.width - fgeom.left_width -
+ fgeom.right_width,
+ clip.height - fgeom.top_height -
+ fgeom.bottom_height,
+ d->layout,
+ text_height,
+ &button_layout,
+ button_states,
+ d->icon_pixbuf,
+ NULL);
+
+ right_region = meta_get_right_border_region (&fgeom, clip.height);
+
+ decor_blend_border_picture (xdisplay,
+ d->context,
+ src,
+ 0, 0,
+ d->picture,
+ &d->border_layout,
+ BORDER_RIGHT,
+ right_region,
+ alpha * 0xffff,
+ shade_alpha,
+ 0);
+ }
+
+ cairo_destroy (cr);
+
+ g_object_unref (G_OBJECT (pixmap));
+
+ XRenderFreePicture (xdisplay, src);
+ }
+
+ if (d->buffer_pixmap)
+ gdk_draw_drawable (d->pixmap,
+ d->gc,
+ d->buffer_pixmap,
+ 0,
+ 0,
+ 0,
+ 0,
+ d->width,
+ d->height);
+
+ if (d->frame_window)
+ {
+ GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window);
+ decor_extents_t extents;
+
+ if (d->state & (WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY))
+ {
+ extents.left = 0;
+ extents.right = 0;
+ extents.top = 10;
+ extents.bottom = 0;
+ }
+ else
+ {
+ extents = _win_extents;
+ }
+
+ gtk_image_set_from_pixmap (GTK_IMAGE (d->decor_image), d->pixmap, NULL);
+ gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height);
+ gdk_window_reparent (gdk_frame_window, d->frame_window, -(d->context->left_space - extents.left), -d->context->bottom_space + extents.bottom + 2);
+ gdk_window_lower (gdk_frame_window);
+ }
+
+ if (d->prop_xid)
+ {
+ /* translate from frame to client window space */
+ if (top_region)
+ XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height);
+ if (bottom_region)
+ XOffsetRegion (bottom_region, -fgeom.left_width, 0);
+ if (left_region)
+ XOffsetRegion (left_region, -fgeom.left_width, 0);
+
+ decor_update_meta_window_property (d, theme, flags,
+ top_region,
+ bottom_region,
+ left_region,
+ right_region);
+ d->prop_xid = 0;
+ }
+
+ if (top_region)
+ XDestroyRegion (top_region);
+ if (bottom_region)
+ XDestroyRegion (bottom_region);
+ if (left_region)
+ XDestroyRegion (left_region);
+ if (right_region)
+ XDestroyRegion (right_region);
+}
+#endif
+
+#define SWITCHER_ALPHA 0xa0a0
+
+static void
+decor_update_switcher_property (decor_t *d)
+{
+ long data[256];
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ gint nQuad;
+ decor_quad_t quads[N_QUADS_MAX];
+ GtkStyle *style;
+ long fgColor[4];
+
+ nQuad = decor_set_lSrStSbX_window_quads (quads, &switcher_context,
+ &d->border_layout,
+ d->border_layout.top.x2 -
+ d->border_layout.top.x1 -
+ switcher_context.extents.left -
+ switcher_context.extents.right -
+ 32);
+
+ decor_quads_to_property (data, GDK_PIXMAP_XID (d->pixmap),
+ &_switcher_extents, &_switcher_extents,
+ 0, 0, quads, nQuad);
+
+ style = gtk_widget_get_style (style_window_rgba);
+
+ fgColor[0] = style->fg[GTK_STATE_NORMAL].red;
+ fgColor[1] = style->fg[GTK_STATE_NORMAL].green;
+ fgColor[2] = style->fg[GTK_STATE_NORMAL].blue;
+ fgColor[3] = SWITCHER_ALPHA;
+
+ gdk_error_trap_push ();
+ XChangeProperty (xdisplay, d->prop_xid,
+ win_decor_atom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ XChangeProperty (xdisplay, d->prop_xid, switcher_fg_atom,
+ XA_INTEGER, 32, PropModeReplace, (guchar *) fgColor, 4);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+}
+
+static void
+draw_switcher_background (decor_t *d)
+{
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ cairo_t *cr;
+ GtkStyle *style;
+ decor_color_t color;
+ double alpha = SWITCHER_ALPHA / 65535.0;
+ double x1, y1, x2, y2, h;
+ int top;
+ unsigned long pixel;
+ ushort a = SWITCHER_ALPHA;
+
+ if (!d->buffer_pixmap)
+ return;
+
+ style = gtk_widget_get_style (style_window_rgba);
+
+ 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;
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap));
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ top = _switcher_extents.top;
+
+ x1 = switcher_context.left_space - _switcher_extents.left;
+ y1 = switcher_context.top_space - _switcher_extents.top;
+ x2 = d->width - switcher_context.right_space + _switcher_extents.right;
+ y2 = d->height - switcher_context.bottom_space + _switcher_extents.bottom;
+
+ h = y2 - y1 - _switcher_extents.top - _switcher_extents.top;
+
+ cairo_set_line_width (cr, 1.0);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ draw_shadow_background (d, cr, switcher_shadow, &switcher_context);
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + 0.5,
+ _switcher_extents.left - 0.5,
+ top - 0.5,
+ 5.0, CORNER_TOPLEFT,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_TOP | SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x1 + _switcher_extents.left,
+ y1 + 0.5,
+ x2 - x1 - _switcher_extents.left -
+ _switcher_extents.right,
+ top - 0.5,
+ 5.0, 0,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_TOP);
+
+ fill_rounded_rectangle (cr,
+ x2 - _switcher_extents.right,
+ y1 + 0.5,
+ _switcher_extents.right - 0.5,
+ top - 0.5,
+ 5.0, CORNER_TOPRIGHT,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_TOP | SHADE_RIGHT);
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y1 + top,
+ _switcher_extents.left - 0.5,
+ h,
+ 5.0, 0,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x2 - _switcher_extents.right,
+ y1 + top,
+ _switcher_extents.right - 0.5,
+ h,
+ 5.0, 0,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_RIGHT);
+
+ fill_rounded_rectangle (cr,
+ x1 + 0.5,
+ y2 - _switcher_extents.top,
+ _switcher_extents.left - 0.5,
+ _switcher_extents.top - 0.5,
+ 5.0, CORNER_BOTTOMLEFT,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_BOTTOM | SHADE_LEFT);
+
+ fill_rounded_rectangle (cr,
+ x1 + _switcher_extents.left,
+ y2 - _switcher_extents.top,
+ x2 - x1 - _switcher_extents.left -
+ _switcher_extents.right,
+ _switcher_extents.top - 0.5,
+ 5.0, 0,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_BOTTOM);
+
+ fill_rounded_rectangle (cr,
+ x2 - _switcher_extents.right,
+ y2 - _switcher_extents.top,
+ _switcher_extents.right - 0.5,
+ _switcher_extents.top - 0.5,
+ 5.0, CORNER_BOTTOMRIGHT,
+ &color, alpha, &color, alpha * 0.75,
+ SHADE_BOTTOM | SHADE_RIGHT);
+
+ cairo_rectangle (cr, x1 + _switcher_extents.left,
+ y1 + top,
+ x2 - x1 - _switcher_extents.left - _switcher_extents.right,
+ h);
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->bg[GTK_STATE_NORMAL],
+ alpha);
+ cairo_fill (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ alpha);
+
+ cairo_stroke (cr);
+
+ cairo_destroy (cr);
+
+ gdk_draw_drawable (d->pixmap,
+ d->gc,
+ d->buffer_pixmap,
+ 0,
+ 0,
+ 0,
+ 0,
+ d->width,
+ d->height);
+
+ pixel = ((((a * style->bg[GTK_STATE_NORMAL].blue ) >> 24) & 0x0000ff) |
+ (((a * style->bg[GTK_STATE_NORMAL].green) >> 16) & 0x00ff00) |
+ (((a * style->bg[GTK_STATE_NORMAL].red ) >> 8) & 0xff0000) |
+ (((a & 0xff00) << 16)));
+
+ decor_update_switcher_property (d);
+
+ gdk_error_trap_push ();
+ XSetWindowBackground (xdisplay, d->prop_xid, pixel);
+ XClearWindow (xdisplay, d->prop_xid);
+
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+
+ d->prop_xid = 0;
+}
+
+static void
+draw_switcher_foreground (decor_t *d)
+{
+ cairo_t *cr;
+ GtkStyle *style;
+ double alpha = SWITCHER_ALPHA / 65535.0;
+
+ if (!d->pixmap || !d->buffer_pixmap)
+ return;
+
+ style = gtk_widget_get_style (style_window_rgba);
+
+ cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap));
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+
+ cairo_rectangle (cr, switcher_context.left_space,
+ d->height - switcher_context.bottom_space,
+ d->width - switcher_context.left_space -
+ switcher_context.right_space,
+ SWITCHER_SPACE);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->bg[GTK_STATE_NORMAL],
+ alpha);
+ cairo_fill (cr);
+
+ if (d->layout)
+ {
+ int w;
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ gdk_cairo_set_source_color_alpha (cr,
+ &style->fg[GTK_STATE_NORMAL],
+ 1.0);
+
+ pango_layout_get_pixel_size (d->layout, &w, NULL);
+
+ cairo_move_to (cr, d->width / 2 - w / 2,
+ d->height - switcher_context.bottom_space +
+ SWITCHER_SPACE / 2 - text_height / 2);
+
+ pango_cairo_show_layout (cr, d->layout);
+ }
+
+ cairo_destroy (cr);
+
+ gdk_draw_drawable (d->pixmap,
+ d->gc,
+ d->buffer_pixmap,
+ 0,
+ 0,
+ 0,
+ 0,
+ d->width,
+ d->height);
+}
+
+static void
+draw_switcher_decoration (decor_t *d)
+{
+ if (d->prop_xid)
+ draw_switcher_background (d);
+
+ draw_switcher_foreground (d);
+}
+
+static gboolean
+draw_decor_list (void *data)
+{
+ GSList *list;
+ decor_t *d;
+
+ draw_idle_id = 0;
+
+ for (list = draw_list; list; list = list->next)
+ {
+ d = (decor_t *) list->data;
+ (*d->draw) (d);
+ }
+
+ 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 *
+pixmap_new_from_pixbuf (GdkPixbuf *pixbuf, int depth)
+{
+ 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, depth);
+ 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 void
+update_default_decorations (GdkScreen *screen)
+{
+ long data[256];
+ Window xroot;
+ GdkDisplay *gdkdisplay = gdk_display_get_default ();
+ Display *xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ Atom bareAtom, normalAtom, activeAtom;
+ decor_t d;
+ gint nQuad;
+ decor_quad_t quads[N_QUADS_MAX];
+ decor_extents_t extents = _win_extents;
+
+ xroot = RootWindowOfScreen (gdk_x11_screen_get_xscreen (screen));
+
+ bareAtom = XInternAtom (xdisplay, DECOR_BARE_ATOM_NAME, FALSE);
+ normalAtom = XInternAtom (xdisplay, DECOR_NORMAL_ATOM_NAME, FALSE);
+ activeAtom = XInternAtom (xdisplay, DECOR_ACTIVE_ATOM_NAME, FALSE);
+
+ if (no_border_shadow)
+ {
+ decor_layout_t layout;
+
+ decor_get_default_layout (&shadow_context, 1, 1, &layout);
+
+ nQuad = decor_set_lSrStSbS_window_quads (quads, &shadow_context,
+ &layout);
+
+ decor_quads_to_property (data, no_border_shadow->pixmap,
+ &_shadow_extents, &_shadow_extents,
+ 0, 0, quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ bareAtom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+
+ if (minimal)
+ {
+ XChangeProperty (xdisplay, xroot,
+ normalAtom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ XChangeProperty (xdisplay, xroot,
+ activeAtom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ }
+ }
+ else
+ {
+ XDeleteProperty (xdisplay, xroot, bareAtom);
+
+ if (minimal)
+ {
+ XDeleteProperty (xdisplay, xroot, normalAtom);
+ XDeleteProperty (xdisplay, xroot, activeAtom);
+ }
+ }
+
+ if (minimal)
+ return;
+
+ memset (&d, 0, sizeof (d));
+
+ d.context = &window_context;
+ d.shadow = border_shadow;
+ d.layout = pango_layout_new (pango_context);
+
+ decor_get_default_layout (d.context, 1, 1, &d.border_layout);
+
+ d.width = d.border_layout.width;
+ d.height = d.border_layout.height;
+
+ extents.top += titlebar_height;
+
+ d.draw = theme_draw_window_decoration;
+
+ if (decor_normal_pixmap)
+ g_object_unref (G_OBJECT (decor_normal_pixmap));
+
+ nQuad = decor_set_lSrStSbS_window_quads (quads, d.context,
+ &d.border_layout);
+
+ decor_normal_pixmap = create_pixmap (d.width, d.height, 32);
+
+ if (decor_normal_pixmap)
+ {
+ d.pixmap = decor_normal_pixmap;
+ d.active = FALSE;
+ d.picture = XRenderCreatePicture (xdisplay,
+ GDK_PIXMAP_XID (d.pixmap),
+ xformat_rgba, 0, NULL);
+
+ (*d.draw) (&d);
+
+ XRenderFreePicture (xdisplay, d.picture);
+
+ decor_quads_to_property (data, GDK_PIXMAP_XID (d.pixmap),
+ &extents, &extents, 0, 0, quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ normalAtom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ }
+
+ if (decor_active_pixmap)
+ g_object_unref (G_OBJECT (decor_active_pixmap));
+
+ decor_active_pixmap = create_pixmap (d.width, d.height, 32);
+
+ if (decor_active_pixmap)
+ {
+ d.pixmap = decor_active_pixmap;
+ d.active = TRUE;
+ d.picture = XRenderCreatePicture (xdisplay,
+ GDK_PIXMAP_XID (d.pixmap),
+ xformat_rgba, 0, NULL);
+
+ (*d.draw) (&d);
+
+ XRenderFreePicture (xdisplay, d.picture);
+
+ decor_quads_to_property (data, GDK_PIXMAP_XID (d.pixmap),
+ &extents, &extents, 0, 0, quads, nQuad);
+
+ XChangeProperty (xdisplay, xroot,
+ activeAtom,
+ XA_INTEGER,
+ 32, PropModeReplace, (guchar *) data,
+ BASE_PROP_SIZE + QUAD_PROP_SIZE * nQuad);
+ }
+
+ if (d.layout)
+ g_object_unref (G_OBJECT (d.layout));
+}
+
+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 unsigned int
+get_mwm_prop (Window xwindow)
+{
+ Display *xdisplay;
+ Atom actual;
+ int err, result, format;
+ unsigned long n, left;
+ unsigned char *data;
+ unsigned int decor = MWM_DECOR_ALL;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ gdk_error_trap_push ();
+
+ result = XGetWindowProperty (xdisplay, xwindow, mwm_hints_atom,
+ 0L, 20L, FALSE, mwm_hints_atom,
+ &actual, &format, &n, &left, &data);
+
+ err = gdk_error_trap_pop ();
+ if (err != Success || result != Success)
+ return decor;
+
+ if (data)
+ {
+ MwmHints *mwm_hints = (MwmHints *) data;
+
+ if (n >= PROP_MOTIF_WM_HINT_ELEMENTS)
+ {
+ if (mwm_hints->flags & MWM_HINTS_DECORATIONS)
+ decor = mwm_hints->decorations;
+ }
+
+ XFree (data);
+ }
+
+ return decor;
+}
+
+static void
+get_event_window_position (decor_t *d,
+ gint i,
+ gint j,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ if (d->frame_window)
+ {
+ *x = pos[i][j].x + pos[i][j].xw * width + _win_extents.left;
+ *y = pos[i][j].y + _win_extents.top +
+ pos[i][j].yh * height + pos[i][j].yth * (titlebar_height - 17);
+
+ if (i == 0 && (j == 0 || j == 2))
+ *y -= titlebar_height;
+ }
+ else
+ {
+ *x = pos[i][j].x + pos[i][j].xw * width;
+ *y = pos[i][j].y +
+ pos[i][j].yh * height + pos[i][j].yth * (titlebar_height - 17);
+ }
+
+ if ((d->state & WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY) &&
+ (j == 0 || j == 2))
+ {
+ *w = 0;
+ }
+ else
+ {
+ *w = pos[i][j].w + pos[i][j].ww * width;
+ }
+
+ if ((d->state & WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY) &&
+ (i == 0 || i == 2))
+ {
+ *h = 0;
+ }
+ else
+ {
+ *h = pos[i][j].h +
+ pos[i][j].hh * height + pos[i][j].hth * (titlebar_height - 17);
+ }
+}
+
+static gboolean
+get_button_position (decor_t *d,
+ gint i,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ if (i > BUTTON_MENU)
+ return FALSE;
+
+ if (d->frame_window)
+ {
+ *x = bpos[i].x + bpos[i].xw * width + _win_extents.left + 4;
+ *y = bpos[i].y + bpos[i].yh * height + bpos[i].yth *
+ (titlebar_height - 17) + _win_extents.top + 2;
+ }
+ else
+ {
+ *x = bpos[i].x + bpos[i].xw * width;
+ *y = bpos[i].y + bpos[i].yh * height + bpos[i].yth *
+ (titlebar_height - 17);
+ }
+
+ *w = bpos[i].w + bpos[i].ww * width;
+ *h = bpos[i].h + bpos[i].hh * height + bpos[i].hth +
+ (titlebar_height - 17);
+
+ /* hack to position multiple buttons on the right */
+ if (i != BUTTON_MENU)
+ *x -= 10 + 16 * i;
+
+ return TRUE;
+}
+
+#ifdef USE_METACITY
+
+#define TOP_RESIZE_HEIGHT 2
+#define RESIZE_EXTENDS 15
+
+static void
+meta_get_event_window_position (decor_t *d,
+ gint i,
+ gint j,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ MetaButtonLayout button_layout;
+ MetaFrameGeometry fgeom;
+ MetaFrameFlags flags;
+ MetaTheme *theme;
+ GdkRectangle clip;
+
+ theme = meta_theme_get_current ();
+
+ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
+ &clip);
+
+ width += fgeom.right_width + fgeom.left_width;
+ height += fgeom.top_height + fgeom.bottom_height;
+
+ switch (i) {
+ case 2: /* bottom */
+ switch (j) {
+ case 2: /* bottom right */
+ if (d->frame_window)
+ {
+ *x = width - fgeom.right_width - RESIZE_EXTENDS +
+ _win_extents.left + 2;
+ *y = height - fgeom.bottom_height - RESIZE_EXTENDS +
+ _win_extents.top + 2;
+ }
+ else
+ {
+ *x = width - fgeom.right_width - RESIZE_EXTENDS;
+ *y = height - fgeom.bottom_height - RESIZE_EXTENDS;
+ }
+ *w = fgeom.right_width + RESIZE_EXTENDS;
+ *h = fgeom.bottom_height + RESIZE_EXTENDS;
+ break;
+ case 1: /* bottom */
+ *x = fgeom.left_width + RESIZE_EXTENDS;
+ *y = height - fgeom.bottom_height;
+ if (d->frame_window)
+ *y += _win_extents.top + 2;
+ *w = width - fgeom.left_width - fgeom.right_width -
+ (2 * RESIZE_EXTENDS);
+ *h = fgeom.bottom_height;
+ break;
+ case 0: /* bottom left */
+ default:
+ *x = 0;
+ *y = height - fgeom.bottom_height - RESIZE_EXTENDS;
+ if (d->frame_window)
+ {
+ *x += _win_extents.left + 4;
+ *y += _win_extents.bottom + 2;
+ }
+ *w = fgeom.left_width + RESIZE_EXTENDS;
+ *h = fgeom.bottom_height + RESIZE_EXTENDS;
+ break;
+ }
+ break;
+ case 1: /* middle */
+ switch (j) {
+ case 2: /* right */
+ *x = width - fgeom.right_width;
+ if (d->frame_window)
+ *x += _win_extents.left + 2;
+ *w = fgeom.right_width;
+ *h = height - fgeom.top_height - fgeom.bottom_height -
+ (2 * RESIZE_EXTENDS);
+ break;
+ case 1: /* middle */
+ *x = fgeom.left_width;
+ *y = fgeom.title_rect.y + TOP_RESIZE_HEIGHT;
+ *w = width - fgeom.left_width - fgeom.right_width;
+ *h = height - fgeom.top_titlebar_edge - fgeom.bottom_height;
+ break;
+ case 0: /* left */
+ default:
+ *x = 0;
+ if (d->frame_window)
+ *x += _win_extents.left + 4;
+ *y = fgeom.top_height + RESIZE_EXTENDS;
+ *w = fgeom.left_width;
+ *h = height - fgeom.top_height - fgeom.bottom_height -
+ (2 * RESIZE_EXTENDS);
+ break;
+ }
+ break;
+ case 0: /* top */
+ default:
+ switch (j) {
+ case 2: /* top right */
+ *x = width - fgeom.right_width - RESIZE_EXTENDS;
+ *y = 0;
+ if (d->frame_window)
+ {
+ *x += _win_extents.left + 2;
+ *y += _win_extents.top + 2 - fgeom.title_rect.height;
+ }
+ *w = fgeom.right_width + RESIZE_EXTENDS;
+ *h = fgeom.top_height + RESIZE_EXTENDS;
+ break;
+ case 1: /* top */
+ *x = fgeom.left_width + RESIZE_EXTENDS;
+ *y = 0;
+ if (d->frame_window)
+ *y += _win_extents.top + 2;
+ *w = width - fgeom.left_width - fgeom.right_width -
+ (2 * RESIZE_EXTENDS);
+ *h = fgeom.title_rect.y + TOP_RESIZE_HEIGHT;
+ break;
+ case 0: /* top left */
+ default:
+ *x = 0;
+ *y = 0;
+ if (d->frame_window)
+ {
+ *x += _win_extents.left + 4;
+ *y += _win_extents.top + 2 - fgeom.title_rect.height;
+ }
+ *w = fgeom.left_width + RESIZE_EXTENDS;
+ *h = fgeom.top_height + RESIZE_EXTENDS;
+ break;
+ }
+ }
+
+ if (!(flags & META_FRAME_ALLOWS_VERTICAL_RESIZE))
+ {
+ /* turn off top and bottom event windows */
+ if (i == 0 || i == 2)
+ *w = *h = 0;
+ }
+
+ if (!(flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE))
+ {
+ /* turn off left and right event windows */
+ if (j == 0 || j == 2)
+ *w = *h = 0;
+ }
+}
+
+static gboolean
+meta_button_present (MetaButtonLayout *button_layout,
+ MetaButtonFunction function)
+{
+ int i;
+
+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
+ if (button_layout->left_buttons[i] == function)
+ return TRUE;
+
+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
+ if (button_layout->right_buttons[i] == function)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+meta_get_button_position (decor_t *d,
+ gint i,
+ gint width,
+ gint height,
+ gint *x,
+ gint *y,
+ gint *w,
+ gint *h)
+{
+ MetaButtonLayout button_layout;
+ MetaFrameGeometry fgeom;
+ MetaFrameFlags flags;
+ MetaTheme *theme;
+ GdkRectangle clip;
+
+#ifdef HAVE_METACITY_2_15_21
+ MetaButtonSpace *space;
+#else
+ GdkRectangle *space;
+#endif
+
+ if (!d->context)
+ {
+ /* undecorated windows implicitly have no buttons */
+ return FALSE;
+ }
+
+ theme = meta_theme_get_current ();
+
+ meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
+ &clip);
+
+ switch (i) {
+ case BUTTON_MENU:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_MENU))
+ return FALSE;
+
+ space = &fgeom.menu_rect;
+ break;
+ case BUTTON_MIN:
+ if (!meta_button_present (&button_layout,
+ META_BUTTON_FUNCTION_MINIMIZE))
+ return FALSE;
+
+ space = &fgeom.min_rect;
+ break;
+ case BUTTON_MAX:
+ if (!meta_button_present (&button_layout,
+ META_BUTTON_FUNCTION_MAXIMIZE))
+ return FALSE;
+
+ space = &fgeom.max_rect;
+ break;
+ case BUTTON_CLOSE:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_CLOSE))
+ return FALSE;
+
+ space = &fgeom.close_rect;
+ break;
+
+#if defined (HAVE_METACITY_2_17_0) && defined (HAVE_LIBWNCK_2_18_1)
+ case BUTTON_SHADE:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_SHADE))
+ return FALSE;
+
+ space = &fgeom.shade_rect;
+ break;
+ case BUTTON_ABOVE:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_ABOVE))
+ return FALSE;
+
+ space = &fgeom.above_rect;
+ break;
+ case BUTTON_STICK:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_STICK))
+ return FALSE;
+
+ space = &fgeom.stick_rect;
+ break;
+ case BUTTON_UNSHADE:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNSHADE))
+ return FALSE;
+
+ space = &fgeom.unshade_rect;
+ break;
+ case BUTTON_UNABOVE:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNABOVE))
+ return FALSE;
+
+ space = &fgeom.unabove_rect;
+ break;
+ case BUTTON_UNSTICK:
+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_UNSTICK))
+ return FALSE;
+
+ space = &fgeom.unstick_rect;
+ break;
+#endif
+
+ default:
+ return FALSE;
+ }
+
+#ifdef HAVE_METACITY_2_15_21
+ if (!space->clickable.width && !space->clickable.height)
+ return FALSE;
+
+ *x = space->clickable.x;
+ *y = space->clickable.y;
+ *w = space->clickable.width;
+ *h = space->clickable.height;
+#else
+ if (!space->width && !space->height)
+ return FALSE;
+
+ *x = space->x;
+ *y = space->y;
+ *w = space->width;
+ *h = space->height;
+#endif
+
+ if (d->frame_window)
+ {
+ *x += _win_extents.left + 4;
+ *y += _win_extents.top + 2;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+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, k, l;
+ gint actions = d->actions;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ wnck_window_get_client_window_geometry (win, &x0, &y0, &width, &height);
+
+ if (d->state & WNCK_WINDOW_STATE_SHADED)
+ {
+ height = 0;
+ k = l = 1;
+ }
+ else
+ {
+ k = 0;
+ l = 2;
+ }
+
+ 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++)
+ {
+ w = 0;
+ h = 0;
+
+ if (actions & event_window_actions[i][j] && i >= k && i <= l)
+ (*theme_get_event_window_position) (d, i, j, width, height,
+ &x, &y, &w, &h);
+
+ if (d->frame_window)
+ {
+ BoxPtr box = &d->event_windows[i][j].pos;
+ box->x1 = x;
+ box->x2 = x + w;
+ box->y1 = y;
+ box->y2 = y + h;
+ }
+ else if (!d->frame_window && w != 0 && h != 0)
+ {
+ XMapWindow (xdisplay, d->event_windows[i][j].window);
+ XMoveResizeWindow (xdisplay, d->event_windows[i][j].window,
+ x, y, w, h);
+ }
+ else if (!d->frame_window)
+ {
+ XUnmapWindow (xdisplay, d->event_windows[i][j].window);
+ }
+ }
+ }
+
+ /* no button event windows if width is less than minimum width */
+ if (width < ICON_SPACE + d->button_width)
+ actions = 0;
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ {
+ static guint button_actions[BUTTON_NUM] = {
+ WNCK_WINDOW_ACTION_CLOSE,
+ WNCK_WINDOW_ACTION_MAXIMIZE,
+ WNCK_WINDOW_ACTION_MINIMIZE,
+ 0,
+ WNCK_WINDOW_ACTION_SHADE,
+
+#ifdef HAVE_LIBWNCK_2_18_1
+ WNCK_WINDOW_ACTION_ABOVE,
+ WNCK_WINDOW_ACTION_STICK,
+ WNCK_WINDOW_ACTION_UNSHADE,
+ WNCK_WINDOW_ACTION_ABOVE,
+ WNCK_WINDOW_ACTION_UNSTICK
+#else
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+#endif
+
+ };
+
+ if (d->frame_window &&
+ button_actions[i] && !(actions & button_actions[i]))
+ {
+ memset (&d->button_windows[i].pos, 0, sizeof (Box));
+ }
+ else if (!d->frame_window &&
+ button_actions[i] && !(actions & button_actions[i]))
+ {
+ XUnmapWindow (xdisplay, d->button_windows[i].window);
+ continue;
+ }
+
+ if (d->frame_window &&
+ (*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h))
+ {
+ BoxPtr box = &d->button_windows[i].pos;
+ box->x1 = x;
+ box->y1 = y;
+ box->x2 = x + w;
+ box->y2 = y + h;
+ }
+ else if (!d->frame_window &&
+ (*theme_get_button_position) (d, i, width, height,
+ &x, &y, &w, &h))
+ {
+ Window win = d->button_windows[i].window;
+ XMapWindow (xdisplay, win);
+ XMoveResizeWindow (xdisplay, win, x, y, w, h);
+ }
+ else if (!d->frame_window)
+ {
+ XUnmapWindow (xdisplay, d->button_windows[i].window);
+ }
+ }
+
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+}
+
+#ifdef HAVE_WNCK_WINDOW_HAS_NAME
+static const char *
+wnck_window_get_real_name (WnckWindow *win)
+{
+ return wnck_window_has_name (win) ? wnck_window_get_name (win) : NULL;
+}
+#define wnck_window_get_name wnck_window_get_real_name
+#endif
+
+static gint
+max_window_name_width (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ const gchar *name;
+ gint w;
+
+ if (!d->layout)
+ {
+ d->layout = pango_layout_new (pango_context);
+ if (!d->layout)
+ return 0;
+
+ pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR);
+ }
+
+ name = wnck_window_get_name (win);
+ if (!name)
+ return 0;
+
+ pango_layout_set_auto_dir (d->layout, FALSE);
+ 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 + 6;
+}
+
+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;
+
+ if (theme_draw_window_decoration != draw_window_decoration)
+ {
+ w = SHRT_MAX;
+ }
+ else
+ {
+ gint width;
+
+ wnck_window_get_client_window_geometry (win, NULL, NULL,
+ &width, NULL);
+
+ w = width - ICON_SPACE - 2 - d->button_width;
+ if (w < 1)
+ w = 1;
+ }
+
+ pango_layout_set_auto_dir (d->layout, FALSE);
+ pango_layout_set_width (d->layout, w * PANGO_SCALE);
+ pango_layout_set_text (d->layout, name, name_length);
+
+ 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)
+ {
+ pango_layout_set_text (d->layout, NULL, 0);
+ 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);
+ }
+}
+
+static void
+update_window_decoration_icon (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->icon)
+ {
+ cairo_pattern_destroy (d->icon);
+ d->icon = NULL;
+ }
+
+ if (d->icon_pixmap)
+ {
+ g_object_unref (G_OBJECT (d->icon_pixmap));
+ d->icon_pixmap = NULL;
+ }
+
+ if (d->icon_pixbuf)
+ g_object_unref (G_OBJECT (d->icon_pixbuf));
+
+ d->icon_pixbuf = wnck_window_get_mini_icon (win);
+ if (d->icon_pixbuf)
+ {
+ cairo_t *cr;
+
+ g_object_ref (G_OBJECT (d->icon_pixbuf));
+
+ if (d->frame_window)
+ d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf,
+ 24);
+ else
+ d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf,
+ 32);
+ 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 void
+calc_button_size (decor_t *d)
+{
+ gint button_width;
+
+ button_width = 0;
+
+ if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
+ button_width += 17;
+
+ if (d->actions & (WNCK_WINDOW_ACTION_MAXIMIZE_HORIZONTALLY |
+ WNCK_WINDOW_ACTION_MAXIMIZE_VERTICALLY |
+ WNCK_WINDOW_ACTION_UNMAXIMIZE_HORIZONTALLY |
+ WNCK_WINDOW_ACTION_UNMAXIMIZE_VERTICALLY))
+ button_width += 17;
+
+ if (d->actions & (WNCK_WINDOW_ACTION_MINIMIZE |
+ WNCK_WINDOW_ACTION_MINIMIZE))
+ button_width += 17;
+
+ if (button_width)
+ button_width++;
+
+ d->button_width = button_width;
+}
+
+static gboolean
+calc_decoration_size (decor_t *d,
+ gint w,
+ gint h,
+ gint name_width,
+ gint *width,
+ gint *height)
+{
+ decor_layout_t layout;
+ int top_width;
+
+ /* To avoid wasting texture memory, we only calculate the minimal
+ * required decoration size then clip and stretch the texture where
+ * appropriate
+ */
+
+ if (!d->frame_window)
+ {
+ calc_button_size (d);
+
+ if (w < ICON_SPACE + d->button_width)
+ return FALSE;
+
+ top_width = name_width + d->button_width + ICON_SPACE;
+ if (w < top_width)
+ top_width = MAX (ICON_SPACE + d->button_width, w);
+
+ decor_get_default_layout (&window_context, top_width, 1, &layout);
+
+ if (!d->context || memcmp (&layout, &d->border_layout, sizeof (layout)))
+ {
+ *width = layout.width;
+ *height = layout.height;
+
+ d->border_layout = layout;
+ d->context = &window_context;
+ d->shadow = border_shadow;
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ calc_button_size (d);
+
+ /* _default_win_extents + top height */
+
+ top_width = name_width + d->button_width + ICON_SPACE;
+ if (w < top_width)
+ top_width = MAX (ICON_SPACE + d->button_width, w);
+
+ decor_get_default_layout (&window_context,
+ d->client_width, d->client_height, &layout);
+
+ *width = layout.width;
+ *height = layout.height;
+
+ d->border_layout = layout;
+ d->context = &window_context;
+ d->shadow = border_shadow;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#ifdef USE_METACITY
+
+static void
+meta_calc_button_size (decor_t *d)
+{
+ gint i, min_x, x, y, w, h, width;
+
+ width = d->border_layout.top.x2 - d->border_layout.top.x1 -
+ d->context->left_space - d->context->right_space;
+ min_x = width;
+
+ 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])
+ {
+ if (meta_get_button_position (d, i, width, 256,
+ &x, &y, &w, &h))
+ {
+ if (x > width / 2 && x < min_x)
+ min_x = x;
+ }
+ }
+ }
+
+ d->button_width = width - min_x + 6;
+}
+
+static gboolean
+meta_calc_decoration_size (decor_t *d,
+ gint w,
+ gint h,
+ gint name_width,
+ gint *width,
+ gint *height)
+{
+ decor_layout_t layout;
+ decor_context_t *context;
+ decor_shadow_t *shadow;
+
+ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
+ {
+ context = &max_window_context;
+ shadow = max_border_shadow;
+ }
+ else
+ {
+ context = &window_context;
+ shadow = border_shadow;
+ }
+
+ if (!d->frame_window)
+ {
+ decor_get_best_layout (context, w, h, &layout);
+
+ if (context != d->context ||
+ memcmp (&layout, &d->border_layout, sizeof (layout)))
+ {
+ *width = layout.width;
+ *height = layout.height;
+
+ d->border_layout = layout;
+ d->context = context;
+ d->shadow = shadow;
+
+ meta_calc_button_size (d);
+
+ return TRUE;
+ }
+ }
+ else
+ {
+ if ((d->state & META_MAXIMIZED) == META_MAXIMIZED)
+ decor_get_default_layout (context, d->client_width,
+ d->client_height - titlebar_height,
+ &layout);
+ else
+ decor_get_default_layout (context, d->client_width,
+ d->client_height, &layout);
+
+ *width = layout.width;
+ *height = layout.height;
+
+ d->border_layout = layout;
+
+ d->context = context;
+
+ meta_calc_button_size (d);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
+static gboolean
+update_window_decoration_size (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ GdkPixmap *pixmap, *buffer_pixmap = NULL;
+ Picture picture;
+ gint width, height;
+ gint x, y, w, h, name_width;
+ Display *xdisplay;
+ XRenderPictFormat *format;
+ int depth;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ wnck_window_get_client_window_geometry (win, &x, &y, &w, &h);
+
+ name_width = max_window_name_width (win);
+
+ if (!(*theme_calc_decoration_size) (d, w, h, name_width, &width, &height))
+ {
+ update_window_decoration_name (win);
+ return FALSE;
+ }
+
+ gdk_error_trap_push ();
+
+ if (d->frame_window)
+ depth = gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window));
+ else
+ depth = 32;
+
+ pixmap = create_pixmap (width, height, depth);
+
+ gdk_flush ();
+
+ if (!pixmap || gdk_error_trap_pop ())
+ {
+ memset (pixmap, 0, sizeof (pixmap));
+ return FALSE;
+ }
+
+ gdk_error_trap_push ();
+
+ buffer_pixmap = create_pixmap (width, height, depth);
+
+ gdk_flush ();
+
+ if (!buffer_pixmap || gdk_error_trap_pop ())
+ {
+ memset (buffer_pixmap, 0, sizeof (buffer_pixmap));
+ g_object_unref (G_OBJECT (pixmap));
+ return FALSE;
+ }
+
+ format = get_format_for_drawable (d, GDK_DRAWABLE (buffer_pixmap));
+ picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap),
+ format, 0, NULL);
+
+ if (d->pixmap)
+ g_object_unref (G_OBJECT (d->pixmap));
+
+ if (d->buffer_pixmap)
+ g_object_unref (G_OBJECT (d->buffer_pixmap));
+
+ if (d->gc)
+ g_object_unref (G_OBJECT (d->gc));
+
+ if (d->picture)
+ XRenderFreePicture (xdisplay, d->picture);
+
+ d->pixmap = pixmap;
+ d->buffer_pixmap = buffer_pixmap;
+ d->gc = gdk_gc_new (pixmap);
+
+ d->picture = picture;
+
+ 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
+move_resize_window (WnckWindow *win,
+ int direction,
+ decor_event *gtkwd_event)
+{
+ 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] = gtkwd_event->x_root;
+ ev.xclient.data.l[1] = gtkwd_event->y_root;
+ ev.xclient.data.l[2] = direction;
+ ev.xclient.data.l[3] = gtkwd_event->button;
+ ev.xclient.data.l[4] = 1;
+
+ XUngrabPointer (xdisplay, gtkwd_event->time);
+ XUngrabKeyboard (xdisplay, gtkwd_event->time);
+
+ XSendEvent (xdisplay, xroot, FALSE,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &ev);
+
+ XSync (xdisplay, FALSE);
+}
+
+static void
+restack_window (WnckWindow *win,
+ int stack_mode)
+{
+ 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 = restack_window_atom;
+ ev.xclient.format = 32;
+
+ ev.xclient.data.l[0] = 2;
+ ev.xclient.data.l[1] = None;
+ ev.xclient.data.l[2] = stack_mode;
+ ev.xclient.data.l[3] = 0;
+ ev.xclient.data.l[4] = 0;
+
+ 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_get_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;
+ if (msec > STICKY_REVERT_DELAY / 1000)
+ return FALSE;
+
+ msec = msec * 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);
+
+#if GTK_CHECK_VERSION (2, 10, 0)
+ if (!gtk_check_version (2, 10, 0))
+ gtk_window_set_type_hint (GTK_WINDOW (tip_window),
+ GDK_WINDOW_TYPE_HINT_TOOLTIP);
+#endif
+
+ 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,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type,
+ guint state,
+ const char *tip)
+{
+ switch (gtkwd_type) {
+ case GButtonPress:
+ hide_tooltip ();
+ break;
+ case GButtonRelease:
+ break;
+ case GEnterNotify:
+ if (!(state & PRESSED_EVENT_WINDOW))
+ {
+ if (wnck_window_is_active (win))
+ tooltip_start_delay (tip);
+ }
+ break;
+ case GLeaveNotify:
+ hide_tooltip ();
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+common_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type,
+ int button,
+ int max,
+ char *tooltip)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[button];
+
+ handle_tooltip_event (win, gtkwd_event, gtkwd_type, state, tooltip);
+
+ if (d->frame_window && gtkwd_type == GEnterNotify)
+ {
+ GdkCursor* cursor;
+ cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gdk_window_set_cursor (d->frame_window, cursor);
+ gdk_cursor_unref (cursor);
+ }
+
+ switch (gtkwd_type) {
+ case GButtonPress:
+ if (gtkwd_event->button <= max)
+ d->button_states[button] |= PRESSED_EVENT_WINDOW;
+ break;
+ case GButtonRelease:
+ if (gtkwd_event->button <= max)
+ d->button_states[button] &= ~PRESSED_EVENT_WINDOW;
+ break;
+ case GEnterNotify:
+ d->button_states[button] |= IN_EVENT_WINDOW;
+ break;
+ case GLeaveNotify:
+ d->button_states[button] &= ~IN_EVENT_WINDOW;
+ break;
+ default:
+ break;
+ }
+
+ if (state != d->button_states[button])
+ queue_decor_draw (d);
+}
+
+#define BUTTON_EVENT_ACTION_STATE (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)
+
+static void
+close_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_CLOSE];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_CLOSE, 1, _("Close Window"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_close (win, gtkwd_event->time);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+max_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_MAX];
+
+ if (wnck_window_is_maximized (win))
+ common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX,
+ 3, _("Unmaximize Window"));
+ else
+ common_button_event (win, gtkwd_event, gtkwd_type, BUTTON_MAX,
+ 3, _("Maximize Window"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button <= 3)
+ {
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ {
+ if (gtkwd_event->button == 2)
+ {
+ if (wnck_window_is_maximized_vertically (win))
+ wnck_window_unmaximize_vertically (win);
+ else
+ wnck_window_maximize_vertically (win);
+ }
+ else if (gtkwd_event->button == 3)
+ {
+ if (wnck_window_is_maximized_horizontally (win))
+ wnck_window_unmaximize_horizontally (win);
+ else
+ wnck_window_maximize_horizontally (win);
+ }
+ else
+ {
+ if (wnck_window_is_maximized (win))
+ wnck_window_unmaximize (win);
+ else
+ wnck_window_maximize (win);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+min_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_MIN];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_MIN, 1, _("Minimize Window"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_minimize (win);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+action_menu_unmap (GObject *object)
+{
+ action_menu_mapped = FALSE;
+}
+
+static void
+position_action_menu (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
+{
+ WnckWindow *win = (WnckWindow *) user_data;
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ gint bx, by, width, height;
+
+ wnck_window_get_client_window_geometry (win, x, y, &width, &height);
+
+ if ((*theme_get_button_position) (d, BUTTON_MENU, width, height,
+ &bx, &by, &width, &height))
+ *x = *x - _win_extents.left + bx;
+
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ {
+ GtkRequisition req;
+
+ gtk_widget_size_request (GTK_WIDGET (menu), &req);
+ *x = MAX (0, *x - req.width + width);
+ }
+
+ *push_in = TRUE;
+}
+
+static void
+action_menu_map (WnckWindow *win,
+ long button,
+ Time time)
+{
+ GdkDisplay *gdkdisplay;
+ GdkScreen *screen;
+
+ gdkdisplay = gdk_display_get_default ();
+ screen = gdk_display_get_default_screen (gdkdisplay);
+
+ if (action_menu)
+ {
+ if (action_menu_mapped)
+ {
+ gtk_widget_destroy (action_menu);
+ action_menu_mapped = FALSE;
+ action_menu = NULL;
+ return;
+ }
+ else
+ gtk_widget_destroy (action_menu);
+ }
+
+ switch (wnck_window_get_window_type (win)) {
+ case WNCK_WINDOW_DESKTOP:
+ case WNCK_WINDOW_DOCK:
+ /* don't allow window action */
+ return;
+ case WNCK_WINDOW_NORMAL:
+ case WNCK_WINDOW_DIALOG:
+
+#ifndef HAVE_LIBWNCK_2_19_4
+ case WNCK_WINDOW_MODAL_DIALOG:
+#endif
+
+ case WNCK_WINDOW_TOOLBAR:
+ case WNCK_WINDOW_MENU:
+ case WNCK_WINDOW_UTILITY:
+ case WNCK_WINDOW_SPLASHSCREEN:
+ /* allow window action menu */
+ break;
+ }
+
+ 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);
+
+ if (!button || button == 1)
+ {
+ gtk_menu_popup (GTK_MENU (action_menu),
+ NULL, NULL,
+ position_action_menu, (gpointer) win,
+ button,
+ time);
+ }
+ else
+ {
+ gtk_menu_popup (GTK_MENU (action_menu),
+ NULL, NULL,
+ NULL, NULL,
+ button,
+ time);
+ }
+
+ action_menu_mapped = TRUE;
+}
+
+static void
+menu_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_MENU, 1, _("Window Menu"));
+
+ switch (gtkwd_type) {
+ case GButtonPress:
+ if (gtkwd_event->button == 1)
+ action_menu_map (win,
+ gtkwd_event->button,
+ gtkwd_event->time);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+shade_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_SHADE];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_SHADE, 1, _("Shade"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ {
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_shade (win);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+above_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_ABOVE];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_ABOVE, 1, _("Make Above"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+#ifdef HAVE_LIBWNCK_2_18_1
+ wnck_window_make_above (win);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+stick_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_STICK];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_STICK, 1, _("Stick"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_stick (win);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+unshade_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_UNSHADE];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_UNSHADE, 1, _("Unshade"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_unshade (win);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+unabove_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_UNABOVE];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_UNABOVE, 1, _("Unmake Above"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+#ifdef HAVE_LIBWNCK_2_18_1
+ wnck_window_unmake_above (win);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+unstick_button_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ guint state = d->button_states[BUTTON_UNSTICK];
+
+ common_button_event (win, gtkwd_event, gtkwd_type,
+ BUTTON_UNSTICK, 1, _("Unstick"));
+
+ switch (gtkwd_type) {
+ case GButtonRelease:
+ if (gtkwd_event->button == 1)
+ if (state == BUTTON_EVENT_ACTION_STATE)
+ wnck_window_unstick (win);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+handle_title_button_event (WnckWindow *win,
+ int action,
+ decor_event *gtkwd_event)
+{
+ switch (action) {
+ case CLICK_ACTION_SHADE:
+ if (wnck_window_is_shaded (win))
+ wnck_window_unshade (win);
+ else
+ wnck_window_shade (win);
+ break;
+ case CLICK_ACTION_MAXIMIZE:
+ if (wnck_window_is_maximized (win))
+ wnck_window_unmaximize (win);
+ else
+ wnck_window_maximize (win);
+ break;
+ case CLICK_ACTION_MINIMIZE:
+ if (!wnck_window_is_minimized (win))
+ wnck_window_minimize (win);
+ break;
+ case CLICK_ACTION_RAISE:
+ restack_window (win, Above);
+ break;
+ case CLICK_ACTION_LOWER:
+ restack_window (win, Below);
+ break;
+ case CLICK_ACTION_MENU:
+ action_menu_map (win, gtkwd_event->button, gtkwd_event->time);
+ break;
+ }
+}
+
+static void
+handle_mouse_wheel_title_event (WnckWindow *win,
+ unsigned int button)
+{
+ switch (wheel_action) {
+ case WHEEL_ACTION_SHADE:
+ if (button == 4)
+ {
+ if (!wnck_window_is_shaded (win))
+ wnck_window_shade (win);
+ }
+ else if (button == 5)
+ {
+ if (wnck_window_is_shaded (win))
+ wnck_window_unshade (win);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static double
+square (double x)
+{
+ return x * x;
+}
+
+static double
+dist (double x1, double y1,
+ double x2, double y2)
+{
+ return sqrt (square (x1 - x2) + square (y1 - y2));
+}
+
+static void
+title_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ static int last_button_num = 0;
+ static Window last_button_xwindow = None;
+ static Time last_button_time = 0;
+ static int last_button_x = 0;
+ static int last_button_y = 0;
+
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->frame_window && gtkwd_type == GEnterNotify)
+ {
+ GdkCursor* cursor = gdk_cursor_new (GDK_LEFT_PTR);
+ gdk_window_set_cursor (d->frame_window, cursor);
+ gdk_cursor_unref (cursor);
+ }
+
+ if (gtkwd_type != GButtonPress)
+ return;
+
+ if (gtkwd_event->button == 1)
+ {
+ if (gtkwd_event->button == last_button_num &&
+ gtkwd_event->window == last_button_xwindow &&
+ gtkwd_event->time < last_button_time + double_click_timeout &&
+ dist (gtkwd_event->x, gtkwd_event->y,
+ last_button_x, last_button_y) < DOUBLE_CLICK_DISTANCE)
+ {
+ handle_title_button_event (win, double_click_action,
+ gtkwd_event);
+
+ last_button_num = 0;
+ last_button_xwindow = None;
+ last_button_time = 0;
+ last_button_x = 0;
+ last_button_y = 0;
+ }
+ else
+ {
+ last_button_num = gtkwd_event->button;
+ last_button_xwindow = gtkwd_event->window;
+ last_button_time = gtkwd_event->time;
+ last_button_x = gtkwd_event->x;
+ last_button_y = gtkwd_event->y;
+
+ restack_window (win, Above);
+
+ move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event);
+ }
+ }
+ else if (gtkwd_event->button == 2)
+ {
+ handle_title_button_event (win, middle_click_action,
+ gtkwd_event);
+ }
+ else if (gtkwd_event->button == 3)
+ {
+ handle_title_button_event (win, right_click_action,
+ gtkwd_event);
+ }
+ else if (gtkwd_event->button == 4 ||
+ gtkwd_event->button == 5)
+ {
+ handle_mouse_wheel_title_event (win, gtkwd_event->button);
+ }
+}
+
+static void
+frame_common_event (WnckWindow *win,
+ int direction,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->frame_window && gtkwd_type == GEnterNotify)
+ {
+ GdkCursor *cursor = NULL;
+
+ switch (direction)
+ {
+ case WM_MOVERESIZE_SIZE_TOPLEFT:
+ cursor = gdk_cursor_new (GDK_TOP_LEFT_CORNER);
+ break;
+ case WM_MOVERESIZE_SIZE_LEFT:
+ cursor = gdk_cursor_new (GDK_LEFT_SIDE);
+ break;
+ case WM_MOVERESIZE_SIZE_BOTTOMLEFT:
+ cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER);
+ break;
+ case WM_MOVERESIZE_SIZE_BOTTOM:
+ cursor = gdk_cursor_new (GDK_BOTTOM_SIDE);
+ break;
+ case WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
+ cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER);
+ break;
+ case WM_MOVERESIZE_SIZE_RIGHT:
+ cursor = gdk_cursor_new (GDK_RIGHT_SIDE);
+ break;
+ case WM_MOVERESIZE_SIZE_TOPRIGHT:
+ cursor = gdk_cursor_new (GDK_TOP_RIGHT_CORNER);
+ break;
+ case WM_MOVERESIZE_SIZE_TOP:
+ cursor = gdk_cursor_new (GDK_TOP_SIDE);
+ break;
+ default:
+ break;
+ }
+
+ if (cursor)
+ {
+ gdk_window_set_cursor (d->frame_window, cursor);
+ gdk_cursor_unref (cursor);
+ }
+ }
+
+ if (gtkwd_type != GButtonPress)
+ return;
+
+ switch (gtkwd_event->button) {
+ case 1:
+ move_resize_window (win, direction, gtkwd_event);
+ restack_window (win, Above);
+ break;
+ case 2:
+ handle_title_button_event (win, middle_click_action,
+ gtkwd_event);
+ break;
+ case 3:
+ handle_title_button_event (win, right_click_action,
+ gtkwd_event);
+ break;
+ }
+}
+
+static void
+top_left_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_TOPLEFT,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+top_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_TOP,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+top_right_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_TOPRIGHT,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+left_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_LEFT,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+right_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_RIGHT,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+bottom_left_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMLEFT,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+bottom_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOM,
+ gtkwd_event, gtkwd_type);
+}
+
+static void
+bottom_right_event (WnckWindow *win,
+ decor_event *gtkwd_event,
+ decor_event_type gtkwd_type)
+{
+ frame_common_event (win, WM_MOVERESIZE_SIZE_BOTTOMRIGHT,
+ gtkwd_event, gtkwd_type);
+}
+
+void
+frame_window_realized (GtkWidget *widget,
+ gpointer data)
+{
+ decor_t *d = (decor_t *) data;
+
+ if (d)
+ {
+ GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window);
+ gdk_window_reparent (gdk_frame_window, d->frame_window,
+ -_win_extents.left - 2, -_win_extents.top - 2);
+ gdk_window_lower (gdk_frame_window);
+
+ }
+}
+
+static event_callback
+find_event_callback_for_point (decor_t *d,
+ int x,
+ int y,
+ Bool *enter,
+ Bool *leave,
+ BoxPtr *entered_box)
+{
+ int i, j;
+ BoxPtr box;
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ {
+ box = &d->button_windows[i].pos;
+ if (x >= box->x1 && x <= box->x2 &&
+ y >= box->y1 && y <= box->y2)
+ {
+ if (d->last_pos_entered != box)
+ {
+ if (enter)
+ *enter = TRUE;
+ if (leave && d->last_pos_entered)
+ *leave = TRUE;
+ if (entered_box)
+ *entered_box = box;
+ }
+ return d->button_windows[i].callback;
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ box = &d->event_windows[i][j].pos;
+ if (x >= box->x1 && x <= box->x2 &&
+ y >= box->y1 && y <= box->y2)
+ {
+ if (d->last_pos_entered != box)
+ {
+ if (enter)
+ *enter = TRUE;
+ if (leave && d->last_pos_entered)
+ *leave = TRUE;
+ if (entered_box)
+ *entered_box = box;
+ }
+ return d->event_windows[i][j].callback;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static event_callback
+find_leave_event_callback (decor_t *d)
+{
+ int i, j;
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ {
+ if (d->last_pos_entered == &d->button_windows[i].pos)
+ return d->button_windows[i].callback;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (d->last_pos_entered == &d->event_windows[i][j].pos)
+ return d->event_windows[i][j].callback;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+frame_handle_button_press (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ decor_t *d = (decor_t *) user_data;
+
+ if (d)
+ {
+ /* Check to see where the event happened and fill out an appropriate
+ * struct
+ */
+ event_callback cb;
+
+ cb = find_event_callback_for_point (d, event->x, event->y,
+ NULL, NULL, NULL);
+
+ if (cb && d->decorated)
+ {
+ decor_event gtkwd_event;
+
+ gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
+ gtkwd_event.button = event->button;
+ gtkwd_event.x = event->x;
+ gtkwd_event.y = event->y;
+ gtkwd_event.x_root = event->x_root;
+ gtkwd_event.y_root = event->y_root;
+ gtkwd_event.time = event->time;
+
+ (*cb) (d->win, &gtkwd_event, GButtonPress);
+ }
+ }
+}
+
+static void
+frame_handle_button_release (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ decor_t *d = (decor_t *) user_data;
+
+ if (d)
+ {
+ event_callback cb;
+
+ cb = find_event_callback_for_point (d, event->x, event->y,
+ NULL, NULL, NULL);
+
+ if (cb && d->decorated)
+ {
+ decor_event gtkwd_event;
+
+ gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
+ gtkwd_event.button = event->button;
+ gtkwd_event.x = event->x;
+ gtkwd_event.y = event->y;
+ gtkwd_event.x_root = event->x_root;
+ gtkwd_event.y_root = event->y_root;
+ gtkwd_event.time = event->time;
+
+ (*cb) (d->win, &gtkwd_event, GButtonRelease);
+ }
+ }
+}
+
+static void
+frame_handle_motion (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ decor_t *d = (decor_t *) user_data;
+
+ if (d)
+ {
+ event_callback cb = NULL;
+ Bool send_enter = FALSE;
+ Bool send_leave = FALSE;
+ BoxPtr entered_box;
+
+ cb = find_event_callback_for_point (d, event->x, event->y,
+ &send_enter, &send_leave,
+ &entered_box);
+
+ if (cb && d->decorated)
+ {
+ decor_event gtkwd_event;
+
+ gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
+ gtkwd_event.x = event->x;
+ gtkwd_event.y = event->y;
+ gtkwd_event.x_root = event->x_root;
+ gtkwd_event.y_root = event->y_root;
+ gtkwd_event.time = event->time;
+
+ if (send_enter)
+ (*cb) (d->win, &gtkwd_event, GEnterNotify);
+
+ if (send_leave)
+ {
+ event_callback leave_cb;
+
+ leave_cb = find_leave_event_callback (d);
+
+ if (leave_cb)
+ (*leave_cb) (d->win, &gtkwd_event, GLeaveNotify);
+
+ }
+
+ if (send_enter)
+ d->last_pos_entered = entered_box;
+ }
+ else if (d->last_pos_entered && d->decorated)
+ {
+ /* We are not in an event / button window but last_pos_entered
+ * is still set, so send a GLeaveNotify to last_pos_entered
+ * and set it to NULL
+ */
+
+ event_callback leave_cb;
+
+ leave_cb = find_leave_event_callback (d);
+
+ if (leave_cb)
+ {
+ decor_event gtkwd_event;
+
+ gtkwd_event.window = GDK_WINDOW_XID (d->frame_window);
+ gtkwd_event.x = event->x;
+ gtkwd_event.y = event->y;
+ gtkwd_event.x_root = event->x_root;
+ gtkwd_event.y_root = event->y_root;
+ gtkwd_event.time = event->time;
+
+ (*leave_cb) (d->win, &gtkwd_event, GLeaveNotify);
+ }
+
+ d->last_pos_entered = NULL;
+ }
+ }
+}
+
+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)
+ {
+ int width, height;
+
+ wnck_window_get_client_window_geometry (win, NULL, NULL,
+ &width, &height);
+
+ if (width != d->client_width || height != d->client_height)
+ {
+ d->client_width = width;
+ d->client_height = height;
+
+ 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);
+ if (!update_window_decoration_size (win))
+ queue_decor_draw (d);
+
+ update_event_windows (win);
+ }
+}
+
+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);
+ if (!update_window_decoration_size (win))
+ queue_decor_draw (d);
+
+ update_event_windows (win);
+ }
+}
+
+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
+add_frame_window (WnckWindow *win,
+ Window frame,
+ Bool mode)
+{
+ 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 ());
+
+ /* If we have already done this, there is no need to do it again, except
+ * if the property changed.
+ *
+ * The reason this check is here is because sometimes the PropertyNotify X
+ * event can come a bit after the property on the window is actually set
+ * which might result in this function being called twice - once by
+ * wnck through window_opened and once through our X event handler
+ * event_filter_func
+ */
+
+ if (d->created && mode && d->frame_window)
+ return;
+
+ d->active = wnck_window_is_active (win);
+ d->win = win;
+ d->last_pos_entered = NULL;
+
+ attr.event_mask = ButtonPressMask | EnterWindowMask |
+ LeaveWindowMask | ExposureMask;
+ attr.override_redirect = TRUE;
+
+ gdk_error_trap_push ();
+
+ if (mode)
+ {
+ GdkColormap *colormap;
+
+ d->frame_window = create_gdk_window (frame);
+ d->decor_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ colormap = get_colormap_for_drawable (GDK_DRAWABLE (d->frame_window));
+
+ d->decor_image = gtk_image_new ();
+
+ gtk_widget_set_colormap (d->decor_window, colormap);
+ gtk_widget_set_colormap (d->decor_image, colormap);
+
+ d->decor_event_box = gtk_event_box_new ();
+ gtk_event_box_set_visible_window (GTK_EVENT_BOX (d->decor_event_box),
+ FALSE);
+ gtk_widget_set_events (d->decor_event_box, GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK);
+
+ g_signal_connect (G_OBJECT (d->decor_event_box), "button-press-event",
+ G_CALLBACK (frame_handle_button_press),
+ (gpointer) (d));
+
+ g_signal_connect (G_OBJECT (d->decor_event_box), "button-release-event",
+ G_CALLBACK (frame_handle_button_release),
+ (gpointer) (d));
+
+ g_signal_connect (G_OBJECT (d->decor_event_box), "motion-notify-event",
+ G_CALLBACK (frame_handle_motion),
+ (gpointer) (d));
+
+ gtk_container_add (GTK_CONTAINER (d->decor_event_box), d->decor_image);
+ gtk_event_box_set_above_child (GTK_EVENT_BOX (d->decor_event_box), TRUE);
+ gtk_widget_show_all (d->decor_event_box);
+ gtk_window_set_decorated (GTK_WINDOW (d->decor_window), FALSE);
+ gtk_window_set_default_size (GTK_WINDOW (d->decor_window), 1000, 1000);
+ gtk_container_add (GTK_CONTAINER (d->decor_window), d->decor_event_box);
+
+ /* Assumed realization happens here */
+
+ g_signal_connect (G_OBJECT (d->decor_window), "realize",
+ G_CALLBACK (frame_window_realized), (gpointer) d);
+
+ gtk_widget_show_all (d->decor_window);
+ gtk_widget_show (d->decor_window);
+
+ g_object_set_data (G_OBJECT (d->frame_window),
+ "client_wnck_window", win);
+ }
+ else
+ {
+ d->frame_window = NULL;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ d->event_windows[i][j].window =
+ 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].window,
+ cursor[i][j].cursor);
+ }
+ }
+
+ attr.event_mask |= ButtonReleaseMask;
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ {
+ d->button_windows[i].window =
+ XCreateWindow (xdisplay,
+ frame,
+ 0, 0, 1, 1, 0,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWEventMask, &attr);
+
+ d->button_states[i] = 0;
+ }
+ }
+
+ gdk_display_sync (gdk_display_get_default ());
+ if (!gdk_error_trap_pop ())
+ {
+ if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE))
+ d->decorated = TRUE;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ {
+ Window win = d->event_windows[i][j].window;
+ g_hash_table_insert (frame_table,
+ GINT_TO_POINTER (win),
+ GINT_TO_POINTER (xid));
+ }
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ g_hash_table_insert (frame_table,
+ GINT_TO_POINTER (d->button_windows[i].window),
+ GINT_TO_POINTER (xid));
+
+ if (d->frame_window)
+ {
+ g_hash_table_insert (frame_table,
+ GINT_TO_POINTER (frame),
+ 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
+ {
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ d->event_windows[i][j].window = None;
+ }
+
+ d->created = TRUE;
+}
+
+static gboolean
+update_switcher_window (WnckWindow *win,
+ Window selected)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ GdkPixmap *pixmap, *buffer_pixmap = NULL;
+ gint height, width = 0;
+ WnckWindow *selected_win;
+ Display *xdisplay;
+ XRenderPictFormat *format;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ wnck_window_get_client_window_geometry (win, NULL, NULL, &width, NULL);
+
+ decor_get_default_layout (&switcher_context, width, 1, &d->border_layout);
+
+ width = d->border_layout.width;
+ height = d->border_layout.height;
+
+ d->decorated = FALSE;
+ d->draw = draw_switcher_decoration;
+
+ if (!d->pixmap && switcher_pixmap)
+ {
+ g_object_ref (G_OBJECT (switcher_pixmap));
+
+ d->pixmap = switcher_pixmap;
+ }
+
+ if (!d->buffer_pixmap && switcher_buffer_pixmap)
+ {
+ g_object_ref (G_OBJECT (switcher_buffer_pixmap));
+ d->buffer_pixmap = switcher_buffer_pixmap;
+ }
+
+ if (!d->width)
+ d->width = switcher_width;
+
+ if (!d->height)
+ d->height = switcher_height;
+
+ selected_win = wnck_window_get (selected);
+ if (selected_win)
+ {
+ glong name_length;
+ PangoLayoutLine *line;
+ const gchar *name;
+
+ if (d->name)
+ {
+ g_free (d->name);
+ d->name = NULL;
+ }
+
+ name = wnck_window_get_name (selected_win);
+ if (name && (name_length = strlen (name)))
+ {
+ if (!d->layout)
+ {
+ d->layout = pango_layout_new (pango_context);
+ if (d->layout)
+ pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR);
+ }
+
+ if (d->layout)
+ {
+ int tw;
+
+ tw = width - switcher_context.left_space -
+ switcher_context.right_space - 64;
+ pango_layout_set_auto_dir (d->layout, FALSE);
+ pango_layout_set_width (d->layout, tw * PANGO_SCALE);
+ pango_layout_set_text (d->layout, name, name_length);
+
+ 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;
+ }
+ else
+ {
+ d->name = g_strndup (name, name_length);
+ strcpy (d->name + name_length - 3, "...");
+ }
+ }
+ else
+ d->name = g_strndup (name, name_length);
+
+ if (d->layout)
+ pango_layout_set_text (d->layout, d->name, name_length);
+ }
+ }
+ else if (d->layout)
+ {
+ g_object_unref (G_OBJECT (d->layout));
+ d->layout = NULL;
+ }
+ }
+
+ if (selected != switcher_selected_window)
+ {
+ gtk_label_set_text (GTK_LABEL (switcher_label), "");
+ if (selected_win && d->name)
+ gtk_label_set_text (GTK_LABEL (switcher_label), d->name);
+ switcher_selected_window = selected;
+ }
+
+ if (width == d->width && height == d->height)
+ {
+ if (!d->gc)
+ d->gc = gdk_gc_new (d->pixmap);
+
+ if (!d->picture)
+ {
+ XRenderPictFormat *format;
+
+ format = get_format_for_drawable (d,
+ GDK_DRAWABLE (d->buffer_pixmap));
+ d->picture = XRenderCreatePicture (xdisplay,
+ GDK_PIXMAP_XID (buffer_pixmap),
+ format, 0, NULL);
+ }
+ queue_decor_draw (d);
+ return FALSE;
+ }
+
+ pixmap = create_pixmap (width, height, 32);
+ if (!pixmap)
+ return FALSE;
+
+ buffer_pixmap = create_pixmap (width, height, 32);
+ if (!buffer_pixmap)
+ {
+ g_object_unref (G_OBJECT (pixmap));
+ return FALSE;
+ }
+
+ if (switcher_pixmap)
+ g_object_unref (G_OBJECT (switcher_pixmap));
+
+ if (switcher_buffer_pixmap)
+ g_object_unref (G_OBJECT (switcher_buffer_pixmap));
+
+ if (d->pixmap)
+ g_object_unref (G_OBJECT (d->pixmap));
+
+ if (d->buffer_pixmap)
+ g_object_unref (G_OBJECT (d->buffer_pixmap));
+
+ if (d->gc)
+ g_object_unref (G_OBJECT (d->gc));
+
+ if (d->picture)
+ XRenderFreePicture (xdisplay, d->picture);
+
+ switcher_pixmap = pixmap;
+ switcher_buffer_pixmap = buffer_pixmap;
+
+ switcher_width = width;
+ switcher_height = height;
+
+ g_object_ref (G_OBJECT (pixmap));
+ g_object_ref (G_OBJECT (buffer_pixmap));
+
+ d->pixmap = pixmap;
+ d->buffer_pixmap = buffer_pixmap;
+ d->gc = gdk_gc_new (pixmap);
+
+ format = get_format_for_drawable (d, GDK_DRAWABLE (d->buffer_pixmap));
+ d->picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap),
+ format, 0, NULL);
+
+ d->width = width;
+ d->height = height;
+
+ d->prop_xid = wnck_window_get_xid (win);
+
+ queue_decor_draw (d);
+
+ return TRUE;
+}
+
+static void
+remove_frame_window (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ Display *xdisplay;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+
+ if (d->pixmap)
+ {
+ g_object_unref (G_OBJECT (d->pixmap));
+ d->pixmap = NULL;
+ }
+
+ if (d->buffer_pixmap)
+ {
+ g_object_unref (G_OBJECT (d->buffer_pixmap));
+ d->buffer_pixmap = NULL;
+ }
+
+ if (d->gc)
+ {
+ g_object_unref (G_OBJECT (d->gc));
+ d->gc = NULL;
+ }
+
+ if (d->picture && !d->frame_window)
+ {
+ XRenderFreePicture (xdisplay, d->picture);
+ d->picture = 0;
+ }
+
+ 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)
+ {
+ g_object_unref (G_OBJECT (d->icon_pixmap));
+ d->icon_pixmap = NULL;
+ }
+
+ if (d->icon_pixbuf)
+ {
+ g_object_unref (G_OBJECT (d->icon_pixbuf));
+ d->icon_pixbuf = NULL;
+ }
+
+ if (d->force_quit_dialog)
+ {
+ GtkWidget *dialog = d->force_quit_dialog;
+
+ d->force_quit_dialog = NULL;
+ gtk_widget_destroy (dialog);
+ }
+
+ if (d->frame_window)
+ {
+ gdk_window_destroy (d->frame_window);
+ d->frame_window = NULL;
+ }
+
+ if (d->decor_image)
+ {
+ g_object_unref (d->decor_image);
+ d->decor_image = NULL;
+ }
+
+ if (d->decor_event_box)
+ {
+ g_object_unref (d->decor_event_box);
+ d->decor_event_box = NULL;
+ }
+
+ if (d->decor_window)
+ {
+ g_object_unref (d->decor_window);
+ d->decor_window = NULL;
+ }
+
+ d->width = 0;
+ d->height = 0;
+
+ d->decorated = FALSE;
+
+ d->state = 0;
+ d->actions = 0;
+
+ d->context = NULL;
+ d->shadow = NULL;
+
+ draw_list = g_slist_remove (draw_list, d);
+}
+
+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 && 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 && 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 window;
+ gulong xid;
+ unsigned int i, j;
+
+ 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[BUTTON_NUM] = {
+ close_button_event,
+ max_button_event,
+ min_button_event,
+ menu_button_event,
+ shade_button_event,
+ above_button_event,
+ stick_button_event,
+ unshade_button_event,
+ unabove_button_event,
+ unstick_button_event
+ };
+
+ d = calloc (1, sizeof (decor_t));
+ if (!d)
+ return;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ d->event_windows[i][j].callback = callback[i][j];
+
+ for (i = 0; i < BUTTON_NUM; i++)
+ d->button_windows[i].callback = button_callback[i];
+
+ wnck_window_get_client_window_geometry (win, NULL, NULL,
+ &d->client_width,
+ &d->client_height);
+
+ d->draw = theme_draw_window_decoration;
+
+ d->created = FALSE;
+ d->pixmap = NULL;
+ d->gc = NULL;
+ d->buffer_pixmap = NULL;
+ d->picture = None;
+
+ connect_window (win);
+
+ g_object_set_data (G_OBJECT (win), "decor", d);
+
+ xid = wnck_window_get_xid (win);
+
+ if (get_window_prop (xid, select_window_atom, &window))
+ {
+ d->prop_xid = wnck_window_get_xid (win);
+ update_switcher_window (win, window);
+ }
+ else if (get_window_prop (xid, frame_input_window_atom, &window))
+ {
+ add_frame_window (win, window, FALSE);
+ }
+ else if (get_window_prop (xid, frame_output_window_atom, &window))
+ {
+ add_frame_window (win, window, TRUE);
+ }
+}
+
+static void
+window_closed (WnckScreen *screen,
+ WnckWindow *win)
+{
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ remove_frame_window (win);
+
+ g_object_set_data (G_OBJECT (win), "decor", NULL);
+
+ gdk_error_trap_push ();
+ XDeleteProperty (xdisplay, wnck_window_get_xid (win), win_decor_atom);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+
+ 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
+force_quit_dialog_realize (GtkWidget *dialog,
+ void *data)
+{
+ WnckWindow *win = data;
+
+ gdk_error_trap_push ();
+ XSetTransientForHint (gdk_display,
+ GDK_WINDOW_XID (dialog->window),
+ wnck_window_get_xid (win));
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+}
+
+static char *
+get_client_machine (Window xwindow)
+{
+ Atom atom, type;
+ gulong nitems, bytes_after;
+ guchar *str = NULL;
+ int format, result;
+ char *retval;
+
+ atom = XInternAtom (gdk_display, "WM_CLIENT_MACHINE", FALSE);
+
+ gdk_error_trap_push ();
+
+ result = XGetWindowProperty (gdk_display,
+ xwindow, atom,
+ 0, G_MAXLONG,
+ FALSE, XA_STRING, &type, &format, &nitems,
+ &bytes_after, &str);
+
+ gdk_error_trap_pop ();
+
+ if (result != Success)
+ return NULL;
+
+ if (type != XA_STRING)
+ {
+ XFree (str);
+ return NULL;
+ }
+
+ retval = g_strdup ((gchar *) str);
+
+ XFree (str);
+
+ return retval;
+}
+
+static void
+kill_window (WnckWindow *win)
+{
+ WnckApplication *app;
+
+ app = wnck_window_get_application (win);
+ if (app)
+ {
+ gchar buf[257], *client_machine;
+ int pid;
+
+ pid = wnck_application_get_pid (app);
+ client_machine = get_client_machine (wnck_application_get_xid (app));
+
+ if (client_machine && pid > 0)
+ {
+ if (gethostname (buf, sizeof (buf) - 1) == 0)
+ {
+ if (strcmp (buf, client_machine) == 0)
+ kill (pid, 9);
+ }
+ }
+
+ if (client_machine)
+ g_free (client_machine);
+ }
+
+ gdk_error_trap_push ();
+ XKillClient (gdk_display, wnck_window_get_xid (win));
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+}
+
+static void
+force_quit_dialog_response (GtkWidget *dialog,
+ gint response,
+ void *data)
+{
+ WnckWindow *win = data;
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (response == GTK_RESPONSE_ACCEPT)
+ kill_window (win);
+
+ if (d->force_quit_dialog)
+ {
+ d->force_quit_dialog = NULL;
+ gtk_widget_destroy (dialog);
+ }
+}
+
+static void
+show_force_quit_dialog (WnckWindow *win,
+ Time timestamp)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ GtkWidget *dialog;
+ gchar *str, *tmp;
+
+ if (d->force_quit_dialog)
+ return;
+
+ tmp = g_markup_escape_text (wnck_window_get_name (win), -1);
+ str = g_strdup_printf (_("The window \"%s\" is not responding."), tmp);
+
+ g_free (tmp);
+
+ dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "<b>%s</b>\n\n%s",
+ str,
+ _("Forcing this application to "
+ "quit will cause you to lose any "
+ "unsaved changes."));
+ g_free (str);
+
+ gtk_window_set_icon_name (GTK_WINDOW (dialog), "force-quit");
+
+ gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label),
+ TRUE);
+ gtk_label_set_line_wrap (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label),
+ TRUE);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ _("_Force Quit"),
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+
+ g_signal_connect (G_OBJECT (dialog), "realize",
+ G_CALLBACK (force_quit_dialog_realize),
+ win);
+
+ g_signal_connect (G_OBJECT (dialog), "response",
+ G_CALLBACK (force_quit_dialog_response),
+ win);
+
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ gtk_widget_realize (dialog);
+
+ gdk_x11_window_set_user_time (dialog->window, timestamp);
+
+ gtk_widget_show (dialog);
+
+ d->force_quit_dialog = dialog;
+}
+
+static void
+hide_force_quit_dialog (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->force_quit_dialog)
+ {
+ gtk_widget_destroy (d->force_quit_dialog);
+ d->force_quit_dialog = NULL;
+ }
+}
+
+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_input_window_atom)
+ {
+ WnckWindow *win;
+
+ xid = xevent->xproperty.window;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ Window frame, window;
+
+ if (!get_window_prop (xid, select_window_atom, &window))
+ {
+ if (get_window_prop (xid, frame_input_window_atom, &frame))
+ add_frame_window (win, frame, FALSE);
+ else
+ remove_frame_window (win);
+ }
+ }
+ }
+ if (xevent->xproperty.atom == frame_output_window_atom)
+ {
+ WnckWindow *win;
+
+ xid = xevent->xproperty.window;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ Window frame, window;
+
+ if (!get_window_prop (xid, select_window_atom, &window))
+ {
+ if (get_window_prop (xid, frame_output_window_atom, &frame))
+ add_frame_window (win, frame, TRUE);
+ else
+ remove_frame_window (win);
+ }
+ }
+ }
+ else if (xevent->xproperty.atom == mwm_hints_atom)
+ {
+ WnckWindow *win;
+
+ xid = xevent->xproperty.window;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ gboolean decorated = FALSE;
+
+ if (get_mwm_prop (xid) & (MWM_DECOR_ALL | MWM_DECOR_TITLE))
+ decorated = TRUE;
+
+ if (decorated != d->decorated)
+ {
+ d->decorated = decorated;
+ if (decorated)
+ {
+ d->context = NULL;
+ d->width = d->height = 0;
+
+ update_window_decoration_size (win);
+ update_event_windows (win);
+ }
+ else
+ {
+ gdk_error_trap_push ();
+ XDeleteProperty (xdisplay, xid, win_decor_atom);
+ gdk_display_sync (gdk_display_get_default ());
+ gdk_error_trap_pop ();
+ }
+ }
+ }
+ }
+ else if (xevent->xproperty.atom == select_window_atom)
+ {
+ WnckWindow *win;
+
+ xid = xevent->xproperty.window;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ Window select;
+
+ if (get_window_prop (xid, select_window_atom, &select))
+ update_switcher_window (win, select);
+ }
+ }
+ break;
+ case DestroyNotify:
+ g_hash_table_remove (frame_table,
+ GINT_TO_POINTER (xevent->xproperty.window));
+ break;
+ case ClientMessage:
+ if (xevent->xclient.message_type == toolkit_action_atom)
+ {
+ long action;
+
+ action = xevent->xclient.data.l[0];
+ if (action == toolkit_action_window_menu_atom)
+ {
+ WnckWindow *win;
+
+ win = wnck_window_get (xevent->xclient.window);
+ if (win)
+ {
+ action_menu_map (win,
+ xevent->xclient.data.l[2],
+ xevent->xclient.data.l[1]);
+ }
+ }
+ else if (action == toolkit_action_force_quit_dialog_atom)
+ {
+ WnckWindow *win;
+
+ win = wnck_window_get (xevent->xclient.window);
+ if (win)
+ {
+ if (xevent->xclient.data.l[2])
+ show_force_quit_dialog (win,
+ xevent->xclient.data.l[1]);
+ else
+ hide_force_quit_dialog (win);
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+ if (xid)
+ {
+ WnckWindow *win;
+
+ win = wnck_window_get (xid);
+ if (win)
+ {
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ gint i, j;
+ event_callback cb = NULL;
+ Window w = xevent->xany.window;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ if (d->event_windows[i][j].window == w)
+ cb = d->event_windows[i][j].callback;
+
+ if (!cb)
+ {
+ for (i = 0; i < BUTTON_NUM; i++)
+ if (d->button_windows[i].window == w)
+ cb = d->button_windows[i].callback;
+ }
+
+ if (cb)
+ {
+ decor_event gtkwd_event;
+ decor_event_type gtkwd_type;
+
+ gtkwd_event.window = w;
+
+ switch (xevent->type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ if (xevent->type == ButtonPress)
+ gtkwd_type = GButtonPress;
+ else
+ gtkwd_type = GButtonRelease;
+ gtkwd_event.button = xevent->xbutton.button;
+ gtkwd_event.x = xevent->xbutton.x;
+ gtkwd_event.y = xevent->xbutton.y;
+ gtkwd_event.x_root = xevent->xbutton.x_root;
+ gtkwd_event.y_root = xevent->xbutton.y_root;
+ gtkwd_event.time = xevent->xbutton.time;
+ break;
+ case EnterNotify:
+ case LeaveNotify:
+ if (xevent->type == EnterNotify)
+ gtkwd_type = GEnterNotify;
+ else
+ gtkwd_type = GLeaveNotify;
+ gtkwd_event.x = xevent->xcrossing.x;
+ gtkwd_event.y = xevent->xcrossing.y;
+ gtkwd_event.x_root = xevent->xcrossing.x_root;
+ gtkwd_event.y_root = xevent->xcrossing.y_root;
+ gtkwd_event.time = xevent->xcrossing.time;
+ break;
+ default:
+ cb = NULL;
+ break;
+ }
+ if (cb)
+ (*cb) (win, &gtkwd_event, gtkwd_type);
+ }
+ }
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static GdkFilterReturn
+selection_event_filter_func (GdkXEvent *gdkxevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ Display *xdisplay;
+ GdkDisplay *gdkdisplay;
+ XEvent *xevent = gdkxevent;
+ int status;
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
+
+ switch (xevent->type) {
+ case SelectionRequest:
+ decor_handle_selection_request (xdisplay, xevent, dm_sn_timestamp);
+ break;
+ case SelectionClear:
+ status = decor_handle_selection_clear (xdisplay, xevent, 0);
+ if (status == DECOR_SELECTION_GIVE_UP)
+ exit (0);
+ default:
+ break;
+ }
+
+ 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
+update_style (GtkWidget *widget)
+{
+ GtkStyle *style;
+ decor_color_t spot_color;
+
+ style = gtk_widget_get_style (widget);
+ g_object_ref (G_OBJECT (style));
+
+ style = gtk_style_attach (style, widget->window);
+
+ 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;
+
+ g_object_unref (G_OBJECT (style));
+
+ shade (&spot_color, &_title_color[0], 1.05);
+ shade (&_title_color[0], &_title_color[1], 0.85);
+}
+
+/* to save some memory, value is specific to current decorations */
+#define TRANSLUCENT_CORNER_SIZE 3
+
+static void
+draw_border_shape (Display *xdisplay,
+ Pixmap pixmap,
+ Picture picture,
+ int width,
+ int height,
+ decor_context_t *c,
+ void *closure)
+{
+ static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
+ GdkColormap *colormap;
+ decor_t d;
+ double save_decoration_alpha;
+
+ memset (&d, 0, sizeof (d));
+
+ d.pixmap = gdk_pixmap_foreign_new_for_display (gdk_display_get_default (),
+ pixmap);
+ d.width = width;
+ d.height = height;
+ d.active = TRUE;
+ d.draw = theme_draw_window_decoration;
+ d.picture = picture;
+ d.context = c;
+
+ /* we use closure argument if maximized */
+ if (closure)
+ d.state |=
+ WNCK_WINDOW_STATE_MAXIMIZED_HORIZONTALLY |
+ WNCK_WINDOW_STATE_MAXIMIZED_VERTICALLY;
+
+ decor_get_default_layout (c, 1, 1, &d.border_layout);
+
+ colormap = get_colormap_for_drawable (GDK_DRAWABLE (d.pixmap));
+ gdk_drawable_set_colormap (d.pixmap, colormap);
+
+ /* create shadow from opaque decoration */
+ save_decoration_alpha = decoration_alpha;
+ decoration_alpha = 1.0;
+
+ (*d.draw) (&d);
+
+ decoration_alpha = save_decoration_alpha;
+
+ XRenderFillRectangle (xdisplay, PictOpSrc, picture, &white,
+ c->left_space,
+ c->top_space,
+ width - c->left_space - c->right_space,
+ height - c->top_space - c->bottom_space);
+
+ g_object_unref (G_OBJECT (d.pixmap));
+}
+
+static int
+update_shadow (void)
+{
+ decor_shadow_options_t opt;
+ Display *xdisplay = gdk_display;
+ GdkDisplay *display = gdk_display_get_default ();
+ GdkScreen *screen = gdk_display_get_default_screen (display);
+
+ opt.shadow_radius = shadow_radius;
+ opt.shadow_opacity = shadow_opacity;
+
+ memcpy (opt.shadow_color, shadow_color, sizeof (shadow_color));
+
+ opt.shadow_offset_x = shadow_offset_x;
+ opt.shadow_offset_y = shadow_offset_y;
+
+ if (no_border_shadow)
+ {
+ decor_shadow_destroy (xdisplay, no_border_shadow);
+ no_border_shadow = NULL;
+ }
+
+ no_border_shadow = decor_shadow_create (xdisplay,
+ gdk_x11_screen_get_xscreen (screen),
+ 1, 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, 0, 0, 0,
+ &opt,
+ &shadow_context,
+ decor_draw_simple,
+ 0);
+
+ if (border_shadow)
+ {
+ decor_shadow_destroy (xdisplay, border_shadow);
+ border_shadow = NULL;
+ }
+
+ border_shadow = decor_shadow_create (xdisplay,
+ gdk_x11_screen_get_xscreen (screen),
+ 1, 1,
+ _win_extents.left,
+ _win_extents.right,
+ _win_extents.top + titlebar_height,
+ _win_extents.bottom,
+ _win_extents.left -
+ TRANSLUCENT_CORNER_SIZE,
+ _win_extents.right -
+ TRANSLUCENT_CORNER_SIZE,
+ _win_extents.top + titlebar_height -
+ TRANSLUCENT_CORNER_SIZE,
+ _win_extents.bottom -
+ TRANSLUCENT_CORNER_SIZE,
+ &opt,
+ &window_context,
+ draw_border_shape,
+ 0);
+
+ if (max_border_shadow)
+ {
+ decor_shadow_destroy (xdisplay, max_border_shadow);
+ max_border_shadow = NULL;
+ }
+
+ max_border_shadow =
+ decor_shadow_create (xdisplay,
+ gdk_x11_screen_get_xscreen (screen),
+ 1, 1,
+ _max_win_extents.left,
+ _max_win_extents.right,
+ _max_win_extents.top + max_titlebar_height,
+ _max_win_extents.bottom,
+ _max_win_extents.left - TRANSLUCENT_CORNER_SIZE,
+ _max_win_extents.right - TRANSLUCENT_CORNER_SIZE,
+ _max_win_extents.top + max_titlebar_height -
+ TRANSLUCENT_CORNER_SIZE,
+ _max_win_extents.bottom - TRANSLUCENT_CORNER_SIZE,
+ &opt,
+ &max_window_context,
+ draw_border_shape,
+ (void *) 1);
+
+ if (switcher_shadow)
+ {
+ decor_shadow_destroy (xdisplay, switcher_shadow);
+ switcher_shadow = NULL;
+ }
+
+ switcher_shadow = decor_shadow_create (xdisplay,
+ gdk_x11_screen_get_xscreen (screen),
+ 1, 1,
+ _switcher_extents.left,
+ _switcher_extents.right,
+ _switcher_extents.top,
+ _switcher_extents.bottom,
+ _switcher_extents.left -
+ TRANSLUCENT_CORNER_SIZE,
+ _switcher_extents.right -
+ TRANSLUCENT_CORNER_SIZE,
+ _switcher_extents.top -
+ TRANSLUCENT_CORNER_SIZE,
+ _switcher_extents.bottom -
+ TRANSLUCENT_CORNER_SIZE,
+ &opt,
+ &switcher_context,
+ decor_draw_simple,
+ 0);
+
+ return 1;
+}
+
+static void
+update_window_decoration (WnckWindow *win)
+{
+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+
+ if (d->decorated)
+ {
+ /* force size update */
+ d->context = NULL;
+ d->width = d->height = 0;
+
+ update_window_decoration_size (win);
+ update_event_windows (win);
+ }
+ else
+ {
+ Window xid = wnck_window_get_xid (win);
+ Window select;
+
+ if (get_window_prop (xid, select_window_atom, &select))
+ {
+ /* force size update */
+ d->context = NULL;
+ d->width = d->height = 0;
+ switcher_width = switcher_height = 0;
+
+ update_switcher_window (win, select);
+ }
+ }
+}
+
+static const PangoFontDescription *
+get_titlebar_font (void)
+{
+ if (use_system_font)
+ {
+ return NULL;
+ }
+ else
+ return titlebar_font;
+}
+
+#ifdef USE_GCONF
+static void
+titlebar_font_changed (GConfClient *client)
+{
+ gchar *str;
+
+ str = gconf_client_get_string (client,
+ COMPIZ_TITLEBAR_FONT_KEY,
+ NULL);
+ if (!str)
+ str = g_strdup ("Sans Bold 12");
+
+ if (titlebar_font)
+ pango_font_description_free (titlebar_font);
+
+ titlebar_font = pango_font_description_from_string (str);
+
+ g_free (str);
+}
+
+static void
+titlebar_click_action_changed (GConfClient *client,
+ const gchar *key,
+ int *action_value,
+ int default_value)
+{
+ gchar *action;
+
+ *action_value = default_value;
+
+ action = gconf_client_get_string (client, key, NULL);
+ if (action)
+ {
+ if (strcmp (action, "toggle_shade") == 0)
+ *action_value = CLICK_ACTION_SHADE;
+ else if (strcmp (action, "toggle_maximize") == 0)
+ *action_value = CLICK_ACTION_MAXIMIZE;
+ else if (strcmp (action, "minimize") == 0)
+ *action_value = CLICK_ACTION_MINIMIZE;
+ else if (strcmp (action, "raise") == 0)
+ *action_value = CLICK_ACTION_RAISE;
+ else if (strcmp (action, "lower") == 0)
+ *action_value = CLICK_ACTION_LOWER;
+ else if (strcmp (action, "menu") == 0)
+ *action_value = CLICK_ACTION_MENU;
+ else if (strcmp (action, "none") == 0)
+ *action_value = CLICK_ACTION_NONE;
+
+ g_free (action);
+ }
+}
+
+static void
+wheel_action_changed (GConfClient *client)
+{
+ gchar *action;
+
+ wheel_action = WHEEL_ACTION_DEFAULT;
+
+ action = gconf_client_get_string (client, WHEEL_ACTION_KEY, NULL);
+ if (action)
+ {
+ if (strcmp (action, "shade") == 0)
+ wheel_action = WHEEL_ACTION_SHADE;
+ else if (strcmp (action, "none") == 0)
+ wheel_action = WHEEL_ACTION_NONE;
+
+ g_free (action);
+ }
+}
+#endif
+
+#ifdef USE_METACITY
+static MetaButtonFunction
+meta_button_function_from_string (const char *str)
+{
+ if (strcmp (str, "menu") == 0)
+ return META_BUTTON_FUNCTION_MENU;
+ else if (strcmp (str, "minimize") == 0)
+ return META_BUTTON_FUNCTION_MINIMIZE;
+ else if (strcmp (str, "maximize") == 0)
+ return META_BUTTON_FUNCTION_MAXIMIZE;
+ else if (strcmp (str, "close") == 0)
+ return META_BUTTON_FUNCTION_CLOSE;
+
+#ifdef HAVE_METACITY_2_17_0
+ else if (strcmp (str, "shade") == 0)
+ return META_BUTTON_FUNCTION_SHADE;
+ else if (strcmp (str, "above") == 0)
+ return META_BUTTON_FUNCTION_ABOVE;
+ else if (strcmp (str, "stick") == 0)
+ return META_BUTTON_FUNCTION_STICK;
+ else if (strcmp (str, "unshade") == 0)
+ return META_BUTTON_FUNCTION_UNSHADE;
+ else if (strcmp (str, "unabove") == 0)
+ return META_BUTTON_FUNCTION_UNABOVE;
+ else if (strcmp (str, "unstick") == 0)
+ return META_BUTTON_FUNCTION_UNSTICK;
+#endif
+
+ else
+ return META_BUTTON_FUNCTION_LAST;
+}
+
+static MetaButtonFunction
+meta_button_opposite_function (MetaButtonFunction ofwhat)
+{
+ switch (ofwhat)
+ {
+#ifdef HAVE_METACITY_2_17_0
+ case META_BUTTON_FUNCTION_SHADE:
+ return META_BUTTON_FUNCTION_UNSHADE;
+ case META_BUTTON_FUNCTION_UNSHADE:
+ return META_BUTTON_FUNCTION_SHADE;
+
+ case META_BUTTON_FUNCTION_ABOVE:
+ return META_BUTTON_FUNCTION_UNABOVE;
+ case META_BUTTON_FUNCTION_UNABOVE:
+ return META_BUTTON_FUNCTION_ABOVE;
+
+ case META_BUTTON_FUNCTION_STICK:
+ return META_BUTTON_FUNCTION_UNSTICK;
+ case META_BUTTON_FUNCTION_UNSTICK:
+ return META_BUTTON_FUNCTION_STICK;
+#endif
+
+ default:
+ return META_BUTTON_FUNCTION_LAST;
+ }
+}
+
+static void
+meta_initialize_button_layout (MetaButtonLayout *layout)
+{
+ int i;
+
+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
+ {
+ layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
+ layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
+#ifdef HAVE_METACITY_2_23_2
+ layout->left_buttons_has_spacer[i] = FALSE;
+ layout->right_buttons_has_spacer[i] = FALSE;
+#endif
+ }
+}
+
+static void
+meta_update_button_layout (const char *value)
+{
+ MetaButtonLayout new_layout;
+ MetaButtonFunction f;
+ char **sides;
+ int i;
+
+ meta_initialize_button_layout (&new_layout);
+
+ sides = g_strsplit (value, ":", 2);
+
+ if (sides[0] != NULL)
+ {
+ char **buttons;
+ int b;
+ gboolean used[META_BUTTON_FUNCTION_LAST];
+
+ for (i = 0; i < META_BUTTON_FUNCTION_LAST; i++)
+ used[i] = FALSE;
+
+ buttons = g_strsplit (sides[0], ",", -1);
+
+ i = b = 0;
+ while (buttons[b] != NULL)
+ {
+ f = meta_button_function_from_string (buttons[b]);
+#ifdef HAVE_METACITY_2_23_2
+ if (i > 0 && strcmp ("spacer", buttons[b]) == 0)
+ {
+ new_layout.left_buttons_has_spacer[i - 1] = TRUE;
+ f = meta_button_opposite_function (f);
+
+ if (f != META_BUTTON_FUNCTION_LAST)
+ new_layout.left_buttons_has_spacer[i - 2] = TRUE;
+ }
+ else
+#endif
+ {
+ if (f != META_BUTTON_FUNCTION_LAST && !used[f])
+ {
+ used[f] = TRUE;
+ new_layout.left_buttons[i++] = f;
+
+ f = meta_button_opposite_function (f);
+
+ if (f != META_BUTTON_FUNCTION_LAST)
+ new_layout.left_buttons[i++] = f;
+
+ }
+ else
+ {
+ fprintf (stderr, "%s: Ignoring unknown or already-used "
+ "button name \"%s\"\n", program_name, buttons[b]);
+ }
+ }
+ b++;
+ }
+
+ new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
+
+ g_strfreev (buttons);
+
+ if (sides[1] != NULL)
+ {
+ for (i = 0; i < META_BUTTON_FUNCTION_LAST; i++)
+ used[i] = FALSE;
+
+ buttons = g_strsplit (sides[1], ",", -1);
+
+ i = b = 0;
+ while (buttons[b] != NULL)
+ {
+ f = meta_button_function_from_string (buttons[b]);
+#ifdef HAVE_METACITY_2_23_2
+ if (i > 0 && strcmp ("spacer", buttons[b]) == 0)
+ {
+ new_layout.right_buttons_has_spacer[i - 1] = TRUE;
+ f = meta_button_opposite_function (f);
+ if (f != META_BUTTON_FUNCTION_LAST)
+ new_layout.right_buttons_has_spacer[i - 2] = TRUE;
+ }
+ else
+#endif
+ {
+ if (f != META_BUTTON_FUNCTION_LAST && !used[f])
+ {
+ used[f] = TRUE;
+ new_layout.right_buttons[i++] = f;
+
+ f = meta_button_opposite_function (f);
+
+ if (f != META_BUTTON_FUNCTION_LAST)
+ new_layout.right_buttons[i++] = f;
+ }
+ else
+ {
+ fprintf (stderr, "%s: Ignoring unknown or "
+ "already-used button name \"%s\"\n",
+ program_name, buttons[b]);
+ }
+ }
+ b++;
+ }
+ new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
+
+ g_strfreev (buttons);
+ }
+ }
+
+ g_strfreev (sides);
+
+ /* Invert the button layout for RTL languages */
+ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
+ {
+ MetaButtonLayout rtl_layout;
+ int j;
+
+ meta_initialize_button_layout (&rtl_layout);
+
+ i = 0;
+ while (new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST)
+ i++;
+
+ for (j = 0; j < i; j++)
+ {
+ rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
+#ifdef HAVE_METACITY_2_23_2
+ if (j == 0)
+ rtl_layout.right_buttons_has_spacer[i - 1] =
+ new_layout.left_buttons_has_spacer[i - j - 1];
+ else
+ rtl_layout.right_buttons_has_spacer[j - 1] =
+ new_layout.left_buttons_has_spacer[i - j - 1];
+#endif
+ }
+
+ i = 0;
+ while (new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST)
+ i++;
+
+ for (j = 0; j < i; j++)
+ {
+ rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
+#ifdef HAVE_METACITY_2_23_2
+ if (j == 0)
+ rtl_layout.left_buttons_has_spacer[i - 1] =
+ new_layout.right_buttons_has_spacer[i - j - 1];
+ else
+ rtl_layout.left_buttons_has_spacer[j - 1] =
+ new_layout.right_buttons_has_spacer[i - j - 1];
+#endif
+ }
+
+ new_layout = rtl_layout;
+ }
+
+ meta_button_layout = new_layout;
+}
+#endif
+
+static void
+update_border_extents (gint text_height)
+{
+ _win_extents = _default_win_extents;
+ _max_win_extents = _default_win_extents;
+ max_titlebar_height = titlebar_height =
+ (text_height < 17) ? 17 : text_height;
+}
+
+#ifdef USE_METACITY
+static void
+meta_update_border_extents (gint text_height)
+{
+ MetaTheme *theme;
+ gint top_height, bottom_height, left_width, right_width;
+
+ theme = meta_theme_get_current ();
+
+ meta_theme_get_frame_borders (theme,
+ META_FRAME_TYPE_NORMAL,
+ text_height, 0,
+ &top_height,
+ &bottom_height,
+ &left_width,
+ &right_width);
+
+ _win_extents.top = _default_win_extents.top;
+ _win_extents.bottom = bottom_height;
+ _win_extents.left = left_width;
+ _win_extents.right = right_width;
+
+ titlebar_height = top_height - _win_extents.top;
+
+ meta_theme_get_frame_borders (theme,
+ META_FRAME_TYPE_NORMAL,
+ text_height, META_FRAME_MAXIMIZED,
+ &top_height,
+ &bottom_height,
+ &left_width,
+ &right_width);
+
+ _max_win_extents.top = _default_win_extents.top;
+ _max_win_extents.bottom = bottom_height;
+ _max_win_extents.left = left_width;
+ _max_win_extents.right = right_width;
+
+ max_titlebar_height = top_height - _max_win_extents.top;
+}
+#endif
+
+static void
+update_titlebar_font (void)
+{
+ const PangoFontDescription *font_desc;
+ PangoFontMetrics *metrics;
+ PangoLanguage *lang;
+
+ font_desc = get_titlebar_font ();
+ if (!font_desc)
+ {
+ GtkStyle *default_style;
+
+ default_style = gtk_widget_get_default_style ();
+ font_desc = default_style->font_desc;
+ }
+
+ pango_context_set_font_description (pango_context, font_desc);
+
+ lang = pango_context_get_language (pango_context);
+ metrics = pango_context_get_metrics (pango_context, font_desc, lang);
+
+ text_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics));
+
+ pango_font_metrics_unref (metrics);
+}
+
+static void
+decorations_changed (WnckScreen *screen)
+{
+ GdkDisplay *gdkdisplay;
+ GdkScreen *gdkscreen;
+ GList *windows;
+
+ gdkdisplay = gdk_display_get_default ();
+ gdkscreen = gdk_display_get_default_screen (gdkdisplay);
+
+ update_titlebar_font ();
+ (*theme_update_border_extents) (text_height);
+ update_shadow ();
+
+ update_default_decorations (gdkscreen);
+
+ if (minimal)
+ return;
+
+ windows = wnck_screen_get_windows (screen);
+ while (windows != NULL)
+ {
+ decor_t *d = g_object_get_data (G_OBJECT (windows->data), "decor");
+
+ if (d->decorated)
+ {
+
+#ifdef USE_METACITY
+ if (d->draw == draw_window_decoration ||
+ d->draw == meta_draw_window_decoration)
+ d->draw = theme_draw_window_decoration;
+#endif
+
+ }
+
+ update_window_decoration (WNCK_WINDOW (windows->data));
+ windows = windows->next;
+ }
+}
+
+static void
+style_changed (GtkWidget *widget)
+{
+ GdkDisplay *gdkdisplay;
+ GdkScreen *gdkscreen;
+ WnckScreen *screen;
+
+ gdkdisplay = gdk_display_get_default ();
+ gdkscreen = gdk_display_get_default_screen (gdkdisplay);
+ screen = wnck_screen_get_default ();
+
+ update_style (widget);
+
+ pango_cairo_context_set_resolution (pango_context,
+ gdk_screen_get_resolution (gdkscreen));
+
+ decorations_changed (screen);
+}
+
+#ifdef USE_GCONF
+static gboolean
+shadow_settings_changed (GConfClient *client)
+{
+ double radius, opacity;
+ int offset;
+ gchar *color;
+ gboolean changed = FALSE;
+
+ radius = gconf_client_get_float (client,
+ COMPIZ_SHADOW_RADIUS_KEY,
+ NULL);
+ radius = MAX (0.0, MIN (radius, 48.0));
+ if (shadow_radius != radius)
+ {
+ shadow_radius = radius;
+ changed = TRUE;
+ }
+
+ opacity = gconf_client_get_float (client,
+ COMPIZ_SHADOW_OPACITY_KEY,
+ NULL);
+ opacity = MAX (0.0, MIN (opacity, 6.0));
+ if (shadow_opacity != opacity)
+ {
+ shadow_opacity = opacity;
+ changed = TRUE;
+ }
+
+ color = gconf_client_get_string (client,
+ COMPIZ_SHADOW_COLOR_KEY,
+ NULL);
+ if (color)
+ {
+ int c[4];
+
+ if (sscanf (color, "#%2x%2x%2x%2x", &c[0], &c[1], &c[2], &c[3]) == 4)
+ {
+ shadow_color[0] = c[0] << 8 | c[0];
+ shadow_color[1] = c[1] << 8 | c[1];
+ shadow_color[2] = c[2] << 8 | c[2];
+ changed = TRUE;
+ }
+
+ g_free (color);
+ }
+
+ offset = gconf_client_get_int (client,
+ COMPIZ_SHADOW_OFFSET_X_KEY,
+ NULL);
+ offset = MAX (-16, MIN (offset, 16));
+ if (shadow_offset_x != offset)
+ {
+ shadow_offset_x = offset;
+ changed = TRUE;
+ }
+
+ offset = gconf_client_get_int (client,
+ COMPIZ_SHADOW_OFFSET_Y_KEY,
+ NULL);
+ offset = MAX (-16, MIN (offset, 16));
+ if (shadow_offset_y != offset)
+ {
+ shadow_offset_y = offset;
+ changed = TRUE;
+ }
+
+ return changed;
+}
+
+static gboolean
+blur_settings_changed (GConfClient *client)
+{
+ gchar *type;
+ int new_type = blur_type;
+
+ if (cmdline_options & CMDLINE_BLUR)
+ return FALSE;
+
+ type = gconf_client_get_string (client,
+ BLUR_TYPE_KEY,
+ NULL);
+
+ if (type)
+ {
+ if (strcmp (type, "titlebar") == 0)
+ new_type = BLUR_TYPE_TITLEBAR;
+ else if (strcmp (type, "all") == 0)
+ new_type = BLUR_TYPE_ALL;
+ else if (strcmp (type, "none") == 0)
+ new_type = BLUR_TYPE_NONE;
+
+ g_free (type);
+ }
+
+ if (new_type != blur_type)
+ {
+ blur_type = new_type;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+theme_changed (GConfClient *client)
+{
+
+#ifdef USE_METACITY
+ gboolean use_meta_theme;
+
+ if (cmdline_options & CMDLINE_THEME)
+ return FALSE;
+
+ use_meta_theme = gconf_client_get_bool (client,
+ USE_META_THEME_KEY,
+ NULL);
+
+ if (use_meta_theme)
+ {
+ gchar *theme;
+
+ theme = gconf_client_get_string (client,
+ META_THEME_KEY,
+ NULL);
+
+ if (theme)
+ {
+ meta_theme_set_current (theme, TRUE);
+ if (!meta_theme_get_current ())
+ use_meta_theme = FALSE;
+
+ g_free (theme);
+ }
+ else
+ {
+ use_meta_theme = FALSE;
+ }
+ }
+
+ if (use_meta_theme)
+ {
+ theme_draw_window_decoration = meta_draw_window_decoration;
+ theme_calc_decoration_size = meta_calc_decoration_size;
+ theme_update_border_extents = meta_update_border_extents;
+ theme_get_event_window_position = meta_get_event_window_position;
+ theme_get_button_position = meta_get_button_position;
+ }
+ else
+ {
+ theme_draw_window_decoration = draw_window_decoration;
+ theme_calc_decoration_size = calc_decoration_size;
+ theme_update_border_extents = update_border_extents;
+ theme_get_event_window_position = get_event_window_position;
+ theme_get_button_position = get_button_position;
+ }
+
+ return TRUE;
+#else
+ theme_draw_window_decoration = draw_window_decoration;
+ theme_calc_decoration_size = calc_decoration_size;
+ theme_update_border_extents = update_border_extents;
+ theme_get_event_window_position = get_event_window_position;
+ theme_get_button_position = get_button_position;
+
+ return FALSE;
+#endif
+
+}
+
+static gboolean
+theme_opacity_changed (GConfClient *client)
+{
+
+#ifdef USE_METACITY
+ gboolean shade_opacity, changed = FALSE;
+ gdouble opacity;
+
+ opacity = gconf_client_get_float (client,
+ META_THEME_OPACITY_KEY,
+ NULL);
+
+ if (!(cmdline_options & CMDLINE_OPACITY) &&
+ opacity != meta_opacity)
+ {
+ meta_opacity = opacity;
+ changed = TRUE;
+ }
+
+ if (opacity < 1.0)
+ {
+ shade_opacity = gconf_client_get_bool (client,
+ META_THEME_SHADE_OPACITY_KEY,
+ NULL);
+
+ if (!(cmdline_options & CMDLINE_OPACITY_SHADE) &&
+ shade_opacity != meta_shade_opacity)
+ {
+ meta_shade_opacity = shade_opacity;
+ changed = TRUE;
+ }
+ }
+
+ opacity = gconf_client_get_float (client,
+ META_THEME_ACTIVE_OPACITY_KEY,
+ NULL);
+
+ if (!(cmdline_options & CMDLINE_ACTIVE_OPACITY) &&
+ opacity != meta_active_opacity)
+ {
+ meta_active_opacity = opacity;
+ changed = TRUE;
+ }
+
+ if (opacity < 1.0)
+ {
+ shade_opacity =
+ gconf_client_get_bool (client,
+ META_THEME_ACTIVE_SHADE_OPACITY_KEY,
+ NULL);
+
+ if (!(cmdline_options & CMDLINE_ACTIVE_OPACITY_SHADE) &&
+ shade_opacity != meta_active_shade_opacity)
+ {
+ meta_active_shade_opacity = shade_opacity;
+ changed = TRUE;
+ }
+ }
+
+ return changed;
+#else
+ return FALSE;
+#endif
+
+}
+
+static gboolean
+button_layout_changed (GConfClient *client)
+{
+
+#ifdef USE_METACITY
+ gchar *button_layout;
+
+ button_layout = gconf_client_get_string (client,
+ META_BUTTON_LAYOUT_KEY,
+ NULL);
+
+ if (button_layout)
+ {
+ meta_update_button_layout (button_layout);
+
+ meta_button_layout_set = TRUE;
+
+ g_free (button_layout);
+
+ return TRUE;
+ }
+
+ if (meta_button_layout_set)
+ {
+ meta_button_layout_set = FALSE;
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+
+static void
+value_changed (GConfClient *client,
+ const gchar *key,
+ GConfValue *value,
+ void *data)
+{
+ gboolean changed = FALSE;
+
+ if (strcmp (key, COMPIZ_USE_SYSTEM_FONT_KEY) == 0)
+ {
+ if (gconf_client_get_bool (client,
+ COMPIZ_USE_SYSTEM_FONT_KEY,
+ NULL) != use_system_font)
+ {
+ use_system_font = !use_system_font;
+ changed = TRUE;
+ }
+ }
+ else if (strcmp (key, COMPIZ_TITLEBAR_FONT_KEY) == 0)
+ {
+ titlebar_font_changed (client);
+ changed = !use_system_font;
+ }
+ else if (strcmp (key, COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY) == 0)
+ {
+ titlebar_click_action_changed (client, key,
+ &double_click_action,
+ DOUBLE_CLICK_ACTION_DEFAULT);
+ }
+ else if (strcmp (key, COMPIZ_MIDDLE_CLICK_TITLEBAR_KEY) == 0)
+ {
+ titlebar_click_action_changed (client, key,
+ &middle_click_action,
+ MIDDLE_CLICK_ACTION_DEFAULT);
+ }
+ else if (strcmp (key, COMPIZ_RIGHT_CLICK_TITLEBAR_KEY) == 0)
+ {
+ titlebar_click_action_changed (client, key,
+ &right_click_action,
+ RIGHT_CLICK_ACTION_DEFAULT);
+ }
+ else if (strcmp (key, WHEEL_ACTION_KEY) == 0)
+ {
+ wheel_action_changed (client);
+ }
+ else if (strcmp (key, COMPIZ_SHADOW_RADIUS_KEY) == 0 ||
+ strcmp (key, COMPIZ_SHADOW_OPACITY_KEY) == 0 ||
+ strcmp (key, COMPIZ_SHADOW_OFFSET_X_KEY) == 0 ||
+ strcmp (key, COMPIZ_SHADOW_OFFSET_Y_KEY) == 0 ||
+ strcmp (key, COMPIZ_SHADOW_COLOR_KEY) == 0)
+ {
+ if (shadow_settings_changed (client))
+ changed = TRUE;
+ }
+ else if (strcmp (key, BLUR_TYPE_KEY) == 0)
+ {
+ if (blur_settings_changed (client))
+ changed = TRUE;
+ }
+ else if (strcmp (key, USE_META_THEME_KEY) == 0 ||
+ strcmp (key, META_THEME_KEY) == 0)
+ {
+ if (theme_changed (client))
+ changed = TRUE;
+ }
+ else if (strcmp (key, META_BUTTON_LAYOUT_KEY) == 0)
+ {
+ if (button_layout_changed (client))
+ changed = TRUE;
+ }
+ else if (strcmp (key, META_THEME_OPACITY_KEY) == 0 ||
+ strcmp (key, META_THEME_SHADE_OPACITY_KEY) == 0 ||
+ strcmp (key, META_THEME_ACTIVE_OPACITY_KEY) == 0 ||
+ strcmp (key, META_THEME_ACTIVE_SHADE_OPACITY_KEY) == 0)
+ {
+ if (theme_opacity_changed (client))
+ changed = TRUE;
+ }
+
+ if (changed)
+ decorations_changed (data);
+}
+
+#elif USE_DBUS_GLIB
+
+static DBusHandlerResult
+dbus_handle_message (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ WnckScreen *screen = user_data;
+ char **path;
+ const char *interface, *member;
+ DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ interface = dbus_message_get_interface (message);
+ member = dbus_message_get_member (message);
+
+ (void) connection;
+
+ if (!interface || !member)
+ return result;
+
+ if (!dbus_message_is_signal (message, interface, member))
+ return result;
+
+ if (strcmp (member, "changed"))
+ return result;
+
+ if (!dbus_message_get_path_decomposed (message, &path))
+ return result;
+
+ if (!path[0] || !path[1] || !path[2] || !path[3] || !path[4] || !path[5])
+ {
+ dbus_free_string_array (path);
+ return result;
+ }
+
+ if (!strcmp (path[0], "org") &&
+ !strcmp (path[1], "freedesktop") &&
+ !strcmp (path[2], "compiz") &&
+ !strcmp (path[3], "decor") &&
+ !strcmp (path[4], "allscreens"))
+ {
+ result = DBUS_HANDLER_RESULT_HANDLED;
+
+ if (strcmp (path[5], "shadow_radius") == 0)
+ {
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_DOUBLE, &shadow_radius,
+ DBUS_TYPE_INVALID);
+ }
+ else if (strcmp (path[5], "shadow_opacity") == 0)
+ {
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_DOUBLE, &shadow_opacity,
+ DBUS_TYPE_INVALID);
+ }
+ else if (strcmp (path[5], "shadow_color") == 0)
+ {
+ DBusError error;
+ char *str;
+
+ dbus_error_init (&error);
+
+ dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_error_is_set (&error))
+ {
+ int c[4];
+
+ if (sscanf (str, "#%2x%2x%2x%2x",
+ &c[0], &c[1], &c[2], &c[3]) == 4)
+ {
+ shadow_color[0] = c[0] << 8 | c[0];
+ shadow_color[1] = c[1] << 8 | c[1];
+ shadow_color[2] = c[2] << 8 | c[2];
+ }
+ }
+
+ dbus_error_free (&error);
+ }
+ else if (strcmp (path[5], "shadow_x_offset") == 0)
+ {
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_INT32, &shadow_offset_x,
+ DBUS_TYPE_INVALID);
+ }
+ else if (strcmp (path[5], "shadow_y_offset") == 0)
+ {
+ dbus_message_get_args (message, NULL,
+ DBUS_TYPE_INT32, &shadow_offset_y,
+ DBUS_TYPE_INVALID);
+ }
+
+ decorations_changed (screen);
+ }
+
+ dbus_free_string_array (path);
+
+ return result;
+}
+
+static DBusMessage *
+send_and_block_for_shadow_option_reply (DBusConnection *connection,
+ char *path)
+{
+ DBusMessage *message;
+
+ message = dbus_message_new_method_call (NULL,
+ path,
+ DBUS_INTERFACE,
+ DBUS_METHOD_GET);
+ if (message)
+ {
+ DBusMessage *reply;
+ DBusError error;
+
+ dbus_message_set_destination (message, DBUS_DEST);
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (connection,
+ message, -1,
+ &error);
+ dbus_message_unref (message);
+
+ if (!dbus_error_is_set (&error))
+ return reply;
+ }
+
+ return NULL;
+}
+
+#endif
+
+static gboolean
+init_settings (WnckScreen *screen)
+{
+ GtkSettings *settings;
+ GdkScreen *gdkscreen;
+ GdkColormap *colormap;
+ AtkObject *switcher_label_obj;
+
+#ifdef USE_GCONF
+ GConfClient *gconf;
+
+ gconf = gconf_client_get_default ();
+
+ gconf_client_add_dir (gconf,
+ GCONF_DIR,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ gconf_client_add_dir (gconf,
+ METACITY_GCONF_DIR,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ gconf_client_add_dir (gconf,
+ COMPIZ_GCONF_DIR1,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ g_signal_connect (G_OBJECT (gconf),
+ "value_changed",
+ G_CALLBACK (value_changed),
+ screen);
+#elif USE_DBUS_GLIB
+ DBusConnection *connection;
+ DBusMessage *reply;
+ DBusError error;
+
+ dbus_error_init (&error);
+
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
+ if (!dbus_error_is_set (&error))
+ {
+ dbus_bus_add_match (connection, "type='signal'", &error);
+
+ dbus_connection_add_filter (connection,
+ dbus_handle_message,
+ screen, NULL);
+
+ dbus_connection_setup_with_g_main (connection, NULL);
+ }
+
+ reply = send_and_block_for_shadow_option_reply (connection, DBUS_PATH
+ "/shadow_radius");
+ if (reply)
+ {
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_DOUBLE, &shadow_radius,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_unref (reply);
+ }
+
+ reply = send_and_block_for_shadow_option_reply (connection, DBUS_PATH
+ "/shadow_opacity");
+ if (reply)
+ {
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_DOUBLE, &shadow_opacity,
+ DBUS_TYPE_INVALID);
+ dbus_message_unref (reply);
+ }
+
+ reply = send_and_block_for_shadow_option_reply (connection, DBUS_PATH
+ "/shadow_color");
+ if (reply)
+ {
+ DBusError error;
+ char *str;
+
+ dbus_error_init (&error);
+
+ dbus_message_get_args (reply, &error,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_error_is_set (&error))
+ {
+ int c[4];
+
+ if (sscanf (str, "#%2x%2x%2x%2x", &c[0], &c[1], &c[2], &c[3]) == 4)
+ {
+ shadow_color[0] = c[0] << 8 | c[0];
+ shadow_color[1] = c[1] << 8 | c[1];
+ shadow_color[2] = c[2] << 8 | c[2];
+ }
+ }
+
+ dbus_error_free (&error);
+
+ dbus_message_unref (reply);
+ }
+
+ reply = send_and_block_for_shadow_option_reply (connection, DBUS_PATH
+ "/shadow_x_offset");
+ if (reply)
+ {
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_INT32, &shadow_offset_x,
+ DBUS_TYPE_INVALID);
+ dbus_message_unref (reply);
+ }
+
+ reply = send_and_block_for_shadow_option_reply (connection, DBUS_PATH
+ "/shadow_y_offset");
+ if (reply)
+ {
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_INT32, &shadow_offset_y,
+ DBUS_TYPE_INVALID);
+ dbus_message_unref (reply);
+ }
+#endif
+
+ style_window_rgba = gtk_window_new (GTK_WINDOW_POPUP);
+
+ gdkscreen = gdk_display_get_default_screen (gdk_display_get_default ());
+ colormap = gdk_screen_get_rgba_colormap (gdkscreen);
+ if (colormap)
+ gtk_widget_set_colormap (style_window_rgba, colormap);
+
+ gtk_widget_realize (style_window_rgba);
+
+ switcher_label = gtk_label_new ("");
+ switcher_label_obj = gtk_widget_get_accessible (switcher_label);
+ atk_object_set_role (switcher_label_obj, ATK_ROLE_STATUSBAR);
+ gtk_container_add (GTK_CONTAINER (style_window_rgba), switcher_label);
+
+ gtk_widget_set_size_request (style_window_rgba, 0, 0);
+ gtk_window_move (GTK_WINDOW (style_window_rgba), -100, -100);
+ gtk_widget_show_all (style_window_rgba);
+
+ g_signal_connect_object (style_window_rgba, "style-set",
+ G_CALLBACK (style_changed),
+ 0, 0);
+
+ settings = gtk_widget_get_settings (style_window_rgba);
+
+ g_object_get (G_OBJECT (settings), "gtk-double-click-time",
+ &double_click_timeout, NULL);
+
+ pango_context = gtk_widget_create_pango_context (style_window_rgba);
+
+ style_window_rgb = gtk_window_new (GTK_WINDOW_POPUP);
+
+ gdkscreen = gdk_display_get_default_screen (gdk_display_get_default ());
+ colormap = gdk_screen_get_rgb_colormap (gdkscreen);
+ if (colormap)
+ gtk_widget_set_colormap (style_window_rgb, colormap);
+
+ gtk_widget_realize (style_window_rgb);
+
+ switcher_label = gtk_label_new ("");
+ switcher_label_obj = gtk_widget_get_accessible (switcher_label);
+ atk_object_set_role (switcher_label_obj, ATK_ROLE_STATUSBAR);
+ gtk_container_add (GTK_CONTAINER (style_window_rgb), switcher_label);
+
+ gtk_widget_set_size_request (style_window_rgb, 0, 0);
+ gtk_window_move (GTK_WINDOW (style_window_rgb), -100, -100);
+ gtk_widget_show_all (style_window_rgb);
+
+ g_signal_connect_object (style_window_rgb, "style-set",
+ G_CALLBACK (style_changed),
+ 0, 0);
+
+ settings = gtk_widget_get_settings (style_window_rgb);
+
+ g_object_get (G_OBJECT (settings), "gtk-double-click-time",
+ &double_click_timeout, NULL);
+
+ pango_context = gtk_widget_create_pango_context (style_window_rgb);
+
+#ifdef USE_GCONF
+ use_system_font = gconf_client_get_bool (gconf,
+ COMPIZ_USE_SYSTEM_FONT_KEY,
+ NULL);
+ theme_changed (gconf);
+ theme_opacity_changed (gconf);
+ button_layout_changed (gconf);
+#endif
+
+ update_style (style_window_rgba);
+ update_style (style_window_rgb);
+#ifdef USE_GCONF
+ titlebar_font_changed (gconf);
+#endif
+
+ update_titlebar_font ();
+
+#ifdef USE_GCONF
+ titlebar_click_action_changed (gconf,
+ COMPIZ_DOUBLE_CLICK_TITLEBAR_KEY,
+ &double_click_action,
+ DOUBLE_CLICK_ACTION_DEFAULT);
+ titlebar_click_action_changed (gconf,
+ COMPIZ_MIDDLE_CLICK_TITLEBAR_KEY,
+ &middle_click_action,
+ MIDDLE_CLICK_ACTION_DEFAULT);
+ titlebar_click_action_changed (gconf,
+ COMPIZ_RIGHT_CLICK_TITLEBAR_KEY,
+ &right_click_action,
+ RIGHT_CLICK_ACTION_DEFAULT);
+ wheel_action_changed (gconf);
+ shadow_settings_changed (gconf);
+ blur_settings_changed (gconf);
+#endif
+
+ (*theme_update_border_extents) (text_height);
+
+ update_shadow ();
+
+ return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GdkDisplay *gdkdisplay;
+ Display *xdisplay;
+ GdkScreen *gdkscreen;
+ WnckScreen *screen;
+ gint i, j, status;
+ gboolean replace = FALSE;
+
+#ifdef USE_METACITY
+ char *meta_theme = NULL;
+#endif
+
+ program_name = argv[0];
+
+ gtk_init (&argc, &argv);
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ for (i = 0; i < argc; i++)
+ {
+ if (strcmp (argv[i], "--minimal") == 0)
+ {
+ minimal = TRUE;
+ }
+ else if (strcmp (argv[i], "--replace") == 0)
+ {
+ replace = TRUE;
+ }
+ else if (strcmp (argv[i], "--blur") == 0)
+ {
+ if (argc > ++i)
+ {
+ if (strcmp (argv[i], "titlebar") == 0)
+ blur_type = BLUR_TYPE_TITLEBAR;
+ else if (strcmp (argv[i], "all") == 0)
+ blur_type = BLUR_TYPE_ALL;
+ }
+ cmdline_options |= CMDLINE_BLUR;
+ }
+
+#ifdef USE_METACITY
+ else if (strcmp (argv[i], "--opacity") == 0)
+ {
+ if (argc > ++i)
+ meta_opacity = atof (argv[i]);
+ cmdline_options |= CMDLINE_OPACITY;
+ }
+ else if (strcmp (argv[i], "--no-opacity-shade") == 0)
+ {
+ meta_shade_opacity = FALSE;
+ cmdline_options |= CMDLINE_OPACITY_SHADE;
+ }
+ else if (strcmp (argv[i], "--active-opacity") == 0)
+ {
+ if (argc > ++i)
+ meta_active_opacity = atof (argv[i]);
+ cmdline_options |= CMDLINE_ACTIVE_OPACITY;
+ }
+ else if (strcmp (argv[i], "--no-active-opacity-shade") == 0)
+ {
+ meta_active_shade_opacity = FALSE;
+ cmdline_options |= CMDLINE_ACTIVE_OPACITY_SHADE;
+ }
+ else if (strcmp (argv[i], "--metacity-theme") == 0)
+ {
+ if (argc > ++i)
+ meta_theme = argv[i];
+ cmdline_options |= CMDLINE_THEME;
+ }
+#endif
+
+ else if (strcmp (argv[i], "--help") == 0)
+ {
+ fprintf (stderr, "%s "
+ "[--minimal] "
+ "[--replace] "
+ "[--blur none|titlebar|all] "
+
+#ifdef USE_METACITY
+ "[--opacity OPACITY] "
+ "[--no-opacity-shade] "
+ "[--active-opacity OPACITY] "
+ "[--no-active-opacity-shade] "
+ "[--metacity-theme THEME] "
+#endif
+
+ "[--help]"
+
+ "\n", program_name);
+ return 0;
+ }
+ }
+
+ theme_draw_window_decoration = draw_window_decoration;
+ theme_calc_decoration_size = calc_decoration_size;
+ theme_update_border_extents = update_border_extents;
+ theme_get_event_window_position = get_event_window_position;
+ theme_get_button_position = get_button_position;
+
+#ifdef USE_METACITY
+ if (meta_theme)
+ {
+ meta_theme_set_current (meta_theme, TRUE);
+ if (meta_theme_get_current ())
+ {
+ theme_draw_window_decoration = meta_draw_window_decoration;
+ theme_calc_decoration_size = meta_calc_decoration_size;
+ theme_update_border_extents = meta_update_border_extents;
+ theme_get_event_window_position = meta_get_event_window_position;
+ theme_get_button_position = meta_get_button_position;
+ }
+ }
+#endif
+
+ gdkdisplay = gdk_display_get_default ();
+ xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay);
+ gdkscreen = gdk_display_get_default_screen (gdkdisplay);
+
+ frame_input_window_atom = XInternAtom (xdisplay,
+ DECOR_INPUT_FRAME_ATOM_NAME, FALSE);
+ frame_output_window_atom = XInternAtom (xdisplay,
+ DECOR_OUTPUT_FRAME_ATOM_NAME, FALSE);
+
+ win_decor_atom = XInternAtom (xdisplay, DECOR_WINDOW_ATOM_NAME, FALSE);
+ win_blur_decor_atom = XInternAtom (xdisplay, DECOR_BLUR_ATOM_NAME, FALSE);
+ wm_move_resize_atom = XInternAtom (xdisplay, "_NET_WM_MOVERESIZE", FALSE);
+ restack_window_atom = XInternAtom (xdisplay, "_NET_RESTACK_WINDOW", FALSE);
+ select_window_atom = XInternAtom (xdisplay, DECOR_SWITCH_WINDOW_ATOM_NAME,
+ FALSE);
+ mwm_hints_atom = XInternAtom (xdisplay, "_MOTIF_WM_HINTS", FALSE);
+ switcher_fg_atom = XInternAtom (xdisplay,
+ DECOR_SWITCH_FOREGROUND_COLOR_ATOM_NAME,
+ FALSE);
+
+ toolkit_action_atom =
+ XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION", FALSE);
+ toolkit_action_window_menu_atom =
+ XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_WINDOW_MENU", FALSE);
+ toolkit_action_force_quit_dialog_atom =
+ XInternAtom (xdisplay, "_COMPIZ_TOOLKIT_ACTION_FORCE_QUIT_DIALOG",
+ FALSE);
+
+ status = decor_acquire_dm_session (xdisplay,
+ gdk_screen_get_number (gdkscreen),
+ "gwd", replace, &dm_sn_timestamp);
+ if (status != DECOR_ACQUIRE_STATUS_SUCCESS)
+ {
+ if (status == DECOR_ACQUIRE_STATUS_FAILED)
+ {
+ fprintf (stderr,
+ "%s: Could not acquire decoration manager "
+ "selection on screen %d display \"%s\"\n",
+ program_name, gdk_screen_get_number (gdkscreen),
+ DisplayString (xdisplay));
+ }
+ else if (status == DECOR_ACQUIRE_STATUS_OTHER_DM_RUNNING)
+ {
+ fprintf (stderr,
+ "%s: Screen %d on display \"%s\" already "
+ "has a decoration manager; try using the "
+ "--replace option to replace the current "
+ "decoration manager.\n",
+ program_name, gdk_screen_get_number (gdkscreen),
+ DisplayString (xdisplay));
+ }
+
+ return 1;
+ }
+
+ 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);
+ }
+ }
+
+ xformat_rgba = XRenderFindStandardFormat (xdisplay, PictStandardARGB32);
+ xformat_rgb = XRenderFindStandardFormat (xdisplay, PictStandardRGB24);
+
+ frame_table = g_hash_table_new (NULL, NULL);
+
+ if (!create_tooltip_window ())
+ {
+ fprintf (stderr, "%s, Couldn't create tooltip window\n", argv[0]);
+ return 1;
+ }
+
+ screen = wnck_screen_get_default ();
+ wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
+
+ gdk_window_add_filter (NULL,
+ selection_event_filter_func,
+ NULL);
+
+ if (!minimal)
+ {
+ 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;
+ }
+
+ decor_set_dm_check_hint (xdisplay, gdk_screen_get_number (gdkscreen),
+ WINDOW_DECORATION_TYPE_PIXMAP |
+ WINDOW_DECORATION_TYPE_WINDOW);
+
+ update_default_decorations (gdkscreen);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/gtk/window-decorator/gwd.schemas.in b/gtk/window-decorator/gwd.schemas.in
new file mode 100644
index 0000000..89b8c9c
--- /dev/null
+++ b/gtk/window-decorator/gwd.schemas.in
@@ -0,0 +1,81 @@
+<gconfschemafile>
+ <schemalist>
+ <schema>
+ <key>/schemas/apps/gwd/blur_type</key>
+ <applyto>/apps/gwd/blur_type</applyto>
+ <owner>gwd</owner>
+ <type>string</type>
+ <default>none</default>
+ <locale name="C">
+ <short>Blur type</short>
+ <long>Type of blur used for window decorations</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/use_metacity_theme</key>
+ <applyto>/apps/gwd/use_metacity_theme</applyto>
+ <owner>gwd</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Use metacity theme</short>
+ <long>Use metacity theme when drawing window decorations</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/mouse_wheel_action</key>
+ <applyto>/apps/gwd/mouse_wheel_action</applyto>
+ <owner>gwd</owner>
+ <type>string</type>
+ <default>none</default>
+ <locale name="C">
+ <short>Title bar mouse wheel action</short>
+ <long>Action to take when scrolling the mouse wheel on a window title bar.</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/metacity_theme_opacity</key>
+ <applyto>/apps/gwd/metacity_theme_opacity</applyto>
+ <owner>gwd</owner>
+ <type>float</type>
+ <default>0.75</default>
+ <locale name="C">
+ <short>Metacity theme opacity</short>
+ <long>Opacity to use for metacity theme decorations</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/metacity_theme_shade_opacity</key>
+ <applyto>/apps/gwd/metacity_theme_shade_opacity</applyto>
+ <owner>gwd</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Metacity theme opacity shade</short>
+ <long>Shade windows with metacity theme decorations from opaque to translucent</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/metacity_theme_active_opacity</key>
+ <applyto>/apps/gwd/metacity_theme_active_opacity</applyto>
+ <owner>gwd</owner>
+ <type>float</type>
+ <default>1.0</default>
+ <locale name="C">
+ <short>Metacity theme active window opacity</short>
+ <long>Opacity to use for active windows with metacity theme decorations</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/apps/gwd/metacity_theme_active_shade_opacity</key>
+ <applyto>/apps/gwd/metacity_theme_active_shade_opacity</applyto>
+ <owner>gwd</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Metacity theme active window opacity shade</short>
+ <long>Shade active windows with metacity theme decorations from opaque to translucent</long>
+ </locale>
+ </schema>
+ </schemalist>
+</gconfschemafile>
diff --git a/images/CMakeLists.txt b/images/CMakeLists.txt
new file mode 100644
index 0000000..77589a4
--- /dev/null
+++ b/images/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+set (_images
+ icon.png
+ freedesktop.png
+)
+
+install (
+ FILES ${_images}
+ DESTINATION ${COMPIZ_DESTDIR}${compiz_imagedir}
+)
diff --git a/images/freedesktop.png b/images/freedesktop.png
new file mode 100644
index 0000000..9d8b69d
--- /dev/null
+++ b/images/freedesktop.png
Binary files differ
diff --git a/images/icon.png b/images/icon.png
new file mode 100644
index 0000000..e3688d5
--- /dev/null
+++ b/images/icon.png
Binary files differ
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644
index 0000000..31b7b94
--- /dev/null
+++ b/include/CMakeLists.txt
@@ -0,0 +1,11 @@
+set (_headers
+ compiz.h
+ decoration.h
+)
+
+install (
+ FILES ${_headers}
+ DESTINATION ${COMPIZ_DESTDIR}${includedir}/compiz
+)
+
+add_subdirectory (core)
diff --git a/include/compiz-common.h.in b/include/compiz-common.h.in
new file mode 100644
index 0000000..ca09527
--- /dev/null
+++ b/include/compiz-common.h.in
@@ -0,0 +1,9 @@
+#ifndef COMPIZ_COMMON_H
+#define COMPIZ_COMMON_H
+
+#define COMPIZ_VERSION_MAJOR @COMPIZ_VERSION_MAJOR@
+#define COMPIZ_VERSION_MINOR @COMPIZ_VERSION_MINOR@
+#define COMPIZ_VERSION_MICRO @COMPIZ_VERSION_MICRO@
+
+#define COMPIZ_VERSION_STRING "@COMPIZ_VERSION_MAJOR@.@COMPIZ_VERSION_MINOR@.@COMPIZ_VERSION_MICRO@"
+#endif
diff --git a/include/compiz.h b/include/compiz.h
new file mode 100644
index 0000000..aa942b9
--- /dev/null
+++ b/include/compiz.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2007 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 <compiz-common.h>
+
+#include <string>
+#include <list>
+#include <cstdarg>
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY (x)
+
+#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))
+
+#define TIMEVALDIFF(tv1, tv2) \
+ ((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
+ ((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) + \
+ ((tv1)->tv_usec - (tv2)->tv_usec)) / 1000 : \
+ ((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) + \
+ (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)) / 1000
+
+#define MULTIPLY_USHORT(us1, us2) \
+ (((GLuint) (us1) * (GLuint) (us2)) / 0xffff)
+
+#define DEG2RAD (M_PI / 180.0f)
+
+#if defined(HAVE_SCANDIR_POSIX)
+ // POSIX (2008) defines the comparison function like this:
+ #define scandir(a,b,c,d) scandir((a), (b), (c), (int(*)(const dirent **, const dirent **))(d));
+#else
+ #define scandir(a,b,c,d) scandir((a), (b), (c), (int(*)(const void*,const void*))(d));
+#endif
+
+typedef std::string CompString;
+typedef std::list<CompString> CompStringList;
+
+CompString compPrintf (const char *format, ...);
+CompString compPrintf (const char *format, va_list ap);
+
+
+
+typedef enum {
+ CompLogLevelFatal = 0,
+ CompLogLevelError,
+ CompLogLevelWarn,
+ CompLogLevelInfo,
+ CompLogLevelDebug
+} CompLogLevel;
+
+void
+compLogMessage (const char *componentName,
+ CompLogLevel level,
+ const char *format,
+ ...);
+
+const char *
+logLevelToString (CompLogLevel level);
+
+extern char *programName;
+extern char **programArgv;
+extern int programArgc;
+extern bool zcomp;
+
+#endif
diff --git a/include/core/CMakeLists.txt b/include/core/CMakeLists.txt
new file mode 100644
index 0000000..f541c9c
--- /dev/null
+++ b/include/core/CMakeLists.txt
@@ -0,0 +1,30 @@
+set (_headers
+ action.h
+ atoms.h
+ core.h
+ countedlist.h
+ icon.h
+ match.h
+ modifierhandler.h
+ option.h
+ output.h
+ plugin.h
+ point.h
+ pluginclasshandler.h
+ pluginclasses.h
+ propertywriter.h
+ rect.h
+ region.h
+ screen.h
+ serialization.h
+ session.h
+ size.h
+ timer.h
+ window.h
+ wrapsystem.h
+)
+
+install (
+ FILES ${_headers}
+ DESTINATION ${COMPIZ_DESTDIR}${includedir}/compiz/core
+)
diff --git a/include/core/action.h b/include/core/action.h
new file mode 100644
index 0000000..006ba30
--- /dev/null
+++ b/include/core/action.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _COMPACTION_H
+#define _COMPACTION_H
+
+#include <boost/function.hpp>
+
+#include <X11/Xlib-xcb.h>
+
+#include <core/option.h>
+
+class PrivateAction;
+
+#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 CompNoMask (1 << 25)
+
+/**
+ * Context of an event occuring.
+ */
+class CompAction {
+ public:
+ typedef enum {
+ StateInitKey = 1 << 0,
+ StateTermKey = 1 << 1,
+ StateInitButton = 1 << 2,
+ StateTermButton = 1 << 3,
+ StateInitBell = 1 << 4,
+ StateInitEdge = 1 << 5,
+ StateTermEdge = 1 << 6,
+ StateInitEdgeDnd = 1 << 7,
+ StateTermEdgeDnd = 1 << 8,
+ StateCommit = 1 << 9,
+ StateCancel = 1 << 10,
+ StateAutoGrab = 1 << 11,
+ StateNoEdgeDelay = 1 << 12
+ } StateEnum;
+
+ /**
+ * Type of event a CompAction is bound to.
+ */
+ typedef enum {
+ BindingTypeNone = 0,
+ BindingTypeKey = 1 << 0,
+ BindingTypeButton = 1 << 1,
+ BindingTypeEdgeButton = 1 << 2
+ } BindingTypeEnum;
+
+ class KeyBinding {
+ public:
+ KeyBinding ();
+ KeyBinding (const KeyBinding&);
+ KeyBinding (int keycode, unsigned int modifiers = 0);
+
+ unsigned int modifiers () const;
+ int keycode () const;
+
+ bool fromString (const CompString &str);
+ CompString toString () const;
+
+ private:
+ unsigned int mModifiers;
+ int mKeycode;
+ };
+
+ class ButtonBinding {
+ public:
+ ButtonBinding ();
+ ButtonBinding (const ButtonBinding&);
+ ButtonBinding (int button, unsigned int modifiers = 0);
+
+ unsigned int modifiers () const;
+ int button () const;
+
+ bool fromString (const CompString &str);
+ CompString toString () const;
+
+ private:
+ unsigned int mModifiers;
+ int mButton;
+ };
+
+ typedef unsigned int State;
+ typedef unsigned int BindingType;
+ typedef boost::function <bool (CompAction *, State, CompOption::Vector &)> CallBack;
+
+ public:
+ CompAction ();
+ CompAction (const CompAction &);
+ ~CompAction ();
+
+ CallBack initiate ();
+ CallBack terminate ();
+
+ void setInitiate (const CallBack &initiate);
+ void setTerminate (const CallBack &terminate);
+
+ State state ();
+ BindingType type ();
+
+ KeyBinding & key ();
+ void setKey (const KeyBinding &key);
+
+ ButtonBinding & button ();
+ void setButton (const ButtonBinding &button);
+
+ unsigned int edgeMask ();
+ void setEdgeMask (unsigned int edge);
+
+ bool bell ();
+ void setBell (bool bell);
+
+ void setState (State state);
+
+ void copyState (const CompAction &action);
+
+ bool operator== (const CompAction& val);
+ CompAction & operator= (const CompAction &action);
+
+ bool keyFromString (const CompString &str);
+ bool buttonFromString (const CompString &str);
+ bool edgeMaskFromString (const CompString &str);
+
+ CompString keyToString ();
+ CompString buttonToString ();
+ CompString edgeMaskToString ();
+
+ static CompString edgeToString (unsigned int edge);
+
+ private:
+ PrivateAction *priv;
+};
+
+#endif
diff --git a/include/core/atoms.h b/include/core/atoms.h
new file mode 100644
index 0000000..6cd0b50
--- /dev/null
+++ b/include/core/atoms.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _ATOMS_H
+#define _ATOMS_H
+
+#include <X11/Xlib-xcb.h>
+
+namespace Atoms {
+ extern Atom supported;
+ extern Atom supportingWmCheck;
+
+ extern Atom utf8String;
+
+ extern Atom wmName;
+
+ extern Atom winType;
+ extern Atom winTypeDesktop;
+ extern Atom winTypeDock;
+ extern Atom winTypeToolbar;
+ extern Atom winTypeMenu;
+ extern Atom winTypeUtil;
+ extern Atom winTypeSplash;
+ extern Atom winTypeDialog;
+ extern Atom winTypeNormal;
+ extern Atom winTypeDropdownMenu;
+ extern Atom winTypePopupMenu;
+ extern Atom winTypeTooltip;
+ extern Atom winTypeNotification;
+ extern Atom winTypeCombo;
+ extern Atom winTypeDnd;
+
+ extern Atom winOpacity;
+ extern Atom winBrightness;
+ extern Atom winSaturation;
+ extern Atom winActive;
+ extern Atom winDesktop;
+
+ extern Atom workarea;
+
+ extern Atom desktopViewport;
+ extern Atom desktopGeometry;
+ extern Atom currentDesktop;
+ extern Atom numberOfDesktops;
+
+ extern Atom winState;
+ extern Atom winStateModal;
+ extern Atom winStateSticky;
+ extern Atom winStateMaximizedVert;
+ extern Atom winStateMaximizedHorz;
+ extern Atom winStateShaded;
+ extern Atom winStateSkipTaskbar;
+ extern Atom winStateSkipPager;
+ extern Atom winStateHidden;
+ extern Atom winStateFullscreen;
+ extern Atom winStateAbove;
+ extern Atom winStateBelow;
+ extern Atom winStateDemandsAttention;
+ extern Atom winStateDisplayModal;
+
+ extern Atom winActionMove;
+ extern Atom winActionResize;
+ extern Atom winActionStick;
+ extern Atom winActionMinimize;
+ extern Atom winActionMaximizeHorz;
+ extern Atom winActionMaximizeVert;
+ extern Atom winActionFullscreen;
+ extern Atom winActionClose;
+ extern Atom winActionShade;
+ extern Atom winActionChangeDesktop;
+ extern Atom winActionAbove;
+ extern Atom winActionBelow;
+
+ extern Atom wmAllowedActions;
+
+ extern Atom wmStrut;
+ extern Atom wmStrutPartial;
+
+ extern Atom wmUserTime;
+
+ extern Atom wmIcon;
+ extern Atom wmIconGeometry;
+
+ extern Atom clientList;
+ extern Atom clientListStacking;
+
+ extern Atom frameExtents;
+ extern Atom frameWindow;
+
+ extern Atom wmState;
+ extern Atom wmChangeState;
+ extern Atom wmProtocols;
+ extern Atom wmClientLeader;
+
+ extern Atom wmDeleteWindow;
+ extern Atom wmTakeFocus;
+ extern Atom wmPing;
+ extern Atom wmSyncRequest;
+
+ extern Atom wmSyncRequestCounter;
+
+ extern Atom wmFullscreenMonitors;
+
+ extern Atom closeWindow;
+ extern Atom wmMoveResize;
+ extern Atom moveResizeWindow;
+ extern Atom restackWindow;
+
+ extern Atom showingDesktop;
+
+ extern Atom xBackground[2];
+
+ extern Atom toolkitAction;
+ extern Atom toolkitActionWindowMenu;
+ extern Atom toolkitActionForceQuitDialog;
+
+ extern Atom mwmHints;
+
+ extern Atom xdndAware;
+ extern Atom xdndEnter;
+ extern Atom xdndLeave;
+ extern Atom xdndPosition;
+ extern Atom xdndStatus;
+ extern Atom xdndDrop;
+
+ extern Atom manager;
+ extern Atom targets;
+ extern Atom multiple;
+ extern Atom timestamp;
+ extern Atom version;
+ extern Atom atomPair;
+
+ extern Atom startupId;
+
+ void init (Display *dpy);
+};
+
+#endif
diff --git a/include/core/core.h b/include/core/core.h
new file mode 100644
index 0000000..40f2eec
--- /dev/null
+++ b/include/core/core.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2007 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_CORE_H
+#define _COMPIZ_CORE_H
+
+#define CORE_ABIVERSION 20080618
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <X11/Xlib-xcb.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xdamage.h>
+#include <X11/extensions/Xinerama.h>
+#include <X11/extensions/sync.h>
+#include <X11/Xregion.h>
+#include <X11/XKBlib.h>
+
+// X11 Bool defination breaks BOOST_FOREACH. Convert it to a typedef */
+#ifdef Bool
+typedef Bool XBool;
+#undef Bool
+typedef XBool Bool;
+#endif
+
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#define foreach BOOST_FOREACH
+
+/*
+ * WORDS_BIGENDIAN should be defined before including this file for
+ * IMAGE_BYTE_ORDER and BITMAP_BIT_ORDER to be set correctly.
+ */
+#define LSBFirst 0
+#define MSBFirst 1
+
+#ifdef WORDS_BIGENDIAN
+# define IMAGE_BYTE_ORDER MSBFirst
+# define BITMAP_BIT_ORDER MSBFirst
+#else
+# define IMAGE_BYTE_ORDER LSBFirst
+# define BITMAP_BIT_ORDER LSBFirst
+#endif
+
+#include <core/pluginclasses.h>
+#include <core/screen.h>
+#include <core/window.h>
+#include <core/plugin.h>
+#include <core/option.h>
+#include <core/action.h>
+#include <core/icon.h>
+#include <core/match.h>
+#include <core/output.h>
+#include <core/point.h>
+#include <core/rect.h>
+#include <core/session.h>
+#include <core/size.h>
+#include <core/region.h>
+#include <core/countedlist.h>
+
+#endif
diff --git a/include/core/countedlist.h b/include/core/countedlist.h
new file mode 100644
index 0000000..304338c
--- /dev/null
+++ b/include/core/countedlist.h
@@ -0,0 +1,114 @@
+/*
+ * countedlist.h
+ *
+ * Created on: Dec 15, 2009
+ * Author: erkin
+ */
+
+#ifndef COUNTEDLIST_H_
+#define COUNTEDLIST_H_
+
+
+template<typename value_type,
+ typename allocator_type = std::allocator<value_type> >
+class CountedList : protected std::list<value_type, allocator_type>
+{
+public:
+ typedef std::list<value_type, allocator_type> Base;
+ typedef typename Base::size_type size_type;
+ typedef typename Base::iterator iterator;
+ typedef typename Base::const_iterator const_iterator;
+ typedef typename Base::reverse_iterator reverse_iterator;
+ typedef typename Base::const_reverse_iterator const_reverse_iterator;
+ typedef typename Base::reference reference;
+ typedef typename Base::const_reference const_reference;
+
+ CountedList () : Base (), mCount (0) { }
+
+ // Overriden std::list methods
+
+ bool empty () const { return Base::empty (); }
+ size_type size () const { return mCount; }
+ size_type max_size() const { return Base::max_size(); }
+
+ iterator begin () { return Base::begin (); }
+ const_iterator begin () const { return Base::begin (); }
+ iterator end () { return Base::end (); }
+ const_iterator end () const { return Base::end (); }
+
+ reverse_iterator rbegin () { return Base::rbegin (); }
+ const_reverse_iterator rbegin () const { return Base::rbegin (); }
+ reverse_iterator rend () { return Base::rend (); }
+ const_reverse_iterator rend () const { return Base::rend (); }
+
+ reference front () { return Base::front (); }
+ const_reference front () const { return Base::front (); }
+ reference back () { return Base::back (); }
+ const_reference back () const { return Base::back (); }
+
+ void reverse () { Base::reverse (); }
+ void sort () { Base::sort (); }
+
+ template<typename _StrictWeakOrdering>
+ void sort(_StrictWeakOrdering __comp) { Base::sort (__comp); }
+
+ void resize (size_type __new_size, value_type __x = value_type ())
+ {
+ mCount = __new_size;
+ Base::resize (__new_size, __x);
+ }
+ void clear ()
+ {
+ mCount = 0;
+ Base::clear ();
+ }
+ void push_front (const value_type& __x)
+ {
+ mCount++;
+ Base::push_front (__x);
+ }
+ void push_back (const value_type& __x)
+ {
+ mCount++;
+ Base::push_back (__x);
+ }
+ void pop_front ()
+ {
+ if (mCount > 0)
+ mCount--;
+ Base::pop_front ();
+ }
+ void pop_back ()
+ {
+ if (mCount > 0)
+ mCount--;
+ Base::pop_back ();
+ }
+ iterator insert (iterator __position, const value_type& __x)
+ {
+ mCount++;
+ return Base::insert (__position, __x);
+ }
+ void insert (iterator __position, size_type __n, const value_type& __x)
+ {
+ mCount += __n;
+ Base::insert (__position, __n, __x);
+ }
+ iterator erase (iterator __position)
+ {
+ if (mCount > 0)
+ mCount--;
+ return Base::erase (__position);
+ }
+ void remove (const value_type& __value)
+ {
+ if (mCount > 0)
+ mCount--;
+ Base::remove (__value);
+ }
+
+protected:
+ size_type mCount;
+};
+
+#endif /* COUNTEDLIST_H_ */
diff --git a/include/core/icon.h b/include/core/icon.h
new file mode 100644
index 0000000..f985a7b
--- /dev/null
+++ b/include/core/icon.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _COMPICON_H
+#define _COMPICON_H
+
+#include <core/size.h>
+
+class CompScreen;
+
+/**
+ * Wraps an application icon pixel map and it's meta information (such as dimensions)
+ */
+class CompIcon : public CompSize {
+ public:
+ CompIcon (CompScreen *screen, unsigned width, unsigned int height);
+ ~CompIcon ();
+
+ /**
+ * Gets a pointer to the pixel data for this icon.
+ */
+ unsigned char* data ();
+
+ private:
+ CompSize mSize;
+ unsigned char *mData;
+};
+
+#endif
diff --git a/include/core/match.h b/include/core/match.h
new file mode 100644
index 0000000..8949566
--- /dev/null
+++ b/include/core/match.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _COMPMATCH_H
+#define _COMPMATCH_H
+
+#include <core/core.h>
+
+class PrivateMatch;
+class CompWindow;
+class CompDisplay;
+
+/**
+ * Object which represents a series of window properties
+ * that can be matched in a window. Used for determining which
+ * windows to operate on, in core or in plugins
+ */
+class CompMatch {
+ public:
+
+ /**
+ * TODO
+ */
+ class Expression {
+ public:
+ virtual ~Expression () {};
+ virtual bool evaluate (CompWindow *window) = 0;
+ };
+
+ public:
+ CompMatch ();
+ CompMatch (const CompString);
+ CompMatch (const CompMatch &);
+ ~CompMatch ();
+
+ static const CompMatch emptyMatch;
+
+ void update ();
+
+ /**
+ * Returns true if the specified CompWindow has the properties
+ * specified in the match object
+ */
+ bool evaluate (CompWindow *window);
+
+ CompString toString () const;
+ bool isEmpty () const;
+
+ CompMatch & operator= (const CompMatch &);
+ CompMatch & operator&= (const CompMatch &);
+ CompMatch & operator|= (const CompMatch &);
+
+ const CompMatch & operator& (const CompMatch &);
+ const CompMatch & operator| (const CompMatch &);
+ const CompMatch & operator! ();
+
+ CompMatch & operator= (const CompString &);
+ CompMatch & operator&= (const CompString &);
+ CompMatch & operator|= (const CompString &);
+
+ const CompMatch & operator& (const CompString &);
+ const CompMatch & operator| (const CompString &);
+
+ bool operator== (const CompMatch &) const;
+ bool operator!= (const CompMatch &) const;
+
+ private:
+ PrivateMatch *priv;
+};
+
+#endif
diff --git a/include/core/modifierhandler.h b/include/core/modifierhandler.h
new file mode 100644
index 0000000..aa7c3df
--- /dev/null
+++ b/include/core/modifierhandler.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ * Sam Spilsbury <smspillaz@gmail.com>
+ */
+
+#include <core/core.h>
+
+/**
+ * Toplevel class which provides access to display
+ * level modifier information
+ */
+class ModifierHandler
+{
+ public:
+
+ ModifierHandler ();
+ ~ModifierHandler ();
+
+ typedef enum
+ {
+ Alt = 1,
+ Meta,
+ Super,
+ Hyper,
+ ModeSwitch,
+ NumLock,
+ ScrollLock,
+ ModNum
+ } Modifier;
+
+ typedef enum
+ {
+ AltMask = (1 << 16),
+ MetaMask = (1 << 17),
+ SuperMask = (1 << 18),
+ HyperMask = (1 << 19),
+ ModeSwitchMask = (1 << 20),
+ NumLockMask = (1 << 21),
+ ScrollLockMask = (1 << 22),
+ NoMask = (1 << 25),
+ } ModMask;
+
+ public:
+
+
+ /**
+ * Takes an X11 Keycode and returns a bitmask
+ * with modifiers that have been pressed
+ */
+ unsigned int keycodeToModifiers (int keycode);
+
+ /**
+ * Updates X11 Modifier mappings
+ */
+ void updateModifierMappings ();
+
+ /**
+ * Takes a virtual modMask and returns a real modifier mask
+ * by removing unused bits
+ */
+ unsigned int virtualToRealModMask (unsigned int modMask);
+
+ /**
+ * Returns a bit modifier mask for a Motifier enum
+ */
+ unsigned int modMask (Modifier);
+
+ /**
+ * Returns a const bit modifier mask for what should be ignored
+ */
+ unsigned int ignoredModMask ();
+
+ /**
+ * Returns a const XModifierKeymap for compiz
+ */
+ const XModifierKeymap * modMap ();
+
+ friend class CompScreen;
+
+ private:
+
+ static const unsigned int virtualModMask[7];
+
+ static const int maskTable[8];
+
+ static const int maskTableSize = 8;
+
+ ModMask mModMask[ModNum];
+ unsigned int mIgnoredModMask;
+ XModifierKeymap *mModMap;
+};
diff --git a/include/core/option.h b/include/core/option.h
new file mode 100644
index 0000000..09cf033
--- /dev/null
+++ b/include/core/option.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _COMPOPTION_H
+#define _COMPOPTION_H
+
+#include <compiz.h>
+
+#include <vector>
+
+class PrivateOption;
+class PrivateValue;
+class PrivateRestriction;
+class CompAction;
+class CompMatch;
+class CompScreen;
+
+/**
+ * A configuration option with boolean, int, float, String, Color, Key, Button,
+ * Edge, Bell, or List.
+ */
+class CompOption {
+ /**
+ * Option data types
+ */
+ public:
+ typedef enum {
+ TypeBool,
+ TypeInt,
+ TypeFloat,
+ TypeString,
+ TypeColor,
+ TypeAction,
+ TypeKey,
+ TypeButton,
+ TypeEdge,
+ TypeBell,
+ TypeMatch,
+ TypeList,
+ /* internal use only */
+ TypeUnset
+ } Type;
+
+ /**
+ * A value of an Option
+ */
+ class Value {
+ public:
+ typedef std::vector<Value> Vector;
+
+ public:
+ Value ();
+ Value (const Value &);
+ Value (const bool b);
+ Value (const int i);
+ Value (const float f);
+ Value (const unsigned short *color);
+ Value (const CompString& s);
+ Value (const char *s);
+ Value (const CompMatch& m);
+ Value (const CompAction& a);
+ Value (Type type, const Vector& l);
+ ~Value ();
+
+ Type type () const;
+
+ void set (const bool b);
+ void set (const int i);
+ void set (const float f);
+ void set (const unsigned short *color);
+ void set (const CompString& s);
+ void set (const char *s);
+ void set (const CompMatch& m);
+ void set (const CompAction& a);
+ void set (Type type, const Vector& l);
+
+ bool b ();
+ int i ();
+ float f ();
+ unsigned short* c ();
+ CompString s ();
+ CompMatch & match ();
+ CompAction & action ();
+ Type listType ();
+ Vector & list ();
+
+ bool operator== (const Value& val);
+ bool operator!= (const Value& val);
+ Value & operator= (const Value &val);
+
+ operator bool ();
+ operator int ();
+ operator float ();
+ operator unsigned short * ();
+ operator CompString ();
+ operator CompMatch & ();
+ operator CompAction & ();
+ operator CompAction * ();
+ operator Type ();
+ operator Vector & ();
+
+ private:
+ PrivateValue *priv;
+ };
+
+ /**
+ * TODO
+ */
+ class Restriction {
+ public:
+ Restriction ();
+ Restriction (const Restriction &);
+ ~Restriction ();
+
+ int iMin ();
+ int iMax ();
+ float fMin ();
+ float fMax ();
+ float fPrecision ();
+
+ void set (int, int);
+ void set (float, float, float);
+
+ bool inRange (int);
+ bool inRange (float);
+
+ Restriction & operator= (const Restriction &rest);
+ private:
+ PrivateRestriction *priv;
+ };
+
+ typedef std::vector<CompOption> Vector;
+
+ /**
+ * TODO
+ */
+ class Class {
+ public:
+ virtual Vector & getOptions () = 0;
+
+ virtual CompOption * getOption (const CompString &name);
+
+ virtual bool setOption (const CompString &name,
+ Value &value) = 0;
+ };
+
+ public:
+ CompOption ();
+ CompOption (const CompOption &);
+ CompOption (CompString name, Type type);
+ ~CompOption ();
+
+ void setName (CompString name, Type type);
+
+ CompString name ();
+
+ Type type ();
+ Value & value ();
+ Restriction & rest ();
+
+ bool set (Value &val);
+ bool isAction ();
+
+ CompOption & operator= (const CompOption &option);
+
+ public:
+ static CompOption * findOption (Vector &options, CompString name,
+ unsigned int *index = NULL);
+
+ static bool
+ getBoolOptionNamed (const Vector& options,
+ const CompString& name,
+ bool defaultValue = false);
+
+ static int
+ getIntOptionNamed (const Vector& options,
+ const CompString& name,
+ int defaultValue = 0);
+
+ static float
+ getFloatOptionNamed (const Vector& options,
+ const CompString& name,
+ const float& defaultValue = 0.0);
+
+ static CompString
+ getStringOptionNamed (const Vector& options,
+ const CompString& name,
+ const CompString& defaultValue = "");
+
+ static unsigned short *
+ getColorOptionNamed (const Vector& options,
+ const CompString& name,
+ unsigned short *defaultValue);
+
+ static CompMatch
+ getMatchOptionNamed (const Vector& options,
+ const CompString& name,
+ const CompMatch& defaultValue);
+
+ static CompString typeToString (Type type);
+
+ static bool stringToColor (CompString color,
+ unsigned short *rgba);
+
+ static CompString colorToString (unsigned short *rgba);
+
+
+ static bool setOption (CompOption &o, Value &value);
+
+ private:
+ PrivateOption *priv;
+};
+
+extern CompOption::Vector noOptions;
+
+#endif
diff --git a/include/core/output.h b/include/core/output.h
new file mode 100644
index 0000000..a8ac41f
--- /dev/null
+++ b/include/core/output.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2008 Dennis Kasprzyk
+ * Copyright © 2007 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
+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Dennis Kasprzyk makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DENNIS KASPRZYK 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.
+ *
+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
+ * David Reveman <davidr@novell.com>
+ */
+
+#ifndef _COMPOUTPUT_H
+#define _COMPOUTPUT_H
+
+#include <core/core.h>
+#include <core/rect.h>
+
+/**
+ * Represents a phisically attached screen in Compiz, where this
+ * phisical screen is part of an X11 screen in a configuration such
+ * as Xinerama, XRandR, TwinView or MergedFB
+ */
+class CompOutput : public CompRect {
+
+ public:
+ CompOutput ();
+
+ CompString name () const;
+
+ unsigned int id () const;
+
+ /**
+ * Returns a "working area" of the screen, which the geometry
+ * which is not covered by strut windows (such as panels)
+ */
+ const CompRect& workArea () const;
+
+ void setWorkArea (const CompRect&);
+ void setGeometry (int x, int y, int width, int height);
+ void setId (CompString, unsigned int);
+
+ typedef std::vector<CompOutput> vector;
+ typedef std::vector<CompOutput *> ptrVector;
+ typedef std::list<CompOutput *> ptrList;
+
+ private:
+
+ CompString mName;
+ unsigned int mId;
+
+ CompRect mWorkArea;
+};
+
+#endif
diff --git a/include/core/plugin.h b/include/core/plugin.h
new file mode 100644
index 0000000..510f169
--- /dev/null
+++ b/include/core/plugin.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright © 2007 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_PLUGIN_H
+#define _COMPIZ_PLUGIN_H
+
+#include <compiz.h>
+#include <core/option.h>
+
+class CompScreen;
+extern CompScreen *screen;
+
+#include <map>
+
+#define HOME_PLUGINDIR ".compiz-1/plugins"
+
+#define COMPIZ_PLUGIN_20090315(name, classname) \
+ CompPlugin::VTable * name##VTable = NULL; \
+ extern "C" { \
+ CompPlugin::VTable * getCompPluginVTable20090315_##name () \
+ { \
+ if (!name##VTable) \
+ { \
+ name##VTable = new classname (); \
+ name##VTable->initVTable (TOSTRING (name), &name##VTable);\
+ return name##VTable; \
+ } \
+ else \
+ return name##VTable; \
+ } \
+ }
+
+class CompPlugin;
+
+typedef bool (*LoadPluginProc) (CompPlugin *p,
+ const char *path,
+ const char *name);
+
+typedef void (*UnloadPluginProc) (CompPlugin *p);
+
+typedef CompStringList (*ListPluginsProc) (const char *path);
+
+extern LoadPluginProc loaderLoadPlugin;
+extern UnloadPluginProc loaderUnloadPlugin;
+extern ListPluginsProc loaderListPlugins;
+
+union CompPrivate {
+ void *ptr;
+ long val;
+ unsigned long uval;
+ void *(*fptr) (void);
+};
+
+/**
+ * Base plug-in interface for Compiz. All plugins must implement this
+ * interface, which provides basics for loading, unloading, options,
+ * and linking together the plugin and Screen(s).
+ */
+class CompPlugin {
+ public:
+ class VTable {
+ public:
+ VTable ();
+ virtual ~VTable ();
+
+ void initVTable (CompString name,
+ CompPlugin::VTable **self = NULL);
+
+ /**
+ * Gets the name of this compiz plugin
+ */
+ const CompString name () const;
+
+ virtual bool init () = 0;
+
+ virtual void fini ();
+
+ virtual bool initScreen (CompScreen *s);
+
+ virtual void finiScreen (CompScreen *s);
+
+ virtual bool initWindow (CompWindow *w);
+
+ virtual void finiWindow (CompWindow *w);
+
+ virtual CompOption::Vector & getOptions ();
+
+ virtual bool setOption (const CompString &name,
+ CompOption::Value &value);
+ private:
+ CompString mName;
+ VTable **mSelf;
+ };
+
+ /**
+ * TODO (or not?)
+ */
+ template <typename T, typename T2>
+ class VTableForScreenAndWindow : public VTable {
+ bool initScreen (CompScreen *s);
+
+ void finiScreen (CompScreen *s);
+
+ bool initWindow (CompWindow *w);
+
+ void finiWindow (CompWindow *w);
+
+ CompOption::Vector & getOptions ();
+
+ bool setOption (const CompString &name, CompOption::Value &value);
+ };
+
+ /**
+ * TODO (or not?)
+ */
+ template <typename T>
+ class VTableForScreen : public VTable {
+ bool initScreen (CompScreen *s);
+
+ void finiScreen (CompScreen *s);
+
+ CompOption::Vector & getOptions ();
+
+ bool setOption (const CompString &name, CompOption::Value &value);
+ };
+
+ /**
+ * Interface for matching plugins by name.
+ */
+ struct cmpStr
+ {
+ bool operator () (const char *a, const char *b) const
+ {
+ return strcmp (a, b) < 0;
+ }
+ };
+
+ typedef std::map<const char *, CompPlugin *, cmpStr> Map;
+ typedef std::list<CompPlugin *> List;
+
+ public:
+ CompPrivate devPrivate;
+ CompString d