From: Dana Jansens Date: Thu, 10 May 2007 04:42:02 +0000 (+0000) Subject: merge r6257-6267 from trunk X-Git-Tag: openbox-3_3_991-RELEASE~119 X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=d8d9a195c156277be14044d14b64fc7d32f13274;p=dana%2Fopenbox.git merge r6257-6267 from trunk --- diff --git a/COMPLIANCE b/COMPLIANCE index 02358466..fdc40d1d 100644 --- a/COMPLIANCE +++ b/COMPLIANCE @@ -58,8 +58,7 @@ the version of the spec which Openbox is compliant up to for the hint. Openbox doesn't look for hung processes at this time. + _NET_FRAME_EXTENTS (1.3) + _NET_WM_STATE_DEMANDS_ATTENTION (1.3) -- _NET_RESTACK_WINDOW (1.3) - Openbox doesn't support this at this time. ++ _NET_RESTACK_WINDOW (1.3) + _NET_WM_SYNC_REQUEST (1.3) + _NET_WM_FULL_PLACEMENT (1.4) + _NET_WM_MOVERESIZE_CANCEL (1.4) diff --git a/Makefile.am b/Makefile.am index 84bf7523..8e012f57 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,9 +32,7 @@ bin_PROGRAMS = \ bin_SCRIPTS = \ data/xsession/openbox-gnome-session \ - data/xsession/openbox-kde-session \ - data/xsession/openbox-gnome \ - data/xsession/openbox-kde + data/xsession/openbox-kde-session ## render ## @@ -353,25 +351,29 @@ nodist_pkgconfig_DATA = \ dist_pixmap_DATA = \ data/openbox.png -nodist_rc_DATA = \ +dist_rc_DATA = \ data/rc.xml \ data/menu.xml edit = $(SED) \ -e 's!@version\@!$(VERSION)!' \ - -e 's!@xsddir\@!$(xsddir)!' + -e 's!@bindir\@!$(bindir)!' -data/rc.xml: Makefile $(srcdir)/data/rc.xml.in data +data/xsession/openbox-gnome-session: Makefile data \ + $(srcdir)/data/xsession/openbox-gnome-session.in @echo make: creating $@ @rm -f $@ @mkdir data 2>/dev/null || true - @$(edit) $(srcdir)/data/rc.xml.in >$@ + @$(edit) $(srcdir)/data/xsession/openbox-gnome-session.in >$@ + @chmod +x $@ -data/menu.xml: Makefile $(srcdir)/data/menu.xml.in data +data/xsession/openbox-kde-session: Makefile data \ + $(srcdir)/data/xsession/openbox-kde-session.in @echo make: creating $@ @rm -f $@ @mkdir data 2>/dev/null || true - @$(edit) $(srcdir)/data/menu.xml.in >$@ + @$(edit) $(srcdir)/data/xsession/openbox-kde-session.in >$@ + @chmod +x $@ dist_gnomewmfiles_DATA = \ data/gnome-wm-properties/openbox.desktop \ @@ -387,8 +389,8 @@ dist_noinst_DATA = \ version.h.in \ data/rc.xsd \ data/menu.xsd \ - data/rc.xml.in \ - data/menu.xml.in \ + data/xsession/openbox-gnome-session.in \ + data/xsession/openbox-kde-session.in \ render/obrender-3.0.pc.in \ parser/obparser-3.0.pc.in \ tools/themeupdate/themeupdate.py \ @@ -418,10 +420,6 @@ EXTRA_DIST = \ COPYING \ AUTHORS -CLEANFILES = \ - data/rc.xml \ - data/menu.xml - #doc: # $(MAKE) -$(MAKEFLAGS) -C doc/doxygen doc diff --git a/data/menu.xml.in b/data/menu.xml.in deleted file mode 100644 index 9f86dd6a..00000000 --- a/data/menu.xml.in +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - crack-attack - - - xfrisk - - - quake3 - - - - - - xterm - - - mozilla - - - gaim - - - strange-quark - - - - - - - - - - - - obconf - - - - - - - - - - - diff --git a/data/rc.xml.in b/data/rc.xml.in deleted file mode 100644 index 8ccf1cfa..00000000 --- a/data/rc.xml.in +++ /dev/null @@ -1,492 +0,0 @@ - - - - - - - - 10 - 20 - no - - - - yes - no - no - 0 - no - - - - Smart - - - - - Clearlooks - NLIMC - yes - - yes - yes - - sans - 7 - - bold - - normal - - - - sans - 7 - - bold - - normal - - - - sans - 8 - - bold - - normal - - - - sans - 9 - - bold - - normal - - - - sans - 9 - - bold - - normal - - - - - - - 4 - 1 - - desktop one - desktop two - desktop three - desktop four - - - - - yes - Nonpixel - - Center - - - - - TopLeft - - 0 - 0 - no - Above - - Vertical - - no - 300 - 300 - Middle - - - - C-g - - - - - - - - - - - - no - - - no - - - no - - - no - - - no - - - no - - - no - - - no - - - - - - - - - - - - - - - yes - - - yes - - - - - - - - - - - - client-menu - - - - - 3 - 200 - - - - - - - - - - - - - - - - - - - client-menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - client-menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - client-menu - - - client-menu - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - client-list-menu - - - root-menu - - - - - - - - - - - - - - - - - - - - - - - menu.xml - 250 - no - 0 - yes - - - - - - - - - - yes - - no - - - - center - - 200 - - 1 - - - - yes - - - 1 - - - normal - - - no - - no - - - no - - - yes - - true - - - - --> - - diff --git a/data/xsession/openbox-gnome b/data/xsession/openbox-gnome deleted file mode 100755 index c146aa81..00000000 --- a/data/xsession/openbox-gnome +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# A temporary script to be replaced by a real program.. -exec openbox --restart-binary openbox-gnome "$@" diff --git a/data/xsession/openbox-gnome-session b/data/xsession/openbox-gnome-session deleted file mode 100755 index d2b77014..00000000 --- a/data/xsession/openbox-gnome-session +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -# Run GNOME with Openbox as its window manager -export WINDOW_MANAGER=openbox-gnome -exec gnome-session "$@" diff --git a/data/xsession/openbox-kde b/data/xsession/openbox-kde deleted file mode 100755 index 87a5812c..00000000 --- a/data/xsession/openbox-kde +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# A temporary script to be replaced by a real program.. -exec openbox --restart-binary openbox-kde "$@" diff --git a/data/xsession/openbox-kde-session b/data/xsession/openbox-kde-session deleted file mode 100755 index 589a2c56..00000000 --- a/data/xsession/openbox-kde-session +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -# Run KDE with Openbox as its window manager -export KDEWM=openbox-kde -exec startkde "$@" diff --git a/openbox/client.c b/openbox/client.c index 0c4cce1f..4c88daf7 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -451,7 +451,7 @@ void client_manage(Window window) raised to the top. Legacy begets legacy I guess? */ if (!client_restore_session_stacking(self)) - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } /* this has to happen before we try focus the window, but we want it to @@ -2344,13 +2344,25 @@ static void client_calc_layer_recursive(ObClient *self, ObClient *orig, for (it = self->transients; it; it = g_slist_next(it)) client_calc_layer_recursive(it->data, orig, self->layer, - raised ? raised : self->layer != old); + raised ? raised : self->layer > old); - if (!raised && self->layer != old) - if (orig->frame) { /* only restack if the original window is managed */ + /* restack. but only if the original window is managed. + + raised is used so that only the bottom-most window in the stacking + order is raised, the others will automatically come with it. + + also only the highest windows in the stacking order (no transients) + are lowered, cuz the rest come for free + */ + if (!raised && orig->frame) { + if (self->layer > old) { + stacking_remove(CLIENT_AS_WINDOW(self)); + stacking_add_nonintrusive(CLIENT_AS_WINDOW(self)); + } else if (self->layer < old && self->transients == NULL) { stacking_remove(CLIENT_AS_WINDOW(self)); - stacking_add(CLIENT_AS_WINDOW(self)); + stacking_add_nonintrusive(CLIENT_AS_WINDOW(self)); } + } } void client_calc_layer(ObClient *self) @@ -3077,7 +3089,7 @@ void client_set_desktop_recursive(ObClient *self, client_showhide(self); /* raise if it was not already on the desktop */ if (old != DESKTOP_ALL) - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); if (STRUT_EXISTS(self->strut)) screen_update_areas(); } @@ -3302,7 +3314,7 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) self->modal = modal; /* when a window changes modality, then its stacking order with its transients needs to change */ - client_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } if (iconic != self->iconic) client_iconify(self, iconic, FALSE); @@ -3444,17 +3456,10 @@ static void client_present(ObClient *self, gboolean here, gboolean raise) return; if (self->shaded) client_shade(self, FALSE); + if (raise) + stacking_raise(CLIENT_AS_WINDOW(self)); client_focus(self); - - if (raise) { - /* we do this as an action here. this is rather important. this is - because we want the results from the focus change to take place - BEFORE we go about raising the window. when a fullscreen window - loses focus, we need this or else the raise wont be able to raise - above the to-lose-focus fullscreen window. */ - client_raise(self); - } } void client_activate(ObClient *self, gboolean here, gboolean user) @@ -3510,16 +3515,6 @@ void client_bring_helper_windows(ObClient *self) client_bring_helper_windows_recursive(self, self->desktop); } -void client_raise(ObClient *self) -{ - action_run_string("Raise", self, CurrentTime); -} - -void client_lower(ObClient *self) -{ - action_run_string("Lower", self, CurrentTime); -} - gboolean client_focused(ObClient *self) { return self == focus_client; diff --git a/openbox/client.h b/openbox/client.h index 30d40510..5a837391 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -550,26 +550,6 @@ void client_bring_helper_windows(ObClient *self); /*! Calculates the stacking layer for the client window */ void client_calc_layer(ObClient *self); -/*! Raises the client to the top of its stacking layer - Normally actions call to the client_* functions to make stuff go, but this - one is an exception. It just fires off an action, which will be queued. - This is because stacking order rules can be changed by focus state, and so - any time focus changes you have to wait for it to complete before you can - properly restart windows. As such, this only queues an action for later - execution, once the focus change has gone through. -*/ -void client_raise(ObClient *self); - -/*! Lowers the client to the bottom of its stacking layer - Normally actions call to the client_* functions to make stuff go, but this - one is an exception. It just fires off an action, which will be queued. - This is because stacking order rules can be changed by focus state, and so - any time focus changes you have to wait for it to complete before you can - properly restart windows. As such, this only queues an action for later - execution, once the focus change has gone through. -*/ -void client_lower(ObClient *self); - /*! Updates the window's transient status, and any parents of it */ void client_update_transient_for(ObClient *self); /*! Update the protocols that the window supports and adjusts things if they diff --git a/openbox/event.c b/openbox/event.c index 566739c9..6bf6e87b 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -1019,22 +1019,20 @@ static void event_handle_client(ObClient *client, XEvent *e) } if (e->xconfigurerequest.value_mask & CWStackMode) { - switch (e->xconfigurerequest.detail) { - case Below: - case BottomIf: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_lower(client);*/ - break; - - case Above: - case TopIf: - default: - /* Apps are so rude. And this is totally disconnected from - activation/focus. Bleh. */ - /*client_raise(client);*/ - break; + ObClient *sibling = NULL; + + /* get the sibling */ + if (e->xconfigurerequest.value_mask & CWSibling) { + ObWindow *win; + win = g_hash_table_lookup(window_map, + &e->xconfigurerequest.above); + if (WINDOW_IS_CLIENT(win) && WINDOW_AS_CLIENT(win) != client) + sibling = WINDOW_AS_CLIENT(win); } + + /* activate it rather than just focus it */ + stacking_restack_request(client, sibling, + e->xconfigurerequest.detail, TRUE); } break; case UnmapNotify: @@ -1211,6 +1209,43 @@ static void event_handle_client(ObClient *client, XEvent *e) client_convert_gravity(client, grav, &x, &y, w, h); client_find_onscreen(client, &x, &y, w, h, FALSE); client_configure(client, x, y, w, h, FALSE, TRUE); + } else if (msgtype == prop_atoms.net_restack_window) { + if (e->xclient.data.l[0] != 2) { + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s with " + "invalid source indication %ld\n", + client->title, e->xclient.data.l[0]); + } else { + ObClient *sibling = NULL; + if (e->xclient.data.l[1]) { + ObWindow *win = g_hash_table_lookup(window_map, + &e->xclient.data.l[1]); + if (WINDOW_IS_CLIENT(win) && + WINDOW_AS_CLIENT(win) != client) + { + sibling = WINDOW_AS_CLIENT(win); + } + if (sibling == NULL) + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s " + "with invalid sibling 0x%x\n", + client->title, e->xclient.data.l[1]); + } + if (e->xclient.data.l[2] == Below || + e->xclient.data.l[2] == BottomIf || + e->xclient.data.l[2] == Above || + e->xclient.data.l[2] == TopIf || + e->xclient.data.l[2] == Opposite) + { + /* just raise, don't activate */ + stacking_restack_request(client, sibling, + e->xclient.data.l[2], FALSE); + } else + ob_debug_type(OB_DEBUG_APP_BUGS, + "_NET_RESTACK_WINDOW sent for window %s " + "with invalid detail %d\n", + client->title, e->xclient.data.l[2]); + } } break; case PropertyNotify: @@ -1601,7 +1636,7 @@ static gboolean focus_delay_func(gpointer data) event_curtime = d->time; if (focus_client != d->client) { if (client_focus(d->client) && config_focus_raise) - client_raise(d->client); + stacking_raise(CLIENT_AS_WINDOW(d->client)); } event_curtime = old; return FALSE; /* no repeat */ diff --git a/openbox/mouse.c b/openbox/mouse.c index 9edda8eb..9ca79877 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -193,8 +193,8 @@ void mouse_event(ObClient *client, XEvent *e) px = e->xbutton.x_root; py = e->xbutton.y_root; - if (pwx == -1) pwx = e->xbutton.x; - if (pwy == -1) pwy = e->xbutton.y; + if (!button) pwx = e->xbutton.x; + if (!button) pwy = e->xbutton.y; button = e->xbutton.button; state = e->xbutton.state; @@ -216,7 +216,8 @@ void mouse_event(ObClient *client, XEvent *e) context = frame_context(client, e->xbutton.window, pwx, pwy); context = mouse_button_frame_context(context, e->xbutton.button); - pwx = pwy = -1; + if (e->xbutton.button == button) + pwx = pwy = -1; if (e->xbutton.button == button) { /* clicks are only valid if its released over the window */ @@ -258,7 +259,8 @@ void mouse_event(ObClient *client, XEvent *e) fire_binding(OB_MOUSE_ACTION_RELEASE, context, client, e->xbutton.state, e->xbutton.button, - e->xbutton.x_root, e->xbutton.y_root, + e->xbutton.x_root, + e->xbutton.y_root, e->xbutton.time); if (click) fire_binding(OB_MOUSE_ACTION_CLICK, context, @@ -281,10 +283,8 @@ void mouse_event(ObClient *client, XEvent *e) context = frame_context(client, e->xmotion.window, pwx, pwy); context = mouse_button_frame_context(context, button); - if (ABS(e->xmotion.x_root - px) >= - config_mouse_threshold || - ABS(e->xmotion.y_root - py) >= - config_mouse_threshold) { + if (ABS(e->xmotion.x_root - px) >= config_mouse_threshold || + ABS(e->xmotion.y_root - py) >= config_mouse_threshold) { /* You can't drag on buttons */ if (context == OB_FRAME_CONTEXT_MAXIMIZE || diff --git a/openbox/openbox.c b/openbox/openbox.c index d3c80549..18d9884d 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -477,7 +477,7 @@ static void remove_args(gint *argc, gchar **argv, gint index, gint num) { gint i; - for (i = index; i < index + num; ++i) + for (i = index; i < *argc - num; ++i) argv[i] = argv[i+num]; for (; i < *argc; ++i) argv[i] = NULL; @@ -492,31 +492,41 @@ static void parse_args(gint *argc, gchar **argv) if (!strcmp(argv[i], "--version")) { print_version(); exit(0); - } else if (!strcmp(argv[i], "--help")) { + } + else if (!strcmp(argv[i], "--help")) { print_help(); exit(0); - } else if (!strcmp(argv[i], "--g-fatal-warnings")) { + } + else if (!strcmp(argv[i], "--g-fatal-warnings")) { g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); - } else if (!strcmp(argv[i], "--replace")) { + } + else if (!strcmp(argv[i], "--replace")) { ob_replace_wm = TRUE; - } else if (!strcmp(argv[i], "--sync")) { + remove_args(argc, argv, i, 1); + --i; /* this arg was removed so go back */ + } + else if (!strcmp(argv[i], "--sync")) { xsync = TRUE; - } else if (!strcmp(argv[i], "--debug")) { + } + else if (!strcmp(argv[i], "--debug")) { ob_debug_show_output(TRUE); ob_debug_enable(OB_DEBUG_SM, TRUE); ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE); - } else if (!strcmp(argv[i], "--debug-focus")) { + } + else if (!strcmp(argv[i], "--debug-focus")) { ob_debug_show_output(TRUE); ob_debug_enable(OB_DEBUG_SM, TRUE); ob_debug_enable(OB_DEBUG_APP_BUGS, TRUE); ob_debug_enable(OB_DEBUG_FOCUS, TRUE); - } else if (!strcmp(argv[i], "--reconfigure")) { + } + else if (!strcmp(argv[i], "--reconfigure")) { remote_control = 1; /* don't make this do anything if it's not in --help .. } else if (!strcmp(argv[i], "--restart")) { remote_control = 2; */ - } else if (!strcmp(argv[i], "--config")) { + } + else if (!strcmp(argv[i], "--config")) { if (i == *argc - 1) /* no args left */ g_printerr(_("--config requires an argument\n")); else { @@ -533,8 +543,11 @@ static void parse_args(gint *argc, gchar **argv) ob_sm_save_file = g_strdup(argv[i+1]); remove_args(argc, argv, i, 2); --i; /* this arg was removed so go back */ + ob_debug_type(OB_DEBUG_SM, "--sm-save-file %s\n", + ob_sm_save_file); } - } else if (!strcmp(argv[i], "--sm-client-id")) { + } + else if (!strcmp(argv[i], "--sm-client-id")) { if (i == *argc - 1) /* no args left */ /* not translated cuz it's sekret */ g_printerr("--sm-client-id requires an argument\n"); @@ -542,21 +555,14 @@ static void parse_args(gint *argc, gchar **argv) ob_sm_id = g_strdup(argv[i+1]); remove_args(argc, argv, i, 2); --i; /* this arg was removed so go back */ + ob_debug_type(OB_DEBUG_SM, "--sm-client-id %s\n", ob_sm_id); } - } else if (!strcmp(argv[i], "--sm-disable")) { + } + else if (!strcmp(argv[i], "--sm-disable")) { ob_sm_use = FALSE; } #endif - else if (!strcmp(argv[i], "--restart-binary")) { - if (i == *argc - 1) /* no args left */ - /* not translated cuz it's sekret */ - g_printerr("--restart-binary requires an argument\n"); - else { - argv[0] = g_strdup(argv[i+1]); - remove_args(argc, argv, i, 2); - --i; /* this arg was removed so go back */ - } - } else { + else { /* this is a memleak.. oh well.. heh */ gchar *err = g_strdup_printf ("Invalid command line argument '%s'\n", argv[i]); diff --git a/openbox/prop.c b/openbox/prop.c index 3861f7c1..e0559068 100644 --- a/openbox/prop.c +++ b/openbox/prop.c @@ -75,6 +75,8 @@ void prop_startup() CREATE(net_close_window, "_NET_CLOSE_WINDOW"); CREATE(net_wm_moveresize, "_NET_WM_MOVERESIZE"); CREATE(net_moveresize_window, "_NET_MOVERESIZE_WINDOW"); + CREATE(net_request_frame_extents, "_NET_REQUEST_FRAME_EXTENTS"); + CREATE(net_restack_window, "_NET_RESTACK_WINDOW"); CREATE(net_startup_id, "_NET_STARTUP_ID"); @@ -95,7 +97,6 @@ void prop_startup() CREATE(net_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW"); CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT"); CREATE(net_frame_extents, "_NET_FRAME_EXTENTS"); - CREATE(net_request_frame_extents, "_NET_REQUEST_FRAME_EXTENTS"); /* CREATE(net_wm_ping, "_NET_WM_PING"); */ #ifdef SYNC diff --git a/openbox/prop.h b/openbox/prop.h index 4f45b6d4..d1d6a516 100644 --- a/openbox/prop.h +++ b/openbox/prop.h @@ -108,6 +108,8 @@ typedef struct Atoms { Atom net_close_window; Atom net_wm_moveresize; Atom net_moveresize_window; + Atom net_request_frame_extents; + Atom net_restack_window; /* helpful hints to apps that aren't used for anything */ Atom net_wm_full_placement; @@ -132,7 +134,6 @@ typedef struct Atoms { Atom net_wm_user_time; Atom net_wm_user_time_window; Atom net_frame_extents; - Atom net_request_frame_extents; /* application protocols */ /* Atom net_wm_ping; */ diff --git a/openbox/resist.c b/openbox/resist.c index 077c4667..729f83fc 100644 --- a/openbox/resist.c +++ b/openbox/resist.c @@ -36,6 +36,8 @@ void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) if (!resist) return; + frame_client_gravity(c->frame, x, y, c->area.width, c->area.height); + w = c->frame->area.width; h = c->frame->area.height; @@ -112,6 +114,8 @@ void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) if (snapx && snapy) break; } + + frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height); } void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y) @@ -126,6 +130,8 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y) if (!resist) return; + frame_client_gravity(c->frame, x, y, c->area.width, c->area.height); + w = c->frame->area.width; h = c->frame->area.height; @@ -173,6 +179,8 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y) else if (cb <= pb && b > pb && b < pb + resist) *y = pb - h + 1; } + + frame_frame_gravity(c->frame, x, y, c->area.width, c->area.height); } void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h, diff --git a/openbox/resist.h b/openbox/resist.h index 7c3ed3c3..d61e7f2e 100644 --- a/openbox/resist.h +++ b/openbox/resist.h @@ -23,7 +23,13 @@ struct _ObClient; #include +/*! @x The client's x destination (in the client's coordinates, not the frame's + @y The client's y destination (in the client's coordinates, not the frame's +*/ void resist_move_windows(struct _ObClient *c, gint resist, gint *x, gint *y); +/*! @x The client's x destination (in the client's coordinates, not the frame's + @y The client's y destination (in the client's coordinates, not the frame's +*/ void resist_move_monitors(struct _ObClient *c, gint resist, gint *x, gint *y); void resist_size_windows(struct _ObClient *c, gint resist, gint *w, gint *h, ObCorner corn); diff --git a/openbox/screen.c b/openbox/screen.c index 190468aa..51f226a5 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -276,6 +276,7 @@ gboolean screen_annex(const gchar *program_name) supported[i++] = prop_atoms.net_wm_user_time_window; supported[i++] = prop_atoms.net_frame_extents; supported[i++] = prop_atoms.net_request_frame_extents; + supported[i++] = prop_atoms.net_restack_window; supported[i++] = prop_atoms.net_startup_id; #ifdef SYNC supported[i++] = prop_atoms.net_wm_sync_request; diff --git a/openbox/session.c b/openbox/session.c index 2c189ed0..b07f1694 100644 --- a/openbox/session.c +++ b/openbox/session.c @@ -136,7 +136,8 @@ void session_shutdown(gboolean permanent) if (sm_conn) { /* if permanent is true then we will change our session state so that the SM won't run us again */ - session_setup_restart_style(!permanent); + if (permanent) + session_setup_restart_style(FALSE); SmcCloseConnection(sm_conn, 0, NULL); @@ -177,6 +178,7 @@ static gboolean session_connect() &cb, oldid, &ob_sm_id, SM_ERR_LEN-1, sm_err); g_free(oldid); + ob_debug_type(OB_DEBUG_SM, "Connected to SM with id: %s\n", ob_sm_id); if (sm_conn == NULL) ob_debug("Failed to connect to session manager: %s\n", sm_err); return sm_conn != NULL; @@ -195,6 +197,7 @@ static void session_setup_program() .vals = &vals }; SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting program: %s\n", sm_argv[0]); SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -215,6 +218,7 @@ static void session_setup_user() .vals = &vals }; SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting user: %s\n", user); SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -223,7 +227,7 @@ static void session_setup_user() static void session_setup_restart_style(gboolean restart) { - char restart_hint = restart ? SmRestartImmediately : SmRestartIfRunning; + gchar restart_hint = restart ? SmRestartImmediately : SmRestartIfRunning; SmPropValue vals = { .value = &restart_hint, @@ -236,6 +240,7 @@ static void session_setup_restart_style(gboolean restart) .vals = &vals }; SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting restart: %d\n", restart); SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -256,6 +261,7 @@ static void session_setup_pid() .vals = &vals }; SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting pid: %s\n", pid); SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -278,6 +284,7 @@ static void session_setup_priority() .vals = &vals }; SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting priority: %d\n", priority); SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -294,13 +301,15 @@ static void session_setup_clone_command() .num_vals = sm_argc, .vals = vals }; + SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting clone command: (%d)\n", sm_argc); for (i = 0; i < sm_argc; ++i) { vals[i].value = sm_argv[i]; vals[i].length = strlen(sm_argv[i]) + 1; + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i].value); } - SmProp *list = ∝ SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); @@ -318,23 +327,29 @@ static void session_setup_restart_command() .num_vals = sm_argc + 4, .vals = vals }; + SmProp *list = ∝ + ob_debug_type(OB_DEBUG_SM, "Setting restart command: (%d)\n", sm_argc+4); for (i = 0; i < sm_argc; ++i) { vals[i].value = sm_argv[i]; vals[i].length = strlen(sm_argv[i]) + 1; + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i].value); } - vals[i].value = g_strdup("--sm-save-file"); - vals[i].length = strlen("--sm-save-file") + 1; - vals[i+1].value = ob_sm_save_file; - vals[i+1].length = strlen(ob_sm_save_file) + 1; + vals[i].value = g_strdup("--sm-client-id"); + vals[i].length = strlen("--sm-client-id") + 1; + vals[i+1].value = ob_sm_id; + vals[i+1].length = strlen(ob_sm_id) + 1; + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i].value); + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i+1].value); - vals[i+2].value = g_strdup("--sm-client-id"); - vals[i+2].length = strlen("--sm-client-id") + 1; - vals[i+3].value = ob_sm_id; - vals[i+3].length = strlen(ob_sm_id) + 1; + vals[i+2].value = g_strdup("--sm-save-file"); + vals[i+2].length = strlen("--sm-save-file") + 1; + vals[i+3].value = ob_sm_save_file; + vals[i+3].length = strlen(ob_sm_save_file) + 1; + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i+2].value); + ob_debug_type(OB_DEBUG_SM, " %s\n", vals[i+3].value); - SmProp *list = ∝ SmcSetProperties(sm_conn, 1, &list); g_free(prop.name); g_free(prop.type); diff --git a/openbox/stacking.c b/openbox/stacking.c index 18747b9c..564b995e 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -25,6 +25,7 @@ #include "group.h" #include "frame.h" #include "window.h" +#include "debug.h" GList *stacking_list = NULL; @@ -416,7 +417,7 @@ void stacking_add_nonintrusive(ObWindow *win) /* insert above its highest parent (or its highest child !) */ it_below = find_highest_relative(client); - if (!it_below) { + if (!it_below && client != focus_client) { /* nothing to put it directly above, so try find the focused client to put it underneath it */ if (focus_client && focus_client->layer == client->layer) { @@ -425,10 +426,16 @@ void stacking_add_nonintrusive(ObWindow *win) } } if (!it_below) { - /* there is no window to put this directly above, so put it at the - bottom */ - stacking_list = g_list_prepend(stacking_list, win); - stacking_lower(win); + if (client == focus_client) { + /* it's focused so put it at the top */ + stacking_list = g_list_append(stacking_list, win); + stacking_raise(win); + } else { + /* there is no window to put this directly above, so put it at the + bottom */ + stacking_list = g_list_prepend(stacking_list, win); + stacking_lower(win); + } } else { /* make sure it's not in the wrong layer though ! */ for (; it_below; it_below = g_list_next(it_below)) @@ -453,3 +460,141 @@ void stacking_add_nonintrusive(ObWindow *win) g_list_free(wins); } } + +/*! Returns TRUE if client is occluded by the sibling. If sibling is NULL it + tries against all other clients. +*/ +static gboolean stacking_occluded(ObClient *client, ObClient *sibling) +{ + GList *it; + gboolean occluded = FALSE; + gboolean found = FALSE; + + /* no need for any looping in this case */ + if (sibling && client->layer != sibling->layer) + return occluded; + + for (it = stacking_list; it; + it = (found ? g_list_previous(it) :g_list_next(it))) + if (WINDOW_IS_CLIENT(it->data)) { + ObClient *c = it->data; + if (found) { + if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area)) + { + if (sibling != NULL) { + if (c == sibling) { + occluded = TRUE; + break; + } + } + else if (c->layer == client->layer) { + occluded = TRUE; + break; + } + else if (c->layer > client->layer) + break; /* we past its layer */ + } + } + else if (c == client) + found = TRUE; + } + return occluded; +} + +/*! Returns TRUE if client is occludes the sibling. If sibling is NULL it tries + against all other clients. +*/ +static gboolean stacking_occludes(ObClient *client, ObClient *sibling) +{ + GList *it; + gboolean occludes = FALSE; + gboolean found = FALSE; + + /* no need for any looping in this case */ + if (sibling && client->layer != sibling->layer) + return occludes; + + for (it = stacking_list; it; it = g_list_next(it)) + if (WINDOW_IS_CLIENT(it->data)) { + ObClient *c = it->data; + if (found) { + if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area)) + { + if (sibling != NULL) { + if (c == sibling) { + occludes = TRUE; + break; + } + } + else if (c->layer == client->layer) { + occludes = TRUE; + break; + } + else if (c->layer > client->layer) + break; /* we past its layer */ + } + } + else if (c == client) + found = TRUE; + } + return occludes; +} + +void stacking_restack_request(ObClient *client, ObClient *sibling, + gint detail, gboolean activate) +{ + switch (detail) { + case Below: + ob_debug("Restack request Below for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + /* just lower it */ + stacking_lower(CLIENT_AS_WINDOW(client)); + break; + case BottomIf: + ob_debug("Restack request BottomIf for client %s sibling " + "%s\n", + client->title, sibling ? sibling->title : "(all)"); + /* if this client occludes sibling (or anything if NULL), then + lower it to the bottom */ + if (stacking_occludes(client, sibling)) + stacking_lower(CLIENT_AS_WINDOW(client)); + break; + case Above: + ob_debug("Restack request Above for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + if (activate) + /* use user=TRUE because it is impossible to get a timestamp + for this */ + client_activate(client, FALSE, TRUE); + else + stacking_raise(CLIENT_AS_WINDOW(client)); + break; + case TopIf: + ob_debug("Restack request TopIf for client %s sibling %s\n", + client->title, sibling ? sibling->title : "(all)"); + if (stacking_occluded(client, sibling)) { + if (activate) + /* use user=TRUE because it is impossible to get a timestamp + for this */ + client_activate(client, FALSE, TRUE); + else + stacking_raise(CLIENT_AS_WINDOW(client)); + } + break; + case Opposite: + ob_debug("Restack request Opposite for client %s sibling " + "%s\n", + client->title, sibling ? sibling->title : "(all)"); + if (stacking_occluded(client, sibling)) { + if (activate) + /* use user=TRUE because it is impossible to get a timestamp + for this */ + client_activate(client, FALSE, TRUE); + else + stacking_raise(CLIENT_AS_WINDOW(client)); + } + else if (stacking_occludes(client, sibling)) + stacking_lower(CLIENT_AS_WINDOW(client)); + break; + } +} diff --git a/openbox/stacking.h b/openbox/stacking.h index 2391f650..afa4a6c6 100644 --- a/openbox/stacking.h +++ b/openbox/stacking.h @@ -59,4 +59,18 @@ void stacking_lower(ObWindow *window); */ void stacking_below(ObWindow *window, ObWindow *below); +/*! Restack a window based upon a sibling (or all windows) in various ways. + @param client The client to be restacked + @param sibling Another client to compare to, or NULL to compare to all + windows + @param detail One of Above, Below, TopIf, BottomIf, Opposite + @param activate If TRUE, and if the window is going to be raised, it will + be activated instead + See http://tronche.com/gui/x/xlib/window/configure.html for details on + how each detail works with and without a sibling. +*/ +void stacking_restack_request(struct _ObClient *client, + struct _ObClient *sibling, + gint detail, gboolean); + #endif