From ff404156032b2ed8f7fdd95b091aa2df169b5219 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <fourdan.olivier@wanadoo.fr>
Date: Tue, 5 Oct 2004 21:37:29 +0000
Subject: [PATCH] Fix XShape bug, now gkrellm and other shaped windows work.

(Old svn revision: 12035)
---
 src/client.c     |  8 +++--
 src/compositor.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/compositor.h |  3 +-
 src/events.c     |  3 +-
 4 files changed, 94 insertions(+), 5 deletions(-)

diff --git a/src/client.c b/src/client.c
index b886e38b9..c52f72af4 100644
--- a/src/client.c
+++ b/src/client.c
@@ -1359,6 +1359,7 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture)
     XWindowChanges wc;
     XSetWindowAttributes attributes;
     Client *c = NULL;
+    gboolean shaped;
     unsigned long valuemask;
     int i;
 
@@ -1457,8 +1458,9 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture)
     c->fullscreen_old_height = c->height;
     c->border_width = attr.border_width;
     c->cmap = attr.colormap;
-    
-    if (clientCheckShape(c))
+
+    shaped = clientCheckShape(c);
+    if (shaped)
     {
         FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_HAS_BORDER);
     }
@@ -1593,7 +1595,7 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture)
     valuemask = CWEventMask;
     attributes.event_mask = (CLIENT_EVENT_MASK);
     XChangeWindowAttributes (display_info->dpy, c->window, valuemask, &attributes);
-    if (display_info->shape)
+    if ((shaped) && (display_info->shape))
     {
         XShapeSelectInput (display_info->dpy, c->window, ShapeNotifyMask);
     }
diff --git a/src/compositor.c b/src/compositor.c
index 64ad12393..cb2cdefc8 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1473,6 +1473,58 @@ restack_win (CWindow *cw, Window above)
     }
 }
 
+void
+resize_win (CWindow *cw, gint width, gint height)
+{
+    XserverRegion damage = None;
+
+    g_return_if_fail (cw != NULL);
+    TRACE ("entering resize_win");
+    
+    damage = XFixesCreateRegion (myScreenGetXDisplay (cw->screen_info), NULL, 0);
+    if ((damage != None) && (cw->extents != None))
+    {
+        XFixesCopyRegion (myScreenGetXDisplay (cw->screen_info), damage, cw->extents);
+    }
+
+    if ((cw->attr.width != width) || (cw->attr.height != height))
+    {
+#if HAVE_NAME_WINDOW_PIXMAP
+        if (cw->name_window_pixmap)
+        {
+            XFreePixmap (myScreenGetXDisplay (cw->screen_info), cw->name_window_pixmap);
+            cw->name_window_pixmap = None;
+        }
+#endif
+        if (cw->picture)
+        {
+            XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->picture);
+            cw->picture = None;
+        }
+    
+        if (cw->shadow)
+        {
+            XRenderFreePicture (myScreenGetXDisplay (cw->screen_info), cw->shadow);
+            cw->shadow = None;
+        }
+    }
+    cw->attr.width = width;
+    cw->attr.height = height;
+
+    if (damage)
+    {
+        XserverRegion extents = win_extents (cw);
+        if (extents)
+        {
+            XFixesUnionRegion (myScreenGetXDisplay (cw->screen_info), damage, damage, extents);
+            XFixesDestroyRegion (myScreenGetXDisplay (cw->screen_info), extents);
+            add_damage (cw->screen_info, damage);
+        }
+    }
+    cw->screen_info->clipChanged = TRUE;
+    repair_screen (cw->screen_info);
+}
+
 static void
 destroy_win (ScreenInfo *screen_info, Window id, gboolean gone)
 {
@@ -1659,6 +1711,15 @@ compositorHandleConfigureNotify (DisplayInfo *display_info, XConfigureEvent *ev)
         return;
     }
     
+    if ((cw->attr.x == ev->x) && (cw->attr.y == ev->y) &&
+        (cw->attr.width == ev->width) && (cw->attr.height == ev->height) &&
+        (cw->attr.border_width == ev->border_width))
+    {
+        /* Nothing has changed, just adjust stack */
+        restack_win (cw, ev->above);
+        return;
+    }
+
     damage = XFixesCreateRegion (display_info->dpy, NULL, 0);
     if ((damage != None) && (cw->extents != None))
     {
@@ -2123,3 +2184,27 @@ compositorDamageWindow (DisplayInfo *display_info, Window id)
     }
 #endif /* HAVE_COMPOSITOR */
 }
+
+void
+compositorResizeWindow (DisplayInfo *display_info, Window id, gint new_width, gint new_height)
+{
+#ifdef HAVE_COMPOSITOR
+    CWindow *cw;
+    
+    g_return_if_fail (display_info != NULL);
+    g_return_if_fail (id != None);
+    TRACE ("entering compositorResizeWindow: 0x%lx", id);
+    
+    if (!(display_info->enable_compositor))
+    {
+        TRACE ("compositor disabled");
+        return;
+    }
+
+    cw = find_cwindow_in_display (display_info, id);
+    if (cw)
+    {
+        resize_win (cw, new_width, new_height);
+    }
+#endif /* HAVE_COMPOSITOR */
+}
diff --git a/src/compositor.h b/src/compositor.h
index 0a7d2a39c..9f507dfd7 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -36,7 +36,6 @@ void compositorWindowMap (DisplayInfo *, Window);
 void compositorWindowUnmap (DisplayInfo *, Window);
 void compositorAddWindow (DisplayInfo *, Window, Client *c);
 void compositorRemoveWindow (DisplayInfo *, Window);
-void compositorWindowSetOpacity (DisplayInfo *, Window, guint);
 
 void compositorHandleEvent (DisplayInfo *, XEvent *);
 void compositorInitDisplay (DisplayInfo *);
@@ -44,6 +43,8 @@ void compositorInitDisplay (DisplayInfo *);
 void compositorManageScreen (ScreenInfo *);
 void compositorUnmanageScreen (ScreenInfo *);
 
+void compositorWindowSetOpacity (DisplayInfo *, Window, guint);
 void compositorDamageWindow (DisplayInfo *, Window);
+void compositorResizeWindow (DisplayInfo *, Window, gint, gint);
 
 #endif /* INC_COMPOSITOR_H */
diff --git a/src/events.c b/src/events.c
index bd5338d7f..941a648b8 100644
--- a/src/events.c
+++ b/src/events.c
@@ -1775,10 +1775,11 @@ handleShape (DisplayInfo *display_info, XShapeEvent * ev)
     if (c)
     {
         frameDraw (c, FALSE, TRUE);
+        compositorResizeWindow (display_info, c->frame, ev->width + ev->x, ev->height + ev->y);
     }
     else
     {
-        compositorDamageWindow (display_info, ev->window);
+        compositorResizeWindow (display_info, ev->window, ev->width + ev->x, ev->height + ev->y);
     }
 }
 
-- 
GitLab