Allow ObWindow subclasses to redirect a child window of the top-level window
authorDana Jansens <danakj@orodu.net>
Fri, 25 Jun 2010 11:04:18 +0000 (13:04 +0200)
committerDana Jansens <danakj@orodu.net>
Sat, 26 Jun 2010 23:30:51 +0000 (01:30 +0200)
This means ObClient redirects the client window itself, rather than the
 parenting frame window.
Added a "toparea" to the ObWindow that tracks the top-level window's area,
 so the "area" can track the redirected window's area inside the top-level
 window.
Added window_set_top_area() that must be called before window_set_abstract()
 for subclasses of ObWindow.  This sets the initial position/size/border of
 ObWindow's top-most window, that will be given in window_set_abstract().
 After that, it can track any changes made to the window's geometry on its
 own.

Decor is now invisible since it needs to be drawn by the Compositing code
 explicitly.

13 files changed:
openbox/client.c
openbox/composite.c
openbox/dock.c
openbox/event.c
openbox/focus_cycle_indicator.c
openbox/focus_cycle_popup.c
openbox/frame.c
openbox/framerender.c
openbox/menuframe.c
openbox/popup.c
openbox/unmanaged.c
openbox/window.c
openbox/window.h

index de3e51242f877ba33181bf79e21ccf775f090be3..37e326f2c17dccd30cd1bf717ab2d1f0a77b95dc 100644 (file)
@@ -257,8 +257,11 @@ void client_manage(Window window, ObPrompt *prompt)
        onto the frame */
     client_update_opacity(self);
 
+    window_set_top_area(CLIENT_AS_WINDOW(self),
+                        &self->area, self->border_width);
     window_set_abstract(CLIENT_AS_WINDOW(self),
                         &self->frame->window, /* top level window */
+                        &self->window,        /* composite redir window */
                         &self->layer,         /* stacking layer */
                         &self->frame->depth,  /* window depth */
                         &self->alpha);        /* opacity */
@@ -540,6 +543,7 @@ ObClient *client_fake_manage(Window window)
 
     window_set_abstract(CLIENT_AS_WINDOW(self),
                         &self->frame->window, /* top level window */
+                        &self->window,        /* composite redir window */
                         &self->layer,         /* stacking layer */
                         &self->frame->depth,  /* window depth */
                         NULL);                /* opacity */
@@ -1201,7 +1205,7 @@ static void client_get_area(ObClient *self)
     POINT_SET(self->root_pos, wattrib.x, wattrib.y);
     self->border_width = wattrib.border_width;
 
-    ob_debug("client area: %d %d  %d %d  bw %d", wattrib.x, wattrib.y,
+    ob_debug("client area: %d,%d  %dx%d  bw %d", wattrib.x, wattrib.y,
              wattrib.width, wattrib.height, wattrib.border_width);
 }
 
index 3d517866072ac0ed295b5229177bf07dca53f662..877ed20c91b6562d4dce6b99a7149c60b7436066 100644 (file)
@@ -435,7 +435,7 @@ static gboolean composite(gpointer data)
         if (win->type == OB_WINDOW_CLASS_PROMPT)
             continue;
 
-        if (!win->mapped)
+        if (!win->mapped || !win->is_redir)
             continue;
 
         if (win->type == OB_WINDOW_CLASS_CLIENT) {
@@ -449,12 +449,13 @@ static gboolean composite(gpointer data)
         if (win->pixmap == None) {
             obt_display_ignore_errors(TRUE);
             win->pixmap = XCompositeNameWindowPixmap(obt_display,
-                                                     window_top(win));
+                                                     window_redir(win));
             obt_display_ignore_errors(FALSE);
             if (obt_display_error_occured) {
                 ob_debug_type(OB_DEBUG_CM,
                               "Error in XCompositeNameWindowPixmap for "
-                              "window 0x%x", window_top(win));
+                              "window 0x%x of 0x%x",
+                              window_redir(win), window_top(win));
                 /* it can error but still return an ID, which will cause an
                    error to occur if you try to free it etc */
                 if (win->pixmap) {
@@ -510,10 +511,10 @@ static gboolean composite(gpointer data)
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-        x = win->area.x;
-        y = win->area.y;
-        w = win->area.width + win->border * 2;
-        h = win->area.height + win->border * 2;
+        x = win->toparea.x + win->area.x;
+        y = win->toparea.y + win->area.y;
+        w = win->area.width;
+        h = win->area.height;
 
         if (win->alpha && *win->alpha < 0xffffffff)
             glColor4ui(0xffffffff, 0xffffffff, 0xffffffff, *win->alpha);
@@ -562,18 +563,20 @@ static void composite_window_redir(ObWindow *w)
 {
     if (!composite_enabled()) return;
 
-    if (w->redir) return;
-    XCompositeRedirectWindow(obt_display, window_top(w),
+    if (w->is_redir) return;
+
+    XCompositeRedirectWindow(obt_display, window_redir(w),
                              CompositeRedirectManual);
-    w->redir = TRUE;
+    w->is_redir = TRUE;
 }
 
 static void composite_window_unredir(ObWindow *w)
 {
     if (!w->redir) return;
-    XCompositeUnredirectWindow(obt_display, window_top(w),
+
+    XCompositeUnredirectWindow(obt_display, window_redir(w),
                                CompositeRedirectManual);
-    w->redir = FALSE;
+    w->is_redir = FALSE;
 }
 
 void composite_window_setup(ObWindow *w)
@@ -586,6 +589,7 @@ void composite_window_setup(ObWindow *w)
 
     w->damage = XDamageCreate(obt_display, window_top(w),
                               XDamageReportNonEmpty);
+    glGenTextures(1, &w->texture);
 
     composite_window_redir(w);
 }
@@ -599,7 +603,6 @@ void composite_window_cleanup(ObWindow *w)
 #endif
 
     composite_window_unredir(w);
-
     composite_window_invalid(w);
     if (w->damage) {
         XDamageDestroy(obt_display, w->damage);
index 606a8b7346b027e132aa9c83438e7797a7416a86..18fe0058c496da33ffeaabd14e4009757634409c 100644 (file)
@@ -58,6 +58,8 @@ static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
 void dock_startup(gboolean reconfig)
 {
     XSetWindowAttributes attrib;
+    const Rect r = {0, 0, 1, 1};
+    const gint b = 0;
 
     if (reconfig) {
         GList *it;
@@ -94,7 +96,7 @@ void dock_startup(gboolean reconfig)
     attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK;
     dock->depth = RrDepth(ob_rr_inst);
     dock->frame = XCreateWindow(obt_display, obt_root(ob_screen),
-                                0, 0, 1, 1, 0,
+                                r.x, r.y, r.width, r.height, b,
                                 dock->depth, InputOutput,
                                 RrVisual(ob_rr_inst),
                                 CWOverrideRedirect | CWEventMask |
@@ -109,8 +111,10 @@ void dock_startup(gboolean reconfig)
     OBT_PROP_SET32(dock->frame, NET_WM_WINDOW_TYPE, ATOM,
                    OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DOCK));
 
+    window_set_top_area(DOCK_AS_WINDOW(dock), &r, b);
     window_set_abstract(DOCK_AS_WINDOW(dock),
                         &dock->frame,         /* top level window */
+                        &dock->frame,         /* composite redir window */
                         &config_dock_layer,   /* stacking layer */
                         &dock->depth,         /* window depth */
                         NULL);
index 38379571e5d10327059ab5b740d6ce34317aff12..d23447b36251f9afa76329af4fb1df2dd95401c6 100644 (file)
@@ -555,7 +555,7 @@ static void event_process(const XEvent *ec, gpointer data)
                window unmap -> get focusout
                window map -> send focusin
                get first focus out -> fall back to something (new window
-                 hasn't received focus yet, so something else) -> send focusin
+               hasn't received focus yet, so something else) -> send focusin
                which means the "something else" is the last thing to get a
                focusin sent to it, so the new window doesn't end up with focus.
 
@@ -640,37 +640,64 @@ static void event_process(const XEvent *ec, gpointer data)
 
         if (!obwin && xe->parent == obt_root(ob_screen))
             obwin = UNMANAGED_AS_WINDOW(unmanaged_new(xe->window));
-
-        if (obwin && xe->window == window_top(obwin) &&
-            obwin->type != OB_WINDOW_CLASS_PROMPT)
-        {
-            obwin->mapped = 0;
-            RECT_SET(obwin->area, xe->x, xe->y, xe->width, xe->height);
-            obwin->border = xe->border_width;
-#ifdef USE_COMPOSITING
-            if (!obwin->texture) glGenTextures(1, &obwin->texture);
-#endif
-        }
     }
     else if ((obwin && obwin->type != OB_WINDOW_CLASS_PROMPT) &&
-               ((e->type == ConfigureNotify &&
-                 e->xconfigure.window == window_top(obwin)) ||
-                (e->type == MapNotify &&
-                 e->xmap.window == window_top(obwin))))
+             ((e->type == ConfigureNotify &&
+               /* for configure notify, track the position/size of
+                  both the top-level window and the redir window (when
+                  it is not the top-level window) */
+               e->xconfigure.send_event == FALSE &&
+               ((e->xconfigure.window == window_redir(obwin) &&
+                 window_redir(obwin) != window_top(obwin)) ||
+                (e->xconfigure.window == window_top(obwin)))) ||
+              (e->type == MapNotify &&
+               e->xmap.window == window_redir(obwin))))
     {
         gboolean pixchange = FALSE;
 
         if (e->type == ConfigureNotify) {
             XConfigureEvent const *xe = &e->xconfigure;
-            if (obwin->area.width != xe->width ||
-                obwin->area.height != xe->height ||
-                obwin->border != xe->border_width)
-            {
-                pixchange = TRUE;
+
+            if (xe->window == window_redir(obwin)) {
+                int x, y, w, h;
+
+                /* if the redir window's size changes.. */
+                if (obwin->area.width != xe->width ||
+                    obwin->area.height != xe->height ||
+                    /* or its border changes.. (assume only the top-level
+                       window will ever have a border) */
+                    (window_top(obwin) == window_redir(obwin) &&
+                     obwin->topborder != xe->border_width))
+                {
+                    /* ..then need to change the pixmap */
+                    pixchange = TRUE;
+                }
+
+                /* set the redir window's area */
+                if (window_redir(obwin) == window_top(obwin)) {
+                    /* same window then its area fills the whole top level
+                       window */
+                    x = 0;
+                    y = 0;
+                    w = xe->width + xe->border_width * 2;
+                    h = xe->height + xe->border_width * 2;
+                }
+                else {
+                    /* different window then it is inside the top level
+                       window */
+                    x = xe->x;
+                    y = xe->y;
+                    w = xe->width;
+                    h = xe->height;
+                }
+                RECT_SET(obwin->area, x, y, w, h);
+            }
+
+            /* set the top window's area/border */
+            if (xe->window == window_top(obwin)) {
+                RECT_SET(obwin->toparea, xe->x, xe->y, xe->width, xe->height);
+                obwin->topborder = xe->border_width;
             }
-            RECT_SET(obwin->area, xe->x, xe->y,
-                     xe->width, xe->height);
-            obwin->border = xe->border_width;
         }
 
         if (e->type == MapNotify) {
@@ -680,9 +707,10 @@ static void event_process(const XEvent *ec, gpointer data)
 
         if (pixchange)
             composite_window_invalid(obwin);
-    } else if ((e->type == UnmapNotify) && obwin &&
-               obwin->type != OB_WINDOW_CLASS_PROMPT &&
-               e->xunmap.window == window_top(obwin))
+    }
+    else if ((e->type == UnmapNotify) && obwin &&
+             obwin->type != OB_WINDOW_CLASS_PROMPT &&
+             e->xunmap.window == window_top(obwin))
     {
         obwin->mapped = FALSE;
     }
index 8ffe90e359bd553483a8ccb5c04e7e246e23f48d..05b5a1b06fc6c7cd0b4fa42f820dee4ed61ac1de 100644 (file)
@@ -42,10 +42,12 @@ static RrAppearance *a_focus_indicator;
 static RrColor      *color_white;
 static gboolean      visible;
 
-static Window create_window(Window parent, gint depth, gulong mask,
+static Window create_window(Window parent, const Rect *r, gint border,
+                            gint depth, gulong mask,
                             XSetWindowAttributes *attrib)
 {
-    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
+    return XCreateWindow(obt_display, parent,
+                         r->x, r->y, r->width, r->height, border,
                          depth, InputOutput,
                          0, mask, attrib);
 
@@ -56,6 +58,8 @@ void focus_cycle_indicator_startup(gboolean reconfig)
     Window w;
     gint depth;
     XSetWindowAttributes attr;
+    const Rect r = {0, 0, 1, 1};
+    const gint b = 0;
 
     visible = FALSE;
 
@@ -65,18 +69,18 @@ void focus_cycle_indicator_startup(gboolean reconfig)
     attr.override_redirect = True;
     attr.background_pixel = BlackPixel(obt_display, ob_screen);
 
-    w = create_window(obt_root(ob_screen), depth,
+    w = create_window(obt_root(ob_screen), &r, b, depth,
                       CWOverrideRedirect | CWBackPixel, &attr);
-    focus_indicator.top = window_internal_new(w, depth);
-    w = create_window(obt_root(ob_screen), depth,
+    focus_indicator.top = window_internal_new(w, &r, b, depth);
+    w = create_window(obt_root(ob_screen), &r, b, depth,
                       CWOverrideRedirect | CWBackPixel, &attr);
-    focus_indicator.left = window_internal_new(w, depth);
-    w = create_window(obt_root(ob_screen), depth,
+    focus_indicator.left = window_internal_new(w, &r, b, depth);
+    w = create_window(obt_root(ob_screen), &r, b, depth,
                       CWOverrideRedirect | CWBackPixel, &attr);
-    focus_indicator.right = window_internal_new(w, depth);
-    w = create_window(obt_root(ob_screen), depth,
+    focus_indicator.right = window_internal_new(w, &r, b, depth);
+    w = create_window(obt_root(ob_screen), &r, b, depth,
                       CWOverrideRedirect | CWBackPixel, &attr);
-    focus_indicator.bottom = window_internal_new(w, depth);
+    focus_indicator.bottom = window_internal_new(w, &r, b, depth);
 
     stacking_add(INTERNAL_AS_WINDOW(focus_indicator.top));
     stacking_add(INTERNAL_AS_WINDOW(focus_indicator.left));
index 661ac25a72b2f3348e86fa39e8ff48055a18fd5e..f31600407f65801b0d432f153878eab20cfb16a6 100644 (file)
@@ -109,19 +109,18 @@ static gboolean popup_setup    (ObFocusCyclePopup *p,
 static void     popup_render   (ObFocusCyclePopup *p,
                                 const ObClient *c);
 
-static Window create_window(Window parent, guint bwidth, gint depth,
-                            gulong mask,
-                            XSetWindowAttributes *attr)
+static inline Window create_window(Window parent)
 {
-    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, bwidth,
-                         (depth ? depth : RrDepth(ob_rr_inst)), InputOutput,
-                         RrVisual(ob_rr_inst), mask, attr);
+    return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
+                         RrDepth(ob_rr_inst), InputOutput,
+                         RrVisual(ob_rr_inst), 0, NULL);
 }
 
 void focus_cycle_popup_startup(gboolean reconfig)
 {
     XSetWindowAttributes attrib;
     RrPixel32 *p;
+    const Rect r = {0, 0, 1, 1};
 
     single_popup = icon_popup_new();
 
@@ -154,17 +153,19 @@ void focus_cycle_popup_startup(gboolean reconfig)
     attrib.override_redirect = True;
     attrib.border_pixel=RrColorPixel(ob_rr_theme->osd_border_color);
     popup->depth = RrDepth(ob_rr_inst);
-    popup->bg = create_window(obt_root(ob_screen), ob_rr_theme->obwidth,
-                              popup->depth,
+    popup->bg = XCreateWindow(obt_display, obt_root(ob_screen),
+                              r.x, r.y, r.width, r.height,
+                              ob_rr_theme->obwidth, popup->depth,
+                              InputOutput, RrVisual(ob_rr_inst),
                               CWOverrideRedirect | CWBorderPixel, &attrib);
     popup->layer = OB_STACKING_LAYER_INTERNAL;
 
     /* create the text window used for the icon-mode popup */
-    popup->icon_mode_text = create_window(popup->bg, 0, 0, 0, NULL);
+    popup->icon_mode_text = create_window(popup->bg);
 
     /* create the windows for the up and down arrows */
-    popup->list_mode_up = create_window(popup->bg, 0, 0, 0, NULL);
-    popup->list_mode_down = create_window(popup->bg, 0, 0, 0, NULL);
+    popup->list_mode_up = create_window(popup->bg);
+    popup->list_mode_down = create_window(popup->bg);
 
     popup->targets = NULL;
     popup->n_targets = 0;
@@ -209,7 +210,9 @@ void focus_cycle_popup_startup(gboolean reconfig)
             }
     }
 
+    window_set_top_area(INTERNAL_AS_WINDOW(popup), &r, ob_rr_theme->obwidth);
     window_set_abstract(INTERNAL_AS_WINDOW(popup),
+                        &popup->bg,
                         &popup->bg,
                         &popup->layer,
                         &popup->depth,
@@ -339,8 +342,8 @@ static gboolean popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
                     t->text = text;
                     t->icon = client_icon(t->client);
                     RrImageRef(t->icon); /* own the icon so it won't go away */
-                    t->iconwin = create_window(p->bg, 0, 0, 0, NULL);
-                    t->textwin = create_window(p->bg, 0, 0, 0, NULL);
+                    t->iconwin = create_window(p->bg);
+                    t->textwin = create_window(p->bg);
 
                     p->targets = g_list_prepend(p->targets, t);
                     ++n;
index 731c18d8a41159a582199f36eecf25aaef1911ad..024a23e3a7c87e663d1c3fefdf50ecc7cf716741 100644 (file)
@@ -510,7 +510,9 @@ void frame_grab_client(ObFrame *self)
        send a mapnotify or we create race conditions.
     */
 
-    /* reparent the client to the frame */
+    /* reparent the client to the frame
+       (it should go to 0,0 as the window's redirected "area" is initialized
+       to this value) */
     XReparentWindow(obt_display, self->client->window, self->window, 0, 0);
 
     /*
index 89ad4bdd6d14ed69596abc29771d3c209d6a78a9..a1dbfdf24fba0c09f7f7d437841a974e37e11fbe 100644 (file)
@@ -26,6 +26,8 @@
 
 void framerender_frame(ObFrame *self)
 {
+    if (CLIENT_AS_WINDOW(self->client)->redir)
+        return; /* being rendered with composite */
     if (frame_iconify_animating(self))
         return; /* delay redrawing until the animation is done */
     if (!self->need_render)
index 2f7d2b5de0b76ecfe78c3f055e4439d048495697..c9617d313394f5f34f8ea29e71a9f434d06cbc06 100644 (file)
@@ -56,11 +56,11 @@ static void menu_frame_hide(ObMenuFrame *self);
 
 static gboolean submenu_hide_timeout(gpointer data);
 
-static Window createWindow(Window parent, gint depth, gulong mask,
+static Window createWindow(Window parent, gulong mask,
                            XSetWindowAttributes *attrib)
 {
     return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
-                         (depth ? depth : RrDepth(ob_rr_inst)), InputOutput,
+                         RrDepth(ob_rr_inst), InputOutput,
                          RrVisual(ob_rr_inst), mask, attrib);
 }
 
@@ -109,6 +109,8 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
 {
     ObMenuFrame *self;
     XSetWindowAttributes attr;
+    const Rect r = {0, 0, 1, 1};
+    const gint b = 0;
 
     self = window_new(OB_WINDOW_CLASS_MENUFRAME, ObMenuFrame);
     self->menu = menu;
@@ -119,8 +121,10 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
 
     attr.event_mask = FRAME_EVENTMASK;
     self->depth = RrDepth(ob_rr_inst);
-    self->window = createWindow(obt_root(ob_screen), self->depth,
-                                CWEventMask, &attr);
+    self->window = XCreateWindow(obt_display, obt_root(ob_screen),
+                                 r.x, r.y, r.width, r.height, b, self->depth,
+                                 InputOutput, RrVisual(ob_rr_inst),
+                                 CWEventMask, &attr);
     self->layer =  OB_STACKING_LAYER_INTERNAL;
 
     /* make it a popup menu type window */
@@ -133,8 +137,10 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client)
 
     self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu);
 
+    window_set_top_area(MENUFRAME_AS_WINDOW(self), &r, b);
     window_set_abstract(MENUFRAME_AS_WINDOW(self),
                         &self->window,        /* top level window */
+                        &self->window,        /* composite redir window */
                         &self->layer,         /* stacking layer */
                         &self->depth,         /* window depth */
                         NULL);                /* opacity */
@@ -186,16 +192,16 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
     menu_entry_ref(entry);
 
     attr.event_mask = ENTRY_EVENTMASK;
-    self->window = createWindow(self->frame->window, 0, CWEventMask, &attr);
-    self->text = createWindow(self->window, 0, 0, NULL);
+    self->window = createWindow(self->frame->window, CWEventMask, &attr);
+    self->text = createWindow(self->window, 0, NULL);
     g_hash_table_insert(menu_frame_map, &self->window, self);
     g_hash_table_insert(menu_frame_map, &self->text, self);
     if (entry->type == OB_MENU_ENTRY_TYPE_NORMAL) {
-        self->icon = createWindow(self->window, 0, 0, NULL);
+        self->icon = createWindow(self->window, 0, NULL);
         g_hash_table_insert(menu_frame_map, &self->icon, self);
     }
     if (entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) {
-        self->bullet = createWindow(self->window, 0, 0, NULL);
+        self->bullet = createWindow(self->window, 0, NULL);
         g_hash_table_insert(menu_frame_map, &self->bullet, self);
     }
 
index 1045cadfc957bb1d5234986fcc289a8d48a89e60..cef6ab0790f35dcd49b4daa3beb7cbdea3eb7c72 100644 (file)
@@ -32,6 +32,8 @@ ObPopup *popup_new(void)
 {
     XSetWindowAttributes attrib;
     ObPopup *self;
+    const Rect r = {0, 0, 1, 1};
+    const gint b = 0;
 
     self = window_new(OB_WINDOW_CLASS_INTERNAL, ObPopup);
     self->gravity = NorthWestGravity;
@@ -43,7 +45,7 @@ ObPopup *popup_new(void)
     attrib.override_redirect = True;
     self->depth = RrDepth(ob_rr_inst);
     self->bg = XCreateWindow(obt_display, obt_root(ob_screen),
-                             0, 0, 1, 1, 0, self->depth,
+                             r.x, r.y, r.width, r.height, b, self->depth,
                              InputOutput, RrVisual(ob_rr_inst),
                              CWOverrideRedirect, &attrib);
     self->layer = OB_STACKING_LAYER_INTERNAL;
@@ -58,8 +60,10 @@ ObPopup *popup_new(void)
 
     XMapWindow(obt_display, self->text);
 
+    window_set_top_area(INTERNAL_AS_WINDOW(self), &r, b);
     window_set_abstract(INTERNAL_AS_WINDOW(self),
                         &self->bg,      /* top level window */
+                        &self->bg,      /* composite redir window */
                         &self->layer,   /* stacking layer */
                         &self->depth,   /* window depth */
                         NULL);          /* opacity */
index 8050210bf5880d328e09e3ac758a2675fe24f910..0648015793568bbf70144ca7615697ff08db7c11 100644 (file)
@@ -36,6 +36,7 @@ ObUnmanaged* unmanaged_new(Window w)
 {
     XWindowAttributes at;
     ObUnmanaged *self;
+    Rect r;
 
     if (w == composite_overlay)
         return NULL;
@@ -53,8 +54,11 @@ ObUnmanaged* unmanaged_new(Window w)
     XSelectInput(obt_display, self->window, PropertyChangeMask);
 
     unmanaged_update_opacity(self);
-    
+
+    RECT_SET(r, at.x, at.y, at.width, at.height);
+    window_set_top_area(UNMANAGED_AS_WINDOW(self), &r, at.border_width);
     window_set_abstract(UNMANAGED_AS_WINDOW(self),
+                        &self->window,
                         &self->window,
                         &self->layer,
                         &self->depth,
index dfd4d32004626f80b2096aba24916c4d08688e19..e516eea22e9d043db09b6649c961455cd08d44dd 100644 (file)
@@ -63,13 +63,19 @@ ObWindow* window_new_size(ObWindowClass type, gsize size)
 
 void window_set_abstract(ObWindow *self,
                          const Window *top,
+                         const Window *redir,
                          const ObStackingLayer *layer,
                          const int *depth,
                          const guint32 *alpha)
 {
-    g_assert(!self->top && !self->layer && !self->depth && !self->alpha);
+    g_assert(!self->top && !self->redir && !self->layer && !self->depth &&
+             !self->alpha);
+#ifdef USE_COMPOSITING
+    g_assert(self->area.width > 0 && self->area.height > 0);
+#endif
 
     self->top = top;
+    self->redir = redir;
     self->layer = layer;
     self->depth = depth;
     self->alpha = alpha;
@@ -80,6 +86,17 @@ void window_set_abstract(ObWindow *self,
     composite_window_setup(self);
 }
 
+void window_set_top_area(ObWindow *self, const Rect *r, gint border)
+{
+    g_assert(!self->top);
+
+#ifdef USE_COMPOSITING
+    self->toparea = *r;
+    self->topborder = border;
+    RECT_SET(self->area, 0, 0, self->toparea.width, self->toparea.height);
+#endif
+}
+
 void window_cleanup(ObWindow *self)
 {
     composite_window_cleanup(self);
@@ -121,7 +138,8 @@ void window_remove(Window xwin)
     g_hash_table_remove(window_map, &xwin);
 }
 
-ObInternalWindow* window_internal_new(Window window, int depth)
+ObInternalWindow* window_internal_new(Window window, const Rect *area,
+                                      gint border, gint depth)
 {
     ObInternalWindow *self;
 
@@ -129,8 +147,10 @@ ObInternalWindow* window_internal_new(Window window, int depth)
     self->window = window;
     self->layer = OB_STACKING_LAYER_INTERNAL;
     self->depth = depth;
+    window_set_top_area(INTERNAL_AS_WINDOW(self), area, border);
     window_set_abstract(INTERNAL_AS_WINDOW(self),
                         &self->window, /* top-most window */
+                        &self->window, /* composite redir window */
                         &self->layer,  /* stacking layer */
                         &self->depth,  /* window depth */
                         NULL);         /* opacity */
index c7d5c640adf8bc25297eb5861de5b3f71802586d..21c4792a54a8b2600addeb95d36b0301d284cd7a 100644 (file)
@@ -54,6 +54,8 @@ struct _ObWindow {
 
     /*! Points to the top level Xwindow for the ObWindow */
     const Window *top;
+    /*! Points to the topmost window that should be redirected for composite */
+    const Window *redir;
     /*! Points to the stacking layer for the ObWindow */
     const ObStackingLayer *layer;
     /*! Points to the depth of the ObWindow */
@@ -68,10 +70,11 @@ struct _ObWindow {
     Pixmap pixmap;
     GLXPixmap gpixmap;
     Damage damage;
-    Rect area;
-    gint border;
+    Rect area; /* area of the redirected window */
+    Rect toparea; /* area of the top-level window */
+    gint topborder; /* the border around the top-level window */
     gboolean mapped;
-    gboolean redir;
+    gboolean is_redir;
 #endif
 };
 
@@ -117,9 +120,13 @@ ObWindow* window_new_size(ObWindowClass type, gsize size);
   initialization/creation phase, so that the ObWindow can be used */
 void      window_set_abstract(ObWindow *self,
                               const Window *top,
+                              const Window *redir,
                               const ObStackingLayer *layer,
                               const int *depth,
                               const guint32 *alpha);
+/*! A subclass of ObWindow must call this before setting its top-level
+  window, to the top-level window's initial position/size/border */
+void      window_set_top_area(ObWindow *self, const Rect *r, gint border);
 /*! A subclass of ObWindow must call this when it is going to be destroying
   itself, but _before_ it destroys the members it sets in
   window_set_abstract() */
@@ -135,6 +142,7 @@ typedef void (*ObWindowForeachFunc)(ObWindow *w);
 void      window_foreach(ObWindowForeachFunc func);
 
 #define window_top(w) (*((ObWindow*)w)->top)
+#define window_redir(w) (*((ObWindow*)w)->redir)
 #define window_layer(w) (*((ObWindow*)w)->layer)
 #define window_area(w) (*((ObWindow*)w)->area)
 #define window_depth(w) (*((ObWindow*)w)->depth)
@@ -147,7 +155,8 @@ struct _ObInternalWindow {
     int depth;
 };
 
-ObInternalWindow* window_internal_new(Window window, int depth);
+ObInternalWindow* window_internal_new(Window window, const Rect *area,
+                                      gint border, gint depth);
 
 void window_manage_all(void);
 void window_manage(Window win);