diff options
Diffstat (limited to 'openbox')
| -rw-r--r-- | openbox/Makefile.am | 10 | ||||
| -rw-r--r-- | openbox/client.c | 246 | ||||
| -rw-r--r-- | openbox/client.h | 37 | ||||
| -rw-r--r-- | openbox/config.c | 8 | ||||
| -rw-r--r-- | openbox/config.h | 2 | ||||
| -rw-r--r-- | openbox/event.c | 55 | ||||
| -rw-r--r-- | openbox/extensions.c | 17 | ||||
| -rw-r--r-- | openbox/extensions.h | 16 | ||||
| -rw-r--r-- | openbox/focus.c | 82 | ||||
| -rw-r--r-- | openbox/framerender.c | 31 | ||||
| -rw-r--r-- | openbox/framerender.h | 3 | ||||
| -rw-r--r-- | openbox/menu.c | 10 | ||||
| -rw-r--r-- | openbox/moveresize.c | 42 | ||||
| -rw-r--r-- | openbox/moveresize.h | 1 | ||||
| -rw-r--r-- | openbox/openbox.c | 3 | ||||
| -rw-r--r-- | openbox/parse.h | 2 | ||||
| -rw-r--r-- | openbox/parse.l | 2 | ||||
| -rw-r--r-- | openbox/parse.y | 6 | ||||
| -rw-r--r-- | openbox/screen.c | 17 | ||||
| -rw-r--r-- | openbox/screen.h | 2 | ||||
| -rw-r--r-- | openbox/stacking.c | 18 |
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; } /* |
