summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2003-05-09 16:57:17 +0000
committerDana Jansens <danakj@orodu.net>2003-05-09 16:57:17 +0000
commitf26f23de50cb7941a7702198e3b4d1b2f9de062e (patch)
treeec1d73c8e977d86e9231676c51e684a3415e7a0e /openbox
parent60065663ba9dc448dcf90fd200cd459bcdb9ef9c (diff)
all my changes while i was offline.
better alt-tabbing. better transient handling. i dont even know. lots of fucking cool shit so WATCH the FUCK OUT.
Diffstat (limited to 'openbox')
-rw-r--r--openbox/Makefile.am10
-rw-r--r--openbox/client.c246
-rw-r--r--openbox/client.h37
-rw-r--r--openbox/config.c8
-rw-r--r--openbox/config.h2
-rw-r--r--openbox/event.c55
-rw-r--r--openbox/extensions.c17
-rw-r--r--openbox/extensions.h16
-rw-r--r--openbox/focus.c82
-rw-r--r--openbox/framerender.c31
-rw-r--r--openbox/framerender.h3
-rw-r--r--openbox/menu.c10
-rw-r--r--openbox/moveresize.c42
-rw-r--r--openbox/moveresize.h1
-rw-r--r--openbox/openbox.c3
-rw-r--r--openbox/parse.h2
-rw-r--r--openbox/parse.l2
-rw-r--r--openbox/parse.y6
-rw-r--r--openbox/screen.c17
-rw-r--r--openbox/screen.h2
-rw-r--r--openbox/stacking.c18
21 files changed, 391 insertions, 219 deletions
diff --git a/openbox/Makefile.am b/openbox/Makefile.am
index a82473b5..8e027ddb 100644
--- a/openbox/Makefile.am
+++ b/openbox/Makefile.am
@@ -14,22 +14,24 @@ CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) $(GMODULE_CFLAGS) \
-DBINARY=\"$(binary)\"
INCLUDES=-I..
-LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) @LIBS@
+LIBS=$(X_LIBS) $(XFT_LIBS) $(XINERAMA_LIBS) $(XKB_LIBS) $(XRANDR_LIBS) \
+ $(VIDMODE_LIBS) $(XSHAPE_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) @LIBS@ \
+ @LIBINTL@
bin_PROGRAMS=$(binary)
-openbox3_LDADD=@LIBINTL@ -lobrender -L../render
+openbox3_LDADD=-lobrender -L../render
openbox3_LDFLAGS=-export-dynamic
openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
extensions.c focus.c frame.c grab.c menu.c menu_render.c \
openbox.c framerender.c parse.c plugin.c prop.c screen.c \
stacking.c dispatch.c event.c group.c timer.c xerror.c \
- moveresize.c startup.c
+ moveresize.c startup.c popup.c
noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \
- stacking.h timer.h xerror.h moveresize.h startup.h
+ stacking.h timer.h xerror.h moveresize.h startup.h popup.h
# kill the implicit .c.y rule
%.c: %.y
diff --git a/openbox/client.c b/openbox/client.c
index 47be1bd9..2cd92125 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -38,10 +38,7 @@ static void client_get_gravity(Client *self);
static void client_showhide(Client *self);
static void client_change_allowed_actions(Client *self);
static void client_change_state(Client *self);
-static void client_move_onscreen(Client *self);
-static Client *search_focus_tree(Client *node, Client *skip);
static void client_apply_startup_state(Client *self);
-static Client *search_modal_tree(Client *node, Client *skip);
static guint map_hash(Window *w) { return *w; }
static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; }
@@ -82,6 +79,37 @@ void client_set_list()
stacking_set_list();
}
+/*
+void client_foreach_transient(Client *self, ClientForeachFunc func, void *data)
+{
+ GSList *it;
+
+ for (it = self->transients; it; it = it->next) {
+ if (!func(it->data, data)) return;
+ client_foreach_transient(it->data, func, data);
+ }
+}
+
+void client_foreach_ancestor(Client *self, ClientForeachFunc func, void *data)
+{
+ if (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {
+ if (!func(self->transient_for, data)) return;
+ client_foreach_ancestor(self->transient_for, func, data);
+ } else {
+ GSList *it;
+
+ for (it = self->group->members; it; it = it->next)
+ if (it->data != self &&
+ ((Client*)it->data)->transient_for != TRAN_GROUP) {
+ if (!func(it->data, data)) return;
+ client_foreach_ancestor(it->data, func, data);
+ }
+ }
+ }
+}
+*/
+
void client_manage_all()
{
unsigned int i, j, nchild;
@@ -137,7 +165,7 @@ void client_manage_all()
if (config_focus_new) {
active = g_hash_table_lookup(client_map, &startup_active);
- if (!active || !client_focus(active))
+ if (!(active && client_focus(active)))
focus_fallback(Fallback_NoFocus);
}
}
@@ -266,7 +294,7 @@ void client_manage(Window window)
(!parent && (!self->group ||
!self->group->members->next)))))) ||
(parent && (client_focused(parent) ||
- search_focus_tree(parent, parent)))) {
+ client_search_focus_tree(parent)))) {
client_focus(self);
}
}
@@ -399,7 +427,7 @@ void client_unmanage(Client *self)
client_set_list();
}
-static void client_move_onscreen(Client *self)
+void client_move_onscreen(Client *self)
{
Rect *a;
int x = self->frame->area.x, y = self->frame->area.y;
@@ -415,7 +443,7 @@ static void client_move_onscreen(Client *self)
y = a->y;
frame_frame_gravity(self->frame, &x, &y); /* get where the client
- should be */
+ should be */
client_configure(self , Corner_TopLeft, x, y,
self->area.width, self->area.height,
TRUE, TRUE);
@@ -496,6 +524,7 @@ static void client_get_all(Client *self)
/* defaults */
self->frame = NULL;
self->title = self->icon_title = NULL;
+ self->title_count = 1;
self->name = self->class = self->role = NULL;
self->wmstate = NormalState;
self->transient = FALSE;
@@ -529,7 +558,6 @@ static void client_get_all(Client *self)
client_setup_decor_and_functions(self);
client_update_title(self);
- client_update_icon_title(self);
client_update_class(self);
client_update_strut(self);
client_update_icons(self);
@@ -782,10 +810,6 @@ void client_get_type(Client *self)
else
self->type = Type_Normal;
}
-
- /* this makes sure that these windows appear on all desktops */
- if (self->type == Type_Desktop)
- self->desktop = DESKTOP_ALL;
}
void client_update_protocols(Client *self)
@@ -991,11 +1015,19 @@ void client_setup_decor_and_functions(Client *self)
client_change_allowed_actions(self);
if (self->frame) {
+ /* this makes sure that these windows appear on all desktops */
+ if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL)
+ client_set_desktop(self, DESKTOP_ALL, FALSE);
+
/* change the decors on the frame, and with more/less decorations,
we may also need to be repositioned */
frame_adjust_area(self->frame, TRUE, TRUE);
/* with new decor, the window's maximized size may change */
client_remaximize(self);
+ } else {
+ /* this makes sure that these windows appear on all desktops */
+ if (self->type == Type_Desktop && self->desktop != DESKTOP_ALL)
+ self->desktop = DESKTOP_ALL;
}
}
@@ -1004,7 +1036,9 @@ static void client_change_allowed_actions(Client *self)
guint32 actions[9];
int num = 0;
- actions[num++] = prop_atoms.net_wm_action_change_desktop;
+ /* desktop windows are kept on all desktops */
+ if (self->type != Type_Desktop)
+ actions[num++] = prop_atoms.net_wm_action_change_desktop;
if (self->functions & Func_Shade)
actions[num++] = prop_atoms.net_wm_action_shade;
@@ -1154,6 +1188,9 @@ void client_update_wmhints(Client *self)
void client_update_title(Client *self)
{
+ GList *it;
+ guint32 nums;
+ guint i;
char *data = NULL;
g_free(self->title);
@@ -1165,6 +1202,29 @@ void client_update_title(Client *self)
data = g_strdup("Unnamed Window");
/* look for duplicates and append a number */
+ nums = 0;
+ for (it = client_list; it; it = it->next)
+ if (it->data != self) {
+ Client *c = it->data;
+ if (0 == strncmp(c->title, data, strlen(data)))
+ nums |= 1 << c->title_count;
+ }
+ /* find first free number */
+ for (i = 1; i <= 32; ++i)
+ if (!(nums & (1 << i))) {
+ if (self->title_count == 1 || i == 1)
+ self->title_count = i;
+ break;
+ }
+ /* dont display the number for the first window */
+ if (self->title_count > 1) {
+ char *vdata, *ndata;
+ ndata = g_strdup_printf(" - [%u]", self->title_count);
+ vdata = g_strconcat(data, ndata, NULL);
+ g_free(ndata);
+ g_free(data);
+ data = vdata;
+ }
PROP_SETS(self->window, net_wm_visible_name, data);
@@ -1172,12 +1232,9 @@ void client_update_title(Client *self)
if (self->frame)
frame_adjust_title(self->frame);
-}
-
-void client_update_icon_title(Client *self)
-{
- char *data = NULL;
+ /* update the icon title */
+ data = NULL;
g_free(self->icon_title);
/* try netwm */
@@ -1186,6 +1243,16 @@ void client_update_icon_title(Client *self)
if (!PROP_GETS(self->window, wm_icon_name, locale, &data))
data = g_strdup("Unnamed Window");
+ /* append the title count, dont display the number for the first window */
+ if (self->title_count > 1) {
+ char *vdata, *ndata;
+ ndata = g_strdup_printf(" - [%u]", self->title_count);
+ vdata = g_strconcat(data, ndata, NULL);
+ g_free(ndata);
+ g_free(data);
+ data = vdata;
+ }
+
PROP_SETS(self->window, net_wm_visible_icon_name, data);
self->icon_title = data;
@@ -1342,28 +1409,70 @@ static void client_change_state(Client *self)
frame_adjust_state(self->frame);
}
-static Client *search_focus_tree(Client *node, Client *skip)
+Client *client_search_focus_tree(Client *self)
{
GSList *it;
Client *ret;
- for (it = node->transients; it != NULL; it = it->next) {
- Client *c = it->data;
- if (c == skip) continue; /* circular? */
- if ((ret = search_focus_tree(c, skip))) return ret;
- if (client_focused(c)) return c;
+ for (it = self->transients; it != NULL; it = it->next) {
+ if (client_focused(it->data)) return it->data;
+ if ((ret = client_search_focus_tree(it->data))) return ret;
}
return NULL;
}
+Client *client_search_focus_tree_full(Client *self)
+{
+ if (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {
+ return client_search_focus_tree_full(self->transient_for);
+ } else {
+ GSList *it;
+
+ for (it = self->group->members; it; it = it->next)
+ if (((Client*)it->data)->transient_for != TRAN_GROUP) {
+ Client *c;
+ if ((c = client_search_focus_tree_full(it->data)))
+ return c;
+ }
+ return NULL;
+ }
+ } else {
+ /* this function checks the whole tree, the client_search_focus_tree
+ does not, so we need to check this window */
+ if (client_focused(self))
+ return self;
+ return client_search_focus_tree(self);
+ }
+}
+
+static StackLayer calc_layer(Client *self)
+{
+ StackLayer l;
+
+ if (self->iconic) l = Layer_Icon;
+ else if (self->fullscreen) l = Layer_Fullscreen;
+ else if (self->type == Type_Desktop) l = Layer_Desktop;
+ else if (self->type == Type_Dock) {
+ if (!self->below) l = Layer_Top;
+ else l = Layer_Normal;
+ }
+ else if (self->above) l = Layer_Above;
+ else if (self->below) l = Layer_Below;
+ else l = Layer_Normal;
+
+ return l;
+}
+
static void calc_recursive(Client *self, Client *orig, StackLayer l,
gboolean raised)
{
- StackLayer old;
+ StackLayer old, own;
GSList *it;
old = self->layer;
- self->layer = l;
+ own = calc_layer(self);
+ self->layer = l > own ? l : own;
for (it = self->transients; it; it = it->next)
calc_recursive(it->data, orig, l, raised ? raised : l != old);
@@ -1376,7 +1485,6 @@ static void calc_recursive(Client *self, Client *orig, StackLayer l,
void client_calc_layer(Client *self)
{
StackLayer l;
- gboolean f;
Client *orig;
orig = self;
@@ -1397,25 +1505,7 @@ void client_calc_layer(Client *self)
}
}
- /* is us or one of our transients focused? */
- if (client_focused(self))
- f = TRUE;
- else if (search_focus_tree(self, self))
- f = TRUE;
- else
- f = FALSE;
-
- if (self->iconic) l = Layer_Icon;
- /* fullscreen windows are only in the fullscreen layer while focused */
- else if (self->fullscreen && f) l = Layer_Fullscreen;
- else if (self->type == Type_Desktop) l = Layer_Desktop;
- else if (self->type == Type_Dock) {
- if (!self->below) l = Layer_Top;
- else l = Layer_Normal;
- }
- else if (self->above) l = Layer_Above;
- else if (self->below) l = Layer_Below;
- else l = Layer_Normal;
+ l = calc_layer(self);
calc_recursive(self, orig, l, FALSE);
}
@@ -1698,31 +1788,30 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
{
GSList *it;
- /* move up the transient chain as far as possible first if deiconifying */
- if (!iconic)
- while (self->transient_for) {
- if (self->transient_for != TRAN_GROUP) {
- if (self->transient_for->iconic == iconic)
- break;
- self = self->transient_for;
- } else {
- GSList *it;
-
- /* the check for TRAN_GROUP is to prevent an infinate loop with
- 2 transients of the same group at the head of the group's
- members list */
- for (it = self->group->members; it; it = it->next) {
- Client *c = it->data;
+ /* move up the transient chain as far as possible first */
+ if (self->transient_for) {
+ if (self->transient_for != TRAN_GROUP) {
+ if (self->transient_for->iconic != iconic) {
+ client_iconify(self->transient_for, iconic, curdesk);
+ return;
+ }
+ } else {
+ GSList *it;
- if (c != self && c->transient_for->iconic != iconic &&
- c->transient_for != TRAN_GROUP) {
- self = it->data;
- break;
- }
+ /* the check for TRAN_GROUP is to prevent an infinate loop with
+ 2 transients of the same group at the head of the group's
+ members list */
+ for (it = self->group->members; it; it = it->next) {
+ Client *c = it->data;
+ if (c != self && c->iconic != iconic &&
+ c->transient_for != TRAN_GROUP) {
+ client_iconify(it->data, iconic, curdesk);
+ break;
}
- if (it == NULL) break;
}
+ if (it != NULL) return;
}
+ }
if (self->iconic == iconic) return; /* nothing to do */
@@ -1738,13 +1827,18 @@ void client_iconify(Client *self, gboolean iconic, gboolean curdesk)
and because the ICCCM tells us to! */
XUnmapWindow(ob_display, self->window);
- /* update the focus lists.. iconic windows go to the bottom */
- focus_order_to_bottom(self);
+ /* update the focus lists.. iconic windows go to the bottom of the
+ list, put the new iconic window at the 'top of the bottom'. */
+ focus_order_to_top(self);
} else {
if (curdesk)
client_set_desktop(self, screen_desktop, FALSE);
self->wmstate = self->shaded ? IconicState : NormalState;
XMapWindow(ob_display, self->window);
+
+ /* this puts it after the current focused window */
+ focus_order_remove(self);
+ focus_order_add_new(self);
}
client_change_state(self);
client_showhide(self);
@@ -1941,25 +2035,19 @@ void client_set_desktop(Client *self, guint target, gboolean donthide)
dispatch_client(Event_Client_Desktop, self, target, old);
}
-static Client *search_modal_tree(Client *node, Client *skip)
+Client *client_search_modal_child(Client *self)
{
GSList *it;
Client *ret;
- for (it = node->transients; it != NULL; it = it->next) {
+ for (it = self->transients; it != NULL; it = it->next) {
Client *c = it->data;
- if (c == skip) continue; /* circular? */
- if ((ret = search_modal_tree(c, skip))) return ret;
+ if ((ret = client_search_modal_child(c))) return ret;
if (c->modal) return c;
}
return NULL;
}
-Client *client_find_modal_child(Client *self)
-{
- return search_modal_tree(self, self);
-}
-
gboolean client_validate(Client *self)
{
XEvent e;
@@ -2118,7 +2206,7 @@ Client *client_focus_target(Client *self)
Client *child;
/* if we have a modal child, then focus it, not us */
- child = client_find_modal_child(self);
+ child = client_search_modal_child(self);
if (child) return child;
return self;
}
diff --git a/openbox/client.h b/openbox/client.h
index e7ee3085..faa04e63 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -112,6 +112,7 @@ typedef enum {
typedef struct Client {
Window window;
+ /*! The window's decorations. NULL while the window is being managed! */
struct Frame *frame;
/*! The number of unmap events to ignore on the window */
@@ -133,10 +134,13 @@ typedef struct Client {
GSList *transients;
/*! The desktop on which the window resides (0xffffffff for all
desktops) */
- unsigned int desktop;
+ guint desktop;
/*! Normal window title */
gchar *title;
+ /*! The count for the title. When another window with the same title
+ exists, a count will be appended to it. */
+ guint title_count;
/*! Window title when iconified */
gchar *icon_title;
@@ -341,6 +345,11 @@ gboolean client_focused(Client *self);
void client_configure(Client *self, Corner anchor, int x, int y, int w, int h,
gboolean user, gboolean final);
+/*! Moves a client so that it is on screen if it is entirely out of the
+ viewable screen.
+*/
+void client_move_onscreen(Client *self);
+
/*! Fullscreen's or unfullscreen's the client window
@param fs true if the window should be made fullscreen; false if it should
be returned to normal state.
@@ -389,11 +398,6 @@ void client_kill(Client *self);
desktop has been changed. Generally this should be FALSE. */
void client_set_desktop(Client *self, guint target, gboolean donthide);
-/*! Return a modal child of the client window
- @return A modal child of the client window, or 0 if none was found.
-*/
-Client *client_find_modal_child(Client *self);
-
/*! Validate client, by making sure no Destroy or Unmap events exist in
the event queue for the window.
@return true if the client is valid; false if the client has already
@@ -440,10 +444,8 @@ void client_update_normal_hints(Client *self);
process.
*/
void client_update_wmhints(Client *self);
-/*! Updates the window's title */
+/*! Updates the window's title and icon title */
void client_update_title(Client *self);
-/*! Updates the window's icon title */
-void client_update_icon_title(Client *self);
/*! Updates the window's application name and class */
void client_update_class(Client *self);
/*! Updates the strut for the client */
@@ -464,4 +466,21 @@ void client_get_type(Client *self);
Icon *client_icon(Client *self, int w, int h);
+/*! Searches a client's transients for a focused window. The function does not
+ check for the passed client, only for its transients.
+ If no focused transient is found, NULL is returned.
+*/
+Client *client_search_focus_tree(Client *self);
+
+/*! Searches a client's transient tree for a focused window. The function
+ searches up the tree and down other branches as well as the passed client's.
+ If no focused client is found, NULL is returned.
+*/
+Client *client_search_focus_tree_full(Client *self);
+
+/*! Return a modal child of the client window
+ @return A modal child of the client window, or 0 if none was found.
+*/
+Client *client_search_modal_child(Client *self);
+
#endif
diff --git a/openbox/config.c b/openbox/config.c
index db8856e6..959f6c2c 100644
--- a/openbox/config.c
+++ b/openbox/config.c
@@ -5,6 +5,7 @@ gboolean config_focus_new;
gboolean config_focus_follow;
gboolean config_focus_last;
gboolean config_focus_last_on_desktop;
+gboolean config_focus_popup;
char *config_theme;
@@ -37,6 +38,12 @@ static void parse_focus(char *name, ParseToken *value)
else {
config_focus_last_on_desktop = value->data.bool;
}
+ } else if (!g_ascii_strcasecmp(name, "cyclingdialog")) {
+ if (value->type != TOKEN_BOOL)
+ yyerror("invalid value");
+ else {
+ config_focus_popup = value->data.bool;
+ }
} else
yyerror("invalid option");
parse_free_token(value);
@@ -95,6 +102,7 @@ void config_startup()
config_focus_follow = FALSE;
config_focus_last = TRUE;
config_focus_last_on_desktop = TRUE;
+ config_focus_popup = TRUE;
parse_reg_section("focus", NULL, parse_focus);
diff --git a/openbox/config.h b/openbox/config.h
index 27b00dd7..081561cb 100644
--- a/openbox/config.h
+++ b/openbox/config.h
@@ -11,6 +11,8 @@ extern gboolean config_focus_follow;
extern gboolean config_focus_last;
/*! Focus the last focused window as a fallback when switching desktops */
extern gboolean config_focus_last_on_desktop;
+/*! Show a popup dialog while cycling focus */
+extern gboolean config_focus_popup;
/* The name of the theme */
char *config_theme;
diff --git a/openbox/event.c b/openbox/event.c
index eea6583b..39dfca5c 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -144,6 +144,9 @@ static Window event_get_window(XEvent *e)
case ConfigureRequest:
window = e->xconfigurerequest.window;
break;
+ case ConfigureNotify:
+ window = e->xconfigure.window;
+ break;
default:
#ifdef XKB
if (extensions_xkb && e->type == extensions_xkb_event_basep) {
@@ -308,6 +311,16 @@ static gboolean event_ignore(XEvent *e, Client *client)
#ifdef DEBUG_FOCUS
g_message("found pending FocusIn");
#endif
+ /* is the focused window getting a FocusOut/In back to
+ itself? */
+ if (fe.xfocus.window == e->xfocus.window) {
+#ifdef DEBUG_FOCUS
+ g_message("focused window got an Out/In back to "
+ "itself IGNORED both");
+#endif
+ return TRUE;
+ }
+
/* once all the FocusOut's have been dealt with, if there
is a FocusIn still left and it is valid, then use it */
event_process(&fe);
@@ -451,6 +464,21 @@ static void event_handle_root(XEvent *e)
else if (e->xproperty.atom == prop_atoms.net_desktop_layout)
screen_update_layout();
break;
+ case ConfigureNotify:
+#ifdef XRANDR
+ XRRUpdateConfiguration(e);
+#endif
+ if (e->xconfigure.width != screen_physical_size.width ||
+ e->xconfigure.height != screen_physical_size.height)
+ screen_resize(e->xconfigure.width, e->xconfigure.height);
+ break;
+ default:
+ ;
+#ifdef VIDMODE
+ if (extensions_vidmode && e->type == extensions_vidmode_event_basep) {
+ g_message("VIDMODE EVENT");
+ }
+#endif
}
}
@@ -490,15 +518,25 @@ static void event_handle_client(Client *client, XEvent *e)
}
break;
case FocusIn:
+#ifdef DEBUG_FOCUS
+ g_message("FocusIn on client for %lx", client->window);
+#endif
focus_set_client(client);
+ frame_adjust_focus(client->frame, TRUE);
+ break;
case FocusOut:
#ifdef DEBUG_FOCUS
- g_message("Focus%s on client for %lx", (e->type==FocusIn?"In":"Out"),
- client->window);
+ g_message("FocusOut on client for %lx", client->window);
#endif
- /* focus state can affect the stacking layer */
- client_calc_layer(client);
- frame_adjust_focus(client->frame, e->type == FocusIn);
+ /* are we a fullscreen window or a transient of one? (checks layer)
+ if we are then we need to be iconified since we are losing focus
+ */
+ if (client->layer == Layer_Fullscreen && !client->iconic &&
+ !client_search_focus_tree_full(client))
+ /* iconify fullscreen windows when they and their transients
+ aren't focused */
+ client_iconify(client, TRUE, TRUE);
+ frame_adjust_focus(client->frame, FALSE);
break;
case EnterNotify:
if (client_normal(client)) {
@@ -797,11 +835,10 @@ static void event_handle_client(Client *client, XEvent *e)
client_setup_decor_and_functions(client);
}
else if (msgtype == prop_atoms.net_wm_name ||
- msgtype == prop_atoms.wm_name)
- client_update_title(client);
- else if (msgtype == prop_atoms.net_wm_icon_name ||
+ msgtype == prop_atoms.wm_name ||
+ msgtype == prop_atoms.net_wm_icon_name ||
msgtype == prop_atoms.wm_icon_name)
- client_update_icon_title(client);
+ client_update_title(client);
else if (msgtype == prop_atoms.wm_class)
client_update_class(client);
else if (msgtype == prop_atoms.wm_protocols) {
diff --git a/openbox/extensions.c b/openbox/extensions.c
index 3fe43194..be1ac547 100644
--- a/openbox/extensions.c
+++ b/openbox/extensions.c
@@ -7,7 +7,10 @@ gboolean extensions_shape = FALSE;
int extensions_shape_event_basep;
gboolean extensions_xinerama = FALSE;
int extensions_xinerama_event_basep;
-
+gboolean extensions_randr = FALSE;
+int extensions_randr_event_basep;
+gboolean extensions_vidmode = FALSE;
+int extensions_vidmode_event_basep;
void extensions_query_all()
{
@@ -31,4 +34,16 @@ void extensions_query_all()
XineramaQueryExtension(ob_display, &extensions_xinerama_event_basep,
&junk);
#endif
+
+#ifdef XRANDR
+ extensions_randr =
+ XRRQueryExtension(ob_display, &extensions_randr_event_basep,
+ &junk);
+#endif
+
+#ifdef VIDMODE
+ extensions_vidmode =
+ XF86VidModeQueryExtension(ob_display, &extensions_vidmode_event_basep,
+ &junk);
+#endif
}
diff --git a/openbox/extensions.h b/openbox/extensions.h
index 3c11076a..cda1bf7e 100644
--- a/openbox/extensions.h
+++ b/openbox/extensions.h
@@ -11,6 +11,12 @@
#ifdef XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
+#ifdef XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#ifdef VIDMODE
+#include <X11/extensions/xf86vmode.h>
+#endif
#include <glib.h>
/*! Does the display have the XKB extension? */
@@ -28,6 +34,16 @@ extern gboolean extensions_xinerama;
/*! Base for events for the Xinerama extension */
extern int extensions_xinerama_event_basep;
+/*! Does the display have the RandR extension? */
+extern gboolean extensions_randr;
+/*! Base for events for the Randr extension */
+extern int extensions_randr_event_basep;
+
+/*! Does the display have the VidMode extension? */
+extern gboolean extensions_vidmode;
+/*! Base for events for the VidMode extension */
+extern int extensions_vidmode_event_basep;
+
void extensions_query_all();
#endif
diff --git a/openbox/focus.c b/openbox/focus.c
index 5e47dd28..7a2d079e 100644
--- a/openbox/focus.c
+++ b/openbox/focus.c
@@ -1,6 +1,5 @@
#include "event.h"
#include "openbox.h"
-#include "grab.h"
#include "framerender.h"
#include "client.h"
#include "config.h"
@@ -12,6 +11,7 @@
#include "focus.h"
#include "parse.h"
#include "stacking.h"
+#include "popup.h"
#include <X11/Xlib.h>
#include <glib.h>
@@ -23,6 +23,7 @@ GList **focus_order = NULL; /* these lists are created when screen_startup
Window focus_backup = None;
static Client *focus_cycle_target = NULL;
+static Popup *focus_cycle_popup = NULL;
void focus_startup()
{
@@ -32,6 +33,7 @@ void focus_startup()
XSetWindowAttributes attrib;
focus_client = NULL;
+ focus_cycle_popup = popup_new(TRUE);
attrib.override_redirect = TRUE;
focus_backup = XCreateWindow(ob_display, ob_root,
@@ -54,6 +56,9 @@ void focus_shutdown()
g_free(focus_order);
focus_order = NULL;
+ popup_free(focus_cycle_popup);
+ focus_cycle_popup = NULL;
+
XDestroyWindow(ob_display, focus_backup);
/* reset focus to root */
@@ -98,9 +103,11 @@ void focus_set_client(Client *client)
if (client != NULL)
push_to_top(client);
- /* set the NET_ACTIVE_WINDOW hint */
- active = client ? client->window : None;
- PROP_SET32(ob_root, net_active_window, window, active);
+ /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */
+ if (ob_state != State_Exiting) {
+ active = client ? client->window : None;
+ PROP_SET32(ob_root, net_active_window, window, active);
+ }
if (focus_client != NULL)
dispatch_client(Event_Client_Focus, focus_client, 0, 0);
@@ -206,7 +213,11 @@ void focus_fallback(FallbackType type)
for (it = focus_order[screen_desktop]; it != NULL; it = it->next)
if (type != Fallback_Unfocusing || it->data != old)
- if (client_normal(it->data) && client_focus(it->data))
+ if (client_normal(it->data) &&
+ /* dont fall back to 'anonymous' fullscreen windows. theres no
+ checks for this is in transient/group fallbacks. */
+ !((Client*)it->data)->fullscreen &&
+ client_focus(it->data))
return;
/* nothing to focus */
@@ -215,38 +226,28 @@ void focus_fallback(FallbackType type)
static void popup_cycle(Client *c, gboolean show)
{
- XSetWindowAttributes attrib;
- static Window coords = None;
-
- if (coords == None) {
- attrib.override_redirect = TRUE;
- coords = XCreateWindow(ob_display, ob_root,
- 0, 0, 1, 1, 0, render_depth, InputOutput,
- render_visual, CWOverrideRedirect, &attrib);
- g_assert(coords != None);
-
- grab_pointer(TRUE, None);
-
- XMapWindow(ob_display, coords);
- }
-
if (!show) {
- XDestroyWindow(ob_display, coords);
- coords = None;
-
- grab_pointer(FALSE, None);
+ popup_hide(focus_cycle_popup);
} else {
Rect *a;
- Size s;
a = screen_area(c->desktop);
-
- framerender_size_popup_label(c->title, &s);
- XMoveResizeWindow(ob_display, coords,
- a->x + (a->width - s.width) / 2,
- a->y + (a->height - s.height) / 2,
- s.width, s.height);
- framerender_popup_label(coords, &s, c->title);
+ popup_position(focus_cycle_popup, CenterGravity,
+ a->x + a->width / 2, a->y + a->height / 2);
+/* popup_size(focus_cycle_popup, a->height/2, a->height/16);
+ popup_show(focus_cycle_popup, c->title,
+ client_icon(c, a->height/16, a->height/16));
+*/
+ /* XXX the size and the font extents need to be related on some level
+ */
+ popup_size(focus_cycle_popup, 320, 48);
+
+ /* use the transient's parent's title/icon */
+ while (c->transient_for && c->transient_for != TRAN_GROUP)
+ c = c->transient_for;
+
+ popup_show(focus_cycle_popup, (c->iconic ? c->icon_title : c->title),
+ client_icon(c, 48, 48));
}
}
@@ -294,15 +295,18 @@ Client *focus_cycle(gboolean forward, gboolean linear, gboolean done,
it = it->prev;
if (it == NULL) it = g_list_last(list);
}
- ft = client_focus_target(it->data);
- if (ft == it->data && client_normal(ft) &&
+ /*ft = client_focus_target(it->data);*/
+ ft = it->data;
+ if (ft->transients == NULL && /*ft == it->data &&*/client_normal(ft) &&
(ft->can_focus || ft->focus_notify) &&
(ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) {
- if (focus_cycle_target)
- frame_adjust_focus(focus_cycle_target->frame, FALSE);
- focus_cycle_target = ft;
- frame_adjust_focus(focus_cycle_target->frame, TRUE);
- popup_cycle(ft, TRUE);
+ if (ft != focus_cycle_target) { /* prevents flicker */
+ if (focus_cycle_target)
+ frame_adjust_focus(focus_cycle_target->frame, FALSE);
+ focus_cycle_target = ft;
+ frame_adjust_focus(focus_cycle_target->frame, TRUE);
+ }
+ popup_cycle(ft, config_focus_popup);
return ft;
}
} while (it != start);
diff --git a/openbox/framerender.c b/openbox/framerender.c
index 0f4c6659..737dfe95 100644
--- a/openbox/framerender.c
+++ b/openbox/framerender.c
@@ -218,34 +218,3 @@ static void framerender_close(Frame *self, Appearance *a)
theme_button_size, theme_button_size);
paint(self->close, a);
}
-
-void framerender_popup_label(Window win, Size *sz, char *text)
-{
- Appearance *a;
-
- a = theme_app_hilite_label;
- a->texture[0].data.text.string = text;
- RECT_SET(a->area, 0, 0, sz->width, sz->height);
- a->texture[0].position = a->area;
- a->texture[0].position.x += theme_bevel;
- a->texture[0].position.y += theme_bevel;
- a->texture[0].position.width -= theme_bevel * 2;
- a->texture[0].position.height -= theme_bevel * 2;
-
- XSetWindowBorderWidth(ob_display, win, theme_bwidth);
- XSetWindowBorder(ob_display, win, theme_b_color->pixel);
-
- paint(win, a);
-}
-
-void framerender_size_popup_label(char *text, Size *sz)
-{
- Appearance *a;
-
- a = theme_app_hilite_label;
- a->texture[0].data.text.string = text;
-
- appearance_minsize(a, &sz->width, &sz->height);
- sz->width += theme_bevel * 2;
- sz->height += theme_bevel * 2;
-}
diff --git a/openbox/framerender.h b/openbox/framerender.h
index c02c9e7f..9655a932 100644
--- a/openbox/framerender.h
+++ b/openbox/framerender.h
@@ -5,7 +5,4 @@
void framerender_frame(Frame *self);
-void framerender_popup_label(Window win, Size *sz, char *text);
-void framerender_size_popup_label(char *text, Size *sz);
-
#endif
diff --git a/openbox/menu.c b/openbox/menu.c
index 42a183ab..88eef9c5 100644
--- a/openbox/menu.c
+++ b/openbox/menu.c
@@ -76,6 +76,16 @@ void menu_startup()
menu_add_entry(m, menu_entry_new("--", NULL));
a = action_from_string("exit");
menu_add_entry(m, menu_entry_new("exit", a));
+
+ m = menu_new("client menu", "client", NULL);
+ a = action_from_string("iconify");
+ menu_add_entry(m, menu_entry_new("iconify", a));
+ a = action_from_string("toggleshade");
+ menu_add_entry(m, menu_entry_new("(un)shade", a));
+ a = action_from_string("togglemaximizefull");
+ menu_add_entry(m, menu_entry_new("(un)maximize", a));
+ a = action_from_string("close");
+ menu_add_entry(m, menu_entry_new("close", a));
}
void menu_shutdown()
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index 08d96ad6..7878b9f2 100644
--- a/openbox/moveresize.c
+++ b/openbox/moveresize.c
@@ -4,6 +4,7 @@
#include "client.h"
#include "dispatch.h"
#include "openbox.h"
+#include "popup.h"
#include <X11/Xlib.h>
#include <glib.h>
@@ -13,7 +14,6 @@ Client *moveresize_client = NULL;
static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
-static Window coords = None;
static int start_x, start_y, start_cx, start_cy, start_cw, start_ch;
static int cur_x, cur_y;
static guint button;
@@ -23,6 +23,8 @@ static Corner lockcorner;
static guint button_return, button_escape, button_left, button_right,
button_up, button_down;
+static Popup *popup = NULL;
+
#define POPUP_X (10)
#define POPUP_Y (10)
@@ -34,29 +36,24 @@ void moveresize_startup()
button_right = XKeysymToKeycode(ob_display, XStringToKeysym("Right"));
button_up = XKeysymToKeycode(ob_display, XStringToKeysym("Up"));
button_down = XKeysymToKeycode(ob_display, XStringToKeysym("Down"));
+
+ popup = popup_new(FALSE);
+ popup_size_to_string(popup, "W: 0000 W: 0000");
+ popup_position(popup, NorthWestGravity, POPUP_X, POPUP_Y);
+}
+
+void moveresize_shutdown()
+{
+ popup_free(popup);
+ popup = NULL;
}
static void popup_coords(char *format, int a, int b)
{
- XSetWindowAttributes attrib;
- Size s;
char *text;
- if (coords == None) {
- attrib.override_redirect = TRUE;
- coords = XCreateWindow(ob_display, ob_root,
- 0, 0, 1, 1, 0, render_depth, InputOutput,
- render_visual, CWOverrideRedirect, &attrib);
- g_assert(coords != None);
-
- XMapWindow(ob_display, coords);
- }
-
text = g_strdup_printf(format, a, b);
- framerender_size_popup_label(text, &s);
- XMoveResizeWindow(ob_display, coords,
- POPUP_X, POPUP_Y, s.width, s.height);
- framerender_popup_label(coords, &s, text);
+ popup_show(popup, text, NULL);
g_free(text);
}
@@ -127,8 +124,7 @@ void moveresize_end(gboolean cancel)
grab_keyboard(FALSE);
grab_pointer(FALSE, None);
- XDestroyWindow(ob_display, coords);
- coords = None;
+ popup_hide(popup);
if (moving) {
client_configure(moveresize_client, Corner_TopLeft,
@@ -156,7 +152,9 @@ static void do_move()
client_configure(moveresize_client, Corner_TopLeft, cur_x, cur_y,
start_cw, start_ch, TRUE, FALSE);
- popup_coords("X: %d Y: %d", moveresize_client->frame->area.x,
+ /* this would be better with a fixed width font ... XXX can do it better
+ if there are 2 text boxes */
+ popup_coords("X: %4d Y: %4d", moveresize_client->frame->area.x,
moveresize_client->frame->area.y);
}
@@ -178,7 +176,9 @@ static void do_resize()
client_configure(moveresize_client, lockcorner, moveresize_client->area.x,
moveresize_client->area.y, cur_x, cur_y, TRUE, FALSE);
- popup_coords("W: %d H: %d", moveresize_client->logical_size.width,
+ /* this would be better with a fixed width font ... XXX can do it better
+ if there are 2 text boxes */
+ popup_coords("W: %4d H: %4d", moveresize_client->logical_size.width,
moveresize_client->logical_size.height);
}
diff --git a/openbox/moveresize.h b/openbox/moveresize.h
index ba717cd8..4b9cdac4 100644
--- a/openbox/moveresize.h
+++ b/openbox/moveresize.h
@@ -9,6 +9,7 @@ extern gboolean moveresize_in_progress;
extern Client *moveresize_client;
void moveresize_startup();
+void moveresize_shutdown();
void moveresize_start(Client *c, int x, int y, guint button, guint32 corner);
void moveresize_end(gboolean cancel);
diff --git a/openbox/openbox.c b/openbox/openbox.c
index ea9b895f..304d52c6 100644
--- a/openbox/openbox.c
+++ b/openbox/openbox.c
@@ -166,7 +166,6 @@ int main(int argc, char **argv)
font_startup();
theme_startup();
event_startup();
- moveresize_startup();
grab_startup();
plugin_startup();
/* load the plugins specified in the pluginrc */
@@ -187,6 +186,7 @@ int main(int argc, char **argv)
menu_startup();
frame_startup();
stacking_startup();
+ moveresize_startup();
focus_startup();
screen_startup();
group_startup();
@@ -210,6 +210,7 @@ int main(int argc, char **argv)
group_shutdown();
screen_shutdown();
focus_shutdown();
+ moveresize_shutdown();
stacking_shutdown();
frame_shutdown();
menu_shutdown();
diff --git a/openbox/parse.h b/openbox/parse.h
index 3ce5ebbd..abd5bb2d 100644
--- a/openbox/parse.h
+++ b/openbox/parse.h
@@ -11,7 +11,7 @@ typedef enum {
TOKEN_INTEGER = INTEGER,
TOKEN_STRING = STRING,
TOKEN_IDENTIFIER = IDENTIFIER,
- TOKEN_BOOL = BOOL,
+ TOKEN_BOOL = BOOLEAN,
TOKEN_LIST,
TOKEN_LBRACE = '{',
TOKEN_RBRACE = '}',
diff --git a/openbox/parse.l b/openbox/parse.l
index 3762f335..a7cd6c63 100644
--- a/openbox/parse.l
+++ b/openbox/parse.l
@@ -31,7 +31,7 @@ bool ([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[yY][eE][sS]|[nN][oO]|[oO][nN]|[oO][
{bool} { yylval.bool = (!g_ascii_strcasecmp("true", yytext) ||
!g_ascii_strcasecmp("yes", yytext) ||
!g_ascii_strcasecmp("on", yytext));
- return BOOL;
+ return BOOLEAN;
}
{identifier} { yylval.identifier = g_strdup(yytext); return IDENTIFIER; }
[{}()\[\]=,] { yylval.character = *yytext; return *yytext; }
diff --git a/openbox/parse.y b/openbox/parse.y
index aa59fe4c..7e92efd6 100644
--- a/openbox/parse.y
+++ b/openbox/parse.y
@@ -41,7 +41,7 @@ void parse_set_section(char *section);
%token <integer> INTEGER
%token <string> STRING
%token <identifier> IDENTIFIER
-%token <bool> BOOL
+%token <bool> BOOLEAN
%token <character> '('
%token <character> ')'
%token <character> '{'
@@ -78,7 +78,7 @@ token:
| INTEGER { t.type = TOKEN_INTEGER; t.data.integer = $1; }
| STRING { t.type = TOKEN_STRING; t.data.string = $1; }
| IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
- | BOOL { t.type = TOKEN_BOOL; t.data.bool = $1; }
+ | BOOLEAN { t.type = TOKEN_BOOL; t.data.bool = $1; }
| list { t.type = TOKEN_LIST; t.data.list = $1; }
| '{' { t.type = $1; t.data.character = $1; }
| '}' { t.type = $1; t.data.character = $1; }
@@ -107,7 +107,7 @@ listtoken:
| INTEGER { t.type = TOKEN_INTEGER; t.data.integer = $1; }
| STRING { t.type = TOKEN_STRING; t.data.string = $1; }
| IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
- | BOOL { t.type = TOKEN_BOOL; t.data.bool = $1; }
+ | BOOLEAN { t.type = TOKEN_BOOL; t.data.bool = $1; }
| list { t.type = TOKEN_LIST; t.data.list = $1; }
| '{' { t.type = $1; t.data.character = $1; }
| '}' { t.type = $1; t.data.character = $1; }
diff --git a/openbox/screen.c b/openbox/screen.c
index 7f9b4397..04bc21c5 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -7,6 +7,7 @@
#include "frame.h"
#include "focus.h"
#include "dispatch.h"
+#include "extensions.h"
#include "../render/render.h"
#include <X11/Xlib.h>
@@ -16,7 +17,7 @@
#endif
/*! The event mask to grab on the root window */
-#define ROOT_EVENTMASK (/*ColormapChangeMask |*/ PropertyChangeMask | \
+#define ROOT_EVENTMASK (StructureNotifyMask | PropertyChangeMask | \
EnterWindowMask | LeaveWindowMask | \
SubstructureNotifyMask | SubstructureRedirectMask | \
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask)
@@ -160,7 +161,8 @@ void screen_startup()
guint i;
/* get the initial size */
- screen_resize();
+ screen_resize(WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen)),
+ HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen)));
/* set the names */
screen_desktop_names = g_new(char*,
@@ -201,14 +203,14 @@ void screen_shutdown()
g_free(area);
}
-void screen_resize()
+void screen_resize(int w, int h)
{
- /* XXX RandR support here? */
+ GList *it;
guint32 geometry[2];
/* Set the _NET_DESKTOP_GEOMETRY hint */
- geometry[0] = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
- geometry[1] = HeightOfScreen(ScreenOfDisplay(ob_display, ob_screen));
+ geometry[0] = w;
+ geometry[1] = h;
PROP_SETA32(ob_root, net_desktop_geometry, cardinal, geometry, 2);
screen_physical_size.width = geometry[0];
screen_physical_size.height = geometry[1];
@@ -218,7 +220,8 @@ void screen_resize()
screen_update_struts();
- /* XXX adjust more stuff ? */
+ for (it = client_list; it; it = it->next)
+ client_move_onscreen(it->data);
}
void screen_set_num_desktops(guint num)
diff --git a/openbox/screen.h b/openbox/screen.h
index f68b3beb..f493bd82 100644
--- a/openbox/screen.h
+++ b/openbox/screen.h
@@ -43,7 +43,7 @@ void screen_startup();
void screen_shutdown();
/*! Figure out the new size of the screen and adjust stuff for it */
-void screen_resize();
+void screen_resize(int w, int h);
/*! Change the number of available desktops */
void screen_set_num_desktops(guint num);
diff --git a/openbox/stacking.c b/openbox/stacking.c
index 6ff01721..ab1e1955 100644
--- a/openbox/stacking.c
+++ b/openbox/stacking.c
@@ -70,7 +70,7 @@ static GList *find_lowest_transient(Client *c)
static void raise_recursive(Client *client)
{
Window wins[2]; /* only ever restack 2 windows. */
- GList *it;
+ GList *it, *low;
GSList *sit;
g_assert(stacking_list != NULL); /* this would be bad */
@@ -86,15 +86,15 @@ static void raise_recursive(Client *client)
/* find 'it' where it is the positiion in the stacking order where
'client' will be inserted *before* */
- it = find_lowest_transient(client);
- if (it)
- it = it->next;
- else {
- /* the stacking list is from highest to lowest */
- for (it = stacking_list; it; it = it->next) {
- if (client->layer >= ((Client*)it->data)->layer)
- break;
+ low = find_lowest_transient(client);
+ /* the stacking list is from highest to lowest */
+ for (it = g_list_last(stacking_list); it; it = it->prev) {
+ if (it == low || client->layer < ((Client*)it->data)->layer) {
+ it = it->next;
+ break;
}
+ if (it == stacking_list)
+ break;
}
/*