From 4349a7a9f5d30a8a6d506990c0d779cad503cbfe Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 10 Jun 2010 19:26:52 -0400 Subject: [PATCH] Show unmanaged windows in composite. *Stacking will be broken though still!!* 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 ! --- Makefile.am | 2 + openbox/client.c | 3 ++ openbox/composite.c | 31 ++++++++++++++++ openbox/composite.h | 4 ++ openbox/dock.c | 2 + openbox/event.c | 55 +++++++++++++++++++++------ openbox/focus_cycle_indicator.c | 5 +++ openbox/focus_cycle_popup.c | 2 + openbox/menuframe.c | 2 + openbox/popup.c | 1 + openbox/stacking.c | 19 ++++++++-- openbox/stacking.h | 3 +- openbox/unmanaged.c | 66 +++++++++++++++++++++++++++++++++ openbox/unmanaged.h | 31 ++++++++++++++++ openbox/window.c | 12 ++++-- openbox/window.h | 10 +++++ 16 files changed, 227 insertions(+), 21 deletions(-) create mode 100644 openbox/unmanaged.c create mode 100644 openbox/unmanaged.h diff --git a/Makefile.am b/Makefile.am index 9e8ed5f7..8e2b1b55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -347,6 +347,8 @@ openbox_openbox_SOURCES = \ openbox/startupnotify.h \ openbox/translate.c \ openbox/translate.h \ + openbox/unmanaged.c \ + openbox/unmanaged.h \ openbox/window.c \ openbox/window.h diff --git a/openbox/client.c b/openbox/client.c index 79ca2342..5c19684a 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -563,6 +563,8 @@ void client_unmanage(ObClient *self) 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(); @@ -702,6 +704,7 @@ void client_fake_unmanage(ObClient *self) { /* 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)); } diff --git a/openbox/composite.c b/openbox/composite.c index cf2bdd03..ab5aef0b 100644 --- a/openbox/composite.c +++ b/openbox/composite.c @@ -24,6 +24,7 @@ #include "screen.h" #include "event.h" #include "client.h" +#include "window.h" #include "frame.h" #include "geom.h" #include "gettext.h" @@ -417,6 +418,7 @@ time_fix(&dif); } glXSwapBuffers(obt_display, obcomp.overlay); glFinish(); + usleep(10000); GLenum gler; while ((gler = glGetError()) != GL_NO_ERROR) { printf("gl error %d\n", gler); @@ -426,3 +428,32 @@ time_fix(&dif); #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 +} + + diff --git a/openbox/composite.h b/openbox/composite.h index 26146334..7b41e383 100644 --- a/openbox/composite.h +++ b/openbox/composite.h @@ -27,6 +27,8 @@ #include "geom.h" +struct _ObWindow; + #define MAX_DEPTH 32 typedef GLXPixmap (*CreatePixmapT)(Display *display, @@ -74,5 +76,7 @@ struct ObCompositor { void composite_startup(gboolean reconfig); void composite_shutdown(gboolean reconfig); +Window composite_overlay(void); +void composite_redir(struct _ObWindow *w, gboolean on); #endif diff --git a/openbox/dock.c b/openbox/dock.c index 068c65d5..b54ed437 100644 --- a/openbox/dock.c +++ b/openbox/dock.c @@ -130,6 +130,8 @@ void dock_shutdown(gboolean reconfig) return; } + window_cleanup(DOCK_AS_WINDOW(dock)); + g_hash_table_destroy(dock->dock_map); XDestroyWindow(obt_display, dock->frame); diff --git a/openbox/event.c b/openbox/event.c index 5c7a1952..a508abfa 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -38,6 +38,7 @@ #include "moveresize.h" #include "group.h" #include "stacking.h" +#include "unmanaged.h" #include "ping.h" #include "obt/display.h" #include "obt/xqueue.h" @@ -88,6 +89,7 @@ static gboolean event_handle_prompt(ObPrompt *p, XEvent *e); 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); @@ -457,6 +459,7 @@ static void event_process(const XEvent *ec, gpointer data) ObWindow *obwin = NULL; ObMenuFrame *menu = NULL; ObPrompt *prompt = NULL; + ObUnmanaged *um = NULL; gboolean used; /* make a copy we can mangle */ @@ -485,6 +488,9 @@ static void event_process(const XEvent *ec, gpointer data) case OB_WINDOW_CLASS_PROMPT: prompt = WINDOW_AS_PROMPT(obwin); break; + case OB_WINDOW_CLASS_UNMANAGED: + um = WINDOW_AS_UNMANAGED(obwin); + break; } } else @@ -621,16 +627,22 @@ static void event_process(const XEvent *ec, gpointer data) 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 && @@ -659,6 +671,7 @@ static void event_process(const XEvent *ec, gpointer data) } if (pixchange) { +#ifdef USE_COMPOSITING if (obwin->gpixmap != None) { glXDestroyGLXPixmap(obt_display, obwin->gpixmap); obwin->gpixmap = None; @@ -667,6 +680,7 @@ static void event_process(const XEvent *ec, gpointer data) XFreePixmap(obt_display, obwin->pixmap); obwin->pixmap = None; } +#endif } } else if ((e->type == UnmapNotify) && obwin && obwin->type != OB_WINDOW_CLASS_PROMPT && @@ -674,7 +688,8 @@ static void event_process(const XEvent *ec, gpointer data) { obwin->mapped = FALSE; } -#endif + else if (um) + event_handle_unmanaged(um, e); else if (client) event_handle_client(client, e); else if (dockapp) @@ -685,8 +700,6 @@ static void event_process(const XEvent *ec, gpointer data) 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 */ @@ -1408,6 +1421,7 @@ static void event_handle_client(ObClient *client, XEvent *e) break; } client_unmanage(client); + unmanaged_new(e->xunmap.window); break; case DestroyNotify: ob_debug("DestroyNotify for window 0x%x", client->window); @@ -1426,6 +1440,7 @@ static void event_handle_client(ObClient *client, XEvent *e) 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); @@ -1782,6 +1797,22 @@ static void event_handle_dock(ObDock *s, XEvent *e) } } +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) { diff --git a/openbox/focus_cycle_indicator.c b/openbox/focus_cycle_indicator.c index 655b87f8..8ffe90e3 100644 --- a/openbox/focus_cycle_indicator.c +++ b/openbox/focus_cycle_indicator.c @@ -116,6 +116,11 @@ void focus_cycle_indicator_shutdown(gboolean reconfig) 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); diff --git a/openbox/focus_cycle_popup.c b/openbox/focus_cycle_popup.c index f30ba8b7..3de68d67 100644 --- a/openbox/focus_cycle_popup.c +++ b/openbox/focus_cycle_popup.c @@ -222,6 +222,8 @@ void focus_cycle_popup_shutdown(gboolean reconfig) { icon_popup_free(single_popup); + window_cleanup(INTERNAL_AS_WINDOW(popup)); + window_remove(popup->bg); stacking_remove(INTERNAL_AS_WINDOW(&popup)); diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 10e7ca9b..9413e800 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -152,6 +152,8 @@ void menu_frame_free(ObMenuFrame *self) 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); diff --git a/openbox/popup.c b/openbox/popup.c index b87a4ad8..297fc529 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -73,6 +73,7 @@ void popup_free(ObPopup *self) 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); diff --git a/openbox/stacking.c b/openbox/stacking.c index 58a85eca..7c8f216e 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -74,7 +74,11 @@ static void do_restack(GList *wins, GList *before) 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)); } @@ -101,7 +105,11 @@ static void do_restack(GList *wins, GList *before) #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)); } @@ -445,10 +453,13 @@ void stacking_add(ObWindow *win) /* 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) diff --git a/openbox/stacking.h b/openbox/stacking.h index c14aa2ed..be247f34 100644 --- a/openbox/stacking.h +++ b/openbox/stacking.h @@ -35,7 +35,8 @@ typedef enum { 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 */ diff --git a/openbox/unmanaged.c b/openbox/unmanaged.c new file mode 100644 index 00000000..4c99d872 --- /dev/null +++ b/openbox/unmanaged.c @@ -0,0 +1,66 @@ +/* -*- 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)); +} diff --git a/openbox/unmanaged.h b/openbox/unmanaged.h new file mode 100644 index 00000000..a1a3b977 --- /dev/null +++ b/openbox/unmanaged.h @@ -0,0 +1,31 @@ +/* -*- 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 +#include + +typedef struct _ObUnmanaged ObUnmanaged; + +/*! Create a new structure to watch an unmanaged window */ +ObUnmanaged* unmanaged_new(Window w); +void unmanaged_destroy(ObUnmanaged *self); + +#endif diff --git a/openbox/window.c b/openbox/window.c index 0656816b..967e92be 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -73,13 +73,17 @@ void window_set_abstract(ObWindow *self, #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) diff --git a/openbox/window.h b/openbox/window.h index a8876803..946525c3 100644 --- a/openbox/window.h +++ b/openbox/window.h @@ -39,6 +39,7 @@ typedef enum { OB_WINDOW_CLASS_DOCK, OB_WINDOW_CLASS_CLIENT, OB_WINDOW_CLASS_INTERNAL, + OB_WINDOW_CLASS_UNMANAGED, OB_WINDOW_CLASS_PROMPT } ObWindowClass; @@ -66,6 +67,7 @@ struct _ObWindow { Rect area; gint border; gboolean mapped; + gboolean redir; #endif }; @@ -77,6 +79,8 @@ struct _ObWindow { (((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) @@ -90,12 +94,14 @@ struct _ObPrompt; #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); @@ -109,6 +115,10 @@ void window_set_abstract(ObWindow *self, 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); -- 2.34.1