adds window_cleanup() that subclasses of ObWindow call to tell the parent they are going away, allowing it to clean up using the abstract pointers.
unmanaged windows get OB_STACKING_LAYER_ALL, but the stacking code is not made to handle this value yet. unexpected behaviour may result !
openbox/startupnotify.h \
openbox/translate.c \
openbox/translate.h \
+ openbox/unmanaged.c \
+ openbox/unmanaged.h \
openbox/window.c \
openbox/window.h
don't generate more events */
XSelectInput(obt_display, self->window, NoEventMask);
+ window_cleanup(CLIENT_AS_WINDOW(self));
+
/* ignore enter events from the unmap so it doesnt mess with the focus */
if (!config_focus_under_mouse)
ignore_start = event_start_ignore_all_enters();
{
/* this is all that got allocated to get the decorations */
+ window_cleanup(CLIENT_AS_WINDOW(self));
frame_free(self->frame);
window_free(CLIENT_AS_WINDOW(self));
}
#include "screen.h"
#include "event.h"
#include "client.h"
+#include "window.h"
#include "frame.h"
#include "geom.h"
#include "gettext.h"
}
glXSwapBuffers(obt_display, obcomp.overlay);
glFinish();
+ usleep(10000);
GLenum gler;
while ((gler = glGetError()) != GL_NO_ERROR) {
printf("gl error %d\n", gler);
#endif
return TRUE;
}
+
+Window composite_overlay(void)
+{
+#ifdef USE_COMPOSITING
+ return obcomp.overlay;
+#else
+ return 0;
+#endif
+}
+
+void composite_redir(ObWindow *w, gboolean on)
+{
+#ifdef USE_COMPOSITING
+ if (on) {
+ if (w->redir) return;
+ XCompositeRedirectWindow(obt_display, window_top(w),
+ CompositeRedirectManual);
+ w->redir = TRUE;
+ }
+ else {
+ if (!w->redir) return;
+ XCompositeUnredirectWindow(obt_display, window_top(w),
+ CompositeRedirectManual);
+ w->redir = FALSE;
+ }
+#endif
+}
+
+
#include "geom.h"
+struct _ObWindow;
+
#define MAX_DEPTH 32
typedef GLXPixmap (*CreatePixmapT)(Display *display,
void composite_startup(gboolean reconfig);
void composite_shutdown(gboolean reconfig);
+Window composite_overlay(void);
+void composite_redir(struct _ObWindow *w, gboolean on);
#endif
return;
}
+ window_cleanup(DOCK_AS_WINDOW(dock));
+
g_hash_table_destroy(dock->dock_map);
XDestroyWindow(obt_display, dock->frame);
#include "moveresize.h"
#include "group.h"
#include "stacking.h"
+#include "unmanaged.h"
#include "ping.h"
#include "obt/display.h"
#include "obt/xqueue.h"
static void event_handle_dock(ObDock *s, XEvent *e);
static void event_handle_dockapp(ObDockApp *app, XEvent *e);
static void event_handle_client(ObClient *c, XEvent *e);
+static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e);
static gboolean event_handle_user_input(ObClient *client, XEvent *e);
static gboolean is_enter_focus_event_ignored(gulong serial);
static void event_ignore_enter_range(gulong start, gulong end);
ObWindow *obwin = NULL;
ObMenuFrame *menu = NULL;
ObPrompt *prompt = NULL;
+ ObUnmanaged *um = NULL;
gboolean used;
/* make a copy we can mangle */
case OB_WINDOW_CLASS_PROMPT:
prompt = WINDOW_AS_PROMPT(obwin);
break;
+ case OB_WINDOW_CLASS_UNMANAGED:
+ um = WINDOW_AS_UNMANAGED(obwin);
+ break;
}
}
else
if (client && client != focus_client)
frame_adjust_focus(client->frame, FALSE);
}
-#ifdef USE_COMPOSITING
- else if ((e->type == CreateNotify) && obwin &&
- obwin->type != OB_WINDOW_CLASS_PROMPT &&
- e->xcreatewindow.window == window_top(obwin))
- {
+ else if (e->type == CreateNotify) {
XCreateWindowEvent const *xe = &e->xcreatewindow;
- obwin->mapped = 0;
- RECT_SET(obwin->area, xe->x, xe->y, xe->width, xe->height);
- obwin->border = xe->border_width;
- if (!obwin->texture) glGenTextures(1, &obwin->texture);
+
+ 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 &&
}
if (pixchange) {
+#ifdef USE_COMPOSITING
if (obwin->gpixmap != None) {
glXDestroyGLXPixmap(obt_display, obwin->gpixmap);
obwin->gpixmap = None;
XFreePixmap(obt_display, obwin->pixmap);
obwin->pixmap = None;
}
+#endif
}
} else if ((e->type == UnmapNotify) && obwin &&
obwin->type != OB_WINDOW_CLASS_PROMPT &&
{
obwin->mapped = FALSE;
}
-#endif
+ else if (um)
+ event_handle_unmanaged(um, e);
else if (client)
event_handle_client(client, e);
else if (dockapp)
event_handle_menu(menu, e);
else if (window == obt_root(ob_screen))
event_handle_root(e);
- else if (e->type == MapRequest)
- window_manage(window);
else if (e->type == MappingNotify) {
/* keyboard layout changes for modifier mapping changes. reload the
modifier map, and rebind all the key bindings as appropriate */
break;
}
client_unmanage(client);
+ unmanaged_new(e->xunmap.window);
break;
case DestroyNotify:
ob_debug("DestroyNotify for window 0x%x", client->window);
ob_debug("ReparentNotify for window 0x%x", client->window);
client_unmanage(client);
+ unmanaged_new(e->xreparent.window);
break;
case MapRequest:
ob_debug("MapRequest for 0x%lx", client->window);
}
}
+static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e)
+{
+ Window w;
+
+ switch (e->type) {
+ case DestroyNotify:
+ unmanaged_destroy(um);
+ break;
+ case MapRequest:
+ w = window_top(um);
+ unmanaged_destroy(um);
+ window_manage(w);
+ break;
+ }
+}
+
static void event_handle_dockapp(ObDockApp *app, XEvent *e)
{
switch (e->type) {
RrAppearanceFree(a_focus_indicator);
+ window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.top));
+ window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.left));
+ window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.right));
+ window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.bottom));
+
window_remove(focus_indicator.top->window);
window_remove(focus_indicator.left->window);
window_remove(focus_indicator.right->window);
{
icon_popup_free(single_popup);
+ window_cleanup(INTERNAL_AS_WINDOW(popup));
+
window_remove(popup->bg);
stacking_remove(INTERNAL_AS_WINDOW(&popup));
self->entries = g_list_delete_link(self->entries, self->entries);
}
+ window_cleanup(MENUFRAME_AS_WINDOW(self));
+
stacking_remove(MENUFRAME_AS_WINDOW(self));
window_remove(self->window);
if (self) {
popup_hide(self); /* make sure it's not showing or is being delayed and
will be shown */
+ window_cleanup(INTERNAL_AS_WINDOW(self));
XDestroyWindow(obt_display, self->bg);
XDestroyWindow(obt_display, self->text);
RrAppearanceFree(self->a_bg);
g_assert(wins);
/* pls only restack stuff in the same layer at a time */
for (it = wins; it; it = next) {
+ while (it && window_layer(it->data) == OB_STACKING_LAYER_ALL)
+ it = g_list_next(it);
next = g_list_next(it);
+ while (next && window_layer(next->data) == OB_STACKING_LAYER_ALL)
+ next = g_list_next(next);
if (!next) break;
g_assert (window_layer(it->data) == window_layer(next->data));
}
#ifdef DEBUG
/* some debug checking of the stacking list's order */
for (it = stacking_list; ; it = next) {
+ while (it && window_layer(it->data) == OB_STACKING_LAYER_ALL)
+ it = g_list_next(it);
next = g_list_next(it);
+ while (next && window_layer(next->data) == OB_STACKING_LAYER_ALL)
+ next = g_list_next(next);
if (!next) break;
g_assert(window_layer(it->data) >= window_layer(next->data));
}
/* don't add windows that are being unmanaged ! */
if (WINDOW_IS_CLIENT(win)) g_assert(WINDOW_AS_CLIENT(win)->managed);
- stacking_list = g_list_append(stacking_list, win);
-
- stacking_raise(win);
- /* stacking_list_tail set by stacking_raise() */
+ if (WINDOW_IS_UNMANAGED(win))
+ stacking_list = g_list_prepend(stacking_list, win);
+ else {
+ stacking_list = g_list_append(stacking_list, win);
+ stacking_raise(win);
+ /* stacking_list_tail set by stacking_raise() */
+ }
}
static GList *find_highest_relative(ObClient *client)
OB_STACKING_LAYER_ABOVE, /*!< 3 - normal windows w/ above */
OB_STACKING_LAYER_FULLSCREEN, /*!< 4 - fullscreeen windows */
OB_STACKING_LAYER_INTERNAL, /*!< 5 - openbox windows/menus */
- OB_NUM_STACKING_LAYERS
+ OB_NUM_STACKING_LAYERS,
+ OB_STACKING_LAYER_ALL = 0xffffffff /*!< 0xffffffff - unmamnaged windows */
} ObStackingLayer;
/* list of ObWindow*s in stacking order from highest to lowest */
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ unmanaged.c for the Openbox window manager
+ Copyright (c) 2010 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#include "unmanaged.h"
+#include "composite.h"
+#include "window.h"
+#include "obt/display.h"
+
+struct _ObUnmanaged {
+ ObWindow super;
+ Window win;
+ ObStackingLayer layer;
+ gint depth;
+
+};
+
+ObUnmanaged* unmanaged_new(Window w)
+{
+ XWindowAttributes at;
+ ObUnmanaged *self;
+
+ if (w == composite_overlay())
+ return NULL;
+ if (!XGetWindowAttributes(obt_display, w, &at))
+ return NULL;
+ if (at.class == InputOnly)
+ return NULL;
+
+ self = window_new(OB_WINDOW_CLASS_UNMANAGED, ObUnmanaged);
+ self->win = w;
+ self->layer = OB_STACKING_LAYER_ALL;
+ self->depth = at.depth;
+
+ window_set_abstract(UNMANAGED_AS_WINDOW(self),
+ &self->win,
+ &self->layer,
+ &self->depth);
+
+ window_add(&self->win, UNMANAGED_AS_WINDOW(self));
+ stacking_add(UNMANAGED_AS_WINDOW(self));
+
+ return self;
+}
+
+void unmanaged_destroy(ObUnmanaged *self)
+{
+ window_cleanup(UNMANAGED_AS_WINDOW(self));
+ stacking_remove(UNMANAGED_AS_WINDOW(self));
+ window_remove(self->win);
+ window_free(UNMANAGED_AS_WINDOW(self));
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ unmanaged.h for the Openbox window manager
+ Copyright (c) 2010 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+*/
+
+#ifndef __unmanaged_h
+#define __unmanaged_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+typedef struct _ObUnmanaged ObUnmanaged;
+
+/*! Create a new structure to watch an unmanaged window */
+ObUnmanaged* unmanaged_new(Window w);
+void unmanaged_destroy(ObUnmanaged *self);
+
+#endif
#ifdef USE_COMPOSITING
if (self->type != OB_WINDOW_CLASS_PROMPT) {
- self->damage = XDamageCreate(obt_display, *self->top,
+ self->damage = XDamageCreate(obt_display, window_top(self),
XDamageReportNonEmpty);
-
- XCompositeRedirectWindow(obt_display, *self->top,
- CompositeRedirectManual);
}
#endif
+
+ composite_redir(self, TRUE);
+}
+
+void window_cleanup(ObWindow *self)
+{
+ composite_redir(self, FALSE);
}
void window_free(ObWindow *self)
OB_WINDOW_CLASS_DOCK,
OB_WINDOW_CLASS_CLIENT,
OB_WINDOW_CLASS_INTERNAL,
+ OB_WINDOW_CLASS_UNMANAGED,
OB_WINDOW_CLASS_PROMPT
} ObWindowClass;
Rect area;
gint border;
gboolean mapped;
+ gboolean redir;
#endif
};
(((ObWindow*)win)->type == OB_WINDOW_CLASS_CLIENT)
#define WINDOW_IS_INTERNAL(win) \
(((ObWindow*)win)->type == OB_WINDOW_CLASS_INTERNAL)
+#define WINDOW_IS_UNMANAGED(win) \
+ (((ObWindow*)win)->type == OB_WINDOW_CLASS_UNMANAGED)
#define WINDOW_IS_PROMPT(win) \
(((ObWindow*)win)->type == OB_WINDOW_CLASS_PROMPT)
#define WINDOW_AS_DOCK(win) ((struct _ObDock*)win)
#define WINDOW_AS_CLIENT(win) ((struct _ObClient*)win)
#define WINDOW_AS_INTERNAL(win) ((struct _ObInternalWindow*)win)
+#define WINDOW_AS_UNMANAGED(win) ((struct _ObUnmanaged*)win)
#define WINDOW_AS_PROMPT(win) ((struct _ObPrompt*)win)
#define MENUFRAME_AS_WINDOW(menu) ((ObWindow*)menu)
#define DOCK_AS_WINDOW(dock) ((ObWindow*)dock)
#define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
#define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern)
+#define UNMANAGED_AS_WINDOW(um) ((ObWindow*)um)
#define PROMPT_AS_WINDOW(prompt) ((ObWindow*)prompt)
void window_startup (gboolean reconfig);
const Window *top,
const ObStackingLayer *layer,
const int *depth);
+/*! 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_cleanup(ObWindow *self);
void window_free(ObWindow *self);
ObWindow* window_find (Window xwin);