]> git.tdb.fi Git - geometrycompositor.git/blobdiff - source/main.c
Refresh the screen only when there's no events to process
[geometrycompositor.git] / source / main.c
index 21189b6b2c30cacae8a87801632ee3ba4a982725..3f788848c119c6b230185a3878652566dd7214fd 100644 (file)
@@ -5,6 +5,7 @@
 #include <X11/Xlib.h>
 #include <X11/extensions/Xcomposite.h>
 #include <X11/extensions/Xdamage.h>
+#include <X11/extensions/shape.h>
 #include <GL/gl.h>
 #include <GL/glx.h>
 
@@ -41,6 +42,7 @@ typedef struct CompositedScreen
        CompositedWindow *windows;
        unsigned nwindows;
        unsigned windows_capacity;
+       int dirty;
 } CompositedScreen;
 
 typedef struct Compositor
@@ -52,6 +54,7 @@ typedef struct Compositor
        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
        PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
        PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
+       int dirty;
 } Compositor;
 
 static const char *vshader =
@@ -302,6 +305,18 @@ CompositedScreen *find_screen_by_root(Compositor *compositor, Window root)
        return NULL;
 }
 
+CompositedScreen *find_screen_by_window(Compositor *compositor, Window w)
+{
+       unsigned i, j;
+
+       for(i=0; i<compositor->nscreens; ++i)
+               for(j=0; j<compositor->screens[i].nwindows; ++j)
+                       if(compositor->screens[i].windows[j].window==w)
+                               return &compositor->screens[i];
+
+       return NULL;
+}
+
 int initialize_screen(Compositor *compositor, unsigned number)
 {
        CompositedScreen *screen;
@@ -328,6 +343,7 @@ int initialize_screen(Compositor *compositor, unsigned number)
        XSelectInput(compositor->display, screen->root, SubstructureNotifyMask);
        screen->overlay = XCompositeGetOverlayWindow(compositor->display, screen->root);
        XGetGeometry(compositor->display, screen->overlay, &dummy_root, &x, &y, &screen->width, &screen->height, &border, &depth);
+       XShapeCombineRectangles(compositor->display, screen->overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
 
        if(!initialize_gl(compositor, screen))
                return 0;
@@ -382,6 +398,13 @@ int initialize_compositor(Compositor *compositor)
        else if(major_ver<1)
                return with_error("XDamage 1.0 or later is required");
 
+       if(!XShapeQueryExtension(compositor->display, &event_base, &error_base))
+               return with_error("XShape is required but was not found");
+       else if(!XShapeQueryVersion(compositor->display, &major_ver, &minor_ver))
+               return with_error("Cannot determine XShape version");
+       else if(major_ver<1 || (major_ver==1 && minor_ver<1))
+               return with_error("XShape 1.1 or later is required");
+
        compositor->glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((unsigned char *)"glXCreateContextAttribsARB");
        compositor->glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXBindTexImageEXT");
        compositor->glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)glXGetProcAddress((unsigned char *)"glXReleaseTexImageEXT");
@@ -447,10 +470,27 @@ void process_unmap_event(Compositor *compositor, XUnmapEvent *event)
                window->map_state = IsUnviewable;
 }
 
-void process_event(Compositor *compositor)
+void process_damage_event(Compositor *compositor, XDamageNotifyEvent *event)
+{
+       CompositedScreen *screen = find_screen_by_window(compositor, event->drawable);
+       if(!screen)
+               return;
+
+       screen->dirty = 1;
+       compositor->dirty = 1;
+}
+
+int process_event(Compositor *compositor)
 {
        XEvent event;
-       XNextEvent(compositor->display, &event);
+       if(compositor->dirty)
+       {
+               if(!XCheckMaskEvent(compositor->display, -1, &event))
+                       return 0;
+       }
+       else
+               XNextEvent(compositor->display, &event);
+
        switch(event.type)
        {
        case CreateNotify:
@@ -463,9 +503,13 @@ void process_event(Compositor *compositor)
                process_unmap_event(compositor, &event.xunmap);
                break;
        default:
-               if(event.type!=compositor->damage_event+XDamageNotify)
+               if(event.type==compositor->damage_event+XDamageNotify)
+                       process_damage_event(compositor, (XDamageNotifyEvent *)&event);
+               else
                        printf("Event %d\n", event.type);
        }
+
+       return 1;
 }
 
 void refresh_screens(Compositor *compositor)
@@ -499,7 +543,11 @@ void refresh_screens(Compositor *compositor)
                }
                XUngrabServer(compositor->display);
                glXSwapBuffers(compositor->display, screen->glx_window);
+
+               screen->dirty = 0;
        }
+
+       compositor->dirty = 0;
 }
 
 int main()
@@ -511,8 +559,8 @@ int main()
 
        while(1)
        {
-               process_event(&compositor);
-               refresh_screens(&compositor);
+               if(!process_event(&compositor))
+                       refresh_screens(&compositor);
        }
 
        shutdown_compositor(&compositor);