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 */
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 */
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);
}
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) {
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) {
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);
{
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)
w->damage = XDamageCreate(obt_display, window_top(w),
XDamageReportNonEmpty);
+ glGenTextures(1, &w->texture);
composite_window_redir(w);
}
#endif
composite_window_unredir(w);
-
composite_window_invalid(w);
if (w->damage) {
XDamageDestroy(obt_display, w->damage);
void dock_startup(gboolean reconfig)
{
XSetWindowAttributes attrib;
+ const Rect r = {0, 0, 1, 1};
+ const gint b = 0;
if (reconfig) {
GList *it;
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 |
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);
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.
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) {
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;
}
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);
Window w;
gint depth;
XSetWindowAttributes attr;
+ const Rect r = {0, 0, 1, 1};
+ const gint b = 0;
visible = FALSE;
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));
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();
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;
}
}
+ 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,
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;
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);
/*
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)
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);
}
{
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;
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 */
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 */
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);
}
{
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;
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;
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 */
{
XWindowAttributes at;
ObUnmanaged *self;
+ Rect r;
if (w == composite_overlay)
return NULL;
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,
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;
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);
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;
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 */
/*! 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 */
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
};
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() */
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)
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);