From 0961c14054a24ba5914b72167de280686f529fde Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 25 Jun 2010 13:04:18 +0200 Subject: [PATCH] Allow ObWindow subclasses to redirect a child window of the top-level window 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. --- openbox/client.c | 6 ++- openbox/composite.c | 29 ++++++------ openbox/dock.c | 6 ++- openbox/event.c | 82 ++++++++++++++++++++++----------- openbox/focus_cycle_indicator.c | 24 ++++++---- openbox/focus_cycle_popup.c | 29 ++++++------ openbox/frame.c | 4 +- openbox/framerender.c | 2 + openbox/menuframe.c | 22 +++++---- openbox/popup.c | 6 ++- openbox/unmanaged.c | 6 ++- openbox/window.c | 24 +++++++++- openbox/window.h | 17 +++++-- 13 files changed, 175 insertions(+), 82 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index de3e5124..37e326f2 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -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); } diff --git a/openbox/composite.c b/openbox/composite.c index 3d517866..877ed20c 100644 --- a/openbox/composite.c +++ b/openbox/composite.c @@ -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); diff --git a/openbox/dock.c b/openbox/dock.c index 606a8b73..18fe0058 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -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); diff --git a/openbox/event.c b/openbox/event.c index 38379571..d23447b3 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -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; } diff --git a/openbox/focus_cycle_indicator.c b/openbox/focus_cycle_indicator.c index 8ffe90e3..05b5a1b0 100644 --- a/openbox/focus_cycle_indicator.c +++ b/openbox/focus_cycle_indicator.c @@ -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)); diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index 661ac25a..f3160040 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -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; diff --git a/openbox/frame.c b/openbox/frame.c index 731c18d8..024a23e3 100644 --- a/openbox/frame.c +++ b/openbox/frame.c @@ -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); /* diff --git a/openbox/framerender.c b/openbox/framerender.c index 89ad4bdd..a1dbfdf2 100644 --- a/openbox/framerender.c +++ b/openbox/framerender.c @@ -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) diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 2f7d2b5d..c9617d31 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -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); } diff --git a/openbox/popup.c b/openbox/popup.c index 1045cadf..cef6ab07 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -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 */ diff --git a/openbox/unmanaged.c b/openbox/unmanaged.c index 8050210b..06480157 100644 --- a/openbox/unmanaged.c +++ b/openbox/unmanaged.c @@ -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, diff --git a/openbox/window.c b/openbox/window.c index dfd4d320..e516eea2 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -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 */ diff --git a/openbox/window.h b/openbox/window.h index c7d5c640..21c4792a 100644 --- a/openbox/window.h +++ b/openbox/window.h @@ -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); -- 2.34.1