From b79d8dae9a62206eb425a505b660c9dabbfefb27 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <fourdan.olivier@wanadoo.fr>
Date: Sun, 9 Dec 2007 11:22:37 +0000
Subject: [PATCH] Add support for overlays from Composite extension version 0.3

(Old svn revision: 26452)
---
 defaults/defaults            |   4 +-
 mcs-plugin/wmtweaks_plugin.c |   2 +-
 src/compositor.c             | 109 ++++++++++++++++++++++++++++-------
 src/display.h                |  15 ++++-
 src/frame.c                  |   4 --
 src/screen.h                 |   7 +++
 6 files changed, 113 insertions(+), 28 deletions(-)

diff --git a/defaults/defaults b/defaults/defaults
index 7e3a54ed2..5393b4c88 100644
--- a/defaults/defaults
+++ b/defaults/defaults
@@ -2,7 +2,7 @@ activate_action=bring
 borderless_maximize=true
 box_move=false
 box_resize=false
-button_layout=O|HMC
+button_layout=OT|SHMC
 button_offset=0
 button_spacing=0
 click_to_focus=true
@@ -52,7 +52,7 @@ title_shadow_inactive=false
 title_vertical_offset_active=0
 title_vertical_offset_inactive=0
 toggle_workspaces=false
-unredirect_overlays=false
+unredirect_overlays=true
 use_compositing=false
 workspace_count=4
 wrap_cycle=true
diff --git a/mcs-plugin/wmtweaks_plugin.c b/mcs-plugin/wmtweaks_plugin.c
index f2b0bed7f..be781d1fe 100644
--- a/mcs-plugin/wmtweaks_plugin.c
+++ b/mcs-plugin/wmtweaks_plugin.c
@@ -76,7 +76,7 @@ static gboolean restore_on_move = TRUE;
 static gboolean scroll_workspaces = TRUE;
 static gboolean snap_resist = FALSE;
 static gboolean toggle_workspaces = FALSE;
-static gboolean unredirect_overlays = FALSE;
+static gboolean unredirect_overlays = TRUE;
 static gboolean use_compositing = FALSE;
 static gboolean wrap_layout = FALSE;
 static gboolean wrap_cycle = FALSE;
diff --git a/src/compositor.c b/src/compositor.c
index 4e67d9757..b80096ed4 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -73,7 +73,7 @@
 #define WIN_IS_DOCK(cw)                 (WIN_HAS_CLIENT(cw) && (cw->c->type & WINDOW_DOCK))
 #define WIN_IS_OVERRIDE(cw)             (cw->attr.override_redirect)
 #define WIN_IS_ARGB(cw)                 (cw->argb)
-#define WIN_IS_OPAQUE(cw)               (((cw->opacity == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw)) || (cw->screen_info->overlays))
+#define WIN_IS_OPAQUE(cw)               ((cw->opacity == NET_WM_OPAQUE) && !WIN_IS_ARGB(cw))
 #define WIN_IS_NATIVE_OPAQUE(cw)        ((cw->native_opacity) && !WIN_IS_ARGB(cw))
 #define WIN_IS_FULLSCREEN(cw)           ((cw->attr.x <= 0) && \
                                            (cw->attr.y <= 0) && \
@@ -550,7 +550,7 @@ shadow_picture (ScreenInfo *screen_info, gdouble opacity,
         return (None);
     }
 
-    shadowPixmap = XCreatePixmap (display_info->dpy, screen_info->xroot,
+    shadowPixmap = XCreatePixmap (display_info->dpy, screen_info->output,
                                 shadowImage->width, shadowImage->height, 8);
     if (shadowPixmap == None)
     {
@@ -603,7 +603,7 @@ solid_picture (ScreenInfo *screen_info, gboolean argb,
     g_return_val_if_fail (render_format != NULL , None);
 
     pixmap = XCreatePixmap (display_info->dpy,
-                            screen_info->xroot, 1, 1, argb ? 32 : 8);
+                            screen_info->output, 1, 1, argb ? 32 : 8);
     g_return_val_if_fail (pixmap != None, None);
 
     pa.repeat = TRUE;
@@ -815,7 +815,7 @@ root_tile (ScreenInfo *screen_info)
 #endif
     if (!pixmap)
     {
-        pixmap = XCreatePixmap (dpy, screen_info->xroot, 1, 1,
+        pixmap = XCreatePixmap (dpy, screen_info->output, 1, 1,
                                 DefaultDepth (dpy, screen_info->screen));
         g_return_val_if_fail (pixmap != None, None);
         fill = TRUE;
@@ -867,7 +867,7 @@ create_root_buffer (ScreenInfo *screen_info)
     g_return_val_if_fail (format != NULL, None);
 
     rootPixmap = XCreatePixmap (display_info->dpy,
-                                screen_info->xroot,
+                                screen_info->output,
                                 screen_width, screen_height, depth);
     g_return_val_if_fail (rootPixmap != None, None);
 
@@ -920,15 +920,13 @@ win_extents (CWindow *cw)
 
     /*
        We apply a shadow to the window if:
-       - There is no overlay (ie unredirected windows)
        - It's a window with a frame and the user asked for shadows under regular
          windows,
        - it's an override redirect window that is not shaped, not an argb and
          the user asked for shadows on so called "popup" windows.
      */
 
-    if (!(screen_info->overlays) &&
-         ((screen_info->params->show_popup_shadow &&
+    if ((screen_info->params->show_popup_shadow &&
               WIN_IS_OVERRIDE(cw) &&
               !(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw))) ||
           (screen_info->params->show_frame_shadow &&
@@ -940,7 +938,7 @@ win_extents (CWindow *cw)
               WIN_IS_DOCK(cw) &&
               !WIN_NO_SHADOW(cw) &&
               !WIN_IS_OVERRIDE(cw) &&
-              (!(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw))))))
+              (!(WIN_IS_ARGB(cw) || WIN_IS_SHAPED(cw)))))
     {
         XRectangle sr;
 
@@ -1233,7 +1231,6 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
     gint screen_width;
     gint screen_height;
     gint screen_number;
-    Window xroot;
     CWindow *cw;
 
     TRACE ("entering paint_all");
@@ -1244,7 +1241,6 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
     screen_width = screen_info->width;
     screen_height = screen_info->height;
     screen_number = screen_info->screen;
-    xroot = screen_info->xroot;
 
     /* Create root buffer if not done yet */
     if (screen_info->rootBuffer == None)
@@ -1762,6 +1758,7 @@ static void
 map_win (CWindow *cw)
 {
     ScreenInfo *screen_info;
+    DisplayInfo *display_info;
 
     g_return_if_fail (cw != NULL);
     TRACE ("entering map_win 0x%lx", cw->id);
@@ -1770,9 +1767,17 @@ map_win (CWindow *cw)
     cw->damaged = FALSE;
 
     screen_info = cw->screen_info;
+    display_info = screen_info->display_info;
+
     if (!WIN_IS_REDIRECTED(cw))
     {
         screen_info->overlays++;
+#if HAVE_OVERLAYS
+        if ((screen_info->overlays == 1) && (display_info->have_overlays))
+        {
+            XUnmapWindow (myScreenGetXDisplay (screen_info), screen_info->overlay);
+        }
+#endif /* HAVE_OVERLAYS */
         TRACE ("Mapping unredirected window 0x%lx, overlays increased to %i", cw->id, screen_info->overlays);
         return;
     }
@@ -1804,15 +1809,24 @@ static void
 unmap_win (CWindow *cw)
 {
     ScreenInfo *screen_info;
+    DisplayInfo *display_info;
 
     g_return_if_fail (cw != NULL);
     TRACE ("entering unmap_win 0x%lx", cw->id);
 
     screen_info = cw->screen_info;
+    display_info = screen_info->display_info;
+
     if (!WIN_IS_REDIRECTED(cw) && (screen_info->overlays > 0))
     {
         screen_info->overlays--;
         TRACE ("Unmapped window 0x%lx, overlays decreased to %i", cw->id, screen_info->overlays);
+#if HAVE_OVERLAYS
+        if ((screen_info->overlays == 0) && (display_info->have_overlays))
+        {
+            XMapWindow (myScreenGetXDisplay (screen_info), screen_info->overlay);
+        }
+#endif /* HAVE_OVERLAYS */
     }
 
     if (!screen_info->overlays)
@@ -2191,7 +2205,7 @@ compositorHandlePropertyNotify (DisplayInfo *display_info, XPropertyEvent *ev)
             ScreenInfo *screen_info = myDisplayGetScreenFromRoot (display_info, ev->window);
             if ((screen_info) && (screen_info->rootTile))
             {
-                XClearArea (display_info->dpy, screen_info->xroot, 0, 0, 0, 0, TRUE);
+                XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
                 XRenderFreePicture (display_info->dpy, screen_info->rootTile);
                 screen_info->rootTile = None;
                 add_repair (display_info);
@@ -2657,9 +2671,10 @@ void
 compositorInitDisplay (DisplayInfo *display_info)
 {
 #ifdef HAVE_COMPOSITOR
-#if HAVE_NAME_WINDOW_PIXMAP
     int composite_major, composite_minor;
-#endif
+
+    composite_major = 0;
+    composite_minor = 0;
 
     if (!XCompositeQueryExtension (display_info->dpy,
                                 &display_info->composite_event_base,
@@ -2673,9 +2688,11 @@ compositorInitDisplay (DisplayInfo *display_info)
     else
     {
         display_info->have_composite = TRUE;
+        XCompositeQueryVersion (display_info->dpy, &composite_major, &composite_minor);
 #if DEBUG
         g_print ("composite event base: %i\n", display_info->composite_event_base);
         g_print ("composite error base: %i\n", display_info->composite_error_base);
+        g_print ("composite version: %i.%i\n", composite_major, composite_minor);
 #endif
     }
 
@@ -2712,7 +2729,7 @@ compositorInitDisplay (DisplayInfo *display_info)
 #if DEBUG
         g_print ("fixes event base: %i\n", display_info->fixes_event_base);
         g_print ("fixes error base: %i\n", display_info->fixes_error_base);
-#endif
+#endif /* DEBUG */
     }
 
     display_info->compositor_idle_id = 0;
@@ -2730,11 +2747,16 @@ compositorInitDisplay (DisplayInfo *display_info)
 
     display_info->composite_mode = 0;
 #if HAVE_NAME_WINDOW_PIXMAP
-    XCompositeQueryVersion (display_info->dpy, &composite_major, &composite_minor);
     display_info->have_name_window_pixmap = ((composite_major > 0) || (composite_minor >= 2));
-#else
+#else  /* HAVE_NAME_WINDOW_PIXMAP */
     display_info->have_name_window_pixmap = FALSE;
-#endif
+#endif /* HAVE_NAME_WINDOW_PIXMAP */
+
+#if HAVE_OVERLAYS
+    display_info->have_overlays = ((composite_major > 0) || (composite_minor >= 3));
+#else  /* HAVE_OVERLAYS */
+    display_info->have_overlays = FALSE;
+#endif /* HAVE_OVERLAYS */
 
 #else /* HAVE_COMPOSITOR */
     display_info->enable_compositor = FALSE;
@@ -2799,8 +2821,43 @@ compositorManageScreen (ScreenInfo *screen_info)
         return FALSE;
     }
 
+    screen_info->output = screen_info->xroot;
+#if HAVE_OVERLAYS
+    if (display_info->have_overlays)
+    {
+        screen_info->overlay = XCompositeGetOverlayWindow (display_info->dpy, screen_info->xroot);
+        if (screen_info->overlay != None)
+        {
+#if USE_CHILD_OVERLAY
+            XSetWindowAttributes attributes;
+
+            attributes.override_redirect = TRUE;
+            screen_info->root_overlay = XCreateWindow (display_info->dpy, screen_info->overlay,
+                                                       0, 0, screen_info->width, screen_info->height, 0, 0,
+                                                       InputOutput, CopyFromParent, CWOverrideRedirect, &attributes);
+            XMapWindow (display_info->dpy, screen_info->root_overlay);
+            XRaiseWindow (display_info->dpy, screen_info->overlay);
+            XShapeCombineRectangles (display_info->dpy, screen_info->root_overlay,
+                                     ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
+            screen_info->output = screen_info->root_overlay;
+#else
+            screen_info->output = screen_info->overlay;
+#endif /* USE_CHILD_OVERLAY */
+            XShapeCombineRectangles (display_info->dpy, screen_info->overlay,
+                                     ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted);
+            TRACE ("Overlay enabled");
+        }
+        else
+        {
+            /* Something is wrong with overlay support */
+            TRACE ("Cannot get root window overlay, overlay support disabled");
+            display_info->have_overlays = FALSE;
+        }
+    }
+#endif /* HAVE_OVERLAYS */
+
     pa.subwindow_mode = IncludeInferiors;
-    screen_info->rootPicture = XRenderCreatePicture (display_info->dpy, screen_info->xroot,
+    screen_info->rootPicture = XRenderCreatePicture (display_info->dpy, screen_info->output,
                                                      visual_format, CPSubwindowMode, &pa);
 
     if (screen_info->rootPicture == None)
@@ -2826,7 +2883,7 @@ compositorManageScreen (ScreenInfo *screen_info)
     screen_info->compositor_active = TRUE;
     screen_info->overlays = 0;
 
-    XClearArea (display_info->dpy, screen_info->xroot, 0, 0, 0, 0, TRUE);
+    XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
     compositorSetCMSelection (screen_info, screen_info->xfwm4_win);
     TRACE ("Manual compositing enabled");
 
@@ -2871,6 +2928,18 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
     screen_info->cwindows = NULL;
     TRACE ("Compositor: removed %i window(s) remaining", i);
 
+#if HAVE_OVERLAYS
+    if (display_info->have_overlays)
+    {
+#if USE_CHILD_OVERLAY
+        XDestroyWindow (display_info->dpy, screen_info->root_overlay);
+        screen_info->root_overlay = None;
+#endif /* USE_CHILD_OVERLAY */
+        XCompositeReleaseOverlayWindow (display_info->dpy, screen_info->overlay);
+        screen_info->overlay = None;
+    }
+#endif /* HAVE_OVERLAYS */
+
     if (screen_info->rootPicture)
     {
         XRenderFreePicture (display_info->dpy, screen_info->rootPicture);
diff --git a/src/display.h b/src/display.h
index 8ff460b7c..7d752c913 100644
--- a/src/display.h
+++ b/src/display.h
@@ -31,6 +31,10 @@
 #include <X11/cursorfont.h>
 #include <X11/extensions/shape.h>
 
+#ifndef ShapeInput
+#define ShapeInput 2
+#endif
+
 #ifdef HAVE_RANDR
 #include <X11/extensions/Xrandr.h>
 #endif /* HAVE_RANDR */
@@ -48,6 +52,11 @@
 #define HAVE_NAME_WINDOW_PIXMAP 1
 #endif /* HAVE_NAME_WINDOW_PIXMAP */
 #endif /* COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2 */
+#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 3
+#ifndef HAVE_OVERLAYS
+#define HAVE_OVERLAYS 1
+#endif /* HAVE_OVERLAYS */
+#endif /* COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 3 */
 #endif /* HAVE_COMPOSITOR */
 
 #include <gtk/gtk.h>
@@ -334,6 +343,10 @@ struct _DisplayInfo
     gboolean have_name_window_pixmap;
 #endif /* HAVE_NAME_WINDOW_PIXMAP */
 
+#if HAVE_OVERLAYS
+    gboolean have_overlays;
+#endif /* HAVE_OVERLAYS */
+
 #endif /* HAVE_COMPOSITOR */
 };
 
@@ -384,7 +397,7 @@ Time                     myDisplayGetTime                       (DisplayInfo *,
 Time                     myDisplayGetLastUserTime               (DisplayInfo *);
 void                     myDisplaySetLastUserTime               (DisplayInfo *,
                                                                  Time);
-void                     myDisplayUpdateLastUserTime            (DisplayInfo *, 
+void                     myDisplayUpdateLastUserTime            (DisplayInfo *,
                                                                  Time);
 gboolean                 myDisplayTestXrender                   (DisplayInfo *,
                                                                  gdouble);
diff --git a/src/frame.c b/src/frame.c
index 1990d5111..6336eaba4 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -37,10 +37,6 @@
 #include "frame.h"
 #include "compositor.h"
 
-#ifndef ShapeInput
-#define ShapeInput 2
-#endif
-
 typedef struct
 {
     xfwmPixmap pm_title;
diff --git a/src/screen.h b/src/screen.h
index 5b5494254..41e51185f 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -134,7 +134,14 @@ struct _ScreenInfo
 #endif
 
 #ifdef HAVE_COMPOSITOR
+#if HAVE_OVERLAYS
+    Window overlay;
+#if USE_CHILD_OVERLAY
+    Window root_overlay;
+#endif /* USE_CHILD_OVERLAY */
+#endif
     GList *cwindows;
+    Window output;
 
     gaussian_conv *gaussianMap;
     gint gaussianSize;
-- 
GitLab