generalize the window managing process into window_manage, which handles dock apps and the like
This commit is contained in:
parent
45e2039a58
commit
e0c1978c51
8 changed files with 170 additions and 129 deletions
|
@ -174,96 +174,16 @@ void client_set_list(void)
|
|||
stacking_set_list();
|
||||
}
|
||||
|
||||
void client_manage_all(void)
|
||||
{
|
||||
guint i, j, nchild;
|
||||
Window w, *children;
|
||||
XWMHints *wmhints;
|
||||
XWindowAttributes attrib;
|
||||
|
||||
XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
|
||||
&w, &w, &children, &nchild);
|
||||
|
||||
/* remove all icon windows from the list */
|
||||
for (i = 0; i < nchild; i++) {
|
||||
if (children[i] == None) continue;
|
||||
wmhints = XGetWMHints(obt_display, children[i]);
|
||||
if (wmhints) {
|
||||
if ((wmhints->flags & IconWindowHint) &&
|
||||
(wmhints->icon_window != children[i]))
|
||||
for (j = 0; j < nchild; j++)
|
||||
if (children[j] == wmhints->icon_window) {
|
||||
children[j] = None;
|
||||
break;
|
||||
}
|
||||
XFree(wmhints);
|
||||
}
|
||||
}
|
||||
|
||||
/* manage windows in reverse order from how they were originally mapped.
|
||||
this is an attempt to manage children windows before their parents, so
|
||||
that when the parent is mapped, it can find the child */
|
||||
for (i = 0; i < nchild; ++i) {
|
||||
if (children[i] == None)
|
||||
continue;
|
||||
if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
|
||||
if (attrib.override_redirect) continue;
|
||||
|
||||
if (attrib.map_state != IsUnmapped)
|
||||
client_manage(children[i]);
|
||||
}
|
||||
}
|
||||
XFree(children);
|
||||
}
|
||||
|
||||
void client_manage(Window window)
|
||||
{
|
||||
ObClient *self;
|
||||
XEvent e;
|
||||
XWindowAttributes attrib;
|
||||
XSetWindowAttributes attrib_set;
|
||||
XWMHints *wmhint;
|
||||
gboolean activate = FALSE;
|
||||
ObAppSettings *settings;
|
||||
gboolean transient = FALSE;
|
||||
Rect place, *monitor;
|
||||
Time launch_time, map_time;
|
||||
|
||||
grab_server(TRUE);
|
||||
|
||||
/* check if it has already been unmapped by the time we started
|
||||
mapping. the grab does a sync so we don't have to here */
|
||||
if (XCheckTypedWindowEvent(obt_display, window, DestroyNotify, &e) ||
|
||||
XCheckTypedWindowEvent(obt_display, window, UnmapNotify, &e))
|
||||
{
|
||||
XPutBackEvent(obt_display, &e);
|
||||
|
||||
ob_debug("Trying to manage unmapped window. Aborting that.\n");
|
||||
grab_server(FALSE);
|
||||
return; /* don't manage it */
|
||||
}
|
||||
|
||||
/* make sure it isn't an override-redirect window */
|
||||
if (!XGetWindowAttributes(obt_display, window, &attrib) ||
|
||||
attrib.override_redirect)
|
||||
{
|
||||
grab_server(FALSE);
|
||||
return; /* don't manage it */
|
||||
}
|
||||
|
||||
/* is the window a docking app */
|
||||
if ((wmhint = XGetWMHints(obt_display, window))) {
|
||||
if ((wmhint->flags & StateHint) &&
|
||||
wmhint->initial_state == WithdrawnState)
|
||||
{
|
||||
dock_add(window, wmhint);
|
||||
grab_server(FALSE);
|
||||
XFree(wmhint);
|
||||
return;
|
||||
}
|
||||
XFree(wmhint);
|
||||
}
|
||||
|
||||
ob_debug("Managing window: 0x%lx", window);
|
||||
|
||||
map_time = event_get_server_time();
|
||||
|
@ -625,8 +545,6 @@ void client_manage(Window window)
|
|||
|
||||
ob_debug("Managed window 0x%lx plate 0x%x (%s)",
|
||||
window, self->frame->window, self->class);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -319,10 +319,7 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data);
|
|||
void client_add_destroy_notify(ObClientCallback func, gpointer data);
|
||||
void client_remove_destroy_notify(ObClientCallback func);
|
||||
|
||||
/*! Manages all existing windows */
|
||||
void client_manage_all();
|
||||
/*! Manages a given window
|
||||
*/
|
||||
/*! Manages a given window */
|
||||
void client_manage(Window win);
|
||||
/*! Unmanages all managed windows */
|
||||
void client_unmanage_all();
|
||||
|
|
|
@ -50,6 +50,9 @@ static void dock_app_grab_button(ObDockApp *app, gboolean grab)
|
|||
}
|
||||
}
|
||||
|
||||
static guint window_hash(Window *w) { return *w; }
|
||||
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
|
||||
|
||||
void dock_startup(gboolean reconfig)
|
||||
{
|
||||
XSetWindowAttributes attrib;
|
||||
|
@ -82,6 +85,9 @@ void dock_startup(gboolean reconfig)
|
|||
|
||||
dock->hidden = TRUE;
|
||||
|
||||
dock->dock_map = g_hash_table_new((GHashFunc)window_hash,
|
||||
(GEqualFunc)window_comp);
|
||||
|
||||
attrib.event_mask = DOCK_EVENT_MASK;
|
||||
attrib.override_redirect = True;
|
||||
attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK;
|
||||
|
@ -117,24 +123,25 @@ void dock_shutdown(gboolean reconfig)
|
|||
return;
|
||||
}
|
||||
|
||||
g_hash_table_destroy(dock->dock_map);
|
||||
|
||||
XDestroyWindow(obt_display, dock->frame);
|
||||
RrAppearanceFree(dock->a_frame);
|
||||
window_remove(dock->frame);
|
||||
stacking_remove(dock);
|
||||
}
|
||||
|
||||
void dock_add(Window win, XWMHints *wmhints)
|
||||
void dock_manage(Window icon_win, Window name_win)
|
||||
{
|
||||
ObDockApp *app;
|
||||
XWindowAttributes attrib;
|
||||
gchar **data;
|
||||
|
||||
app = g_new0(ObDockApp, 1);
|
||||
app->win = win;
|
||||
app->icon_win = (wmhints->flags & IconWindowHint) ?
|
||||
wmhints->icon_window : win;
|
||||
app->name_win = name_win;
|
||||
app->icon_win = icon_win;
|
||||
|
||||
if (OBT_PROP_GETSS(app->win, WM_CLASS, locale, &data)) {
|
||||
if (OBT_PROP_GETSS(app->name_win, WM_CLASS, locale, &data)) {
|
||||
if (data[0]) {
|
||||
app->name = g_strdup(data[0]);
|
||||
if (data[1])
|
||||
|
@ -154,6 +161,7 @@ void dock_add(Window win, XWMHints *wmhints)
|
|||
}
|
||||
|
||||
dock->dock_apps = g_list_append(dock->dock_apps, app);
|
||||
g_hash_table_insert(dock->dock_map, &app->icon_win, app);
|
||||
dock_configure();
|
||||
|
||||
XReparentWindow(obt_display, app->icon_win, dock->frame, app->x, app->y);
|
||||
|
@ -166,32 +174,34 @@ void dock_add(Window win, XWMHints *wmhints)
|
|||
*/
|
||||
if (ob_state() == OB_STATE_STARTING)
|
||||
app->ignore_unmaps += 2;
|
||||
|
||||
if (app->win != app->icon_win) {
|
||||
/* have to map it so that it can be re-managed on a restart */
|
||||
XMoveWindow(obt_display, app->win, -1000, -1000);
|
||||
XMapWindow(obt_display, app->win);
|
||||
}
|
||||
XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
|
||||
XMapWindow(obt_display, app->icon_win);
|
||||
|
||||
if (app->name_win != app->icon_win) {
|
||||
XReparentWindow(obt_display, app->name_win, dock->frame, -1000, -1000);
|
||||
XChangeSaveSet(obt_display, app->name_win, SetModeInsert);
|
||||
XMapWindow(obt_display, app->name_win);
|
||||
}
|
||||
|
||||
XSync(obt_display, False);
|
||||
|
||||
/* specify that if we exit, the window should not be destroyed and should
|
||||
be reparented back to root automatically */
|
||||
XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
|
||||
XSelectInput(obt_display, app->icon_win, DOCKAPP_EVENT_MASK);
|
||||
|
||||
dock_app_grab_button(app, TRUE);
|
||||
|
||||
ob_debug("Managed Dock App: 0x%lx (%s)", app->icon_win, app->class);
|
||||
ob_debug("Managed Dock App: 0x%lx 0x%lx (%s)",
|
||||
app->icon_win, app->name_win, app->class);
|
||||
|
||||
grab_server(FALSE);
|
||||
}
|
||||
|
||||
void dock_remove_all(void)
|
||||
void dock_unmanage_all(void)
|
||||
{
|
||||
while (dock->dock_apps)
|
||||
dock_remove(dock->dock_apps->data, TRUE);
|
||||
dock_unmanage(dock->dock_apps->data, TRUE);
|
||||
}
|
||||
|
||||
void dock_remove(ObDockApp *app, gboolean reparent)
|
||||
void dock_unmanage(ObDockApp *app, gboolean reparent)
|
||||
{
|
||||
dock_app_grab_button(app, FALSE);
|
||||
XSelectInput(obt_display, app->icon_win, NoEventMask);
|
||||
|
@ -199,11 +209,15 @@ void dock_remove(ObDockApp *app, gboolean reparent)
|
|||
XChangeSaveSet(obt_display, app->icon_win, SetModeDelete);
|
||||
XSync(obt_display, False);
|
||||
|
||||
if (reparent)
|
||||
XReparentWindow(obt_display, app->icon_win,
|
||||
obt_root(ob_screen), app->x, app->y);
|
||||
if (reparent) {
|
||||
XReparentWindow(obt_display, app->icon_win, obt_root(ob_screen), 0, 0);
|
||||
if (app->name_win != app->icon_win)
|
||||
XReparentWindow(obt_display, app->name_win,
|
||||
obt_root(ob_screen), 0, 0);
|
||||
}
|
||||
|
||||
dock->dock_apps = g_list_remove(dock->dock_apps, app);
|
||||
g_hash_table_remove(dock->dock_map, &app->icon_win);
|
||||
dock_configure();
|
||||
|
||||
ob_debug("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
|
||||
|
@ -657,13 +671,5 @@ void dock_get_area(Rect *a)
|
|||
|
||||
ObDockApp* dock_find_dockapp(Window xwin)
|
||||
{
|
||||
GList *it;
|
||||
/* there are never that many dock apps, so we can use a list here instead
|
||||
of a hash table */
|
||||
for (it = dock->dock_apps; it; it = g_list_next(it)) {
|
||||
ObDockApp *app = it->data;
|
||||
if (app->icon_win == xwin)
|
||||
return app;
|
||||
}
|
||||
return NULL;
|
||||
return g_hash_table_lookup(dock->dock_map, &xwin);
|
||||
}
|
||||
|
|
|
@ -44,13 +44,14 @@ struct _ObDock
|
|||
gboolean hidden;
|
||||
|
||||
GList *dock_apps;
|
||||
GHashTable *dock_map;
|
||||
};
|
||||
|
||||
struct _ObDockApp {
|
||||
gint ignore_unmaps;
|
||||
|
||||
Window icon_win;
|
||||
Window win;
|
||||
Window name_win;
|
||||
|
||||
gchar *name;
|
||||
gchar *class;
|
||||
|
@ -69,10 +70,10 @@ void dock_shutdown(gboolean reconfig);
|
|||
void dock_configure();
|
||||
void dock_hide(gboolean hide);
|
||||
|
||||
void dock_add(Window win, XWMHints *wmhints);
|
||||
void dock_manage(Window icon_win, Window name_win);
|
||||
|
||||
void dock_remove_all();
|
||||
void dock_remove(ObDockApp *app, gboolean reparent);
|
||||
void dock_unmanage_all();
|
||||
void dock_unmanage(ObDockApp *app, gboolean reparent);
|
||||
|
||||
void dock_app_drag(ObDockApp *app, XMotionEvent *e);
|
||||
void dock_app_configure(ObDockApp *app, gint w, gint h);
|
||||
|
|
|
@ -161,7 +161,13 @@ static Window event_get_window(XEvent *e)
|
|||
case SelectionClear:
|
||||
window = obt_root(ob_screen);
|
||||
break;
|
||||
case CreateNotify:
|
||||
window = e->xcreatewindow.window;
|
||||
break;
|
||||
case MapRequest:
|
||||
window = e->xmaprequest.window;
|
||||
break;
|
||||
case MapNotify:
|
||||
window = e->xmap.window;
|
||||
break;
|
||||
case UnmapNotify:
|
||||
|
@ -639,7 +645,7 @@ static void event_process(const XEvent *ec, gpointer data)
|
|||
else if (window == obt_root(ob_screen))
|
||||
event_handle_root(e);
|
||||
else if (e->type == MapRequest)
|
||||
client_manage(window);
|
||||
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 */
|
||||
|
@ -1625,13 +1631,13 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e)
|
|||
app->ignore_unmaps--;
|
||||
break;
|
||||
}
|
||||
dock_remove(app, TRUE);
|
||||
dock_unmanage(app, TRUE);
|
||||
break;
|
||||
case DestroyNotify:
|
||||
dock_remove(app, FALSE);
|
||||
dock_unmanage(app, FALSE);
|
||||
break;
|
||||
case ReparentNotify:
|
||||
dock_remove(app, FALSE);
|
||||
dock_unmanage(app, FALSE);
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);
|
||||
|
|
|
@ -294,7 +294,7 @@ gint main(gint argc, gchar **argv)
|
|||
ObWindow *w;
|
||||
|
||||
/* get all the existing windows */
|
||||
client_manage_all();
|
||||
window_manage_all();
|
||||
focus_nothing();
|
||||
|
||||
/* focus what was focused if a wm was already running */
|
||||
|
@ -327,10 +327,8 @@ gint main(gint argc, gchar **argv)
|
|||
obt_main_loop_run(ob_main_loop);
|
||||
state = OB_STATE_EXITING;
|
||||
|
||||
if (!reconfigure) {
|
||||
dock_remove_all();
|
||||
client_unmanage_all();
|
||||
}
|
||||
if (!reconfigure)
|
||||
window_unmanage_all();
|
||||
|
||||
menu_shutdown(reconfigure);
|
||||
menu_frame_shutdown(reconfigure);
|
||||
|
|
111
openbox/window.c
111
openbox/window.c
|
@ -22,6 +22,9 @@
|
|||
#include "dock.h"
|
||||
#include "client.h"
|
||||
#include "frame.h"
|
||||
#include "openbox.h"
|
||||
#include "debug.h"
|
||||
#include "grab.h"
|
||||
|
||||
static GHashTable *window_map;
|
||||
|
||||
|
@ -91,3 +94,111 @@ void window_remove(Window xwin)
|
|||
g_assert(xwin != None);
|
||||
g_hash_table_remove(window_map, &xwin);
|
||||
}
|
||||
|
||||
void window_manage_all(void)
|
||||
{
|
||||
guint i, j, nchild;
|
||||
Window w, *children;
|
||||
XWMHints *wmhints;
|
||||
XWindowAttributes attrib;
|
||||
|
||||
if (!XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
|
||||
&w, &w, &children, &nchild)) {
|
||||
ob_debug("XQueryTree failed in window_manage_all");
|
||||
nchild = 0;
|
||||
}
|
||||
|
||||
/* remove all icon windows from the list */
|
||||
for (i = 0; i < nchild; i++) {
|
||||
if (children[i] == None) continue;
|
||||
wmhints = XGetWMHints(obt_display, children[i]);
|
||||
if (wmhints) {
|
||||
if ((wmhints->flags & IconWindowHint) &&
|
||||
(wmhints->icon_window != children[i]))
|
||||
for (j = 0; j < nchild; j++)
|
||||
if (children[j] == wmhints->icon_window) {
|
||||
/* XXX watch the window though */
|
||||
children[j] = None;
|
||||
break;
|
||||
}
|
||||
XFree(wmhints);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nchild; ++i) {
|
||||
if (children[i] == None) continue;
|
||||
if (window_find(children[i])) continue; /* skip our own windows */
|
||||
if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
|
||||
if (attrib.map_state == IsUnmapped)
|
||||
;
|
||||
else
|
||||
window_manage(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (children) XFree(children);
|
||||
}
|
||||
|
||||
void window_manage(Window win)
|
||||
{
|
||||
XEvent e;
|
||||
XWindowAttributes attrib;
|
||||
gboolean no_manage = FALSE;
|
||||
gboolean is_dockapp = FALSE;
|
||||
Window icon_win = None;
|
||||
|
||||
grab_server(TRUE);
|
||||
|
||||
/* check if it has already been unmapped by the time we started
|
||||
mapping. the grab does a sync so we don't have to here */
|
||||
if (XCheckTypedWindowEvent(obt_display, win, DestroyNotify, &e) ||
|
||||
XCheckTypedWindowEvent(obt_display, win, UnmapNotify, &e))
|
||||
{
|
||||
XPutBackEvent(obt_display, &e);
|
||||
ob_debug("Trying to manage unmapped window. Aborting that.\n");
|
||||
no_manage = TRUE;
|
||||
}
|
||||
|
||||
if (!XGetWindowAttributes(obt_display, win, &attrib))
|
||||
no_manage = TRUE;
|
||||
else {
|
||||
XWMHints *wmhints;
|
||||
|
||||
/* is the window a docking app */
|
||||
is_dockapp = FALSE;
|
||||
if ((wmhints = XGetWMHints(obt_display, win))) {
|
||||
if ((wmhints->flags & StateHint) &&
|
||||
wmhints->initial_state == WithdrawnState)
|
||||
{
|
||||
if (wmhints->flags & IconWindowHint)
|
||||
icon_win = wmhints->icon_window;
|
||||
is_dockapp = TRUE;
|
||||
}
|
||||
XFree(wmhints);
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_manage) {
|
||||
if (attrib.override_redirect) {
|
||||
ob_debug("not managing override redirect window 0x%x\n", win);
|
||||
grab_server(FALSE);
|
||||
}
|
||||
else if (is_dockapp) {
|
||||
if (!icon_win)
|
||||
icon_win = win;
|
||||
dock_manage(icon_win, win);
|
||||
}
|
||||
else
|
||||
client_manage(win);
|
||||
}
|
||||
else {
|
||||
grab_server(FALSE);
|
||||
ob_debug("FAILED to manage window 0x%x\n", win);
|
||||
}
|
||||
}
|
||||
|
||||
void window_unmanage_all(void)
|
||||
{
|
||||
dock_unmanage_all();
|
||||
client_unmanage_all();
|
||||
}
|
||||
|
|
|
@ -80,4 +80,8 @@ struct _ObInternalWindow {
|
|||
Window window;
|
||||
};
|
||||
|
||||
void window_manage_all(void);
|
||||
void window_manage(Window win);
|
||||
void window_unmanage_all(void);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue