summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher James Halse Rogers <chris@Burninator.(none)>2007-08-27 20:39:03 +1000
committerChristopher James Halse Rogers <chris@Burninator.(none)>2007-08-27 20:39:03 +1000
commit2ec676133b4e0d5e6187e5339a69bcdaafa1cfcc (patch)
tree33ec0efc4e080e57cb654237f236bbbd5087f02e
parent8035bb2e2bf4fc30aaef4bfb7c3ea8ad110ecdbb (diff)
parenta871a8128029698e9e789e1a00d0e6c5258d7873 (diff)
downloadcompiz-cil-2ec676133b4e0d5e6187e5339a69bcdaafa1cfcc.tar.gz
compiz-cil-2ec676133b4e0d5e6187e5339a69bcdaafa1cfcc.tar.bz2
Merge ../compiz-sharpHEADmaster
-rw-r--r--.gitignore17
-rw-r--r--AUTHORS1
-rw-r--r--COPYING20
-rw-r--r--Makefile.am5
-rw-r--r--README58
-rwxr-xr-xautogen.sh12
-rw-r--r--configure.ac36
-rw-r--r--glue/.gitignore7
-rw-r--r--glue/Makefile.am12
-rw-r--r--glue/compiz-mono.c180
-rw-r--r--include.mk20
-rw-r--r--physics/Constraint.cs26
-rw-r--r--physics/Demo.cs575
-rw-r--r--physics/Geometry.cs97
-rw-r--r--physics/Makefile11
-rw-r--r--physics/Model.cs357
-rw-r--r--physics/Particle.cs54
-rw-r--r--plugins/.gitignore4
-rw-r--r--plugins/Cube.cs13
-rw-r--r--plugins/GLTest.cs90
-rw-r--r--plugins/Makefile13
-rw-r--r--plugins/Scale.cs306
-rw-r--r--plugins/Simple.cs23
-rw-r--r--plugins/SvgCairo.cs89
-rw-r--r--plugins/Zoom.cs158
-rw-r--r--src/.gitignore4
-rw-r--r--src/Display.cs159
-rw-r--r--src/Icon.cs12
-rw-r--r--src/Image.cs22
-rw-r--r--src/Main.cs159
-rw-r--r--src/Makefile11
-rw-r--r--src/Option.cs73
-rw-r--r--src/Plugin.cs27
-rw-r--r--src/PluginLoader.cs276
-rw-r--r--src/Screen.cs416
-rw-r--r--src/TestPlugin.cs80
-rw-r--r--src/Texture.cs36
-rw-r--r--src/Window.cs471
38 files changed, 3930 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..edd5b91
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+*~
+*.swp
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..d6b9e4c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Alp Toker <alp@atoker.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..baed05f
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright 2006 Alp Toker <alp@atoker.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..9b6e716
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = glue
+
+EXTRA_DIST = \
+COPYING \
+README
diff --git a/README b/README
new file mode 100644
index 0000000..070aea1
--- /dev/null
+++ b/README
@@ -0,0 +1,58 @@
+COMPIZ-SHARP
+============
+
+The aim of this project is to provide a means of driving OpenGL
+compositing in the X Window System using the Mono framework. The
+project must achieve this in a way such that effects can be provided
+concurrently by individual effect plugins with their logic written
+purely in a CLS-compliant language supported by Mono, such as C#. The
+infrastructure itself is not restricted to this requirement and may be
+implemented with a combination of C "glue" code and C# in the style of
+existing bindings. The project must yield one or more effect plugins
+that demonstrates a sensible subset of functionality offered by GL
+compositing managers. Common sense should be the guiding force rather
+than a word-for-word adherence to the following plans, as this project
+explores some new ground:
+
+The project should achieve its goals by extending compiz
+non-invasively, ideally as a a regular compiz module which hosts the
+Mono runtime. In the case that this is infeasible or highly inelegant,
+the project mentor may be consulted as to whether it would be a better
+solution to extend compiz itself to allow more flexible extensions by
+working with the author of compiz and contributing to that project
+directly.
+
+David Reveman's description of compiz:
+
+compiz - OpenGL window and compositing manager
+
+ Compiz is an OpenGL compositing manager that uses
+ 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.
+
+The API exposed by the project must cover the subset of entry points
+needed to create functional effect plugins, and should provide
+complete coverage of all relevant public API. The managed (C#) API may
+deviate in terminology from that used in compiz in order to follow the
+naming standards and style of the CLR and existing Mono libraries.
+
+The project should allow plugins to implement effects using Mono's Tao
+OpenGL library. This library has not been widely distributed and is
+not yet in a deliverable form, so some work towards making it
+shippable might be made but productisation of dependent libraries will
+generally be outwith the scope of the project.
+
+Code will be written foremost with maintainability, correctness and
+stability in mind, followed by completeness and performance concerns.
+Progress should be made such that there is demonstrable integration of
+Mono with the compositing manager for the mid-program evaluation, and
+a complete workable framework that meets the requirements set out in
+this specification by the time of the final evaluation.
+
+LICENSE
+=======
+
+All code and documentation produced for the project will be
+contributed under the terms of the MIT X11 license.
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..904cd67
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..38ea1f4
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,36 @@
+AC_PREREQ(2.57)
+AC_INIT([compiz-sharp], [0.1], [alp@atoker.com])
+AC_CONFIG_SRCDIR([Makefile.am])
+AM_INIT_AUTOMAKE([dist-bzip2 foreign])
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_LIBTOOL
+AC_HEADER_STDC
+AC_CHECK_HEADERS([stdlib.h sys/time.h unistd.h])
+
+PKG_CHECK_MODULES(MONO, mono >= 1.0)
+AC_SUBST(MONO_LIBS)
+AC_SUBST(MONO_CFLAGS)
+
+PKG_CHECK_MODULES(COMPIZ, compiz >= 0.0.13)
+AC_SUBST(COMPIZ_LIBS)
+AC_SUBST(COMPIZ_CFLAGS)
+
+plugindir=$libdir/compiz
+AC_SUBST(plugindir)
+
+imagedir=$datadir/compiz
+AC_SUBST(imagedir)
+
+AC_OUTPUT([
+Makefile
+glue/Makefile
+])
+
+echo ""
+echo "This software is at a very early stage of development."
+echo "It is not yet expected to work."
+echo ""
diff --git a/glue/.gitignore b/glue/.gitignore
new file mode 100644
index 0000000..a91c79d
--- /dev/null
+++ b/glue/.gitignore
@@ -0,0 +1,7 @@
+.deps
+.libs
+.msg
+*.lo
+*.la
+*.a
+*.o
diff --git a/glue/Makefile.am b/glue/Makefile.am
new file mode 100644
index 0000000..9e491a4
--- /dev/null
+++ b/glue/Makefile.am
@@ -0,0 +1,12 @@
+libcompmono_la_LDFLAGS = -module -avoid-version -no-undefined
+libcompmono_la_LIBADD = @COMPIZ_LIBS@ @MONO_LIBS@
+libcompmono_la_SOURCES = compiz-mono.c
+
+INCLUDES = \
+ @COMPIZ_CFLAGS@ \
+ @MONO_CFLAGS@ \
+ -I$(top_srcdir)/include
+
+moduledir = $(plugindir)
+
+module_LTLIBRARIES = libcompmono.la
diff --git a/glue/compiz-mono.c b/glue/compiz-mono.c
new file mode 100644
index 0000000..d13e922
--- /dev/null
+++ b/glue/compiz-mono.c
@@ -0,0 +1,180 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+// Plugin loader plugin for compiz-sharp
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+
+#include <compiz.h>
+
+#include <mono/jit/jit.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/environment.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/appdomain.h>
+
+typedef struct _CompMonoData {
+ MonoDomain *domain;
+ MonoAssembly *assembly;
+ MonoClass *loader_class;
+ MonoObject *loader_instance;
+} CompMonoData;
+
+static CompMonoData *data;
+
+static LoadPluginProc baseloaderLoadPlugin;
+static UnloadPluginProc baseloaderUnloadPlugin;
+
+static Bool
+monoloaderLoadPlugin (CompPlugin *p, char *path, char *name)
+{
+ Bool status;
+
+ fprintf (stderr, "monoloaderLoadPlugin %s %s\n", path, name);
+
+ MonoMethodDesc *method_desc = mono_method_desc_new (":Load(intptr,string,string)", FALSE);
+ MonoMethod *method = mono_method_desc_search_in_class (method_desc, data->loader_class);
+
+ gpointer params[3];
+ params[0] = &p;
+ params[1] = (path == NULL) ? NULL : (gpointer*) mono_string_new (data->domain, path);
+ params[2] = (name == NULL) ? NULL : (gpointer*) mono_string_new (data->domain, name);
+
+ MonoObject *mret = mono_runtime_invoke (method, data->loader_instance, params, NULL);
+ status = *(Bool*)mono_object_unbox(mret);
+
+ fprintf (stderr, "ret %d\n", status);
+
+ if (status)
+ return status;
+
+ status = (*baseloaderLoadPlugin) (p, path, name);
+
+ return status;
+}
+
+static void
+monoloaderUnloadPlugin (CompPlugin *p)
+{
+ fprintf (stderr, "monoloaderUnloadPlugin\n");
+
+ MonoMethodDesc *method_desc = mono_method_desc_new (":Unload(intptr)", FALSE);
+ MonoMethod *method = mono_method_desc_search_in_class (method_desc, data->loader_class);
+
+ gpointer params[1];
+ params[0] = &p;
+
+ MonoObject *mret = mono_runtime_invoke (method, data->loader_instance, params, NULL);
+
+ (*baseloaderUnloadPlugin) (p);
+}
+
+static MonoObject *
+plugin_loader_new (CompMonoData *data)
+{
+ MonoMethodDesc *method_desc = mono_method_desc_new (":.ctor()", FALSE);
+ MonoMethod *method = mono_method_desc_search_in_class (method_desc, data->loader_class);
+
+ MonoObject *object = mono_object_new (data->domain, data->loader_class);
+ mono_runtime_invoke (method, object, NULL, NULL);
+
+ return object;
+}
+
+static Bool
+monoInit (CompPlugin *p)
+{
+ data = malloc (sizeof (CompMonoData));
+
+ //initialize Mono
+ mono_set_defaults (0, mono_parse_default_optimizations (NULL));
+
+ //set the domain name to the assembly name
+ //this seems to let the runtime pick up 2.0 deps
+ data->domain = mono_jit_init ("compiz-sharp.dll");
+
+ //enable debugging
+ mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+ mono_debug_init_1 (data->domain);
+
+ data->assembly = mono_domain_assembly_open (data->domain, "compiz-sharp.dll");
+ mono_dllmap_insert (mono_assembly_get_image (data->assembly), "compiz", NULL, "__Internal", NULL);
+ mono_dllmap_insert (mono_assembly_get_image (data->assembly), "compmono", NULL, "__Internal", NULL);
+ data->loader_class = mono_class_from_name (mono_assembly_get_image (data->assembly), "Compiz", "PluginLoader");
+ mono_debug_init_2 (data->assembly);
+
+ mono_class_init (data->loader_class);
+
+ //create a new loader instance
+ data->loader_instance = plugin_loader_new (data);
+
+ //save existing loader load/unload callbacks
+ baseloaderLoadPlugin = loaderLoadPlugin;
+ baseloaderUnloadPlugin = loaderUnloadPlugin;
+
+ //install our new loader load/unload callbacks
+ loaderLoadPlugin = monoloaderLoadPlugin;
+ loaderUnloadPlugin = monoloaderUnloadPlugin;
+
+ return TRUE;
+}
+
+static void
+monoFini (CompPlugin *p)
+{
+ //restore saved loader load/unload callbacks
+ loaderLoadPlugin = baseloaderLoadPlugin;
+ loaderUnloadPlugin = baseloaderUnloadPlugin;
+
+ mono_jit_cleanup (data->domain);
+ free (data);
+}
+
+static Bool
+monoInitDisplay (CompPlugin *p, CompDisplay *d)
+{
+ fprintf (stderr, "InitDisplay\n");
+
+ return TRUE;
+}
+
+static void
+monoFiniDisplay (CompPlugin *p, CompDisplay *d)
+{
+ fprintf (stderr, "FiniDisplay\n");
+}
+
+CompPluginVTable monoVTable = {
+ "compmono",
+ "Mono Loader",
+ "Experimental plugin loader",
+ monoInit,
+ monoFini,
+ monoInitDisplay,
+ monoFiniDisplay,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+};
+
+CompPluginVTable *
+getCompPluginInfo (void)
+{
+ fprintf (stderr, "getCompPluginInfo\n");
+
+ return &monoVTable;
+}
diff --git a/include.mk b/include.mk
new file mode 100644
index 0000000..7eeace2
--- /dev/null
+++ b/include.mk
@@ -0,0 +1,20 @@
+CSC_DEBUGFLAGS=-debug -d:TRACE
+CSC=gmcs $(CSC_DEBUGFLAGS)
+MONO_DEBUGFLAGS=--debug
+RUNTIME=mono $(MONO_DEBUGFLAGS)
+
+#TODO: unsafe, resources
+#curr dir refs go in args
+
+#%.exe:
+%.exe %.dll %.module:
+ $(CSC) $(CSFLAGS) -out:$@ -t:$(TARGET) $(addprefix -pkg:,$(PKGS)) $(addprefix -r:,$(REFS)) $(addprefix -r:,$(filter %.dll,$^)) $(addprefix -addmodule:,$(filter %.module,$^)) $(filter %.cs,$^)
+
+%.exe: TARGET = exe
+
+%.dll: TARGET = library
+
+%.module: TARGET = module
+
+#$(MODULE)_SOURCES := foo.cs
+
diff --git a/physics/Constraint.cs b/physics/Constraint.cs
new file mode 100644
index 0000000..18ca192
--- /dev/null
+++ b/physics/Constraint.cs
@@ -0,0 +1,26 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace PhysModel
+{
+ public interface IConstraint
+ {
+ //void Constrain (Model model);
+ void Constrain ();
+ }
+
+ public class Constraint
+ {
+ public virtual void Constrain (Model model)
+ {
+ Constrain ();
+ }
+
+ public virtual void Constrain ()
+ {
+ }
+ }
+}
diff --git a/physics/Demo.cs b/physics/Demo.cs
new file mode 100644
index 0000000..f52a446
--- /dev/null
+++ b/physics/Demo.cs
@@ -0,0 +1,575 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using Cairo;
+using Gtk;
+using PhysModel;
+
+public class PhysDemo
+{
+ static void OnExpose (object obj, ExposeEventArgs args)
+ {
+ //gtk# 2.8
+ using (Context cr = Gdk.CairoHelper.Create (args.Event.Window))
+ {
+ DrawModel (cr);
+ }
+ }
+
+ public static DrawingArea da;
+
+ public static void Main ()
+ {
+ Application.Init ();
+
+ da = new DrawingArea ();
+ da.ExposeEvent += OnExpose;
+ da.ButtonPressEvent += ButtonPressEvent;
+ da.MotionNotifyEvent += MotionNotifyEvent;
+ da.ButtonReleaseEvent += ButtonReleaseEvent;
+ //da.Events = Gdk.EventMask.ExposureMask | Gdk.EventMask.LeaveNotifyMask | Gdk.EventMask.ButtonPressMask | Gdk.EventMask.PointerMotionMask | Gdk.EventMask.PointerMotionHintMask;
+ da.Events |= Gdk.EventMask.LeaveNotifyMask | Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask | Gdk.EventMask.PointerMotionHintMask;
+
+ Frame frame = new Frame ();
+ frame.Add (da);
+ frame.ShadowType = ShadowType.In;
+
+
+ HBox hb = new HBox (true, 2);
+ Button b;
+
+ b = new Button ("Rope");
+ b.Clicked += delegate {InitRope (model);};
+ hb.PackStart (b);
+ b = new Button ("Snake");
+ b.Clicked += delegate {InitSnake (model);};
+ hb.PackStart (b);
+ b = new Button ("Curtain");
+ b.Clicked += delegate {InitCurtain (model);};
+ hb.PackStart (b);
+ b = new Button ("Grid");
+ b.Clicked += delegate {InitGrid (model);};
+ hb.PackStart (b);
+ b = new Button ("Molecule");
+ b.Clicked += delegate {InitMolecule (model);};
+ hb.PackStart (b);
+ b = new Button ("Wobbly");
+ b.Clicked += delegate {InitWobbly (model);};
+ hb.PackStart (b);
+ b = new Button ("Dock");
+ b.Clicked += delegate {InitDock (model);};
+ hb.PackStart (b);
+ b = new Button ("Clear");
+ b.Clicked += delegate {model = new Model ();};
+ hb.PackStart (b);
+
+ VBox vb = new VBox (false, 4);
+ vb.PackStart (frame, true, true, 0);
+ vb.PackStart (hb, false, true, 0);
+
+ Window win = new Window ("PhysModel#");
+ win.SetDefaultSize (640, 480);
+ win.BorderWidth = 8;
+ win.Add (vb);
+ win.Destroyed += delegate {Application.Quit ();};
+
+ win.ShowAll ();
+
+ model = new Model ();
+
+ //InitRope (model);
+ //InitCurtain (model);
+ //InitDock (model);
+ InitGrid (model);
+
+ GLib.Timeout.Add (40, TimeoutCb);
+ Application.Run ();
+ }
+
+ static Model model;
+
+ public static void InitModelConstants (Model model)
+ {
+ model.Elasticity = 0.7;
+ model.Friction = 10;
+ model.Gravity = new Vector (0, 80);
+ model.K = 10;
+ model.ConstrainIterations = 10;
+ }
+
+ public static void InitModelPolygons (Model model)
+ {
+ double ground_level = 400;
+ Polygon p;
+
+ p = CreateDiamond (250, 300);
+ p.Model = model;
+ model.Polygons.Add (p);
+ model.Constraints.Add (p);
+
+ p = CreateDiamond (400, 150);
+ p.Model = model;
+ model.Polygons.Add (p);
+ model.Constraints.Add (p);
+
+ p = CreateRectangle (-100, 200, 200, 250);
+ p.Model = model;
+ model.Polygons.Add (p);
+ model.Constraints.Add (p);
+
+ p = CreateRectangle (-200, ground_level, 1200, ground_level + 400);
+ p.Model = model;
+ model.Polygons.Add (p);
+ model.Constraints.Add (p);
+
+ p = CreateRectangle (300, 320, 400, 350);
+ p.Model = model;
+ model.Polygons.Add (p);
+ model.Constraints.Add (p);
+ }
+
+ public static void InitSnake (Model model)
+ {
+ InitModelConstants (model);
+ InitModelPolygons (model);
+
+ int nParticles = 20;
+
+ Random rand = new Random ();
+
+ Particle prev = null;
+ Particle pprev = null;
+ for (int i = 0 ; i != nParticles ; i++) {
+ Particle n = new Particle ();
+ n.Position = new PhysModel.Point (rand.Next (100, 300), rand.Next (100, 300));
+ n.PreviousPosition = n.Position;
+ n.Mass = 1;
+ model.Particles.Add (n);
+
+ if (pprev != null) {
+ Stick s = new Stick ();
+ s.A = n;
+ s.B = pprev;
+ s.Length = rand.Next (20, 40);
+ model.Sticks.Add (s);
+ model.Constraints.Add (s);
+ }
+
+ if (prev != null) {
+ Stick s = new Stick ();
+ s.A = n;
+ s.B = prev;
+ s.Length = rand.Next (20, 40);
+ model.Sticks.Add (s);
+ model.Constraints.Add (s);
+ }
+
+ pprev = prev;
+ prev = n;
+ }
+ }
+
+ public static void InitRope (Model model)
+ {
+ InitModelConstants (model);
+ InitModelPolygons (model);
+
+ Particle prev = null;
+ for (int i = 0 ; i != 20 ; i++) {
+ int stickLength = 10;
+
+ Particle n = new Particle ();
+ n.Position = new PhysModel.Point (200, 40 + i * stickLength);
+ n.PreviousPosition = n.Position;
+ n.Mass = 1;
+ model.Particles.Add (n);
+
+ if (prev != null) {
+ Stick s = new Stick ();
+ s.A = n;
+ s.B = prev;
+ s.Length = stickLength;
+ model.Sticks.Add (s);
+ model.Constraints.Add (s);
+ }
+
+ prev = n;
+ }
+ }
+
+ public static void InitCurtain (Model model)
+ {
+ InitModelConstants (model);
+ InitModelPolygons (model);
+
+ int nRopes = 5;
+ int nRopeParticles = 15;
+ int stickLength = 10;
+ int ropeOffset = 30;
+
+ Offset offset = new Offset (new Vector (ropeOffset, 0));
+ model.Offsets.Add (offset);
+ model.Constraints.Add (offset);
+ offset.Particles.Capacity = nRopes;
+
+ for (int i = 0 ; i != nRopes ; i++) {
+ Particle prev = null;
+
+ for (int j = 0 ; j != nRopeParticles ; j++) {
+ PhysModel.Point pos = new PhysModel.Point (200 + i * ropeOffset, 40 + j * stickLength);
+ Particle n = new Particle ();
+ n.Mass = 1;
+ n.Position = pos;
+ n.PreviousPosition = pos;
+ model.Particles.Add (n);
+ if (j == 0)
+ offset.Particles.Add (n);
+ //offset.Particles[i] = n;
+ else {
+ Stick s = new Stick ();
+ s.A = prev;
+ s.B = n;
+ s.Length = stickLength;
+ model.Sticks.Add (s);
+ model.Constraints.Add (s);
+ }
+
+ prev = n;
+ }
+ }
+ }
+
+ public static void InitGrid (Model model)
+ {
+ int width = 8;
+ int height = 8;
+ int distance = 20;
+ Particle[] lastColumn = new Particle[height];
+
+ InitModelConstants (model);
+ InitModelPolygons (model);
+
+ Offset offset = new Offset (new Vector (distance, 0));
+ model.Offsets.Add (offset);
+ model.Constraints.Add (offset);
+ offset.Particles.Capacity = width;
+
+ for (int i = 0 ; i != width ; i++)
+ for (int j = 0 ; j != height ; j++)
+ {
+ PhysModel.Point pos = new PhysModel.Point (200 + i * distance, 40 + j * distance);
+ Particle n = new Particle ();
+ n.Mass = 1;
+ n.Position = pos;
+ n.PreviousPosition = pos;
+ model.Particles.Add (n);
+
+ if (i > 0) {
+ StringLink str = new StringLink (lastColumn[j], n, distance);
+ model.StringLinks.Add (str);
+ model.Constraints.Add (str);
+ }
+ if (j == 0) {
+ offset.Particles.Add (n);
+ //offset.Particles[i] = n;
+ } else {
+ StringLink str = new StringLink (lastColumn[j - 1], n, distance);
+ model.StringLinks.Add (str);
+ model.Constraints.Add (str);
+ }
+
+ lastColumn[j] = n;
+ }
+ }
+
+ public static void InitMolecule (Model model)
+ {
+ InitModelConstants (model);
+
+ int numParticles = 8;
+ int springLength = 50;
+
+ Particle[] particles = new Particle[numParticles];
+
+ Random rand = new Random ();
+
+ for (int i = 0 ; i != numParticles ; i++) {
+ Particle particle = new Particle ();
+ particle.Position = new PhysModel.Point (rand.Next (200, 400), rand.Next (200, 400));
+ particle.PreviousPosition = particle.Position;
+ particle.Mass = 0;
+ model.Particles.Add (particle);
+ particles[i] = particle;
+ }
+
+ for (int i = 0 ; i != numParticles ; i++) {
+ Spring s;
+
+ s = new Spring ();
+ s.A = particles[i];
+ s.B = particles[(i + 1) % numParticles];
+ s.Length = springLength;
+ model.Springs.Add (s);
+
+ s = new Spring ();
+ s.A = particles[i];
+ s.B = particles[(i + 2) % numParticles];
+ s.Length = springLength;
+ model.Springs.Add (s);
+ }
+ }
+
+ public static void InitWobbly (Model model)
+ {
+ int width = 8;
+ int height = 8;
+ int distance = 30;
+ Particle[] lastColumn = new Particle[height];
+
+ InitModelConstants (model);
+ InitModelPolygons (model);
+
+ for (int i = 0 ; i != width ; i++)
+ for (int j = 0 ; j != height ; j++)
+ {
+ PhysModel.Point pos = new PhysModel.Point (200 + i * distance, 40 + j * distance);
+ Particle n = new Particle ();
+ n.Mass = 0;
+ n.Position = pos;
+ n.PreviousPosition = pos;
+ model.Particles.Add (n);
+
+ if (i > 0) {
+ OffsetSpring ospring = new OffsetSpring (lastColumn[j], n, new Vector (distance, 0));
+ model.OffsetSprings.Add (ospring);
+ }
+ if (j > 0) {
+ OffsetSpring ospring = new OffsetSpring (lastColumn[j - 1], n, new Vector (0, distance));
+ model.OffsetSprings.Add (ospring);
+ }
+
+ lastColumn[j] = n;
+ }
+ }
+
+ public static void InitDock (Model model)
+ {
+ InitModelConstants (model);
+
+ int nParticles = 8;
+ int distance = 30;
+
+ Polygon rect = CreateRectangle (10, 10, 700, 500);
+ rect.Model = model;
+ rect.Enclosing = true;
+ model.Polygons.Add (rect);
+ model.Constraints.Add (rect);
+
+ Particle anchorParticle = new Particle ();
+ model.Particles.Add (anchorParticle);
+
+ Anchor anchor = new Anchor ();
+ anchor.Particle = anchorParticle;
+ anchor.Position = new PhysModel.Point (300, 300);
+ anchor.Particle.Position = anchor.Position;
+ model.Anchors.Add (anchor);
+ model.Constraints.Add (anchor);
+
+ for (int i = 0 ; i != nParticles ; i++) {
+ Particle current = new Particle ();
+ current.Position = new PhysModel.Point (200 + i * distance / 3, 40);
+ current.PreviousPosition = current.Position;
+ current.Mass = 2;
+ model.Particles.Add (current);
+
+ Spring s = new Spring ();
+ s.A = anchor.Particle;
+ s.B = current;
+ s.Length = distance;
+ model.Springs.Add (s);
+ //model.Constraints.Add (s);
+
+ foreach (Particle part in model.Particles) {
+ //skip the anchor particle
+ if (part == anchor.Particle || part == current)
+ continue;
+ Spacer spc = new Spacer ();
+ spc.A = part;
+ spc.B = current;
+ spc.Length = distance;
+ model.Spacers.Add (spc);
+ model.Constraints.Add (spc);
+ }
+ }
+ }
+
+ public static void DrawModel (Cairo.Context cr)
+ {
+ cr.Color = new Color (1, 1, 1);
+ cr.Paint ();
+
+ cr.LineJoin = LineJoin.Round;
+ cr.LineCap = LineCap.Round;
+
+ cr.LineWidth = 1;
+ //is this the right replacement for cairo_set_source_rgba?
+ cr.Color = new Color (0.3, 0.3, 0.5, 1);
+ foreach (Polygon p in model.Polygons)
+ DrawPolygon (p, cr);
+
+ cr.Color = new Color (0, 1, 0, 1);
+ foreach (StringLink s in model.StringLinks) {
+ cr.MoveTo (s.A.Position.X, s.A.Position.Y);
+ cr.LineTo (s.B.Position.X, s.B.Position.Y);
+ }
+ cr.Stroke ();
+
+ cr.Color = new Color (0, 0, 0, 0.8);
+ foreach (Spring s in model.Springs) {
+ cr.MoveTo (s.A.Position.X, s.A.Position.Y);
+ cr.LineTo (s.B.Position.X, s.B.Position.Y);
+ }
+ cr.Stroke ();
+
+ cr.LineWidth = 4;
+ cr.Color = new Color (0, 0, 0.5, 0.5);
+ foreach (Offset o in model.Offsets) {
+ cr.MoveTo (o.Particles[0].Position.X, o.Particles[0].Position.Y);
+ for (int i = 1 ; i != o.Particles.Count ; i++)
+ cr.LineTo (o.Particles[i].Position.X, o.Particles[i].Position.Y);
+ }
+ cr.Stroke ();
+
+ cr.LineWidth = 2;
+ cr.Color = new Color (0, 0, 0, 1);
+ foreach (Stick s in model.Sticks) {
+ cr.MoveTo (s.A.Position.X, s.A.Position.Y);
+ cr.LineTo (s.B.Position.X, s.B.Position.Y);
+ }
+ cr.Stroke ();
+
+ cr.Color = new Color (1, 0, 1, 0.4);
+ foreach (OffsetSpring s in model.OffsetSprings) {
+ cr.MoveTo (s.A.Position.X, s.A.Position.Y);
+ cr.LineTo (s.B.Position.X, s.B.Position.Y);
+ }
+ cr.Stroke ();
+
+ cr.Color = new Color (1, 0, 0, 0.4);
+ foreach (Particle o in model.Particles)
+ {
+ cr.Arc (o.Position.X, o.Position.Y, 3, 0, 2 * Math.PI);
+ cr.Fill ();
+ }
+ }
+
+ public static void DrawPolygon (Polygon p, Cairo.Context cr)
+ {
+ for (int i = 0 ; i != p.Points.Count ; i++)
+ cr.LineTo (p.Points[i].X, p.Points[i].Y);
+
+ cr.ClosePath ();
+
+ if (p.Enclosing)
+ cr.Stroke ();
+ else
+ cr.Fill ();
+ }
+
+ public static void ButtonPressEvent (object o, ButtonPressEventArgs args)
+ {
+ Gdk.EventButton e = args.Event;
+
+ if (e.Button != 1)
+ return;
+
+ Particle n = model.FindNearest (new PhysModel.Point (e.X, e.Y));
+
+ Anchor anchor = new Anchor ();
+ anchor.Particle = n;
+ anchor.Position = new PhysModel.Point (e.X, e.Y);
+ mouse_anchor = anchor;
+ model.Anchors.Add (anchor);
+ model.Constraints.Add (anchor);
+ }
+
+ static Anchor mouse_anchor = null;
+
+ public static void MotionNotifyEvent (object o, MotionNotifyEventArgs args)
+ {
+ int x, y;
+ Gdk.ModifierType mask;
+
+ ((Gtk.Widget)o).GdkWindow.GetPointer (out x, out y, out mask);
+ //Gdk.EventMotion e = args.Event;
+
+ if (mouse_anchor == null)
+ return;
+
+ //mouse_anchor.Position = new PhysModel.Point (e.X + 0.5, e.Y + 0.5);
+ mouse_anchor.Position = new PhysModel.Point (x + 0.5, y + 0.5);
+ }
+
+ public static void ButtonReleaseEvent (object o, ButtonReleaseEventArgs args)
+ {
+ Gdk.EventButton e = args.Event;
+
+ //todo, check mask
+ if (e.Button != 1)
+ return;
+
+ //model.DeleteAnchor (mouse_anchor);
+ model.Anchors.Remove (mouse_anchor);
+ model.Constraints.Remove (mouse_anchor);
+ mouse_anchor = null;
+ }
+
+ public static bool TimeoutCb ()
+ {
+ model.Step (0.2);
+
+ da.QueueDraw ();
+
+ //add more here
+
+ return true;
+ }
+
+ public static Polygon CreateRectangle (double x0, double y0, double x1, double y1)
+ {
+ Polygon p = new Polygon ();
+
+ p.Enclosing = false;
+
+ p.Points.Add (new PhysModel.Point (x0, y0));
+ p.Points.Add (new PhysModel.Point (x0, y1));
+ p.Points.Add (new PhysModel.Point (x1, y1));
+ p.Points.Add (new PhysModel.Point (x1, y0));
+
+ //hack
+ p.Init ();
+
+ return p;
+ }
+
+ public static Polygon CreateDiamond (double x, double y)
+ {
+ Polygon p = new Polygon ();
+
+ p.Enclosing = false;
+
+ p.Points.Add (new PhysModel.Point (x, y));
+ p.Points.Add (new PhysModel.Point (x + 10, y + 40));
+ p.Points.Add (new PhysModel.Point (x + 90, y + 40));
+ p.Points.Add (new PhysModel.Point (x + 100, y));
+ p.Points.Add (new PhysModel.Point (x + 50, y - 20));
+
+ //hack
+ p.Init ();
+
+ return p;
+ }
+}
diff --git a/physics/Geometry.cs b/physics/Geometry.cs
new file mode 100644
index 0000000..e78f3c5
--- /dev/null
+++ b/physics/Geometry.cs
@@ -0,0 +1,97 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace PhysModel
+{
+ public struct Point
+ {
+ public double X;
+ public double Y;
+
+ public Point (double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public static Point Origin = new Point (0, 0);
+
+ public static Point operator + (Point a, Vector b)
+ {
+ return new Point (a.X + b.X, a.Y + b.Y);
+ }
+
+ public static Point operator - (Point a, Vector b)
+ {
+ return new Point (a.X - b.X, a.Y - b.Y);
+ }
+
+ public static Vector operator - (Point a, Point b)
+ {
+ return new Vector (a.X - b.X, a.Y - b.Y);
+ }
+
+ //?
+ public static Point operator / (Point a, Vector b)
+ {
+ return new Point (a.X / b.X, a.Y / b.Y);
+ }
+ }
+
+ public struct Vector
+ {
+ public double X;
+ public double Y;
+
+ public Vector (double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public static Vector operator + (Vector a, Vector b)
+ {
+ return new Vector (a.X + b.X, a.Y + b.Y);
+ }
+
+ public static Vector operator - (Vector a, Vector b)
+ {
+ return new Vector (a.X - b.X, a.Y - b.Y);
+ }
+
+ //sanity check this
+ /*
+ public static Vector operator * (Vector a, Vector b)
+ {
+ return new Vector (a.X * b.X, a.Y * b.Y);
+ }
+ */
+
+ //doesn't make sense
+ /*
+ public static Vector operator / (Vector a, Vector b)
+ {
+ return new Vector (a.X / b.X, a.Y / b.Y);
+ }
+ */
+
+ public static Vector operator * (Vector a, double b)
+ {
+ return new Vector (a.X * b, a.Y * b);
+ }
+
+ //?
+ public static Vector operator * (double a, Vector b)
+ {
+ return new Vector (b.X * a, b.Y * a);
+ }
+
+ public static Vector operator / (Vector a, double b)
+ {
+ return new Vector (a.X / b, a.Y / b);
+ }
+ }
+}
diff --git a/physics/Makefile b/physics/Makefile
new file mode 100644
index 0000000..c0d033a
--- /dev/null
+++ b/physics/Makefile
@@ -0,0 +1,11 @@
+CSC=gmcs -debug
+
+all: model.dll
+
+model.dll: Constraint.cs Geometry.cs Model.cs Particle.cs
+ $(CSC) -out:$@ -t:library Constraint.cs Geometry.cs Model.cs Particle.cs
+
+#note, needs Mono.Cairo 2.0, not the 1.0 in pkg-config
+
+demo.exe: model.dll Demo.cs
+ $(CSC) -out:$@ -r:model.dll -r:./Mono.Cairo.dll -pkg:gtk-sharp-2.0 Demo.cs
diff --git a/physics/Model.cs b/physics/Model.cs
new file mode 100644
index 0000000..3433740
--- /dev/null
+++ b/physics/Model.cs
@@ -0,0 +1,357 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+//Based on http://people.freedesktop.org/~krh/akamaru.git
+
+//http://en.wikipedia.org/wiki/Verlet_integration
+//http://www.teknikus.dk/tj/gdc2001.htm
+
+using System;
+using System.Collections.Generic;
+
+namespace PhysModel
+{
+ public class Model : IConstraint
+ {
+ public List<Particle> Particles = new List<Particle> ();
+ public List<IConstraint> Constraints = new List<IConstraint> ();
+
+ public List<Spacer> Spacers = new List<Spacer> ();
+ public List<StringLink> StringLinks = new List<StringLink> ();
+ public List<Stick> Sticks = new List<Stick> ();
+ public List<Spring> Springs = new List<Spring> ();
+ public List<Anchor> Anchors = new List<Anchor> ();
+ public List<Polygon> Polygons = new List<Polygon> ();
+ public List<Offset> Offsets = new List<Offset> ();
+ public List<OffsetSpring> OffsetSprings = new List<OffsetSpring> ();
+
+ public double K;
+ public double Friction;
+ public double Elasticity;
+ public Vector Gravity;
+ public int ConstrainIterations;
+
+ public double Theta;
+
+ public void Add (Particle n)
+ {
+ }
+
+ public void AccumulateForces ()
+ {
+ foreach (Particle n in Particles)
+ n.AccumulateForces (this);
+
+ //for (int i = 0 ; i != Particles.Count ; i++)
+ // Particles[i].AccumulateForces (this);
+
+ foreach (Spring s in Springs)
+ s.AccumulateForces (this);
+
+ foreach (OffsetSpring s in OffsetSprings)
+ s.AccumulateForces (this);
+ }
+
+ public void Constrain ()
+ {
+ foreach (IConstraint c in Constraints)
+ c.Constrain ();
+
+ /*
+ foreach (Anchor a in Anchors)
+ a.Constrain ();
+
+ foreach (StringLink s in StringLinks)
+ s.Constrain ();
+
+ foreach (Spacer s in Spacers)
+ s.Constrain ();
+
+ foreach (Stick s in Sticks)
+ s.Constrain ();
+
+ foreach (Offset o in Offsets)
+ o.Constrain ();
+
+ foreach (Polygon p in Polygons)
+ p.Constrain ();
+ */
+
+ /*
+ foreach (Particle n in Particles)
+ foreach (Polygon p in Polygons)
+ p.Constrain (n); //wrong way round
+ */
+ }
+
+ public void Step (double delta_t)
+ {
+ AccumulateForces ();
+
+ foreach (Particle n in Particles)
+ n.Integrate (delta_t);
+
+ for (int i = 0 ; i != ConstrainIterations ; i++)
+ Constrain ();
+
+ Theta += delta_t;
+ }
+
+ public Particle FindNearest (Point pos)
+ {
+ Particle nearest = null;
+ double nearest_distance = Double.MaxValue;
+
+ foreach (Particle n in Particles) {
+ double distance = n.GetDistance (pos);
+
+ if (nearest == null || distance < nearest_distance) {
+ nearest_distance = distance;
+ nearest = n;
+ }
+ }
+
+ return nearest;
+ }
+ }
+
+ public class Stick : IConstraint
+ {
+ public Particle A;
+ public Particle B;
+ public int Length;
+
+ public void Constrain ()
+ {
+ Point p = A.Position;
+ Vector d = B.Position - p;
+
+ double distance = EstimateDistance (d, Length);
+ //double distance = (Length + (d.X * d.X + d.Y * d.Y) / Length) / 2;
+ //double distance = Math.Sqrt (d.X * d.X + d.Y * d.Y);
+ double fraction = (distance - Length) / distance / 2;
+ A.Position = p + d * fraction;
+ B.Position = p + d * (1 - fraction);
+ }
+
+ protected static double EstimateDistance (Vector d, double r)
+ {
+ //approximate square roots
+ return (r + (d.X * d.X + d.Y * d.Y) / r) / 2;
+ //return Math.Sqrt (d.X * d.X + d.Y * d.Y);
+ }
+ }
+
+ public class StringLink : Stick, IConstraint
+ {
+ /*
+ public Particle A;
+ public Particle B;
+ public int Length;
+ */
+
+ public StringLink (Particle a, Particle b, int length)
+ {
+ this.A = a;
+ this.B = b;
+ this.Length = length;
+ }
+
+ public void Constrain ()
+ {
+ Point p = A.Position;
+ Vector d = B.Position - p;
+
+ double distance = EstimateDistance (d, Length);
+
+ if (distance < Length)
+ return;
+
+ double fraction = (distance - Length) / distance / 2;
+ A.Position = p + d * fraction;
+ B.Position = p + d * (1 - fraction);
+ }
+ }
+
+ public class Spring
+ {
+ public Particle A;
+ public Particle B;
+ public int Length;
+
+ public void AccumulateForces (Model model)
+ {
+ Point pos = A.Position;
+ Vector d = B.Position - pos;
+
+ double distance = Math.Sqrt (d.X*d.X + d.Y*d.Y);
+
+ Vector u = d / distance;
+
+ double displacement = distance - Length;
+
+ A.Force += u * model.K * displacement;
+ B.Force -= u * model.K * displacement;
+ }
+ }
+
+ public class OffsetSpring
+ {
+ public Particle A;
+ public Particle B;
+ public Vector Offset;
+
+ public OffsetSpring (Particle a, Particle b, Vector offset)
+ {
+ this.A = a;
+ this.B = b;
+ this.Offset = offset;
+ }
+
+ public void AccumulateForces (Model model)
+ {
+ //Point middle = (A.Position + B.Position) / 2;
+ Point middle = new Point ((A.Position.X + B.Position.X) / 2, (A.Position.Y + B.Position.Y) / 2);
+
+ Vector d = (middle - Offset / 2) - A.Position;
+
+ A.Force += d * model.K;
+ B.Force -= d * model.K;
+ }
+ }
+
+ public class Spacer : Stick, IConstraint
+ {
+ public void Constrain ()
+ {
+ Point p = A.Position;
+ Vector d = B.Position - p;
+
+ double distance = EstimateDistance (d, Length);
+ if (distance > Length)
+ return;
+
+ double fraction = (distance - Length) / distance / 2;
+ A.Position = p + d * fraction;
+ B.Position = p + d * (1 - fraction);
+ }
+ }
+
+ public class Anchor : IConstraint
+ {
+ public Particle Particle;
+ public Point Position;
+
+ public void Constrain ()
+ {
+ if (Particle != null)
+ Particle.Position = Position;
+ }
+ }
+
+ /*
+ public class Rectangle : Polygon
+ {
+ }
+ */
+
+ public class Polygon : IConstraint
+ {
+ public List<Point> Points = new List<Point> ();
+ public List<Vector> Normals = new List<Vector> ();
+ public bool Enclosing;
+ public Model Model;
+
+ public bool Contains (Point point)
+ {
+ for (int i = 0 ; i != Points.Count ; i++) {
+ Vector d = point - Points[i];
+
+ if (Normals[i].X * d.X + Normals[i].Y * d.Y >= 0)
+ return Enclosing;
+ }
+
+ return !Enclosing;
+ }
+
+ public void ReflectParticle (Particle n, double elasticity)
+ {
+ int edge = 0;
+ double distance = Double.MinValue;
+ Vector norm = new Vector (0, 0);
+
+ for (int i = 0 ; i != Points.Count ; i++) {
+ double d = Normals[i].X * (n.Position.X - Points[i].X) +
+ Normals[i].Y * (n.Position.Y - Points[i].Y);
+
+ if (d > distance) {
+ distance = d;
+ edge = i;
+ norm = Normals[i];
+ }
+ }
+
+ n.Position -= (1 + elasticity) * distance * norm;
+
+ distance = norm.X * (n.PreviousPosition.X - Points[edge].X) +
+ norm.Y * (n.PreviousPosition.Y - Points[edge].Y);
+
+ n.PreviousPosition -= (1 + elasticity) * distance * norm;
+ }
+
+ public void Constrain ()
+ {
+ foreach (Particle n in Model.Particles)
+ if (Contains (n.Position))
+ ReflectParticle (n, Model.Elasticity);
+ }
+
+ //TODO: maybe this should be in Particle or elsewhere?
+ /*
+ public void Constrain (Particle n)
+ {
+ if (Contains (n.Position))
+ ReflectParticle (n, Model.Elasticity);
+ }
+ */
+
+ public void Init ()
+ {
+ //Compute outward pointing normals
+ Normals = new List<Vector> (Points.Count);
+ for (int i = 0 ; i != Points.Count ; i++) {
+ int j = (i + 1) % Points.Count;
+ Vector d = Points[j] - Points[i];
+ double length = Math.Sqrt (d.X*d.X + d.Y*d.Y);
+ //Normals[i] = new Vector (-d.Y / length, d.X / length);
+ Normals.Add (new Vector (-d.Y / length, d.X / length));
+ }
+ }
+ }
+
+ public class Offset : IConstraint
+ {
+ public Offset (Vector delta)
+ {
+ this.Delta = delta;
+ }
+
+ public List<Particle> Particles = new List<Particle> ();
+ public Vector Delta;
+
+ public void Constrain ()
+ {
+ Point pos = Point.Origin;
+
+ for (int i = 0 ; i != Particles.Count ; i++)
+ pos += Particles[i].Position - Point.Origin;
+
+ //improve overloads for point/double?
+ pos = pos / new Vector (Particles.Count, Particles.Count) - Delta * (Particles.Count - 1) / 2;
+
+ for (int i = 0 ; i != Particles.Count ; i++)
+ Particles[i].Position = pos + Delta * (double)i;
+ }
+ }
+}
diff --git a/physics/Particle.cs b/physics/Particle.cs
new file mode 100644
index 0000000..d69aeee
--- /dev/null
+++ b/physics/Particle.cs
@@ -0,0 +1,54 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+
+namespace PhysModel
+{
+ public class Particle
+ {
+ public Vector Force;
+
+ public Point Position;
+ public Point PreviousPosition;
+ public Vector Velocity;
+
+ public double Mass;
+ public double Theta;
+
+ /*
+ public Particle (Point position, double mass)
+ {
+ this.Position = position;
+ this.PreviousPosition = position;
+ this.Mass = mass;
+ }
+ */
+
+ public double GetDistance (Point p)
+ {
+ Vector d = Position - p;
+ return Math.Sqrt (d.X*d.X + d.Y*d.Y);
+ }
+
+ public void AccumulateForces (Model Model)
+ {
+ //Gravity
+ Force = Model.Gravity * Mass;
+
+ //Friction
+ Vector v = Position - PreviousPosition;
+
+ Force -= v * Model.Friction;
+ }
+
+ public void Integrate (double step)
+ {
+ Point original_position = Position;
+ Position += Position - PreviousPosition + Force * step * step;
+ PreviousPosition = original_position;
+ }
+ }
+}
diff --git a/plugins/.gitignore b/plugins/.gitignore
new file mode 100644
index 0000000..b7733d2
--- /dev/null
+++ b/plugins/.gitignore
@@ -0,0 +1,4 @@
+*.mdb
+*.pdb
+*.exe
+*.dll
diff --git a/plugins/Cube.cs b/plugins/Cube.cs
new file mode 100644
index 0000000..4d0519b
--- /dev/null
+++ b/plugins/Cube.cs
@@ -0,0 +1,13 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using Compiz;
+using Cairo;
+using Svg;
+
+//??
+public class CubeScreen : Screen
+{
+}
diff --git a/plugins/GLTest.cs b/plugins/GLTest.cs
new file mode 100644
index 0000000..782f482
--- /dev/null
+++ b/plugins/GLTest.cs
@@ -0,0 +1,90 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using Compiz;
+using Tao.FreeGlut;
+using Tao.OpenGl;
+//using Tao.OpenGl.Glu;
+
+public class MgltestPlugin : Plugin
+{
+ //not very clever or efficient, but ok for now
+ protected Dictionary<IntPtr,Screen> screens = new Dictionary<IntPtr,Screen> ();
+ protected Dictionary<IntPtr,Window> windowPtrs = new Dictionary<IntPtr,Window> ();
+ protected List<Window> windows = new List<Window> ();
+
+ public override bool InitScreen (IntPtr plugin, IntPtr screen)
+ {
+ Console.WriteLine ("initScreen");
+
+ Screen s = new Screen (screen);
+ screens[screen] = s;
+
+ s.PreparePaint += OnPreparePaintScreen;
+ s.Paint += OnPaintScreen;
+ s.DonePaint += OnDonePaintScreen;
+
+ return true;
+ }
+
+ public void OnPreparePaintScreen (PreparePaintScreenHandler inner, IntPtr s, int msSinceLastPaint)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("PreparePaintScreen (managed) " + msSinceLastPaint);
+
+ inner (s, msSinceLastPaint);
+ }
+
+ public bool OnPaintScreen (PaintScreenHandler inner, IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("PaintScreen (managed) " + " " + s + " " + mask);
+
+ Console.Error.WriteLine ("xRotate: " + sa.xRotate);
+ Console.Error.WriteLine ("yRotate: " + sa.yRotate);
+ Console.Error.WriteLine ("vRotate: " + sa.vRotate);
+
+ bool ret = inner (s, ref sa, region, mask);
+
+ Gl.glPushMatrix();
+ Gl.glRotatef (sa.vRotate, sa.vRotate, 0, 0);
+ Glu.gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
+ Glut.glutSolidTorus(0.275, 0.85, 8, 15);
+ Gl.glPopMatrix();
+
+ return ret;
+ }
+
+ public void OnDonePaintScreen (DonePaintScreenHandler inner, IntPtr s)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("DonePaintScreen (managed)");
+
+ inner (s);
+ }
+
+ public override bool InitWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("initWindow");
+
+ Window w = new Window (window);
+ windowPtrs[window] = w;
+ windows.Add (w);
+
+ return true;
+ }
+
+ public override void FiniWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("finiWindow");
+
+ windows.Remove (windowPtrs[window]);
+ windowPtrs.Remove (window);
+ }
+}
diff --git a/plugins/Makefile b/plugins/Makefile
new file mode 100644
index 0000000..a558eb8
--- /dev/null
+++ b/plugins/Makefile
@@ -0,0 +1,13 @@
+REFS=../src/compiz-sharp.dll ../physics/model.dll
+
+all: mscale.dll
+
+Zoom.dll: Zoom.cs
+
+mscale.dll: Scale.cs
+
+mgltest.dll: PKGS=tao-opengl tao-opengl-glu tao-freeglut
+
+mgltest.dll: GLTest.cs
+
+include ../include.mk
diff --git a/plugins/Scale.cs b/plugins/Scale.cs
new file mode 100644
index 0000000..eeedd0f
--- /dev/null
+++ b/plugins/Scale.cs
@@ -0,0 +1,306 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using Compiz;
+using PhysModel;
+
+public class MscalePlugin : Plugin
+{
+ //not very clever or efficient, but ok for now
+ protected Dictionary<IntPtr,Screen> screens = new Dictionary<IntPtr,Screen> ();
+ protected Dictionary<IntPtr,Window> windowPtrs = new Dictionary<IntPtr,Window> ();
+ protected List<Window> windows = new List<Window> ();
+ protected Dictionary<Window,Particle> particles = new Dictionary<Window,Particle> ();
+
+ Model model = new Model ();
+
+ public override bool InitScreen (IntPtr plugin, IntPtr screen)
+ {
+ Console.WriteLine ("initScreen");
+
+ Screen s = new Screen (screen);
+ screens[screen] = s;
+
+ s.PreparePaint += OnPreparePaintScreen;
+ //s.Paint += OnPaintScreen;
+ s.DonePaint += OnDonePaintScreen;
+
+ InitModelConstants (model);
+
+ //add the enclosing rectangle to the physics model
+ //XRectangle s->workArea
+ //Polygon bounds = CreateRectangle (true, 0, 0, 800, 600);
+ //Polygon bounds = CreateRectangle (true, 0, 0, 640, 480);
+ //Polygon bounds = CreateRectangle (false, 50, 50, 640, 480);
+ Polygon bounds = CreateRectangle (true, 50, 50, 640, 480);
+ bounds.Model = model;
+ model.Polygons.Add (bounds);
+ model.Constraints.Add (bounds);
+
+ InitScale ();
+
+ return true;
+ }
+
+ public static void InitModelConstants (Model model)
+ {
+ model.Elasticity = 0.7;
+ model.Friction = 10;
+ model.Gravity = new Vector (0, 80);
+ //model.Gravity = new Vector (0, 0);
+ model.K = 10;
+ model.ConstrainIterations = 10;
+ }
+
+ Anchor anchor;
+
+ public void InitScale ()
+ {
+ Particle anchorParticle = new Particle ();
+ model.Particles.Add (anchorParticle);
+
+ //Anchor anchor = new Anchor ();
+ anchor = new Anchor ();
+ anchor.Particle = anchorParticle;
+ anchor.Position = new PhysModel.Point (320, 240);
+ anchor.Particle.Position = anchor.Position;
+ anchor.Particle.PreviousPosition = anchor.Position; //new
+ model.Anchors.Add (anchor);
+ model.Constraints.Add (anchor);
+ }
+
+ public Particle NewParticle (int x, int y)
+ {
+ int distance = 40;
+
+ Particle current = new Particle ();
+ //current.Position = new PhysModel.Point (200 + i * distance / 3, 40);
+ //current.Position = new PhysModel.Point (10, 10);
+ current.Position = new PhysModel.Point (x, y);
+ current.PreviousPosition = current.Position;
+ current.Mass = 2;
+ model.Particles.Add (current);
+
+ Spring s = new Spring ();
+ s.A = anchor.Particle;
+ s.B = current;
+ s.Length = distance;
+ model.Springs.Add (s);
+ //model.Constraints.Add (s);
+
+ foreach (Particle part in model.Particles) {
+ //skip the anchor particle
+ if (part == anchor.Particle || part == current)
+ continue;
+ Spacer spc = new Spacer ();
+ spc.A = part;
+ spc.B = current;
+ spc.Length = distance;
+ model.Spacers.Add (spc);
+ model.Constraints.Add (spc);
+ }
+
+ return current;
+ }
+
+ //TODO: make this a library function
+ public static Polygon CreateRectangle (bool enclosing, double x0, double y0, double x1, double y1)
+ {
+ Polygon p = new Polygon ();
+
+ p.Enclosing = enclosing;
+
+ p.Points.Add (new PhysModel.Point (x0, y0));
+ p.Points.Add (new PhysModel.Point (x0, y1));
+ p.Points.Add (new PhysModel.Point (x1, y1));
+ p.Points.Add (new PhysModel.Point (x1, y0));
+
+ //hack
+ p.Init ();
+
+ return p;
+ }
+
+ bool changed = false;
+
+ public void OnPreparePaintScreen (PreparePaintScreenHandler inner, IntPtr s, int msSinceLastPaint)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("PreparePaintScreen (managed) " + msSinceLastPaint);
+
+ foreach (Window win in windows)
+ {
+
+ //win.SyncPosition ();
+ int x, y;
+ win.GetPosition (out x, out y);
+ if (x < 1 | y < 1)
+ continue;
+ UpdateWindow (win);
+
+ /*
+ //if (x > 800 | y > 600)
+ // continue;
+
+
+ //particles[win].PreviousPosition = particles[win].Position;
+ particles[win].Position = new PhysModel.Point (x, y);
+ //particles[win].PreviousPosition = new PhysModel.Point (x, y);
+ */
+ }
+
+ model.Step (msSinceLastPaint / 200);
+
+ changed = false;
+
+ //foreach (Window win in windows)
+ // UpdateWindow (win);
+
+ //if (false)
+ foreach (Window win in windows)
+ {
+ //win.Move (dx, dy, false, false);
+ int x, y;
+
+ win.GetPosition (out x, out y);
+
+ int width, height;
+ win.GetSize (out width, out height);
+ x += width/2;
+ y += height/2;
+
+ if (x < 1 | y < 1)
+ continue;
+
+ //if (x > 800 | y > 600)
+ // continue;
+
+ PhysModel.Point oldpoint = new PhysModel.Point (x, y);
+ //PhysModel.Point oldpoint = particles[win].PreviousPosition;
+ Console.WriteLine ("old: " + oldpoint.X + ", " + oldpoint.Y);
+
+ PhysModel.Point point = particles[win].Position;
+ Console.WriteLine ("new: " + point.X + ", " + point.Y);
+
+ PhysModel.Vector vec = point - oldpoint;
+ //PhysModel.Vector vec = oldpoint - point;
+ Console.WriteLine ("delta: " + vec.X + ", " + vec.Y);
+
+ if ((int)vec.X != 0 | (int)vec.Y != 0) {
+ changed = true;
+ win.Move ((int)vec.X, (int)vec.Y, false, false);
+ win.SyncPosition ();
+ }
+ }
+
+ inner (s, msSinceLastPaint);
+ }
+
+ public bool OnPaintScreen (PaintScreenHandler inner, IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("PaintScreen (managed) " + " " + s + " " + mask);
+
+ Console.Error.WriteLine ("xRotate: " + sa.xRotate);
+ Console.Error.WriteLine ("yRotate: " + sa.yRotate);
+ Console.Error.WriteLine ("vRotate: " + sa.vRotate);
+ //Console.Error.WriteLine (": " + my_screen.);
+
+ //restrict rotation on x
+ if (sa.xRotate > 6)
+ sa.xRotate = 6f;
+ else if (sa.xRotate < -6)
+ sa.xRotate = -6f;
+
+ //restrict rotation on v
+ if (sa.vRotate > 6)
+ sa.vRotate = 6f;
+ else if (sa.vRotate < -6)
+ sa.vRotate = -6f;
+
+ //zoom out
+ //sa.zCamera = -1f;
+
+ //mask &= ScreenPaint.Region;
+ //mask |= ScreenPaint.Transformed;
+
+ bool ret = inner (s, ref sa, region, mask);
+
+ return ret;
+ }
+
+ protected int grabIndex;
+
+ public void OnDonePaintScreen (DonePaintScreenHandler inner, IntPtr s)
+ {
+ Screen screen = screens[s];
+
+ Console.Error.WriteLine ("DonePaintScreen (managed)");
+
+ if (false)
+ screen.RemoveGrab (grabIndex);
+
+ //if (false)
+ if (changed) {
+ screen.Damage ();
+ changed = false;
+ }
+
+ inner (s);
+ }
+
+ void UpdateWindow (Window win)
+ {
+ Particle p = particles[win];
+
+ int x, y;
+ win.GetPosition (out x, out y);
+ int width, height;
+ win.GetSize (out width, out height);
+ x += width/2;
+ y += height/2;
+ p.Position = new PhysModel.Point (x, y);
+ }
+
+ public override bool InitWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("initWindow");
+
+ Window w = new Window (window);
+ windowPtrs[window] = w;
+ windows.Add (w);
+
+ int x, y;
+ w.GetPosition (out x, out y);
+ int width, height;
+ w.GetSize (out width, out height);
+ x += width/2;
+ y += height/2;
+ particles[w] = NewParticle (x, y);
+
+
+ //Console.WriteLine (window.Id);
+ //Console.WriteLine (window.Frame);
+
+ //Console.WriteLine (win.UserTime);
+ //Console.WriteLine (win.State);
+ //win.Maximize ();
+
+ return true;
+ }
+
+ public override void FiniWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("finiWindow");
+
+ model.Particles.Remove (particles[windowPtrs[window]]);
+ particles.Remove (windowPtrs[window]);
+ windows.Remove (windowPtrs[window]);
+ windowPtrs.Remove (window);
+ }
+}
diff --git a/plugins/Simple.cs b/plugins/Simple.cs
new file mode 100644
index 0000000..9553239
--- /dev/null
+++ b/plugins/Simple.cs
@@ -0,0 +1,23 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using Compiz;
+
+public class SimpleEffect
+{
+}
+
+//implements/inherits CompScreen class/iface?
+
+//Q: are options one-set-per-screen? i think so
+
+public class SimpleScreen
+{
+ [Option ("Zoom In")]
+ bool zoomIn;
+
+ [Option ("Window types")]
+ WindowType windowTypes;
+}
diff --git a/plugins/SvgCairo.cs b/plugins/SvgCairo.cs
new file mode 100644
index 0000000..d0448c5
--- /dev/null
+++ b/plugins/SvgCairo.cs
@@ -0,0 +1,89 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Runtime.InteropServices;
+using Cairo;
+
+namespace NDesk.Graphics
+{
+ public class Svg
+ {
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_create (out IntPtr svg_cairo);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_destroy (out IntPtr svg_cairo);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse (IntPtr svg_cairo, string filename);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse_file (IntPtr svg_cairo, IntPtr file);
+
+ //TODO: verify
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse_buffer (IntPtr svg_cairo, byte[] buf, uint count);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse_chunk_begin (IntPtr svg_cairo);
+
+ //TODO: verify
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse_chunk (IntPtr svg_cairo, byte[] buf, uint count);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_parse_chunk_end (IntPtr svg_cairo);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_render (IntPtr svg_cairo, IntPtr xrs);
+
+ [DllImport("svg-cairo")]
+ protected static extern IntPtr svg_cairo_set_viewport_dimension (IntPtr svg_cairo, uint width, uint height);
+
+ [DllImport("svg-cairo")]
+ protected static extern void svg_cairo_get_size (IntPtr svg_cairo, out uint width, out uint height);
+
+ protected IntPtr Handle;
+
+ public Svg ()
+ {
+ svg_cairo_create (out Handle);
+ }
+
+ public void Render (Cairo.Context xrs)
+ {
+ svg_cairo_render (Handle, xrs.Handle);
+ }
+
+ public void Parse (string filename)
+ {
+ svg_cairo_parse (Handle, filename);
+ }
+
+ public void SetViewportDimension (uint width, uint height)
+ {
+ svg_cairo_set_viewport_dimension (Handle, width, height);
+ }
+
+ public void GetSize (out uint width, out uint height)
+ {
+ svg_cairo_get_size (Handle, out width, out height);
+ }
+ }
+
+ /* The returned status; not used yet:
+
+ protected enum Status
+ {
+ Success,
+ NoMemory,
+ IOError,
+ FileNotFound,
+ InvalidValue,
+ InvalidCall,
+ ParseError,
+ }
+ */
+}
diff --git a/plugins/Zoom.cs b/plugins/Zoom.cs
new file mode 100644
index 0000000..0b87dd2
--- /dev/null
+++ b/plugins/Zoom.cs
@@ -0,0 +1,158 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using Compiz;
+//using Tao.FreeGlut;
+//using Tao.OpenGl;
+
+/*
+public class ZoomEffect
+{
+}
+*/
+
+public class ZoomScreen
+{
+ const float SensitivityFactor = 0.001f;
+
+ [Option ("Pointer Invert Y")]
+ public bool invertY = false;
+
+ //Warning:
+ //sensitivity factor breaks consistency between interface and implementation
+ //Use a property?
+ [Option ("Pointer Sensitivity")]
+ public float sensitivity = 1.0f * SensitivityFactor;
+
+ //TODO: maybe do key bindings as methods?
+ //[Option ("Zoom In")]
+ //public Binding zoomIn;
+
+ [Option ("Zoom Speed")]
+ public float speed = 1.5f;
+
+ [Option ("Zoom Timestep")]
+ public float timestep = 1.2f;
+
+ [Option ("Filter Linear")]
+ public bool filterLinear = false;
+
+ int grabIndex;
+
+ //begin GL floats
+ float currentZoom = 1.0f;
+ float newZoom = 1.0f;
+
+ float xVelocity = 0.0f;
+ float yVelocity = 0.0f;
+ float zVelocity = 0.0f;
+
+ float xTranslate = 0.0f;
+ float yTranslate = 0.0f;
+
+ float xtrans;
+ float ytrans;
+ float ztrans;
+ //end GL floats
+
+ //XPoint savedPointer;
+ bool grabbed = false;
+
+ float maxTranslate = 0.0f;
+
+ //TODO: fabs() etc. misported
+ bool AdjustVelocity ()
+ {
+ float d, adjust, amount;
+
+ d = (newZoom - currentZoom) * 75.0f;
+
+ adjust = d * 0.002f;
+ amount = Math.Abs (d);
+ if (amount < 1.0f)
+ amount = 1.0f;
+ else if (amount > 5.0f)
+ amount = 5.0f;
+
+ zVelocity = (amount * zVelocity + adjust) / (amount + 1.0f);
+
+ return (Math.Abs (d) < 0.1f && Math.Abs (zVelocity) < 0.005f);
+ }
+
+ void PreparePaint (int msSinceLastPaint)
+ {
+ int steps;
+ float amount, chunk;
+
+ amount = msSinceLastPaint * 0.05f * speed;
+ steps = (int) (amount / (0.5f * timestep));
+ if (steps == 0)
+ steps = 1;
+ chunk = amount / (float) steps;
+
+ //for (; steps != 0 ; steps--)
+ while (steps-- != 0)
+ {
+ xVelocity /= 1.25f;
+ yVelocity /= 1.25f;
+
+ if (AdjustVelocity ())
+ {
+ currentZoom = newZoom;
+ zVelocity = 0.0f;
+ }
+ else
+ {
+ currentZoom += (zVelocity * msSinceLastPaint) / 1;//s->redrawTime;
+ }
+
+ }
+
+ }
+
+ void DonePaint ()
+ {
+ if (currentZoom != newZoom || xVelocity != 0 || yVelocity != 0 || zVelocity != 0)
+ //screen.Damage ();
+ Console.WriteLine ("damage");
+ }
+
+ void Paint (ScreenPaintAttrib sa, ScreenPaint mask)
+ {
+ sa.xTranslate += xtrans;
+ sa.yTranslate += ytrans;
+
+ sa.zCamera = -ztrans;
+
+ /* hack to get sides rendered correctly */
+ if (xtrans > 0.0f)
+ sa.xRotate += 0.000001f;
+ else
+ sa.xRotate -= 0.000001f;
+
+ mask &= ScreenPaint.Region;
+ mask |= ScreenPaint.Transformed;
+
+ //base.Paint (ref sa, mask);
+ }
+
+ void ZoomIn (int x, int y)
+ {
+ }
+
+ void ZoomOut ()
+ {
+ }
+
+ void ZoomTerminate ()
+ {
+ if (false) {
+ newZoom = 1.0f;
+ grabbed = false;
+
+ //screen.Damage ();
+ }
+ }
+}
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..b7733d2
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,4 @@
+*.mdb
+*.pdb
+*.exe
+*.dll
diff --git a/src/Display.cs b/src/Display.cs
new file mode 100644
index 0000000..c91550a
--- /dev/null
+++ b/src/Display.cs
@@ -0,0 +1,159 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Compiz
+{
+ //From Mono.Unix and poll(2)
+ [Flags]
+ public enum PollEvents : short {
+ POLLIN = 0x0001, // There is data to read
+ POLLPRI = 0x0002, // There is urgent data to read
+ POLLOUT = 0x0004, // Writing now will not block
+ POLLERR = 0x0008, // Error condition
+ POLLHUP = 0x0010, // Hung up
+ POLLNVAL = 0x0020, // Invalid request; fd not open
+ // XPG4.2 definitions (via _XOPEN_SOURCE)
+ POLLRDNORM = 0x0040, // Normal data may be read
+ POLLRDBAND = 0x0080, // Priority data may be read
+ POLLWRNORM = 0x0100, // Writing now will not block
+ POLLWRBAND = 0x0200, // Priority data may be written
+ }
+
+ public delegate bool CallBackProc (IntPtr closure);
+
+ public class Display
+ {
+ public IntPtr Handle;
+
+ //TODO: use events here?
+ public virtual void HandleEvent ()
+ {
+ }
+
+ [DllImport("compiz")]
+ protected extern static void addScreenToDisplay (IntPtr display, IntPtr s);
+
+ [DllImport("compiz")]
+ protected extern static int compAddWatchFd (int fd, PollEvents events, CallBackProc callBack, IntPtr closure);
+
+ public int AddWatch (int fd, PollEvents events, CallBackProc cb, IntPtr closure)
+ {
+ return compAddWatchFd (fd, events, cb, closure);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void compRemoveWatchFd (int handle);
+
+ public void RemoveWatch (int handle)
+ {
+ compRemoveWatchFd (handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void focusDefaultWindow (IntPtr display);
+
+ public void FocusDefaultWindow ()
+ {
+ focusDefaultWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void updateModifierMappings (IntPtr display);
+
+ public void UpdateModifierMappings ()
+ {
+ updateModifierMappings (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void warpPointer (IntPtr display, int dx, int dy);
+
+ public void WarpPointer (int dx, int dy)
+ {
+ warpPointer (Handle, dx, dy);
+ }
+ }
+
+ //make these CamelCase before using them
+ public enum DisplayOption
+ {
+ active_plugins,
+ texture_filter,
+ click_to_focus,
+ autoraise,
+ autoraise_delay,
+ close_window,
+ main_menu,
+ run_dialog,
+ command0,
+ run_command0,
+ command1,
+ run_command1,
+ command2,
+ run_command2,
+ command3,
+ run_command3,
+ command4,
+ run_command4,
+ command5,
+ run_command5,
+ command6,
+ run_command6,
+ command7,
+ run_command7,
+ command8,
+ run_command8,
+ command9,
+ run_command9,
+ command10,
+ run_command10,
+ command11,
+ run_command11,
+ slow_animations,
+ lower_window,
+ unmaximize_window,
+ minimize_window,
+ maximize_window,
+ maximize_window_horz,
+ maximize_window_vert,
+ opacity_increase,
+ opacity_decrease,
+ screenshot,
+ run_screenshot,
+ window_screenshot,
+ run_window_screenshot,
+ window_menu,
+ show_desktop,
+ raise_on_click,
+ audible_bell,
+ toggle_window_maximized,
+ toggle_window_maximized_horz,
+ toggle_window_maximized_vert,
+ hide_skip_taskbar_windows,
+ toggle_window_shaded,
+ //num = 54,
+ }
+
+ [StructLayout (LayoutKind.Explicit, Pack=1)]
+ public unsafe struct CompDisplay
+ {
+ [FieldOffset (0)]
+ public IntPtr Display;
+ [FieldOffset (4)]
+ public CompScreen* Screens;
+
+ //[FieldOffset (80)]
+ //public fixed uint Atoms[?];
+
+ [FieldOffset (4512)]
+ public IntPtr HandleEvent;
+
+ [FieldOffset (4516)]
+ public IntPtr privates;
+ }
+}
diff --git a/src/Icon.cs b/src/Icon.cs
new file mode 100644
index 0000000..15d6c7a
--- /dev/null
+++ b/src/Icon.cs
@@ -0,0 +1,12 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace Compiz
+{
+ public class Icon : Texture
+ {
+ }
+}
diff --git a/src/Image.cs b/src/Image.cs
new file mode 100644
index 0000000..f7b9455
--- /dev/null
+++ b/src/Image.cs
@@ -0,0 +1,22 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Compiz
+{
+ public class Image
+ {
+ [DllImport("compiz")]
+ protected extern static bool openImageFile (string filename, out string returnFilename, out IntPtr returnFile);
+
+ [DllImport("compiz")]
+ protected extern static bool readPng (string filename, out byte[] data, out uint width, out uint height);
+
+ [DllImport("compiz")]
+ protected extern static bool readPngBuffer (byte[] buffer, out byte[] data, out uint width, out uint height);
+ }
+}
diff --git a/src/Main.cs b/src/Main.cs
new file mode 100644
index 0000000..5c265cc
--- /dev/null
+++ b/src/Main.cs
@@ -0,0 +1,159 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace Compiz
+{
+ //compiz.exe uses a custom libcompiz.so to control the main loop
+ //this is useful for debugging and experimenting with plugin loading
+ public class Session
+ {
+ [DllImport("compiz")]
+ protected extern static void initSession (string smPrevClientId);
+
+ [DllImport("compiz")]
+ protected unsafe extern static void* addDisplay (string name, string[] plugins, int nPlugin);
+
+ [DllImport("compiz")]
+ protected extern static void eventLoop ();
+
+ [DllImport("compiz")]
+ protected extern static bool pushPlugin (IntPtr plugin);
+ //protected unsafe extern static bool pushPlugin (CompPlugin* plugin);
+
+ [DllImport("compiz")]
+ protected unsafe extern static void* getPlugins ();
+
+ [DllImport("compiz"), SuppressUnmanagedCodeSecurity]
+ protected unsafe extern static void runIteration (void* display, IntPtr tmpRegion);
+
+ [DllImport("compiz")]
+ protected unsafe extern static IntPtr compAddWatchFd (int fd, short events, IntPtr callBack, IntPtr closure);
+
+ [DllImport("X11")]
+ protected extern static int XConnectionNumber (IntPtr display);
+
+ [DllImport("X11")]
+ protected unsafe extern static IntPtr XCreateRegion ();
+
+ const string defaultPlugins = "decoration wobbly fade minimize cube rotate zoom scale move resize place switcher";
+
+ public unsafe static int Main (string[] args)
+ {
+ string[] pluginList = (args.Length != 0) ? args : defaultPlugins.Split (' ');
+
+ CompDisplay* display = (CompDisplay*)addDisplay (null, pluginList, pluginList.Length);
+
+ if (display == null)
+ return 1;
+
+ IntPtr tmpRegion = XCreateRegion ();
+
+ compAddWatchFd (XConnectionNumber (display->Display), 0x0001, IntPtr.Zero, IntPtr.Zero);
+
+ //eventLoop ();
+
+ bool done = false;
+
+ while (true) {
+ runIteration (display, tmpRegion);
+
+ /*
+ if (!done) {
+ done = true;
+ LoadPlugin ("sharp");
+ }
+ */
+
+ //Console.WriteLine (tmpRegion.size);
+ //Console.WriteLine (tmpRegion.numRects);
+
+ //CompPlugin p = getPlugins ();
+ //Console.WriteLine (p.dlhand);
+
+ CompPlugin* plug = (CompPlugin*)getPlugins ();
+
+ while (plug != null) {
+ Console.WriteLine (plug->vTable->Name);
+ //plug->vTable->Init (plug);
+ //plug->vTable->Init (plugPtr);
+ //plug->vTable->initt += delegate {Console.WriteLine ("foo"); return false;};
+ //plug->vTable->initWindow = Marshal.GetFunctionPointerForDelegate (fiz);
+ plug = plug->next;
+ }
+
+ Console.WriteLine ();
+ //CompPluginVTable* vt = (CompPluginVTable*)(plug->vTable);
+
+ }
+
+ return 0;
+ }
+
+ public unsafe static void LoadPlugin (string name)
+ {
+ /*
+ CompPluginVTable vt = new CompPluginVTable ();
+ vt.Name = "sharp";
+
+ CompPlugin p = new CompPlugin ();
+ p.vTable = vt;
+
+ */
+ IntPtr plugPtr = Marshal.AllocCoTaskMem (sizeof (CompPlugin));
+ //IntPtr plugPtr = Marshal.AllocCoTaskMem (Marshal.SizeOf ());
+ //IntPtr plugPtr = Marshal.AllocHGlobal (sizeof (CompPlugin));
+ CompPlugin* p = (CompPlugin*)plugPtr;
+ //p->next = (CompPlugin*)getPlugins ();
+
+ IntPtr vtPtr = Marshal.AllocCoTaskMem (sizeof (CompPluginVTable));
+ //IntPtr vtPtr = Marshal.AllocHGlobal (sizeof (CompPluginVTable));
+ CompPluginVTable* vt = (CompPluginVTable*)vtPtr;
+ p->vTable = vt;
+
+ vt->Name = name;
+
+ //d1 = init;
+ vt->init = Marshal.GetFunctionPointerForDelegate (d1);
+ /*
+
+ InitPluginProc<Display> d2 = initD;
+ vt->initDisplay = Marshal.GetFunctionPointerForDelegate (d2);
+ */
+
+ //pushPlugin (plugPtr);
+ }
+
+ static InitPluginProc d1 = init;
+ public static bool init (IntPtr plugin)
+ {
+ return true;
+ }
+
+ public static bool initD (IntPtr plugin, Display display)
+ {
+ return true;
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe struct Box
+ {
+ public short x1, x2, y1, y2;
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe class Region
+ {
+ public int size;
+ public int numRects;
+ public Box* rects;
+ public Box extents;
+ }
+}
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..ef22a07
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,11 @@
+CSFLAGS=-unsafe
+
+all: compiz-sharp.dll
+
+compiz-sharp.dll: Display.cs Icon.cs Option.cs Plugin.cs PluginLoader.cs Screen.cs Texture.cs Window.cs Image.cs
+
+compiz.exe: compiz-sharp.dll Main.cs
+
+mtest.dll: compiz-sharp.dll TestPlugin.cs
+
+include ../include.mk
diff --git a/src/Option.cs b/src/Option.cs
new file mode 100644
index 0000000..c9f7612
--- /dev/null
+++ b/src/Option.cs
@@ -0,0 +1,73 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace Compiz
+{
+ public enum OptionType
+ {
+ Bool,
+ Int,
+ Float,
+ String,
+ Color,
+ Binding,
+ List,
+ }
+
+ public enum BindingType
+ {
+ None,
+ Key,
+ Button,
+ }
+
+ [AttributeUsage (AttributeTargets.Field, Inherited=true)]
+ public class Option : Attribute
+ {
+ public string name;
+ public string shortDesc;
+ public string longDesc;
+
+ /*
+ CompOptionType type;
+
+ //default value
+ CompOptionValue value;
+
+ CompOptionRestriction rest;
+ */
+
+ public Option (string name)
+ {
+ }
+ }
+
+ /*
+ [AttributeUsage (AttributeTargets.Field, Inherited=true)]
+ public class Restriction : Attribute
+ {
+ }
+
+ public class IntRestriction : Restriction
+ {
+ public int Min;
+ public int Max;
+ }
+
+ public class FloatRestriction : Restriction
+ {
+ public int Min;
+ public int Max;
+ }
+
+ public class StringRestriction : Restriction
+ {
+ public StringRestriction (string regex)
+ {
+ }
+ }
+ */
+}
diff --git a/src/Plugin.cs b/src/Plugin.cs
new file mode 100644
index 0000000..91529f7
--- /dev/null
+++ b/src/Plugin.cs
@@ -0,0 +1,27 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+
+namespace Compiz
+{
+ /*
+ public interface IPlugin
+ {
+ bool InitScreen (IntPtr plugin, IntPtr screen);
+ //void FiniScreen (IntPtr plugin, IntPtr screen);
+ bool InitWindow (IntPtr plugin, IntPtr window);
+ void FiniWindow (IntPtr plugin, IntPtr window);
+ }
+ */
+
+ public abstract class Plugin //: IPlugin
+ {
+ public abstract bool InitScreen (IntPtr plugin, IntPtr screen);
+ //public abstract void FiniScreen (IntPtr plugin, IntPtr screen);
+ public abstract bool InitWindow (IntPtr plugin, IntPtr window);
+ public abstract void FiniWindow (IntPtr plugin, IntPtr window);
+ }
+}
diff --git a/src/PluginLoader.cs b/src/PluginLoader.cs
new file mode 100644
index 0000000..1d08bb7
--- /dev/null
+++ b/src/PluginLoader.cs
@@ -0,0 +1,276 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+namespace Compiz
+{
+ public class PluginLoader
+ {
+ static List<PluginLoader> loaders = new List<PluginLoader> ();
+
+ public PluginLoader ()
+ {
+ Console.Error.WriteLine ("new managed plugin loader");
+
+ //keep references around, cheap hack for now
+ loaders.Add (this);
+ }
+
+ /*
+ public static bool Load (string name)
+ {
+ return false;
+ }
+ */
+
+ protected Plugin LoadAssembly (string name)
+ {
+ //temporary hack
+ string path = Environment.CurrentDirectory + Path.DirectorySeparatorChar + name + ".dll";
+
+ if (!File.Exists (path))
+ return null;
+
+ Assembly asm = Assembly.LoadFile (path);
+
+ //mangle into an acceptable class name
+ //improve this later
+ string className = "";
+ className += Char.ToUpper (name[0]);
+ className += name.Substring (1, name.Length - 1);
+ className += "Plugin";
+
+ Type t = asm.GetType (className);
+
+ if (t == null)
+ return null;
+
+ Plugin p = Activator.CreateInstance (t) as Plugin;
+
+ return p;
+ }
+
+ List<Delegate> delegates = new List<Delegate> ();
+ Dictionary<IntPtr,Plugin> plugins = new Dictionary<IntPtr,Plugin> ();
+
+ public unsafe bool Load (IntPtr plugin, string path, string name)
+ {
+ Console.Error.WriteLine ("managed load " + path + " " + name);
+
+ Plugin plug = LoadAssembly (name);
+ if (plug == null)
+ return false;
+
+ CompPlugin* p = (CompPlugin*)plugin;
+
+ InitPluginProc my_initPlugin;
+ InitPluginProc<IntPtr> my_initDisplay;
+ InitPluginProc<IntPtr> my_initScreen;
+ InitPluginProc<IntPtr> my_initWindow;
+ FiniPluginProc<IntPtr> my_finiWindow;
+ //InitPluginProc<CompWindow> my_initWindow;
+
+ my_initPlugin = initPlugin;
+ my_initDisplay = initDisplay;
+ my_initScreen = plug.InitScreen;
+ my_initWindow = plug.InitWindow;
+ my_finiWindow = plug.FiniWindow;
+
+ //keep references around, cheap hack for now
+ delegates.Add (my_initPlugin);
+ delegates.Add (my_initDisplay);
+ delegates.Add (my_initScreen);
+ delegates.Add (my_initWindow);
+ delegates.Add (my_finiWindow);
+
+ p->vTable = (CompPluginVTable*)Marshal.AllocCoTaskMem (sizeof (CompPluginVTable));
+
+ p->vTable->Name = name;
+ p->vTable->ShortDesc = name;
+ p->vTable->LongDesc = name;
+
+ p->vTable->init = Marshal.GetFunctionPointerForDelegate (my_initPlugin);
+ p->vTable->fini = IntPtr.Zero;
+
+ p->vTable->initDisplay = Marshal.GetFunctionPointerForDelegate (my_initDisplay);
+ p->vTable->finiDisplay = IntPtr.Zero;
+
+ p->vTable->initScreen = Marshal.GetFunctionPointerForDelegate (my_initScreen);
+ p->vTable->finiScreen = IntPtr.Zero;
+
+ p->vTable->initWindow = Marshal.GetFunctionPointerForDelegate (my_initWindow);
+ p->vTable->finiWindow = Marshal.GetFunctionPointerForDelegate (my_finiWindow);
+
+ p->vTable->getDisplayOptions = IntPtr.Zero;
+ p->vTable->setDisplayOption = IntPtr.Zero;
+
+ p->vTable->getScreenOptions = IntPtr.Zero;
+ p->vTable->setScreenOption = IntPtr.Zero;
+
+ p->vTable->deps = null;
+ p->vTable->nDeps = 0;
+
+ plugins[plugin] = plug;
+
+ return true;
+ }
+
+ public unsafe void Unload (IntPtr plugin)
+ {
+ Console.Error.WriteLine ("managed unload");
+
+ //this is not a managed plugin, we can't unload it
+ if (!plugins.ContainsKey (plugin))
+ return;
+
+ CompPlugin* p = (CompPlugin*)plugin;
+
+ Marshal.FreeCoTaskMem ((IntPtr)p->vTable);
+
+ plugins[plugin] = null;
+
+ //TODO: complete unloading, including delegates
+ //this is maybe best done in the Plugin base class
+ }
+
+ bool initPlugin (IntPtr plugin)
+ {
+ Console.Error.WriteLine ("init");
+ return true;
+ }
+
+ bool initDisplay (IntPtr plugin, IntPtr display)
+ {
+ Console.Error.WriteLine ("initDisplay");
+ return true;
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
+ public unsafe struct CompPlugin
+ {
+ public CompPlugin* next;
+ public uint uval; //ulong union
+ public void* devType;
+ public CompPluginVTable* vTable;
+ }
+
+ //public unsafe delegate bool InitPluginProc (CompPlugin* plugin);
+ //[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate bool InitPluginProc (IntPtr plugin);
+ //[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void FiniPluginProc (IntPtr plugin);
+
+ public delegate bool InitPluginProc<T> (IntPtr plugin, T obj);
+ public delegate void FiniPluginProc<T> (IntPtr plugin, T obj);
+
+ public delegate IntPtr GetOptionsProc<T> (T obj, out int count);
+ public delegate bool SetOptionProc<T> (T obj, string name, IntPtr value);
+
+ public enum PluginRule
+ {
+ Before,
+ After,
+ }
+
+ [StructLayout (LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
+ public struct CompPluginDep
+ {
+ public PluginRule rule;
+ //public string plugin;
+ public IntPtr plugin;
+ }
+
+ [StructLayout (LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
+ public unsafe struct CompPluginVTable
+ {
+ public string Name
+ {
+ get {
+ //return System.Text.Encoding.ASCII.GetString (name);
+ return Marshal.PtrToStringAnsi (name);
+ } set {
+ name = Marshal.StringToCoTaskMemAnsi (value);
+ }
+ }
+
+ public string ShortDesc
+ {
+ get {
+ return Marshal.PtrToStringAnsi (shortDesc);
+ } set {
+ shortDesc = Marshal.StringToCoTaskMemAnsi (value);
+ }
+ }
+
+ public string LongDesc
+ {
+ get {
+ return Marshal.PtrToStringAnsi (longDesc);
+ } set {
+ longDesc = Marshal.StringToCoTaskMemAnsi (value);
+ }
+ }
+
+ public IntPtr name;
+ public IntPtr shortDesc;
+ public IntPtr longDesc;
+
+ public IntPtr init;
+ public IntPtr fini;
+
+ public IntPtr initDisplay;
+ public IntPtr finiDisplay;
+
+ public IntPtr initScreen;
+ public IntPtr finiScreen;
+
+ public IntPtr initWindow;
+ public IntPtr finiWindow;
+
+ public IntPtr getDisplayOptions;
+ public IntPtr setDisplayOption;
+ public IntPtr getScreenOptions;
+ public IntPtr setScreenOption;
+
+ public CompPluginDep *deps;
+ public int nDeps;
+ }
+
+ /*
+ [StructLayout (LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
+ public unsafe struct CompPluginVTable
+ {
+ public string name;
+ public string shortDesc;
+ public string longDesc;
+
+ public InitPluginProc init;
+ public FiniPluginProc fini;
+
+ public InitPluginProc<Screen> initScreen;
+ public FiniPluginProc<Screen> finiScreen;
+
+ public InitPluginProc<Window> initWindow;
+ public FiniPluginProc<Window> finiWindow;
+
+ public GetOptionsProc<Display> getDisplayOptions;
+ public SetOptionProc<Display> setDisplayOption;
+
+ public GetOptionsProc<Screen> getScreenOptions;
+ public SetOptionProc<Screen> setScreenOption;
+
+ public CompPluginDep *deps;
+ public int nDeps;
+ }
+ */
+
+ public delegate CompPluginVTable PluginGetInfoProc ();
+}
diff --git a/src/Screen.cs b/src/Screen.cs
new file mode 100644
index 0000000..bcf1cb1
--- /dev/null
+++ b/src/Screen.cs
@@ -0,0 +1,416 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Compiz
+{
+ public class Screen
+ {
+ //protected IntPtr Handle;
+ public IntPtr Handle;
+
+ public Screen (IntPtr handle)
+ {
+ this.Handle = handle;
+ }
+
+ public Display Display
+ {
+ get {
+ unsafe {
+ //CompScreen *w = (CompScreen*)Handle;
+ //Console.Error.WriteLine (w->Display);
+ }
+ return null;
+ }
+ }
+
+ public void Configure ()
+ {
+ }
+
+ /*
+ public void Damage (Region region)
+ {
+ }
+ */
+
+ [DllImport("compiz")]
+ protected extern static void damageScreen (IntPtr screen);
+
+ public void Damage ()
+ {
+ damageScreen (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void damagePendingOnScreen (IntPtr s);
+
+ public void DamagePending ()
+ {
+ damagePendingOnScreen (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void insertWindowIntoScreen (IntPtr s, IntPtr w, uint aboveId);
+
+ public void InsertWindow (Window w, uint aboveId)
+ {
+ insertWindowIntoScreen (Handle, w.Handle, aboveId);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void unhookWindowFromScreen (IntPtr s, IntPtr w);
+
+ public void UnhookWindow (Window w)
+ {
+ unhookWindowFromScreen (Handle, w.Handle);
+ }
+
+
+ [DllImport("compiz")]
+ protected extern static int pushScreenGrab (IntPtr s, uint cursor, string name);
+
+ public int PushGrab (uint cursor, string name)
+ {
+ return pushScreenGrab (Handle, cursor, name);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void removeScreenGrab (IntPtr s, int index, IntPtr restorePointer);
+
+ public void RemoveGrab (int index, IntPtr restorePointer)
+ {
+ removeScreenGrab (Handle, index, restorePointer);
+ }
+
+ public void RemoveGrab (int index)
+ {
+ removeScreenGrab (Handle, index, IntPtr.Zero);
+ }
+
+
+ [DllImport("compiz")]
+ protected extern static bool otherScreenGrabExist (IntPtr s, IntPtr args);
+
+ public bool OtherGrabsExist ()
+ {
+ return otherScreenGrabExist (Handle, IntPtr.Zero);
+ }
+
+
+ [DllImport("compiz")]
+ protected extern static void enableScreenEdge (IntPtr s, ScreenEdge edge);
+
+ public void EnableEdge (ScreenEdge edge)
+ {
+ enableScreenEdge (Handle, edge);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void disableScreenEdge (IntPtr s, ScreenEdge edge);
+
+ public void DisableEdge (ScreenEdge edge)
+ {
+ disableScreenEdge (Handle, edge);
+ }
+
+
+
+ public void RunCommand (string command)
+ {
+ }
+
+ [DllImport("compiz")]
+ protected extern static void moveScreenViewport (IntPtr s, int tx, bool sync);
+
+ public void MoveViewport (int tx, bool sync)
+ {
+ moveScreenViewport (Handle, tx, sync);
+ }
+
+
+
+
+
+
+ public void FocusDefaultWindow ()
+ {
+ }
+
+ public Screen ScreenAtDisplay ()
+ {
+ return null;
+ }
+
+ public void WarpPointer (int dx, int dy)
+ {
+ }
+
+ public bool Lighting
+ {
+ get {
+ return true;
+ }
+ }
+
+ List<Delegate> delegates = new List<Delegate> ();
+
+ public event PreparePaintScreenHandlerNew PreparePaint
+ {
+ add {
+ Console.Error.WriteLine ("PreparePaintScreen_Add " + Handle + " (managed)");
+ unsafe {
+ CompScreen* screen = (CompScreen*)Handle;
+
+ IntPtr base_fptr = screen->PreparePaintScreen;
+
+ PreparePaintScreenHandler base_func = (PreparePaintScreenHandler) Marshal.GetDelegateForFunctionPointer (base_fptr, typeof (PreparePaintScreenHandler));
+ PreparePaintScreenHandler meta_func = delegate (IntPtr s, int msSinceLastPaint) {
+ unsafe {
+ CompScreen* screen = (CompScreen*)s;
+
+ //UNWRAP
+ IntPtr tmp = screen->PreparePaintScreen;
+ screen->PreparePaintScreen = base_fptr;
+
+ base_func (s, msSinceLastPaint);
+
+ //WRAP
+ base_fptr = screen->PreparePaintScreen;
+ screen->PreparePaintScreen = tmp;
+ }
+ };
+ PreparePaintScreenHandler wrap_func = delegate (IntPtr s, int msSinceLastPaint) {value (meta_func, s, msSinceLastPaint);};
+
+ //keep references around, cheap hack for now
+ delegates.Add (wrap_func);
+
+ IntPtr fptr = Marshal.GetFunctionPointerForDelegate (wrap_func);
+ screen->PreparePaintScreen = fptr;
+ }
+ }
+ remove {
+ Console.Error.WriteLine ("PreparePaintScreen_Remove (managed)");
+ }
+ }
+
+ public event PaintScreenHandlerNew Paint
+ {
+ add {
+ Console.Error.WriteLine ("PaintScreen_Add " + Handle + " (managed)");
+ unsafe {
+ CompScreen* screen = (CompScreen*)Handle;
+
+ IntPtr base_fptr = screen->PaintScreen;
+
+ PaintScreenHandler base_func = (PaintScreenHandler) Marshal.GetDelegateForFunctionPointer (base_fptr, typeof (PaintScreenHandler));
+
+ PaintScreenHandler meta_func = delegate (IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask) {
+ unsafe {
+ CompScreen* screen = (CompScreen*)s;
+
+ //UNWRAP
+ IntPtr tmp = screen->PaintScreen;
+ screen->PaintScreen = base_fptr;
+
+ bool ret = base_func (s, ref sa, region, mask);
+
+ //WRAP
+ base_fptr = screen->PaintScreen;
+ screen->PaintScreen = tmp;
+
+ return ret;
+ }
+ };
+ PaintScreenHandler wrap_func = delegate (IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask) {
+ return value (meta_func, s, ref sa, region, mask);
+ };
+
+ //keep references around, cheap hack for now
+ delegates.Add (wrap_func);
+
+ IntPtr fptr = Marshal.GetFunctionPointerForDelegate (wrap_func);
+ screen->PaintScreen = fptr;
+ }
+ }
+ remove {
+ Console.Error.WriteLine ("PaintScreen_Remove (managed)");
+ }
+ }
+
+
+ public event DonePaintScreenHandlerNew DonePaint
+ {
+ add {
+ Console.Error.WriteLine ("DonePaintScreen_Add " + Handle + " (managed)");
+ unsafe {
+ CompScreen* screen = (CompScreen*)Handle;
+
+ IntPtr base_fptr = screen->DonePaintScreen;
+
+ DonePaintScreenHandler base_func = (DonePaintScreenHandler) Marshal.GetDelegateForFunctionPointer (base_fptr, typeof (DonePaintScreenHandler));
+ DonePaintScreenHandler meta_func = delegate (IntPtr s) {
+ unsafe {
+ CompScreen* screen = (CompScreen*)s;
+
+ //UNWRAP
+ IntPtr tmp = screen->DonePaintScreen;
+ screen->DonePaintScreen = base_fptr;
+
+ base_func (s);
+
+ //WRAP
+ base_fptr = screen->DonePaintScreen;
+ screen->DonePaintScreen = tmp;
+ }
+ };
+ DonePaintScreenHandler wrap_func = delegate (IntPtr s) {value (meta_func, s);};
+
+ //keep references around, cheap hack for now
+ delegates.Add (wrap_func);
+
+ IntPtr fptr = Marshal.GetFunctionPointerForDelegate (wrap_func);
+ screen->DonePaintScreen = fptr;
+ }
+ }
+ remove {
+ Console.Error.WriteLine ("DonePaintScreen_Remove (managed)");
+ }
+ }
+
+
+ public PaintScreenHandler PaintScreenOrig;
+ //public PaintScreenHandler PaintScreenNew;
+
+ /*
+ [DllImport ("compmono")]
+ public extern static PaintScreenHandler PaintScreen_Add (IntPtr s, PaintScreenHandler func);
+
+ public event PaintScreenHandler Paint
+ {
+ add {
+ //PaintScreenNew = value;
+ Console.Error.WriteLine ("PaintScreen_Add " + Handle + " (managed)");
+ //PaintScreenOrig = PaintScreen_Add (Handle, value);
+ }
+ remove {
+ Console.Error.WriteLine ("PaintScreen_Remove (managed)");
+ }
+ }
+ */
+
+ [DllImport ("compmono")]
+ public extern static DonePaintScreenHandler DonePaintScreen_Add (IntPtr s, DonePaintScreenHandler func);
+ }
+
+ public delegate void PreparePaintScreenHandlerNew (PreparePaintScreenHandler inner, IntPtr s, int msSinceLastPaint);
+
+ public delegate void PreparePaintScreenHandler (IntPtr s, int msSinceLastPaint);
+
+ public delegate bool PaintScreenHandlerNew (PaintScreenHandler inner, IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask);
+
+ public delegate bool PaintScreenHandler (IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask);
+
+ public delegate void DonePaintScreenHandlerNew (DonePaintScreenHandler inner, IntPtr s);
+ public delegate void DonePaintScreenHandler (IntPtr s);
+
+
+ public enum ScreenOption
+ {
+ DetectRefreshRate,
+ Lighting,
+ RefreshRate,
+ Size,
+ OpacityStep,
+ UnredirectFs,
+ DefaultIcon,
+ }
+
+ public enum ScreenEdge
+ {
+ Left,
+ Right,
+ Top,
+ Bottom,
+ TopLeft,
+ TopRight,
+ BottomLeft,
+ BottomRight,
+ }
+
+ [Flags]
+ public enum ScreenDamage : uint
+ {
+ Pending = 1 << 0,
+ Region = 1 << 1,
+ All = 1 << 2,
+ }
+
+ [Flags]
+ public enum ScreenPaint : uint
+ {
+ Region = 1 << 0,
+ Full = 1 << 1,
+ Transformed = 1 << 2,
+ WithTransformedWindows = 1 << 3,
+ Clear = 1 << 4,
+ }
+
+ [StructLayout (LayoutKind.Sequential, Pack=1)]
+ public struct ScreenPaintAttrib {
+ public float xRotate;
+ public float yRotate;
+ public float vRotate;
+ public float xTranslate;
+ public float yTranslate;
+ public float zTranslate;
+ public float zCamera;
+ }
+
+ public delegate void PaintBackgroundHandler (IntPtr screen, IntPtr region, BackgroundPaint mask);
+
+ [Flags]
+ public enum BackgroundPaint : uint
+ {
+ OnTransformedScreen = 1 << 0,
+ WithStencil = 1 << 1,
+ }
+
+ [StructLayout (LayoutKind.Sequential, Pack=1)]
+ public unsafe struct CompScreen
+ {
+ public CompScreen* Next;
+ public CompDisplay* Display;
+ public CompWindow* Windows;
+ public CompWindow* ReverseWindows;
+
+ //not so great
+ public fixed byte data[1636];
+
+ public IntPtr PreparePaintScreen;
+ public IntPtr DonePaintScreen;
+ public IntPtr PaintScreen;
+ public IntPtr PaintTransformedScreen;
+ public IntPtr PaintBackground;
+ public IntPtr PaintWindow;
+ public IntPtr AddWindowGeometry;
+ public IntPtr DrawWindowGeometry;
+ public IntPtr DrawWindowTexture;
+ public IntPtr DamageWindowRect;
+ public IntPtr FocusWindow;
+ public IntPtr SetWindowScale;
+
+ public IntPtr WindowResizeNotify;
+ public IntPtr WindowMoveNotify;
+ public IntPtr WindowGrabNotify;
+ public IntPtr WindowUngrabNotify;
+
+ public IntPtr privates;
+ }
+}
diff --git a/src/TestPlugin.cs b/src/TestPlugin.cs
new file mode 100644
index 0000000..ac6f6ed
--- /dev/null
+++ b/src/TestPlugin.cs
@@ -0,0 +1,80 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+using Compiz;
+
+public class MtestPlugin : Plugin
+{
+ Screen s;
+
+ public override bool InitScreen (IntPtr plugin, IntPtr screen)
+ {
+ Console.WriteLine ("initScreen");
+
+ s = new Screen (screen);
+ s.PreparePaint += OnPreparePaintScreen;
+ s.Paint += OnPaintScreen;
+
+ return true;
+ }
+
+ public void OnPreparePaintScreen (PreparePaintScreenHandler inner, IntPtr s, int msSinceLastPaint)
+ {
+ Console.Error.WriteLine ("PreparePaintScreen (managed) " + msSinceLastPaint);
+ inner (s, msSinceLastPaint);
+ }
+
+ public bool OnPaintScreen (PaintScreenHandler inner, IntPtr s, ref ScreenPaintAttrib sa, IntPtr region, ScreenPaint mask)
+ {
+ Console.Error.WriteLine ("PaintScreen (managed) " + " " + s + " " + mask);
+
+ Console.Error.WriteLine ("xRotate: " + sa.xRotate);
+ Console.Error.WriteLine ("yRotate: " + sa.yRotate);
+ Console.Error.WriteLine ("vRotate: " + sa.vRotate);
+ //Console.Error.WriteLine (": " + my_screen.);
+
+ //restrict rotation on x
+ if (sa.xRotate > 6)
+ sa.xRotate = 6f;
+ else if (sa.xRotate < -6)
+ sa.xRotate = -6f;
+
+ //restrict rotation on v
+ if (sa.vRotate > 6)
+ sa.vRotate = 6f;
+ else if (sa.vRotate < -6)
+ sa.vRotate = -6f;
+
+ //zoom out
+ //sa.zCamera = -1f;
+
+ //mask &= ScreenPaint.Region;
+ //mask |= ScreenPaint.Transformed;
+
+ bool ret = inner (s, ref sa, region, mask);
+
+ return ret;
+ }
+
+ public override bool InitWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("initWindow");
+
+ //Console.WriteLine (window.Id);
+ //Console.WriteLine (window.Frame);
+
+ Window win = new Window (window);
+ Console.WriteLine (win.UserTime);
+ //Console.WriteLine (win.State);
+ //win.Maximize ();
+
+ return true;
+ }
+
+ public override void FiniWindow (IntPtr plugin, IntPtr window)
+ {
+ Console.WriteLine ("finiWindow");
+ }
+}
diff --git a/src/Texture.cs b/src/Texture.cs
new file mode 100644
index 0000000..827204d
--- /dev/null
+++ b/src/Texture.cs
@@ -0,0 +1,36 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+
+namespace Compiz
+{
+ public class Texture
+ {
+ /*
+ uint Name;
+ int Target;
+ float DX;
+ float DY;
+ IntPtr Pixmap;
+ int Filter;
+ int Wrap;
+ bool OldMipmaps;
+ bool Mipmap;
+ */
+ }
+
+ public enum TextureFilter
+ {
+ Fast,
+ Good,
+ }
+
+ public enum TransFilter
+ {
+ Nothing,
+ Screen,
+ Window,
+ }
+}
diff --git a/src/Window.cs b/src/Window.cs
new file mode 100644
index 0000000..841e537
--- /dev/null
+++ b/src/Window.cs
@@ -0,0 +1,471 @@
+// Copyright 2006 Alp Toker <alp@atoker.com>
+// This software is made available under the MIT License
+// See COPYING for details
+
+using System;
+//using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Compiz
+{
+ [StructLayout (LayoutKind.Sequential, Pack=1)]
+ public unsafe struct CompWindow
+ {
+ public CompScreen* Screen;
+ //public IntPtr Screen;
+ public CompWindow* Next;
+ public CompWindow* Prev;
+
+ public int Refcnt;
+ public uint Id;
+ public uint Frame;
+ public uint MapNum;
+ public uint ActiveNum;
+ //public fixed int XWindowAttributes[23];
+ public XWindowAttributes Attributes;
+ public int ServerX;
+ public int ServerY;
+ }
+
+ //[StructLayout (LayoutKind.Sequential, Size=23)]
+ [StructLayout (LayoutKind.Explicit, Pack=1, Size=23)]
+ //[MarshalAs (UnmanagedType.ByValArray,SizeConst=23)]
+ public struct XWindowAttributes
+ {
+ [FieldOffset (0)]
+ public int X;
+ [FieldOffset (4)]
+ public int Y;
+ [FieldOffset (8)]
+ public int Width;
+ [FieldOffset (12)]
+ public int Height;
+ [FieldOffset (88)]
+ public int foo;
+ }
+
+ public class Window
+ {
+ public IntPtr Handle;
+
+ public Window (IntPtr handle)
+ {
+ this.Handle = handle;
+ }
+
+ /*
+ public Screen Screen
+ {
+ get {
+ unsafe {
+ CompWindow *w = (CompWindow*)Handle;
+ Console.Error.WriteLine (w->Screen);
+ }
+ return null;
+ }
+ }
+ */
+
+ [DllImport("compiz")]
+ protected extern static WindowState constrainWindowState (WindowState state, WindowAction actions);
+
+ public static WindowState ConstrainState (WindowState state, WindowAction actions)
+ {
+ return constrainWindowState (state, actions);
+ }
+
+ [DllImport("compiz")]
+ protected extern static WindowType getWindowType (IntPtr display, uint id);
+
+ public WindowType WindowType
+ {
+ get {
+ return getWindowType (IntPtr.Zero, 0);
+ }
+ }
+
+ [DllImport("compiz")]
+ protected extern static MwmDecor getMwmDecor (IntPtr display, uint id);
+
+ public MwmDecor MwmDecor
+ {
+ get {
+ return getMwmDecor (IntPtr.Zero, 0);
+ }
+ }
+
+ [DllImport("compiz")]
+ protected extern static WindowProtocol getProtocols (IntPtr display, uint id);
+
+ public WindowProtocol Protocols
+ {
+ get {
+ return getProtocols (IntPtr.Zero, 0);
+ }
+ }
+
+
+
+ [DllImport("compiz")]
+ protected extern static uint getClientLeader (IntPtr w);
+
+ public uint ClientLeader ()
+ {
+ return getClientLeader (Handle);
+ }
+
+
+ [DllImport("compiz")]
+ protected extern static WmState getWmState (IntPtr display, uint id);
+
+ [DllImport("compiz")]
+ protected extern static void setWmState (IntPtr display, WmState state, uint id);
+
+ public WmState State
+ {
+ get {
+ return getWmState (IntPtr.Zero, 0);
+ } set {
+ setWmState (IntPtr.Zero, value, 0);
+ }
+ }
+
+ [DllImport("compiz")]
+ protected extern static void setWindowFrameExtents (IntPtr w, ref WindowExtents input, ref WindowExtents output);
+
+ public void SetFrameExtents (ref WindowExtents input, ref WindowExtents output)
+ {
+ setWindowFrameExtents (Handle, ref input, ref output);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void mapWindow (IntPtr w);
+
+ public void Map ()
+ {
+ mapWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void unmapWindow (IntPtr w);
+
+ public void Unmap ()
+ {
+ unmapWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void bindWindow (IntPtr w);
+
+ public void Bind ()
+ {
+ bindWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void releaseWindow (IntPtr w);
+
+ public void Release ()
+ {
+ releaseWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void moveWindow (IntPtr w, int dx, int dy, bool damage, bool immediate);
+
+ public void Move (int dx, int dy, bool damage, bool immediate)
+ {
+ moveWindow (Handle, dx, dy, damage, immediate);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void syncWindowPosition (IntPtr w);
+
+ public void SyncPosition ()
+ {
+ syncWindowPosition (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void sendSyncRequest (IntPtr w);
+
+ public void SendSyncRequest ()
+ {
+ sendSyncRequest (Handle);
+ }
+
+
+
+ [DllImport("compiz")]
+ protected extern static void activateWindow (IntPtr w);
+
+ public void Activate ()
+ {
+ activateWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void closeWindow (IntPtr w, int serverTime);
+
+ public void Close (int serverTime)
+ {
+ closeWindow (Handle, serverTime);
+ }
+
+ [DllImport("compiz")]
+ protected extern static bool focusWindow (IntPtr w);
+
+ public bool Focus ()
+ {
+ return focusWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void hideWindow (IntPtr w);
+
+ public void Hide ()
+ {
+ hideWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void showWindow (IntPtr w);
+
+ public void Show ()
+ {
+ showWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void minimizeWindow (IntPtr w);
+
+ public void Minimize ()
+ {
+ minimizeWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void unminimizeWindow (IntPtr w);
+
+ public void Unminimize ()
+ {
+ unminimizeWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void maximizeWindow (IntPtr w);
+
+ public void Maximize ()
+ {
+ maximizeWindow (Handle);
+ }
+
+ //TODO: verify underlying type of time, make use of bool return
+ [DllImport("compiz")]
+ protected extern static bool getWindowUserTime (IntPtr w, out int time);
+
+ [DllImport("compiz")]
+ protected extern static void setWindowUserTime (IntPtr w, int time);
+
+ public int UserTime
+ {
+ get {
+ int ret;
+ getWindowUserTime (Handle, out ret);
+ return ret;
+ }
+ set {
+ setWindowUserTime (Handle, value);
+ }
+ }
+
+ [DllImport("compiz")]
+ protected extern static bool focusWindowOnMap (IntPtr w);
+
+ public bool FocusOnMap ()
+ {
+ return focusWindowOnMap (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void unredirectWindow (IntPtr w);
+
+ public void Unredirect ()
+ {
+ unredirectWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static void redirectWindow (IntPtr w);
+
+ public void Redirect ()
+ {
+ redirectWindow (Handle);
+ }
+
+ [DllImport("compiz")]
+ protected extern static int defaultViewportForWindow (IntPtr w);
+
+ public int DefaultViewport
+ {
+ get {
+ return defaultViewportForWindow (Handle);
+ }
+ }
+
+ public Icon GetIcon (int width, int height)
+ {
+ return null;
+ }
+
+ public unsafe void GetServerPosition (out int x, out int y)
+ {
+ CompWindow* win = (CompWindow*)Handle;
+
+ x = win->ServerX;
+ y = win->ServerY;
+ }
+
+ public unsafe void GetPosition (out int x, out int y)
+ {
+ CompWindow* win = (CompWindow*)Handle;
+
+ x = win->Attributes.X;
+ y = win->Attributes.Y;
+ }
+
+ public unsafe void GetSize (out int width, out int height)
+ {
+ CompWindow* win = (CompWindow*)Handle;
+
+ width = win->Attributes.Width;
+ height = win->Attributes.Height;
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct WindowExtents {
+ public int Left;
+ public int Right;
+ public int Top;
+ public int Bottom;
+ }
+
+ [Flags]
+ public enum WindowProtocol : uint
+ {
+ Delete = 1 << 0,
+ TakeFocus = 1 << 1,
+ Ping = 1 << 2,
+ SyncRequest = 1 << 3,
+ }
+
+ //TODO: friendly naming, confirm order
+ [Flags]
+ public enum WindowType : uint
+ {
+ Desktop = 1 << 0,
+ Dock = 1 << 1,
+ Toolbar = 1 << 2,
+ Menu = 1 << 3,
+ Utility = 1 << 4,
+ Splash = 1 << 5,
+ Dialog = 1 << 6,
+ ModalDialog = 1 << 7,
+ Normal = 1 << 8,
+ Fullscreen = 1 << 9,
+ Unknown = 1 << 10,
+ }
+
+ public delegate void WindowGrabNotifyHandler (IntPtr window, int x, int y, WindowState state, WindowGrab mask);
+
+ [Flags]
+ public enum WindowGrab : uint
+ {
+ Key = 1 << 0,
+ Button = 1 << 1,
+ Move = 1 << 2,
+ Resize = 1 << 3,
+ }
+
+ [Flags]
+ public enum WindowPaint : uint
+ {
+ Solid = 1 << 0,
+ Translucent = 1 << 1,
+ Transformed = 1 << 2,
+ OnTransformedScreen = 1 << 3,
+ }
+
+ [Flags]
+ public enum WindowAction : uint
+ {
+ Move = 1 << 0,
+ Resize = 1 << 1,
+ Stick = 1 << 2,
+ Minimize = 1 << 3,
+ MaximizeHorz = 1 << 4,
+ MaximizeVert = 1 << 5,
+ Fullscreen = 1 << 6,
+ Close = 1 << 7,
+ Shade = 1 << 8,
+ }
+
+ //check the backing type on this enum: (1L << 0)
+ [Flags]
+ public enum MwmDecor : uint
+ {
+ All = 1 << 0,
+ Border = 1 << 1,
+ Handle = 1 << 2,
+ Title = 1 << 3,
+ Menu = 1 << 4,
+ Minimize = 1 << 5,
+ Maximize = 1 << 6,
+ }
+
+ public enum WmState : int
+ {
+ SizeTopLeft,
+ SizeTop,
+ SizeTopRight,
+ SizeRight,
+ SizeBottomRight,
+ SizeBottom,
+ SizeBottomLeft,
+ SizeLeft,
+ Move,
+ SizeKeyboard,
+ MoveKeyboard,
+ }
+
+ [Flags]
+ public enum WindowState : uint
+ {
+ Modal = 1 << 0,
+ Sticky = 1 << 1,
+ MaximizedVert = 1 << 2,
+ MaximizedHorz = 1 << 3,
+ Shaded = 1 << 4,
+ SkipTaskbar = 1 << 5,
+ SkipPager = 1 << 6,
+ Hidden = 1 << 7,
+ Fullscreen = 1 << 8,
+ Above = 1 << 9,
+ Below = 1 << 10,
+ //compiz typo DemandsAttentation
+ DemandsAttention = 1 << 11,
+ DisplayModal = 1 << 12,
+ Maximized = MaximizedHorz | MaximizedVert,
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct WindowPaintAttrib
+ {
+ public ushort opacity;
+ public ushort brightness;
+ public ushort saturation;
+ public float xScale;
+ public float yScale;
+ }
+}