all repos — openbox @ 567fd15eebdd44e50cef140419dbf7a336708109

openbox fork - make it a bit more like ryudo

Merge branch 'backport' into work

Conflicts:

	configure.ac
	data/rc.xml
	openbox/client.c
	openbox/event.c
	openbox/focus_cycle.c
	openbox/focus_cycle_popup.c
	openbox/openbox.c
	openbox/prop.c
	openbox/prop.h
	openbox/screen.c
	parser/parse.c
	version.h.in
Dana Jansens danakj@orodu.net
commit

567fd15eebdd44e50cef140419dbf7a336708109

parent

3e9dbc01430193035e3d1f5832c019c3f9623db8

M configure.acconfigure.ac

@@ -3,6 +3,9 @@ AC_INIT([openbox], [3.5.0-rc1], [http://bugzilla.icculus.org])

AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([openbox/openbox.c]) +OB_VERSION=$PACKAGE_VERSION +AC_SUBST(OB_VERSION) + dnl Making releases: dnl RR_MICRO_VERSION += 1; dnl RR_INTERFACE_AGE += 1;

@@ -206,6 +209,7 @@ obrender/obrender-3.5.pc

obt/obt-3.5.pc obrender/version.h obt/version.h + version.h ]) AC_CONFIG_COMMANDS([doc], [test -d doc || mkdir doc])
M data/rc.xmldata/rc.xml

@@ -696,16 +696,13 @@ # own rules, but without the comments of course.

# you may use one or more of the name/class/role/type rules to specify # windows to match - <application name="the window's _OB_NAME property (see obxprop)" - class="the window's _OB_CLASS property (see obxprop)" - role="the window's _OB_ROLE property (see obxprop)" - type="the window's _NET_WM_WINDOW_TYPE (see obxprob).. - (if unspecified, then it is 'dialog' for child windows) - one of: normal, dialog, splash, utility, menu, toolbar, - dock, desktop"> - # the name or the class can be set, or both. this is used to match - # windows when they appear. role can optionally be set as well, to - # further restrict your matches. + <application name="the window's _OB_APP_NAME property (see obxprop)" + class="the window's _OB_APP_CLASS property (see obxprop)" + role="the window's _OB_APP_ROLE property (see obxprop)" + type="the window's _OB_APP_TYPE property (see obxprob).. + (if unspecified, then it is 'dialog' for child windows)"> + # you may set only one of name/class/role/type, or you may use more than one + # together to restrict your matches. # the name, class, and role use simple wildcard matching such as those # used by a shell. you can use * to match any characters and ? to match

@@ -718,7 +715,7 @@ # when multiple rules match a window, they will all be applied, in the

# order that they appear in this list - # each element can be left out or set to 'default' to specify to not + # each rule element can be left out or set to 'default' to specify to not # change that attribute of the window <decor>yes</decor>
M obt/prop.cobt/prop.c

@@ -190,9 +190,11 @@ CREATE_(OB_CONFIG_FILE);

CREATE_(OB_WM_ACTION_UNDECORATE); CREATE_(OB_WM_STATE_UNDECORATED); CREATE_(OB_CONTROL); - CREATE_(OB_ROLE); - CREATE_(OB_NAME); - CREATE_(OB_CLASS); + CREATE_(OB_VERSION); + CREATE_(OB_APP_ROLE); + CREATE_(OB_APP_NAME); + CREATE_(OB_APP_CLASS); + CREATE_(OB_APP_TYPE); } Atom obt_prop_atom(ObtPropAtom a)
M obt/prop.hobt/prop.h

@@ -211,9 +211,11 @@ OBT_PROP_OPENBOX_PID, /* this is depreecated in favour of ob_control */

OBT_PROP_OB_THEME, OBT_PROP_OB_CONFIG_FILE, OBT_PROP_OB_CONTROL, - OBT_PROP_OB_ROLE, - OBT_PROP_OB_NAME, - OBT_PROP_OB_CLASS, + OBT_PROP_OB_VERSION, + OBT_PROP_OB_APP_ROLE, + OBT_PROP_OB_APP_NAME, + OBT_PROP_OB_APP_CLASS, + OBT_PROP_OB_APP_TYPE, OBT_PROP_NUM_ATOMS } ObtPropAtom;
M openbox/client.copenbox/client.c

@@ -31,6 +31,7 @@ #include "event.h"

#include "grab.h" #include "prompt.h" #include "focus.h" +#include "focus_cycle.h" #include "stacking.h" #include "openbox.h" #include "group.h"

@@ -75,7 +76,7 @@

static void client_get_all(ObClient *self, gboolean real); static void client_get_startup_id(ObClient *self); static void client_get_session_ids(ObClient *self); -static void client_save_session_ids(ObClient *self); +static void client_save_app_rule_values(ObClient *self); static void client_get_area(ObClient *self); static void client_get_desktop(ObClient *self); static void client_get_state(ObClient *self);

@@ -223,6 +224,7 @@ self = g_new0(ObClient, 1);

self->obwin.type = OB_WINDOW_CLASS_CLIENT; self->window = window; self->prompt = prompt; + self->managed = TRUE; /* non-zero defaults */ self->wmstate = WithdrawnState; /* make sure it gets updated first time */

@@ -550,6 +552,8 @@ if (!config_focus_under_mouse)

event_end_ignore_all_enters(ignore_start); mouse_grab_for_client(self, FALSE); + + self->managed = FALSE; /* remove the window from our save set, unless we are managing an internal ObPrompt window */

@@ -1078,7 +1082,9 @@

/* get the session related properties, these can change decorations from per-app settings */ client_get_session_ids(self); - client_save_session_ids(self); + + /* save the values of the variables used for app rule matching */ + client_save_app_rule_values(self); /* now we got everything that can affect the decorations */ if (!real)

@@ -1912,6 +1918,8 @@ client_update_icons(self);

XFree(hints); } + + focus_cycle_addremove(self, TRUE); } void client_update_title(ObClient *self)

@@ -2292,13 +2300,36 @@ self->pid = pid;

} } -/*! Save the session IDs as seen by Openbox when the window mapped, so that - users can still access them later if the app changes them */ -static void client_save_session_ids(ObClient *self) +/*! Save the properties used for app matching rules, as seen by Openbox when + the window mapped, so that users can still access them later if the app + changes them */ +static void client_save_app_rule_values(ObClient *self) { - OBT_PROP_SETS(self->window, OB_ROLE, utf8, self->role); - OBT_PROP_SETS(self->window, OB_NAME, utf8, self->name); - OBT_PROP_SETS(self->window, OB_CLASS, utf8, self->class); + const gchar *type; + + OBT_PROP_SETS(self->window, OB_APP_ROLE, utf8, self->role); + OBT_PROP_SETS(self->window, OB_APP_NAME, utf8, self->name); + OBT_PROP_SETS(self->window, OB_APP_CLASS, utf8, self->class); + + switch (self->type) { + case OB_CLIENT_TYPE_NORMAL: + type = "normal"; break; + case OB_CLIENT_TYPE_DIALOG: + type = "dialog"; break; + case OB_CLIENT_TYPE_UTILITY: + type = "utility"; break; + case OB_CLIENT_TYPE_MENU: + type = "menu"; break; + case OB_CLIENT_TYPE_TOOLBAR: + type = "toolbar"; break; + case OB_CLIENT_TYPE_SPLASH: + type = "splash"; break; + case OB_CLIENT_TYPE_DESKTOP: + type = "desktop"; break; + case OB_CLIENT_TYPE_DOCK: + type = "dock"; break; + } + OBT_PROP_SETS(self->window, OB_APP_TYPE, utf8, type); } static void client_change_wm_state(ObClient *self)

@@ -3149,7 +3180,7 @@ if (client_normal(self)) {

self->iconic = iconic; /* update the focus lists.. iconic windows go to the bottom of - the list */ + the list. this will also call focus_cycle_addremove(). */ focus_order_to_bottom(self); changed = TRUE;

@@ -3161,9 +3192,10 @@ if (curdesk && self->desktop != screen_desktop &&

self->desktop != DESKTOP_ALL) client_set_desktop(self, screen_desktop, FALSE, FALSE); - /* this puts it after the current focused window */ - focus_order_remove(self); - focus_order_add_new(self); + /* this puts it after the current focused window, this will + also cause focus_cycle_addremove() to be called for the + client */ + focus_order_like_new(self); changed = TRUE; }

@@ -3496,6 +3528,8 @@ else

/* the new desktop's geometry may be different, so we may need to resize, for example if we are maximized */ client_reconfigure(self, FALSE); + + focus_cycle_addremove(self, FALSE); } /* move all transients */

@@ -3511,6 +3545,8 @@ gboolean donthide, gboolean dontraise)

{ self = client_search_top_direct_parent(self); client_set_desktop_recursive(self, target, donthide, dontraise); + + focus_cycle_addremove(NULL, TRUE); } gboolean client_is_direct_child(ObClient *parent, ObClient *child)

@@ -3724,6 +3760,8 @@ if (demands_attention != self->demands_attention)

client_hilite(self, demands_attention); client_change_state(self); /* change the hint to reflect these changes */ + + focus_cycle_addremove(self, TRUE); } ObClient *client_focus_target(ObClient *self)
M openbox/client.hopenbox/client.h

@@ -73,6 +73,7 @@ struct _ObClient

{ ObWindow obwin; Window window; + gboolean managed; /*! If this client is managing an ObPrompt window, then this is set to the prompt */
M openbox/event.copenbox/event.c

@@ -1816,7 +1816,12 @@ }

else if (ob_keycode_match(keycode, OB_KEY_RIGHT)) { /* Right goes to the selected submenu */ - if (frame->child) menu_frame_select_next(frame->child); + if (frame->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) + { + /* make sure it is visible */ + menu_frame_select(frame, frame->selected, TRUE); + menu_frame_select_next(frame->child); + } ret = TRUE; }

@@ -1827,6 +1832,16 @@ }

else if (ob_keycode_match(keycode, OB_KEY_DOWN)) { menu_frame_select_next(frame); + ret = TRUE; + } + + else if (ob_keycode_match(keycode, OB_KEY_HOME)) { + menu_frame_select_first(frame); + ret = TRUE; + } + + else if (ob_keycode_match(keycode, OB_KEY_END)) { + menu_frame_select_last(frame); ret = TRUE; } }
M openbox/focus.copenbox/focus.c

@@ -90,6 +90,9 @@ /* move to the top of the list */

push_to_top(client); /* remove hiliting from the window when it gets focused */ client_hilite(client, FALSE); + + /* make sure the focus cycle popup shows things in the right order */ + focus_cycle_reorder(); } /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */

@@ -199,7 +202,7 @@ if (c->iconic)

focus_order_to_top(c); else { g_assert(!g_list_find(focus_order, c)); - /* if there are any iconic windows, put this above them in the order, + /* if there are only iconic windows, put this above them in the order, but if there are not, then put it under the currently focused one */ if (focus_order && ((ObClient*)focus_order->data)->iconic) focus_order = g_list_insert(focus_order, c, 0);

@@ -207,16 +210,20 @@ else

focus_order = g_list_insert(focus_order, c, 1); } - /* in the middle of cycling..? kill it. */ - focus_cycle_stop(c); + focus_cycle_addremove(c, TRUE); } void focus_order_remove(ObClient *c) { focus_order = g_list_remove(focus_order, c); - /* in the middle of cycling..? kill it. */ - focus_cycle_stop(c); + focus_cycle_addremove(c, TRUE); +} + +void focus_order_like_new(struct _ObClient *c) +{ + focus_order = g_list_remove(focus_order, c); + focus_order_add_new(c); } void focus_order_to_top(ObClient *c)

@@ -232,6 +239,8 @@ for (it = focus_order;

it && !((ObClient*)it->data)->iconic; it = g_list_next(it)); focus_order = g_list_insert_before(focus_order, it, c); } + + focus_cycle_reorder(); } void focus_order_to_bottom(ObClient *c)

@@ -247,6 +256,8 @@ for (it = focus_order;

it && !((ObClient*)it->data)->iconic; it = g_list_next(it)); focus_order = g_list_insert_before(focus_order, it, c); } + + focus_cycle_reorder(); } ObClient *focus_order_find_first(guint desktop)

@@ -294,7 +305,14 @@ gboolean dock_windows,

gboolean desktop_windows, gboolean user_request) { + /* NOTE: if any of these things change on a client, then they should call + focus_cycle_addremove() to make sure the client is not shown/hidden + when it should not be */ + gboolean ok = FALSE; + + /* see if the window is still managed or is going away */ + if (!ft->managed) return FALSE; /* it's on this desktop unless you want all desktops.
M openbox/focus.hopenbox/focus.h

@@ -58,6 +58,10 @@

/*! Move a client to the top of the focus order */ void focus_order_to_top(struct _ObClient *c); +/*! Move a client to where it would be if it was newly added to the focus order + */ +void focus_order_like_new(struct _ObClient *c); + /*! Move a client to the bottom of the focus order (keeps iconic windows at the very bottom always though). */ void focus_order_to_bottom(struct _ObClient *c);
M openbox/focus_cycle.copenbox/focus_cycle.c

@@ -29,7 +29,14 @@

#include <X11/Xlib.h> #include <glib.h> +typedef enum { + OB_CYCLE_NONE = 0, + OB_CYCLE_NORMAL, + OB_CYCLE_DIRECTIONAL +} ObCycleType; + ObClient *focus_cycle_target = NULL; +static ObCycleType focus_cycle_type = OB_CYCLE_NONE; static gboolean focus_cycle_iconic_windows; static gboolean focus_cycle_all_desktops; static gboolean focus_cycle_dock_windows;

@@ -50,17 +57,40 @@ {

if (reconfig) return; } -void focus_cycle_stop(ObClient *ifclient) +void focus_cycle_addremove(ObClient *c, gboolean redraw) +{ + if (!focus_cycle_type) + return; + + if (focus_cycle_type == OB_CYCLE_DIRECTIONAL) { + if (c && focus_cycle_target == c) { + focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE); + } + } + else if (c && redraw) { + gboolean v, s; + + v = focus_cycle_valid(c); + s = focus_cycle_popup_is_showing(c); + + if (v != s) + focus_cycle_reorder(); + } + else if (redraw) { + focus_cycle_reorder(); + } +} + +void focus_cycle_reorder() { - /* stop focus cycling if the given client is a valid focus target, - and so the cycling is being disrupted */ - if (focus_cycle_target && - ((ifclient && (ifclient == focus_cycle_target || - focus_cycle_popup_is_showing(ifclient))) || - !ifclient)) - { - focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,TRUE); - focus_directional_cycle(0, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE); + if (focus_cycle_type == OB_CYCLE_NORMAL) { + focus_cycle_target = focus_cycle_popup_refresh(focus_cycle_target, + TRUE); + focus_cycle_update_indicator(focus_cycle_target); + if (!focus_cycle_target) + focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, + TRUE, TRUE, TRUE, TRUE, TRUE); } }

@@ -115,16 +145,11 @@ it = it->prev;

if (it == NULL) it = g_list_last(list); } ft = it->data; - if (focus_valid_target(ft, screen_desktop, TRUE, - focus_cycle_iconic_windows, - focus_cycle_all_desktops, - focus_cycle_dock_windows, - focus_cycle_desktop_windows, - FALSE)) - { + if (focus_cycle_valid(ft)) { if (interactive) { if (ft != focus_cycle_target) { /* prevents flicker */ focus_cycle_target = ft; + focus_cycle_type = OB_CYCLE_NORMAL; focus_cycle_draw_indicator(showbar ? ft : NULL); } /* same arguments as focus_target_valid */

@@ -137,6 +162,7 @@ mode);

return focus_cycle_target; } else if (ft != focus_cycle_target) { focus_cycle_target = ft; + focus_cycle_type = OB_CYCLE_NORMAL; done = TRUE; break; }

@@ -147,6 +173,7 @@ done_cycle:

if (done && !cancel) ret = focus_cycle_target; focus_cycle_target = NULL; + focus_cycle_type = OB_CYCLE_NONE; g_list_free(order); order = NULL;

@@ -186,9 +213,7 @@

/* the currently selected window isn't interesting */ if (cur == c) continue; - if (!focus_valid_target(it->data, screen_desktop, - TRUE, FALSE, FALSE, dock_windows, - desktop_windows, FALSE)) + if (!focus_cycle_valid(it->data)) continue; /* find the centre coords of this window, from the

@@ -292,16 +317,15 @@ else {

GList *it; for (it = focus_order; it; it = g_list_next(it)) - if (focus_valid_target(it->data, screen_desktop, TRUE, - focus_cycle_iconic_windows, - focus_cycle_all_desktops, - focus_cycle_dock_windows, - focus_cycle_desktop_windows, FALSE)) + if (focus_cycle_valid(it->data)) { ft = it->data; + break; + } } if (ft && ft != focus_cycle_target) {/* prevents flicker */ focus_cycle_target = ft; + focus_cycle_type = OB_CYCLE_DIRECTIONAL; if (!interactive) goto done_cycle; focus_cycle_draw_indicator(showbar ? ft : NULL);

@@ -320,9 +344,20 @@ if (done && !cancel) ret = focus_cycle_target;

first = NULL; focus_cycle_target = NULL; + focus_cycle_type = OB_CYCLE_NONE; focus_cycle_draw_indicator(NULL); focus_cycle_popup_single_hide(); return ret; } + +gboolean focus_cycle_valid(struct _ObClient *client) +{ + return focus_valid_target(client, screen_desktop, TRUE, + focus_cycle_iconic_windows, + focus_cycle_all_desktops, + focus_cycle_dock_windows, + focus_cycle_desktop_windows, + FALSE); +}
M openbox/focus_cycle.hopenbox/focus_cycle.h

@@ -48,6 +48,10 @@ gboolean showbar,

gboolean dialog, gboolean done, gboolean cancel); -void focus_cycle_stop(struct _ObClient *ifclient); +/*! Set @redraw to FALSE if there are more clients to be added/removed first */ +void focus_cycle_addremove(struct _ObClient *ifclient, gboolean redraw); +void focus_cycle_reorder(); + +gboolean focus_cycle_valid(struct _ObClient *client); #endif
M openbox/focus_cycle_popup.copenbox/focus_cycle_popup.c

@@ -18,6 +18,7 @@ See the COPYING file for a copy of the GNU General Public License.

*/ #include "focus_cycle_popup.h" +#include "focus_cycle.h" #include "popup.h" #include "client.h" #include "screen.h"

@@ -98,15 +99,12 @@ static ObFocusCyclePopup popup;

/*! This popup shows a single window */ static ObIconPopup *single_popup; -static gchar *popup_get_name (ObClient *c); -static void popup_setup (ObFocusCyclePopup *p, - gboolean create_targets, - gboolean iconic_windows, - gboolean all_desktops, - gboolean dock_windows, - gboolean desktop_windows); -static void popup_render (ObFocusCyclePopup *p, - const ObClient *c); +static gchar *popup_get_name (ObClient *c); +static gboolean popup_setup (ObFocusCyclePopup *p, + gboolean create_targets, + gboolean refresh_targets); +static void popup_render (ObFocusCyclePopup *p, + const ObClient *c); static Window create_window(Window parent, guint bwidth, gulong mask, XSetWindowAttributes *attr)

@@ -242,12 +240,35 @@ RrAppearanceFree(popup.a_text);

RrAppearanceFree(popup.a_bg); } -static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets, - gboolean iconic_windows, gboolean all_desktops, - gboolean dock_windows, gboolean desktop_windows) +static void popup_target_free(ObFocusCyclePopupTarget *t) +{ + RrImageUnref(t->icon); + g_free(t->text); + XDestroyWindow(obt_display, t->iconwin); + XDestroyWindow(obt_display, t->textwin); + g_free(t); +} + +static gboolean popup_setup(ObFocusCyclePopup *p, gboolean create_targets, + gboolean refresh_targets) { gint maxwidth, n; GList *it; + GList *rtargets; /* old targets for refresh */ + GList *rtlast; + gboolean change; + + if (refresh_targets) { + rtargets = p->targets; + rtlast = g_list_last(rtargets); + p->targets = NULL; + p->n_targets = 0; + change = FALSE; + } + else { + rtargets = rtlast = NULL; + change = TRUE; + } g_assert(p->targets == NULL); g_assert(p->n_targets == 0);

@@ -261,39 +282,82 @@ n = 0;

for (it = g_list_last(focus_order); it; it = g_list_previous(it)) { ObClient *ft = it->data; - if (focus_valid_target(ft, screen_desktop, TRUE, - iconic_windows, - all_desktops, - dock_windows, - desktop_windows, - FALSE)) - { - gchar *text = popup_get_name(ft); + if (focus_cycle_valid(ft)) { + GList *rit; - /* measure */ - p->a_text->texture[0].data.text.string = text; - maxwidth = MAX(maxwidth, RrMinWidth(p->a_text)); + /* reuse the target if possible during refresh */ + for (rit = rtlast; rit; rit = g_list_previous(rit)) { + ObFocusCyclePopupTarget *t = rit->data; + if (t->client == ft) { + if (rit == rtlast) + rtlast = g_list_previous(rit); + rtargets = g_list_remove_link(rtargets, rit); + + p->targets = g_list_concat(rit, p->targets); + ++n; + + if (rit != rtlast) + change = TRUE; /* order changed */ + break; + } + } + + if (!rit) { + gchar *text = popup_get_name(ft); + + /* measure */ + p->a_text->texture[0].data.text.string = text; + maxwidth = MAX(maxwidth, RrMinWidth(p->a_text)); + + if (!create_targets) { + g_free(text); + } else { + ObFocusCyclePopupTarget *t = + g_new(ObFocusCyclePopupTarget, 1); - if (!create_targets) { - g_free(text); - } else { - ObFocusCyclePopupTarget *t = g_new(ObFocusCyclePopupTarget, 1); + t->client = ft; + t->text = text; + t->icon = client_icon(t->client); + RrImageRef(t->icon); /* own the icon so it won't go away */ + t->iconwin = create_window(p->bg, 0, 0, NULL); + t->textwin = create_window(p->bg, 0, 0, NULL); - t->client = ft; - t->text = text; - t->icon = client_icon(t->client); - RrImageRef(t->icon); /* own the icon so it won't go away */ - t->iconwin = create_window(p->bg, 0, 0, NULL); - t->textwin = create_window(p->bg, 0, 0, NULL); + p->targets = g_list_prepend(p->targets, t); + ++n; - p->targets = g_list_prepend(p->targets, t); - ++n; + change = TRUE; /* added a window */ + } } } } + if (rtargets) { + change = TRUE; /* removed a window */ + + while (rtargets) { + popup_target_free(rtargets->data); + rtargets = g_list_delete_link(rtargets, rtargets); + } + } + p->n_targets = n; - p->maxtextw = maxwidth; + if (refresh_targets) + /* don't shrink when refreshing */ + p->maxtextw = MAX(p->maxtextw, maxwidth); + else + p->maxtextw = maxwidth; + + return change; +} + +static void popup_cleanup(void) +{ + while(popup.targets) { + popup_target_free(popup.targets->data); + popup.targets = g_list_delete_link(popup.targets, popup.targets); + } + popup.n_targets = 0; + popup.last_target = NULL; } static gchar *popup_get_name(ObClient *c)

@@ -652,8 +716,7 @@ }

/* do this stuff only when the dialog is first showing */ if (!popup.mapped) { - popup_setup(&popup, TRUE, iconic_windows, all_desktops, - dock_windows, desktop_windows); + popup_setup(&popup, TRUE, FALSE); /* this is fixed once the dialog is shown */ popup.mode = mode; }

@@ -683,19 +746,7 @@ event_end_ignore_all_enters(ignore_start);

popup.mapped = FALSE; - while(popup.targets) { - ObFocusCyclePopupTarget *t = popup.targets->data; - - RrImageUnref(t->icon); - g_free(t->text); - XDestroyWindow(obt_display, t->iconwin); - XDestroyWindow(obt_display, t->textwin); - g_free(t); - - popup.targets = g_list_delete_link(popup.targets, popup.targets); - } - popup.n_targets = 0; - popup.last_target = NULL; + popup_cleanup(); } void focus_cycle_popup_single_show(struct _ObClient *c,

@@ -712,8 +763,7 @@ /* do this stuff only when the dialog is first showing */

if (!popup.mapped) { Rect *a; - popup_setup(&popup, FALSE, iconic_windows, all_desktops, - dock_windows, desktop_windows); + popup_setup(&popup, FALSE, FALSE); g_assert(popup.targets == NULL); /* position the popup */

@@ -738,16 +788,67 @@ {

icon_popup_hide(single_popup); } -gboolean focus_cycle_popup_is_showing(ObClient *client) +gboolean focus_cycle_popup_is_showing(ObClient *c) { if (popup.mapped) { GList *it; for (it = popup.targets; it; it = g_list_next(it)) { ObFocusCyclePopupTarget *t = it->data; - if (t->client == client) + if (t->client == c) return TRUE; } } return FALSE; } + +static ObClient* popup_revert(ObClient *target) +{ + GList *it, *itt; + + for (it = popup.targets; it; it = g_list_next(it)) { + ObFocusCyclePopupTarget *t = it->data; + if (t->client == target) { + /* move to a previous window if possible */ + for (itt = it->prev; itt; itt = g_list_previous(itt)) { + ObFocusCyclePopupTarget *t2 = itt->data; + if (focus_cycle_valid(t2->client)) + return t2->client; + } + + /* otherwise move to a following window if possible */ + for (itt = it->next; itt; itt = g_list_next(itt)) { + ObFocusCyclePopupTarget *t2 = itt->data; + if (focus_cycle_valid(t2->client)) + return t2->client; + } + + /* otherwise, we can't go anywhere there is nowhere valid to go */ + return NULL; + } + } + return NULL; +} + +ObClient* focus_cycle_popup_refresh(ObClient *target, + gboolean redraw) +{ + if (!popup.mapped) return NULL; + + if (!focus_cycle_valid(target)) + target = popup_revert(target); + + redraw = popup_setup(&popup, TRUE, TRUE) && redraw; + + if (!target && popup.targets) + target = ((ObFocusCyclePopupTarget*)popup.targets->data)->client; + + if (target && redraw) { + popup.mapped = FALSE; + popup_render(&popup, target); + XFlush(obt_display); + popup.mapped = TRUE; + } + + return target; +}
M openbox/focus_cycle_popup.hopenbox/focus_cycle_popup.h

@@ -46,7 +46,13 @@ gboolean dock_windows,

gboolean desktop_windows); void focus_cycle_popup_single_hide(void); -/*! Returns TRUE if the popup is showing the client, otherwise FALSE. */ -gboolean focus_cycle_popup_is_showing(struct _ObClient *client); +gboolean focus_cycle_popup_is_showing(struct _ObClient *c); + +/*! Redraws the focus cycle popup, and returns the current target. If + the target given to the function is no longer valid, this will return + a different target that is valid, and which should be considered the + current focus cycling target. */ +struct _ObClient *focus_cycle_popup_refresh(struct _ObClient *target, + gboolean redraw); #endif
M openbox/menuframe.copenbox/menuframe.c

@@ -1300,7 +1300,7 @@ break;

} } } - menu_frame_select(self, it ? it->data : NULL, TRUE); + menu_frame_select(self, it ? it->data : NULL, FALSE); } void menu_frame_select_next(ObMenuFrame *self)

@@ -1325,5 +1325,37 @@ break;

} } } - menu_frame_select(self, it ? it->data : NULL, TRUE); + menu_frame_select(self, it ? it->data : NULL, FALSE); +} + +void menu_frame_select_first(ObMenuFrame *self) +{ + GList *it = NULL; + + if (self->entries) { + for (it = self->entries; it; it = g_list_next(it)) { + ObMenuEntryFrame *e = it->data; + if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) + break; + if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) + break; + } + } + menu_frame_select(self, it ? it->data : NULL, FALSE); +} + +void menu_frame_select_last(ObMenuFrame *self) +{ + GList *it = NULL; + + if (self->entries) { + for (it = g_list_last(self->entries); it; it = g_list_previous(it)) { + ObMenuEntryFrame *e = it->data; + if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) + break; + if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) + break; + } + } + menu_frame_select(self, it ? it->data : NULL, FALSE); }
M openbox/menuframe.hopenbox/menuframe.h

@@ -127,6 +127,8 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,

gboolean immediate); void menu_frame_select_previous(ObMenuFrame *self); void menu_frame_select_next(ObMenuFrame *self); +void menu_frame_select_first(ObMenuFrame *self); +void menu_frame_select_last(ObMenuFrame *self); ObMenuFrame* menu_frame_under(gint x, gint y); ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y);
M openbox/misc.hopenbox/misc.h

@@ -53,6 +53,8 @@ OB_KEY_UP,

OB_KEY_DOWN, OB_KEY_TAB, OB_KEY_SPACE, + OB_KEY_HOME, + OB_KEY_END, OB_NUM_KEYS } ObKey;
M openbox/openbox.copenbox/openbox.c

@@ -224,6 +224,8 @@ keys[OB_KEY_UP] = obt_keyboard_keysym_to_keycode(XK_Up);

keys[OB_KEY_DOWN] = obt_keyboard_keysym_to_keycode(XK_Down); keys[OB_KEY_TAB] = obt_keyboard_keysym_to_keycode(XK_Tab); keys[OB_KEY_SPACE] = obt_keyboard_keysym_to_keycode(XK_space); + keys[OB_KEY_HOME] = obt_keyboard_keysym_to_keycode(XK_Home); + keys[OB_KEY_END] = obt_keyboard_keysym_to_keycode(XK_End); { ObtXmlInst *i;

@@ -411,6 +413,8 @@ g_free(keys[OB_KEY_UP]);

g_free(keys[OB_KEY_DOWN]); g_free(keys[OB_KEY_TAB]); g_free(keys[OB_KEY_SPACE]); + g_free(keys[OB_KEY_HOME]); + g_free(keys[OB_KEY_END]); } while (reconfigure); }
A openbox/prop.c

@@ -0,0 +1,479 @@

+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + prop.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "prop.h" +#include "openbox.h" + +#include <X11/Xatom.h> + +Atoms prop_atoms; + +#define CREATE(var, name) (prop_atoms.var = \ + XInternAtom(ob_display, name, FALSE)) + +void prop_startup(void) +{ + CREATE(cardinal, "CARDINAL"); + CREATE(window, "WINDOW"); + CREATE(pixmap, "PIXMAP"); + CREATE(atom, "ATOM"); + CREATE(string, "STRING"); + CREATE(utf8, "UTF8_STRING"); + + CREATE(manager, "MANAGER"); + + CREATE(wm_colormap_windows, "WM_COLORMAP_WINDOWS"); + CREATE(wm_protocols, "WM_PROTOCOLS"); + CREATE(wm_state, "WM_STATE"); + CREATE(wm_change_state, "WM_CHANGE_STATE"); + CREATE(wm_delete_window, "WM_DELETE_WINDOW"); + CREATE(wm_take_focus, "WM_TAKE_FOCUS"); + CREATE(wm_name, "WM_NAME"); + CREATE(wm_icon_name, "WM_ICON_NAME"); + CREATE(wm_class, "WM_CLASS"); + CREATE(wm_window_role, "WM_WINDOW_ROLE"); + CREATE(wm_client_machine, "WM_CLIENT_MACHINE"); + CREATE(wm_command, "WM_COMMAND"); + CREATE(wm_client_leader, "WM_CLIENT_LEADER"); + CREATE(wm_transient_for, "WM_TRANSIENT_FOR"); + CREATE(motif_wm_hints, "_MOTIF_WM_HINTS"); + CREATE(motif_wm_info, "_MOTIF_WM_INFO"); + + CREATE(sm_client_id, "SM_CLIENT_ID"); + + CREATE(net_wm_full_placement, "_NET_WM_FULL_PLACEMENT"); + + CREATE(net_supported, "_NET_SUPPORTED"); + CREATE(net_client_list, "_NET_CLIENT_LIST"); + CREATE(net_client_list_stacking, "_NET_CLIENT_LIST_STACKING"); + CREATE(net_number_of_desktops, "_NET_NUMBER_OF_DESKTOPS"); + CREATE(net_desktop_geometry, "_NET_DESKTOP_GEOMETRY"); + CREATE(net_desktop_viewport, "_NET_DESKTOP_VIEWPORT"); + CREATE(net_current_desktop, "_NET_CURRENT_DESKTOP"); + CREATE(net_desktop_names, "_NET_DESKTOP_NAMES"); + CREATE(net_active_window, "_NET_ACTIVE_WINDOW"); +/* CREATE(net_restack_window, "_NET_RESTACK_WINDOW");*/ + CREATE(net_workarea, "_NET_WORKAREA"); + CREATE(net_supporting_wm_check, "_NET_SUPPORTING_WM_CHECK"); + CREATE(net_desktop_layout, "_NET_DESKTOP_LAYOUT"); + CREATE(net_showing_desktop, "_NET_SHOWING_DESKTOP"); + + 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"); + + CREATE(net_wm_name, "_NET_WM_NAME"); + CREATE(net_wm_visible_name, "_NET_WM_VISIBLE_NAME"); + CREATE(net_wm_icon_name, "_NET_WM_ICON_NAME"); + CREATE(net_wm_visible_icon_name, "_NET_WM_VISIBLE_ICON_NAME"); + CREATE(net_wm_desktop, "_NET_WM_DESKTOP"); + CREATE(net_wm_window_type, "_NET_WM_WINDOW_TYPE"); + CREATE(net_wm_state, "_NET_WM_STATE"); + CREATE(net_wm_strut, "_NET_WM_STRUT"); + CREATE(net_wm_strut_partial, "_NET_WM_STRUT_PARTIAL"); + CREATE(net_wm_icon, "_NET_WM_ICON"); + CREATE(net_wm_icon_geometry, "_NET_WM_ICON_GEOMETRY"); + CREATE(net_wm_pid, "_NET_WM_PID"); + CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS"); + CREATE(net_wm_user_time, "_NET_WM_USER_TIME"); +/* 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_wm_ping, "_NET_WM_PING"); +#ifdef SYNC + CREATE(net_wm_sync_request, "_NET_WM_SYNC_REQUEST"); + CREATE(net_wm_sync_request_counter, "_NET_WM_SYNC_REQUEST_COUNTER"); +#endif + + CREATE(net_wm_window_type_desktop, "_NET_WM_WINDOW_TYPE_DESKTOP"); + CREATE(net_wm_window_type_dock, "_NET_WM_WINDOW_TYPE_DOCK"); + CREATE(net_wm_window_type_toolbar, "_NET_WM_WINDOW_TYPE_TOOLBAR"); + CREATE(net_wm_window_type_menu, "_NET_WM_WINDOW_TYPE_MENU"); + CREATE(net_wm_window_type_utility, "_NET_WM_WINDOW_TYPE_UTILITY"); + CREATE(net_wm_window_type_splash, "_NET_WM_WINDOW_TYPE_SPLASH"); + CREATE(net_wm_window_type_dialog, "_NET_WM_WINDOW_TYPE_DIALOG"); + CREATE(net_wm_window_type_normal, "_NET_WM_WINDOW_TYPE_NORMAL"); + CREATE(net_wm_window_type_popup_menu, "_NET_WM_WINDOW_TYPE_POPUP_MENU"); + + prop_atoms.net_wm_moveresize_size_topleft = 0; + prop_atoms.net_wm_moveresize_size_top = 1; + prop_atoms.net_wm_moveresize_size_topright = 2; + prop_atoms.net_wm_moveresize_size_right = 3; + prop_atoms.net_wm_moveresize_size_bottomright = 4; + prop_atoms.net_wm_moveresize_size_bottom = 5; + prop_atoms.net_wm_moveresize_size_bottomleft = 6; + prop_atoms.net_wm_moveresize_size_left = 7; + prop_atoms.net_wm_moveresize_move = 8; + prop_atoms.net_wm_moveresize_size_keyboard = 9; + prop_atoms.net_wm_moveresize_move_keyboard = 10; + prop_atoms.net_wm_moveresize_cancel = 11; + + CREATE(net_wm_action_move, "_NET_WM_ACTION_MOVE"); + CREATE(net_wm_action_resize, "_NET_WM_ACTION_RESIZE"); + CREATE(net_wm_action_minimize, "_NET_WM_ACTION_MINIMIZE"); + CREATE(net_wm_action_shade, "_NET_WM_ACTION_SHADE"); + CREATE(net_wm_action_maximize_horz, "_NET_WM_ACTION_MAXIMIZE_HORZ"); + CREATE(net_wm_action_maximize_vert, "_NET_WM_ACTION_MAXIMIZE_VERT"); + CREATE(net_wm_action_fullscreen, "_NET_WM_ACTION_FULLSCREEN"); + CREATE(net_wm_action_change_desktop, "_NET_WM_ACTION_CHANGE_DESKTOP"); + CREATE(net_wm_action_close, "_NET_WM_ACTION_CLOSE"); + CREATE(net_wm_action_above, "_NET_WM_ACTION_ABOVE"); + CREATE(net_wm_action_below, "_NET_WM_ACTION_BELOW"); + + CREATE(net_wm_state_modal, "_NET_WM_STATE_MODAL"); +/* CREATE(net_wm_state_sticky, "_NET_WM_STATE_STICKY");*/ + CREATE(net_wm_state_maximized_vert, "_NET_WM_STATE_MAXIMIZED_VERT"); + CREATE(net_wm_state_maximized_horz, "_NET_WM_STATE_MAXIMIZED_HORZ"); + CREATE(net_wm_state_shaded, "_NET_WM_STATE_SHADED"); + CREATE(net_wm_state_skip_taskbar, "_NET_WM_STATE_SKIP_TASKBAR"); + CREATE(net_wm_state_skip_pager, "_NET_WM_STATE_SKIP_PAGER"); + CREATE(net_wm_state_hidden, "_NET_WM_STATE_HIDDEN"); + CREATE(net_wm_state_fullscreen, "_NET_WM_STATE_FULLSCREEN"); + CREATE(net_wm_state_above, "_NET_WM_STATE_ABOVE"); + CREATE(net_wm_state_below, "_NET_WM_STATE_BELOW"); + CREATE(net_wm_state_demands_attention, "_NET_WM_STATE_DEMANDS_ATTENTION"); + + prop_atoms.net_wm_state_add = 1; + prop_atoms.net_wm_state_remove = 0; + prop_atoms.net_wm_state_toggle = 2; + + prop_atoms.net_wm_orientation_horz = 0; + prop_atoms.net_wm_orientation_vert = 1; + prop_atoms.net_wm_topleft = 0; + prop_atoms.net_wm_topright = 1; + prop_atoms.net_wm_bottomright = 2; + prop_atoms.net_wm_bottomleft = 3; + + CREATE(kde_wm_change_state, "_KDE_WM_CHANGE_STATE"); + CREATE(kde_net_wm_window_type_override,"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); + +/* + CREATE(rootpmapid, "_XROOTPMAP_ID"); + CREATE(esetrootid, "ESETROOT_PMAP_ID"); +*/ + + CREATE(openbox_pid, "_OPENBOX_PID"); + CREATE(ob_theme, "_OB_THEME"); + CREATE(ob_config_file, "_OB_CONFIG_FILE"); + CREATE(ob_wm_action_undecorate, "_OB_WM_ACTION_UNDECORATE"); + CREATE(ob_wm_state_undecorated, "_OB_WM_STATE_UNDECORATED"); + CREATE(ob_control, "_OB_CONTROL"); + CREATE(ob_version, "_OB_VERSION"); + CREATE(ob_app_role, "_OB_APP_ROLE"); + CREATE(ob_app_name, "_OB_APP_NAME"); + CREATE(ob_app_class, "_OB_APP_CLASS"); + CREATE(ob_app_type, "_OB_APP_TYPE"); +} + +#include <X11/Xutil.h> +#include <glib.h> +#include <string.h> + +/* this just isn't used... and it also breaks on 64bit, watch out +static gboolean get(Window win, Atom prop, Atom type, gint size, + guchar **data, gulong num) +{ + gboolean ret = FALSE; + gint res; + guchar *xdata = NULL; + Atom ret_type; + gint ret_size; + gulong ret_items, bytes_left; + glong num32 = 32 / size * num; /\* num in 32-bit elements *\/ + + res = XGetWindowProperty(display, win, prop, 0l, num32, + FALSE, type, &ret_type, &ret_size, + &ret_items, &bytes_left, &xdata); + if (res == Success && ret_items && xdata) { + if (ret_size == size && ret_items >= num) { + *data = g_memdup(xdata, num * (size / 8)); + ret = TRUE; + } + XFree(xdata); + } + return ret; +} +*/ + +static gboolean get_prealloc(Window win, Atom prop, Atom type, gint size, + guchar *data, gulong num) +{ + gboolean ret = FALSE; + gint res; + guchar *xdata = NULL; + Atom ret_type; + gint ret_size; + gulong ret_items, bytes_left; + glong num32 = 32 / size * num; /* num in 32-bit elements */ + + res = XGetWindowProperty(ob_display, win, prop, 0l, num32, + FALSE, type, &ret_type, &ret_size, + &ret_items, &bytes_left, &xdata); + if (res == Success && ret_items && xdata) { + if (ret_size == size && ret_items >= num) { + guint i; + for (i = 0; i < num; ++i) + switch (size) { + case 8: + data[i] = xdata[i]; + break; + case 16: + ((guint16*)data)[i] = ((gushort*)xdata)[i]; + break; + case 32: + ((guint32*)data)[i] = ((gulong*)xdata)[i]; + break; + default: + g_assert_not_reached(); /* unhandled size */ + } + ret = TRUE; + } + XFree(xdata); + } + return ret; +} + +static gboolean get_all(Window win, Atom prop, Atom type, gint size, + guchar **data, guint *num) +{ + gboolean ret = FALSE; + gint res; + guchar *xdata = NULL; + Atom ret_type; + gint ret_size; + gulong ret_items, bytes_left; + + res = XGetWindowProperty(ob_display, win, prop, 0l, G_MAXLONG, + FALSE, type, &ret_type, &ret_size, + &ret_items, &bytes_left, &xdata); + if (res == Success) { + if (ret_size == size && ret_items > 0) { + guint i; + + *data = g_malloc(ret_items * (size / 8)); + for (i = 0; i < ret_items; ++i) + switch (size) { + case 8: + (*data)[i] = xdata[i]; + break; + case 16: + ((guint16*)*data)[i] = ((gushort*)xdata)[i]; + break; + case 32: + ((guint32*)*data)[i] = ((gulong*)xdata)[i]; + break; + default: + g_assert_not_reached(); /* unhandled size */ + } + *num = ret_items; + ret = TRUE; + } + XFree(xdata); + } + return ret; +} + +static gboolean get_stringlist(Window win, Atom prop, gchar ***list, gint *nstr) +{ + XTextProperty tprop; + gboolean ret = FALSE; + + if (XGetTextProperty(ob_display, win, &tprop, prop) && tprop.nitems) { + if (XTextPropertyToStringList(&tprop, list, nstr)) + ret = TRUE; + XFree(tprop.value); + } + return ret; +} + +gboolean prop_get32(Window win, Atom prop, Atom type, guint32 *ret) +{ + return get_prealloc(win, prop, type, 32, (guchar*)ret, 1); +} + +gboolean prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret, + guint *nret) +{ + return get_all(win, prop, type, 32, (guchar**)ret, nret); +} + +gboolean prop_get_string_locale(Window win, Atom prop, gchar **ret) +{ + gchar **list; + gint nstr; + gchar *s; + + if (get_stringlist(win, prop, &list, &nstr) && nstr) { + s = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL); + XFreeStringList(list); + if (s) { + *ret = s; + return TRUE; + } + } + return FALSE; +} + +gboolean prop_get_strings_locale(Window win, Atom prop, gchar ***ret) +{ + GSList *strs = NULL, *it; + gchar *raw, *p; + guint num, i, count = 0; + + if (get_all(win, prop, prop_atoms.string, 8, (guchar**)&raw, &num)) { + + p = raw; + while (p < raw + num) { + ++count; + strs = g_slist_append(strs, p); + p += strlen(p) + 1; /* next string */ + } + + *ret = g_new0(gchar*, count + 1); + (*ret)[count] = NULL; /* null terminated list */ + + for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) { + (*ret)[i] = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL); + /* make sure translation did not fail */ + if (!(*ret)[i]) + (*ret)[i] = g_strdup(""); + } + g_free(raw); + g_slist_free(strs); + return TRUE; + } + return FALSE; +} + +gboolean prop_get_string_utf8(Window win, Atom prop, gchar **ret) +{ + gchar *raw; + gchar *str; + guint num; + + if (get_all(win, prop, prop_atoms.utf8, 8, (guchar**)&raw, &num)) { + str = g_strndup(raw, num); /* grab the first string from the list */ + g_free(raw); + if (g_utf8_validate(str, -1, NULL)) { + *ret = str; + return TRUE; + } + g_free(str); + } + return FALSE; +} + +gboolean prop_get_strings_utf8(Window win, Atom prop, gchar ***ret) +{ + GSList *strs = NULL, *it; + gchar *raw, *p; + guint num, i, count = 0; + + if (get_all(win, prop, prop_atoms.utf8, 8, (guchar**)&raw, &num)) { + + p = raw; + while (p < raw + num) { + ++count; + strs = g_slist_append(strs, p); + p += strlen(p) + 1; /* next string */ + } + + *ret = g_new0(gchar*, count + 1); + + for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) { + if (g_utf8_validate(it->data, -1, NULL)) + (*ret)[i] = g_strdup(it->data); + else + (*ret)[i] = g_strdup(""); + } + g_free(raw); + g_slist_free(strs); + return TRUE; + } + return FALSE; +} + +void prop_set32(Window win, Atom prop, Atom type, gulong val) +{ + XChangeProperty(ob_display, win, prop, type, 32, PropModeReplace, + (guchar*)&val, 1); +} + +void prop_set_array32(Window win, Atom prop, Atom type, gulong *val, + guint num) +{ + XChangeProperty(ob_display, win, prop, type, 32, PropModeReplace, + (guchar*)val, num); +} + +void prop_set_string_utf8(Window win, Atom prop, const gchar *val) +{ + XChangeProperty(ob_display, win, prop, prop_atoms.utf8, 8, + PropModeReplace, (const guchar*)val, strlen(val)); +} + +void prop_set_strings_utf8(Window win, Atom prop, gchar **strs) +{ + GString *str; + gchar **s; + + str = g_string_sized_new(0); + for (s = strs; *s; ++s) { + str = g_string_append(str, *s); + str = g_string_append_c(str, '\0'); + } + XChangeProperty(ob_display, win, prop, prop_atoms.utf8, 8, + PropModeReplace, (guchar*)str->str, str->len); + g_string_free(str, TRUE); +} + +void prop_erase(Window win, Atom prop) +{ + XDeleteProperty(ob_display, win, prop); +} + +void prop_message(Window about, Atom messagetype, glong data0, glong data1, + glong data2, glong data3, glong mask) +{ + prop_message_to(RootWindow(ob_display, ob_screen), about, messagetype, + data0, data1, data2, data3, 0, mask); +} + +void prop_message_to(Window to, Window about, Atom messagetype, + glong data0, glong data1, glong data2, + glong data3, glong data4, glong mask) +{ + XEvent ce; + ce.xclient.type = ClientMessage; + ce.xclient.message_type = messagetype; + ce.xclient.display = ob_display; + ce.xclient.window = about; + ce.xclient.format = 32; + ce.xclient.data.l[0] = data0; + ce.xclient.data.l[1] = data1; + ce.xclient.data.l[2] = data2; + ce.xclient.data.l[3] = data3; + ce.xclient.data.l[4] = data4; + XSendEvent(ob_display, to, FALSE, mask, &ce); +}
A openbox/prop.h

@@ -0,0 +1,267 @@

+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + prop.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __atoms_h +#define __atoms_h + +#include <X11/Xlib.h> +#include <glib.h> +#ifdef HAVE_STRING_H +# include <string.h> +#endif + +/*! The atoms on the X server which this class will cache */ +typedef struct Atoms { + /* types */ + Atom cardinal; /*!< The atom which represents the Cardinal data type */ + Atom window; /*!< The atom which represents window ids */ + Atom pixmap; /*!< The atom which represents pixmap ids */ + Atom atom; /*!< The atom which represents atom values */ + Atom string; /*!< The atom which represents ascii strings */ + Atom utf8; /*!< The atom which represents utf8-encoded strings */ + + /* selection stuff */ + Atom manager; + + /* window hints */ + Atom wm_colormap_windows; + Atom wm_protocols; + Atom wm_state; + Atom wm_delete_window; + Atom wm_take_focus; + Atom wm_change_state; + Atom wm_name; + Atom wm_icon_name; + Atom wm_class; + Atom wm_window_role; + Atom wm_client_machine; + Atom wm_command; + Atom wm_client_leader; + Atom wm_transient_for; + Atom motif_wm_hints; + Atom motif_wm_info; + + /* SM atoms */ + Atom sm_client_id; + + /* NETWM atoms */ + + /* Atoms that are used inside messages - these don't go in net_supported */ + + Atom net_wm_moveresize_size_topleft; + Atom net_wm_moveresize_size_top; + Atom net_wm_moveresize_size_topright; + Atom net_wm_moveresize_size_right; + Atom net_wm_moveresize_size_bottomright; + Atom net_wm_moveresize_size_bottom; + Atom net_wm_moveresize_size_bottomleft; + Atom net_wm_moveresize_size_left; + Atom net_wm_moveresize_move; + Atom net_wm_moveresize_size_keyboard; + Atom net_wm_moveresize_move_keyboard; + Atom net_wm_moveresize_cancel; + + Atom net_wm_state_add; + Atom net_wm_state_remove; + Atom net_wm_state_toggle; + + Atom net_wm_orientation_horz; + Atom net_wm_orientation_vert; + Atom net_wm_topleft; + Atom net_wm_topright; + Atom net_wm_bottomright; + Atom net_wm_bottomleft; + + /* types that we use but don't support */ + + Atom net_wm_window_type_popup_menu; + + /* Everything below here must go in net_supported on the root window */ + + /* root window properties */ + Atom net_supported; + Atom net_client_list; + Atom net_client_list_stacking; + Atom net_number_of_desktops; + Atom net_desktop_geometry; + Atom net_desktop_viewport; + Atom net_current_desktop; + Atom net_desktop_names; + Atom net_active_window; +/* Atom net_restack_window;*/ + Atom net_workarea; + Atom net_supporting_wm_check; + Atom net_desktop_layout; + Atom net_showing_desktop; + + /* root window messages */ + 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; + + /* startup-notification extension */ + Atom net_startup_id; + + /* application window properties */ + Atom net_wm_name; + Atom net_wm_visible_name; + Atom net_wm_icon_name; + Atom net_wm_visible_icon_name; + Atom net_wm_desktop; + Atom net_wm_window_type; + Atom net_wm_state; + Atom net_wm_strut; + Atom net_wm_strut_partial; + Atom net_wm_icon; + Atom net_wm_icon_geometry; + Atom net_wm_pid; + Atom net_wm_allowed_actions; + Atom net_wm_user_time; +/* Atom net_wm_user_time_window; */ + Atom net_frame_extents; + + /* application protocols */ + Atom net_wm_ping; +#ifdef SYNC + Atom net_wm_sync_request; + Atom net_wm_sync_request_counter; +#endif + + Atom net_wm_window_type_desktop; + Atom net_wm_window_type_dock; + Atom net_wm_window_type_toolbar; + Atom net_wm_window_type_menu; + Atom net_wm_window_type_utility; + Atom net_wm_window_type_splash; + Atom net_wm_window_type_dialog; + Atom net_wm_window_type_normal; + + Atom net_wm_action_move; + Atom net_wm_action_resize; + Atom net_wm_action_minimize; + Atom net_wm_action_shade; +/* Atom net_wm_action_stick;*/ + Atom net_wm_action_maximize_horz; + Atom net_wm_action_maximize_vert; + Atom net_wm_action_fullscreen; + Atom net_wm_action_change_desktop; + Atom net_wm_action_close; + Atom net_wm_action_above; + Atom net_wm_action_below; + + Atom net_wm_state_modal; +/* Atom net_wm_state_sticky;*/ + Atom net_wm_state_maximized_vert; + Atom net_wm_state_maximized_horz; + Atom net_wm_state_shaded; + Atom net_wm_state_skip_taskbar; + Atom net_wm_state_skip_pager; + Atom net_wm_state_hidden; + Atom net_wm_state_fullscreen; + Atom net_wm_state_above; + Atom net_wm_state_below; + Atom net_wm_state_demands_attention; + + /* KDE atoms */ + + Atom kde_wm_change_state; + Atom kde_net_wm_frame_strut; + Atom kde_net_wm_window_type_override; + +/* + Atom rootpmapid; + Atom esetrootid; +*/ + + /* Openbox specific atoms */ + + Atom ob_wm_action_undecorate; + Atom ob_wm_state_undecorated; + Atom openbox_pid; /* this is depreecated in favour of ob_control */ + Atom ob_theme; + Atom ob_config_file; + Atom ob_control; + Atom ob_version; + Atom ob_app_role; + Atom ob_app_name; + Atom ob_app_class; + Atom ob_app_type; +} Atoms; +extern Atoms prop_atoms; + +void prop_startup(); + +gboolean prop_get32(Window win, Atom prop, Atom type, guint32 *ret); +gboolean prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret, + guint *nret); +gboolean prop_get_string_locale(Window win, Atom prop, gchar **ret); +gboolean prop_get_string_utf8(Window win, Atom prop, gchar **ret); +gboolean prop_get_strings_locale(Window win, Atom prop, gchar ***ret); +gboolean prop_get_strings_utf8(Window win, Atom prop, gchar ***ret); + +void prop_set32(Window win, Atom prop, Atom type, gulong val); +void prop_set_array32(Window win, Atom prop, Atom type, gulong *val, + guint num); +void prop_set_string_utf8(Window win, Atom prop, const gchar *val); +void prop_set_strings_utf8(Window win, Atom prop, gchar **strs); + +void prop_erase(Window win, Atom prop); + +void prop_message(Window about, Atom messagetype, glong data0, glong data1, + glong data2, glong data3, glong mask); +void prop_message_to(Window to, Window about, Atom messagetype, + glong data0, glong data1, glong data2, + glong data3, glong data4, glong mask); + +#define PROP_GET32(win, prop, type, ret) \ + (prop_get32(win, prop_atoms.prop, prop_atoms.type, ret)) +#define PROP_GETA32(win, prop, type, ret, nret) \ + (prop_get_array32(win, prop_atoms.prop, prop_atoms.type, ret, \ + nret)) +#define PROP_GETS(win, prop, type, ret) \ + (prop_get_string_##type(win, prop_atoms.prop, ret)) +#define PROP_GETSS(win, prop, type, ret) \ + (prop_get_strings_##type(win, prop_atoms.prop, ret)) + +#define PROP_SET32(win, prop, type, val) \ + prop_set32(win, prop_atoms.prop, prop_atoms.type, val) +#define PROP_SETA32(win, prop, type, val, num) \ + prop_set_array32(win, prop_atoms.prop, prop_atoms.type, val, num) +#define PROP_SETS(win, prop, val) \ + prop_set_string_utf8(win, prop_atoms.prop, val) +#define PROP_SETSS(win, prop, strs) \ + prop_set_strings_utf8(win, prop_atoms.prop, strs) + +#define PROP_ERASE(win, prop) prop_erase(win, prop_atoms.prop) + +#define PROP_MSG(about, msgtype, data0, data1, data2, data3) \ + (prop_message(about, prop_atoms.msgtype, data0, data1, data2, data3, \ + SubstructureNotifyMask | SubstructureRedirectMask)) + +#define PROP_MSG_TO(to, about, msgtype, data0, data1, data2, data3, data4, \ + mask) \ + (prop_message_to(to, about, prop_atoms.msgtype, \ + data0, data1, data2, data3, data4, mask)) + +#endif
M openbox/screen.copenbox/screen.c

@@ -32,6 +32,7 @@ #include "event.h"

#include "focus.h" #include "focus_cycle.h" #include "popup.h" +#include "version.h" #include "obrender/render.h" #include "gettext.h" #include "obt/display.h"

@@ -294,14 +295,19 @@ supported[i++] = OBT_PROP_ATOM(OPENBOX_PID);

supported[i++] = OBT_PROP_ATOM(OB_THEME); supported[i++] = OBT_PROP_ATOM(OB_CONFIG_FILE); supported[i++] = OBT_PROP_ATOM(OB_CONTROL); - supported[i++] = OBT_PROP_ATOM(OB_ROLE); - supported[i++] = OBT_PROP_ATOM(OB_NAME); - supported[i++] = OBT_PROP_ATOM(OB_CLASS); + supported[i++] = OBT_PROP_ATOM(OB_VERSION); + supported[i++] = OBT_PROP_ATOM(OB_APP_ROLE); + supported[i++] = OBT_PROP_ATOM(OB_APP_NAME); + supported[i++] = OBT_PROP_ATOM(OB_APP_CLASS); + supported[i++] = OBT_PROP_ATOM(OB_APP_TYPE); g_assert(i == num_support); OBT_PROP_SETA32(obt_root(ob_screen), NET_SUPPORTED, ATOM, supported, num_support); g_free(supported); + + OBT_PROP_SETS(RootWindow(obt_display, ob_screen), OB_VERSION, utf8, + OPENBOX_VERSION); screen_tell_ksplash();

@@ -705,9 +711,6 @@ for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {

if (WINDOW_IS_CLIENT(it->data)) { ObClient *c = it->data; if (client_hide(c)) { - /* in the middle of cycling..? kill it. */ - focus_cycle_stop(c); - if (c == focus_client) { /* c was focused and we didn't do fallback clearly so make sure openbox doesnt still consider the window focused.

@@ -722,6 +725,8 @@ }

} } } + + focus_cycle_addremove(NULL, TRUE); event_end_ignore_all_enters(ignore_start);
A parser/parse.c

@@ -0,0 +1,532 @@

+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + parse.c for the Openbox window manager + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "parse.h" +#include <glib.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +static gboolean xdg_start; +static gchar *xdg_config_home_path; +static gchar *xdg_data_home_path; +static GSList *xdg_config_dir_paths; +static GSList *xdg_data_dir_paths; + +struct Callback { + gchar *tag; + ParseCallback func; + gpointer data; +}; + +struct _ObParseInst { + GHashTable *callbacks; +}; + +static void destfunc(struct Callback *c) +{ + g_free(c->tag); + g_free(c); +} + +ObParseInst* parse_startup(void) +{ + ObParseInst *i = g_new(ObParseInst, 1); + i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)destfunc); + return i; +} + +void parse_shutdown(ObParseInst *i) +{ + if (i) { + g_hash_table_destroy(i->callbacks); + g_free(i); + } +} + +void parse_register(ObParseInst *i, const gchar *tag, + ParseCallback func, gpointer data) +{ + struct Callback *c; + + if ((c = g_hash_table_lookup(i->callbacks, tag))) { + g_error("Tag '%s' already registered", tag); + return; + } + + c = g_new(struct Callback, 1); + c->tag = g_strdup(tag); + c->func = func; + c->data = data; + g_hash_table_insert(i->callbacks, c->tag, c); +} + +gboolean parse_load_rc(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root) +{ + GSList *it; + gboolean r = FALSE; + + if (file && parse_load(file, "openbox_config", doc, root)) + return TRUE; + + for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) { + gchar *path; + + path = g_build_filename(it->data, "openbox", "rc.xml", NULL); + r = parse_load(path, "openbox_config", doc, root); + g_free(path); + } + + return r; +} + +gboolean parse_load_theme(const gchar *name, xmlDocPtr *doc, xmlNodePtr *root, + gchar **retpath) +{ + GSList *it; + gchar *path; + gboolean r = FALSE; + gchar *eng; + + /* backward compatibility.. */ + path = g_build_filename(g_get_home_dir(), ".themes", name, + "openbox-3", "themerc.xml", NULL); + if (parse_load(path, "openbox_theme", doc, root) && + parse_attr_string("engine", *root, &eng)) + { + if (!strcmp(eng, "box")) { + *retpath = g_path_get_dirname(path); + r = TRUE; + } + g_free(eng); + } + g_free(path); + + if (!r) { + for (it = xdg_data_dir_paths; !r && it; it = g_slist_next(it)) { + path = g_build_filename(it->data, "themes", name, "openbox-3", + "themerc.xml", NULL); + if (parse_load(path, "openbox_theme", doc, root) && + parse_attr_string("engine", *root, &eng)) + { + if (!strcmp(eng, "box")) { + *retpath = g_path_get_dirname(path); + r = TRUE; + } + g_free(eng); + } + g_free(path); + } + } + return r; +} + +gboolean parse_load_menu(const gchar *file, xmlDocPtr *doc, xmlNodePtr *root) +{ + GSList *it; + gchar *path; + gboolean r = FALSE; + + if (file[0] == '/') { + r = parse_load(file, "openbox_menu", doc, root); + } else { + for (it = xdg_config_dir_paths; !r && it; it = g_slist_next(it)) { + path = g_build_filename(it->data, "openbox", file, NULL); + r = parse_load(path, "openbox_menu", doc, root); + g_free(path); + } + } + return r; +} + +gboolean parse_load(const gchar *path, const gchar *rootname, + xmlDocPtr *doc, xmlNodePtr *root) +{ + struct stat s; + + if (stat(path, &s) < 0) + return FALSE; + + /* XML_PARSE_BLANKS is needed apparently. When it loads a theme file, + without this option, the tree is weird and has extra nodes in it. */ + if ((*doc = xmlReadFile(path, NULL, + XML_PARSE_NOBLANKS | XML_PARSE_RECOVER))) { + *root = xmlDocGetRootElement(*doc); + if (!*root) { + xmlFreeDoc(*doc); + *doc = NULL; + g_message("%s is an empty document", path); + } else { + if (xmlStrcmp((*root)->name, (const xmlChar*)rootname)) { + xmlFreeDoc(*doc); + *doc = NULL; + g_message("XML Document %s is of wrong type. Root " + "node is not '%s'", path, rootname); + } + } + } + if (!*doc) + return FALSE; + return TRUE; +} + +gboolean parse_load_mem(gpointer data, guint len, const gchar *rootname, + xmlDocPtr *doc, xmlNodePtr *root) +{ + if ((*doc = xmlParseMemory(data, len))) { + *root = xmlDocGetRootElement(*doc); + if (!*root) { + xmlFreeDoc(*doc); + *doc = NULL; + g_message("Given memory is an empty document"); + } else { + if (xmlStrcmp((*root)->name, (const xmlChar*)rootname)) { + xmlFreeDoc(*doc); + *doc = NULL; + g_message("XML Document in given memory is of wrong " + "type. Root node is not '%s'\n", rootname); + } + } + } + if (!*doc) + return FALSE; + return TRUE; +} + +void parse_close(xmlDocPtr doc) +{ + xmlFreeDoc(doc); +} + +void parse_tree(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) +{ + while (node) { + struct Callback *c = g_hash_table_lookup(i->callbacks, node->name); + + if (c) + c->func(i, doc, node, c->data); + + node = node->next; + } +} + +gchar *parse_string(xmlDocPtr doc, xmlNodePtr node) +{ + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); + gchar *s = g_strdup(c ? (gchar*)c : ""); + xmlFree(c); + return s; +} + +gint parse_int(xmlDocPtr doc, xmlNodePtr node) +{ + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); + gint i = c ? atoi((gchar*)c) : 0; + xmlFree(c); + return i; +} + +gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node) +{ + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); + gboolean b = FALSE; + if (c && !xmlStrcasecmp(c, (const xmlChar*) "true")) + b = TRUE; + else if (c && !xmlStrcasecmp(c, (const xmlChar*) "yes")) + b = TRUE; + else if (c && !xmlStrcasecmp(c, (const xmlChar*) "on")) + b = TRUE; + xmlFree(c); + return b; +} + +gboolean parse_contains(const gchar *val, xmlDocPtr doc, xmlNodePtr node) +{ + xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE); + gboolean r; + r = !xmlStrcasecmp(c, (const xmlChar*) val); + xmlFree(c); + return r; +} + +xmlNodePtr parse_find_node(const gchar *tag, xmlNodePtr node) +{ + while (node) { + if (!xmlStrcmp(node->name, (const xmlChar*) tag)) + return node; + node = node->next; + } + return NULL; +} + +gboolean parse_attr_bool(const gchar *name, xmlNodePtr node, gboolean *value) +{ + xmlChar *c = xmlGetProp(node, (const xmlChar*) name); + gboolean r = FALSE; + if (c) { + if (!xmlStrcasecmp(c, (const xmlChar*) "true")) + *value = TRUE, r = TRUE; + else if (!xmlStrcasecmp(c, (const xmlChar*) "yes")) + *value = TRUE, r = TRUE; + else if (!xmlStrcasecmp(c, (const xmlChar*) "on")) + *value = TRUE, r = TRUE; + else if (!xmlStrcasecmp(c, (const xmlChar*) "false")) + *value = FALSE, r = TRUE; + else if (!xmlStrcasecmp(c, (const xmlChar*) "no")) + *value = FALSE, r = TRUE; + else if (!xmlStrcasecmp(c, (const xmlChar*) "off")) + *value = FALSE, r = TRUE; + } + xmlFree(c); + return r; +} + +gboolean parse_attr_int(const gchar *name, xmlNodePtr node, gint *value) +{ + xmlChar *c = xmlGetProp(node, (const xmlChar*) name); + gboolean r = FALSE; + if (c) { + *value = atoi((gchar*)c); + r = TRUE; + } + xmlFree(c); + return r; +} + +gboolean parse_attr_string(const gchar *name, xmlNodePtr node, gchar **value) +{ + xmlChar *c = xmlGetProp(node, (const xmlChar*) name); + gboolean r = FALSE; + if (c) { + *value = g_strdup((gchar*)c); + r = TRUE; + } + xmlFree(c); + return r; +} + +gboolean parse_attr_contains(const gchar *val, xmlNodePtr node, + const gchar *name) +{ + xmlChar *c = xmlGetProp(node, (const xmlChar*) name); + gboolean r = FALSE; + if (c) + r = !xmlStrcasecmp(c, (const xmlChar*) val); + xmlFree(c); + return r; +} + +static gint slist_path_cmp(const gchar *a, const gchar *b) +{ + return strcmp(a, b); +} + +typedef GSList* (*GSListFunc) (gpointer list, gconstpointer data); + +static GSList* slist_path_add(GSList *list, gpointer data, GSListFunc func) +{ + g_assert(func); + + if (!data) + return list; + + if (!g_slist_find_custom(list, data, (GCompareFunc) slist_path_cmp)) + list = func(list, data); + else + g_free(data); + + return list; +} + +static GSList* split_paths(const gchar *paths) +{ + GSList *list = NULL; + gchar **spl, **it; + + if (!paths) + return NULL; + spl = g_strsplit(paths, ":", -1); + for (it = spl; *it; ++it) + list = slist_path_add(list, *it, (GSListFunc) g_slist_append); + g_free(spl); + return list; +} + +void parse_paths_startup(void) +{ + const gchar *path; + + if (xdg_start) + return; + xdg_start = TRUE; + + path = g_getenv("XDG_CONFIG_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_config_home_path = g_build_filename(path, NULL); + else + xdg_config_home_path = g_build_filename(g_get_home_dir(), ".config", + NULL); + + path = g_getenv("XDG_DATA_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_data_home_path = g_build_filename(path, NULL); + else + xdg_data_home_path = g_build_filename(g_get_home_dir(), ".local", + "share", NULL); + + path = g_getenv("XDG_CONFIG_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_config_dir_paths = split_paths(path); + else { + xdg_config_dir_paths = slist_path_add(xdg_config_dir_paths, + g_strdup(CONFIGDIR), + (GSListFunc) g_slist_append); + xdg_config_dir_paths = slist_path_add(xdg_config_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "etc", "xdg", NULL), + (GSListFunc) g_slist_append); + } + xdg_config_dir_paths = slist_path_add(xdg_config_dir_paths, + g_strdup(xdg_config_home_path), + (GSListFunc) g_slist_prepend); + + path = g_getenv("XDG_DATA_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + xdg_data_dir_paths = split_paths(path); + else { + xdg_data_dir_paths = slist_path_add(xdg_data_dir_paths, + g_strdup(DATADIR), + (GSListFunc) g_slist_append); + xdg_data_dir_paths = slist_path_add(xdg_data_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "local", "share", NULL), + (GSListFunc) g_slist_append); + xdg_data_dir_paths = slist_path_add(xdg_data_dir_paths, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "share", NULL), + (GSListFunc) g_slist_append); + } + xdg_data_dir_paths = slist_path_add(xdg_data_dir_paths, + g_strdup(xdg_data_home_path), + (GSListFunc) g_slist_prepend); +} + +void parse_paths_shutdown(void) +{ + GSList *it; + + if (!xdg_start) + return; + xdg_start = FALSE; + + for (it = xdg_config_dir_paths; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(xdg_config_dir_paths); + xdg_config_dir_paths = NULL; + for (it = xdg_data_dir_paths; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(xdg_data_dir_paths); + xdg_data_dir_paths = NULL; + g_free(xdg_config_home_path); + xdg_config_home_path = NULL; + g_free(xdg_data_home_path); + xdg_data_home_path = NULL; +} + +gchar *parse_expand_tilde(const gchar *f) +{ + gchar *ret; + GRegex *regex; + + if (!f) + return NULL; + + regex = g_regex_new("(?:^|(?<=[ \\t]))~(?:(?=[/ \\t])|$)", + G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL); + ret = g_regex_replace_literal(regex, f, -1, 0, g_get_home_dir(), 0, NULL); + g_regex_unref(regex); + + return ret; +} + +gboolean parse_mkdir(const gchar *path, gint mode) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(path != NULL, FALSE); + g_return_val_if_fail(path[0] != '\0', FALSE); + + if (!g_file_test(path, G_FILE_TEST_IS_DIR)) + if (mkdir(path, mode) == -1) + ret = FALSE; + + return ret; +} + +gboolean parse_mkdir_path(const gchar *path, gint mode) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(path != NULL, FALSE); + g_return_val_if_fail(path[0] == '/', FALSE); + + if (!g_file_test(path, G_FILE_TEST_IS_DIR)) { + gchar *c, *e; + + c = g_strdup(path); + e = c; + while ((e = strchr(e + 1, '/'))) { + *e = '\0'; + if (!(ret = parse_mkdir(c, mode))) + goto parse_mkdir_path_end; + *e = '/'; + } + ret = parse_mkdir(c, mode); + + parse_mkdir_path_end: + g_free(c); + } + + return ret; +} + +const gchar* parse_xdg_config_home_path(void) +{ + return xdg_config_home_path; +} + +const gchar* parse_xdg_data_home_path(void) +{ + return xdg_data_home_path; +} + +GSList* parse_xdg_config_dir_paths(void) +{ + return xdg_config_dir_paths; +} + +GSList* parse_xdg_data_dir_paths(void) +{ + return xdg_data_dir_paths; +}
M po/hu.popo/hu.po

@@ -1,15 +1,16 @@

-# Hungarian messages for openbox. -# Copyright (C) 2007 Mikael Magnusson +# Hungarian translation of openbox. +# Copyright (C) 2007 Dana Jansens # This file is distributed under the same license as the openbox package. # Robert Kuszinger <hiding@freemail.hu>, 2007. +# Laszlo Dvornik <dvornik@gnome.hu>, 2010. # msgid "" msgstr "" -"Project-Id-Version: Openbox 3.4.7\n" +"Project-Id-Version: openbox 3.4.10\n" "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n" -"POT-Creation-Date: 2008-11-15 22:28+0100\n" -"PO-Revision-Date: 2008-03-17 19:25+0100\n" -"Last-Translator: Robert Kuszinger <hiding@freemail.hu>\n" +"POT-Creation-Date: 2010-01-08 22:39+0100\n" +"PO-Revision-Date: 2010-01-08 22:23+0100\n" +"Last-Translator: Laszlo Dvornik <dvornik@gnome.hu>\n" "Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n"

@@ -19,7 +20,7 @@

#: openbox/actions.c:149 #, c-format msgid "Invalid action \"%s\" requested. No such action exists." -msgstr "Érvénytelen művelet \"%s\". Nem létezik ilyen." +msgstr "Érvénytelen művelet \"%s\". Nem létezik ilyen művelet." #: openbox/actions/execute.c:128 msgid "No"

@@ -38,54 +39,43 @@ #, c-format

msgid "Failed to convert the path \"%s\" from utf8" msgstr "Az útvonalat nem sikerült átalakítani utf8-ból: \"%s\"" -#: openbox/actions/exit.c:52 openbox/actions/session.c:64 -#: openbox/client.c:3465 +#: openbox/actions/exit.c:62 openbox/client.c:3474 msgid "Cancel" msgstr "Mégsem" -#: openbox/actions/exit.c:53 +#: openbox/actions/exit.c:63 msgid "Exit" msgstr "Kilépés" -#: openbox/actions/exit.c:56 +#: openbox/actions/exit.c:67 +msgid "Are you sure you want to log out?" +msgstr "Biztos, hogy ki akarsz jelentkezni?" + +#: openbox/actions/exit.c:68 +msgid "Log Out" +msgstr "Kijelentkezés" + +#: openbox/actions/exit.c:71 msgid "Are you sure you want to exit Openbox?" -msgstr "Biztos, hogy ki akarsz lépni az Openboxból?" +msgstr "Biztos ki akar lépni az Openboxból?" -#: openbox/actions/exit.c:57 +#: openbox/actions/exit.c:72 msgid "Exit Openbox" msgstr "Kilépés az Openboxból" -#. TRANSLATORS: Don't translate the word "SessionLogout" as it's the -#. name of the action you write in rc.xml -#: openbox/actions/session.c:43 -msgid "" -"The SessionLogout action is not available since Openbox was built without " -"session management support" -msgstr "" -"A SessionLogout művelet nem elérhető mivel az Openbox szekciókezelés " -"támogatása nélkül lett lefordítva" - -#: openbox/actions/session.c:65 openbox/actions/session.c:70 -msgid "Log Out" -msgstr "Kijelentkezés" - -#: openbox/actions/session.c:69 -msgid "Are you sure you want to log out?" -msgstr "Biztos, hogy ki akarsz jelentkezni?" - -#: openbox/client.c:2012 +#: openbox/client.c:2016 msgid "Unnamed Window" -msgstr "Névtelen Ablak" +msgstr "Névtelen ablak" -#: openbox/client.c:2026 openbox/client.c:2058 +#: openbox/client.c:2030 openbox/client.c:2062 msgid "Killing..." msgstr "Kilövés..." -#: openbox/client.c:2028 openbox/client.c:2060 +#: openbox/client.c:2032 openbox/client.c:2064 msgid "Not Responding" -msgstr "Nem Válaszol" +msgstr "Nem válaszol" -#: openbox/client.c:3454 +#: openbox/client.c:3463 #, c-format msgid "" "The window \"%s\" does not seem to be responding. Do you want to force it "

@@ -93,24 +83,24 @@ "to exit by sending the %s signal?"

msgstr "" "A(z) \"%s\" ablak nem válaszol. Erőltessük a kilépést a %s jelzés küldésével?" -#: openbox/client.c:3456 +#: openbox/client.c:3465 msgid "End Process" -msgstr "Folyamat Vége" +msgstr "Folyamat vége" -#: openbox/client.c:3460 +#: openbox/client.c:3469 #, c-format msgid "" "The window \"%s\" does not seem to be responding. Do you want to disconnect " "it from the X server?" -msgstr "A(z) \"%s\" ablak nem válaszol. Lekapcsoljuk az X szerverről?" +msgstr "A(z) \"%s\" ablak nem válaszol. Lekapcsoljuk az X kiszolgálóról?" -#: openbox/client.c:3462 +#: openbox/client.c:3471 msgid "Disconnect" -msgstr "Szétkapcsolódás" +msgstr "Lekapcsolódás" #: openbox/client_list_combined_menu.c:87 openbox/client_list_menu.c:91 msgid "Go there..." -msgstr "Menjünk oda..." +msgstr "Ugrás..." #: openbox/client_list_combined_menu.c:94 msgid "Manage desktops"

@@ -118,7 +108,7 @@ msgstr "Munkaasztal-kezelés"

#: openbox/client_list_combined_menu.c:95 openbox/client_list_menu.c:155 msgid "_Add new desktop" -msgstr "Új _munkaasztal" +msgstr "Új munk_aasztal" #: openbox/client_list_combined_menu.c:96 openbox/client_list_menu.c:156 msgid "_Remove last desktop"

@@ -154,7 +144,7 @@ msgstr "Mindig _alul"

#: openbox/client_menu.c:379 msgid "_Send to desktop" -msgstr "Munkaasztalra _küldeni" +msgstr "Munkaasztalra _küldés" #: openbox/client_menu.c:383 msgid "Client menu"

@@ -166,15 +156,15 @@ msgstr "_Visszaállítás"

#: openbox/client_menu.c:397 msgid "_Move" -msgstr "_Mozgatás" +msgstr "Á_thelyezés" #: openbox/client_menu.c:399 msgid "Resi_ze" -msgstr "_Átméretezés" +msgstr "Átmérete_zés" #: openbox/client_menu.c:401 msgid "Ico_nify" -msgstr "Iko_nná alakítás" +msgstr "Iko_nizálás" #: openbox/client_menu.c:405 msgid "Ma_ximize"

@@ -186,117 +176,121 @@ msgstr "_Görgetés fel/le"

#: openbox/client_menu.c:411 msgid "Un/_Decorate" -msgstr "_Dekoráció eltávilítása" +msgstr "_Dekoráció eltávolítása" #: openbox/client_menu.c:415 msgid "_Close" msgstr "_Bezárás" -#: openbox/config.c:781 +#: openbox/config.c:798 #, c-format msgid "Invalid button \"%s\" specified in config file" msgstr "Érvénytelen gomb a konfigurációs fájlban \"%s\"" #: openbox/keyboard.c:157 msgid "Conflict with key binding in config file" -msgstr "Ütköző billentyű-műveletek a konfigurációs fájlban" +msgstr "Ütköző billentyű hozzárendelések a konfigurációs fájlban" #: openbox/menu.c:102 openbox/menu.c:110 #, c-format msgid "Unable to find a valid menu file \"%s\"" -msgstr "Nem található ilyen érvényes menü fájl: \"%s\"" +msgstr "Nem található ilyen érvényes menüfájl: \"%s\"" #: openbox/menu.c:170 #, c-format msgid "Failed to execute command for pipe-menu \"%s\": %s" -msgstr "Sikertelen parancsfuttatás a csővezeték-menüben \"%s\": %s" +msgstr "Nem sikerült végrehajtani a parancsot a csővezeték-menüben \"%s\": %s" #: openbox/menu.c:184 #, c-format msgid "Invalid output from pipe-menu \"%s\"" -msgstr "Érvnytelen válasz a csővezeték menüből \"%s\"" +msgstr "Érvnytelen kimenet a csővezeték-menüből \"%s\"" #: openbox/menu.c:197 #, c-format msgid "Attempted to access menu \"%s\" but it does not exist" msgstr "\"%s\" menü elérésére történt kísérlet, de az nem létezik" -#: openbox/menu.c:367 openbox/menu.c:368 +#: openbox/menu.c:370 openbox/menu.c:371 msgid "More..." msgstr "Tovább..." #: openbox/mouse.c:373 #, c-format msgid "Invalid button \"%s\" in mouse binding" -msgstr "Érvénytelen gomb \"%s\" az egér parancsoknál" +msgstr "Érvénytelen gomb \"%s\" az egér hozzárendeléseknél" #: openbox/mouse.c:379 #, c-format msgid "Invalid context \"%s\" in mouse binding" -msgstr "Érvénytelen környezet az egér parancsoknál: \"%s\"" +msgstr "Érvénytelen környezet az egér hozzárendeléseknél: \"%s\"" #: openbox/openbox.c:133 #, c-format msgid "Unable to change to home directory \"%s\": %s" -msgstr "Nem lehet a saját mappába váltani \"%s\": %s" +msgstr "Nem lehet a saját könyvtárba váltani \"%s\": %s" #: openbox/openbox.c:152 msgid "Failed to open the display from the DISPLAY environment variable." -msgstr "Nem nyitható meg a DISPLAY változóban beállított képernyő" +msgstr "" +"Nem sikerült megnyitni a DISPLAY környezeti változóban beállított képernyőt." #: openbox/openbox.c:183 msgid "Failed to initialize the obrender library." -msgstr "Nem sikerült használatba venni az obernder függvénykönyvtárat" +msgstr "Nem sikerült előkészíteni az obrender programkönyvtárat." #: openbox/openbox.c:194 msgid "X server does not support locale." -msgstr "Az X kiszolgáló nem támogatja ezt a nemzetközi beállítást." +msgstr "Az X-kiszolgáló nem támogatja ezt a nemzetközi beállítást." #: openbox/openbox.c:196 msgid "Cannot set locale modifiers for the X server." -msgstr "A nemzetközi beálljtás módosítók nem állíthatók be az X szerveren." +msgstr "" +"Nem lehet beállítani a nemzetközi beállítás-módosítókat az X-kiszolgálón." -#: openbox/openbox.c:263 +#: openbox/openbox.c:265 msgid "Unable to find a valid config file, using some simple defaults" -msgstr "Nincs konfigurációs fájl, ezért egyszerű alapértelmezéseket használunk" +msgstr "" +"Nem található érvényes konfigurációs fájl, ezért egyszerű alapértelmezés " +"lesznek használva" -#: openbox/openbox.c:297 +#: openbox/openbox.c:299 msgid "Unable to load a theme." -msgstr "Nem tölthető be a téma." +msgstr "Nem lehet betölteni témát." -#: openbox/openbox.c:377 +#: openbox/openbox.c:379 #, c-format msgid "" "One or more XML syntax errors were found while parsing the Openbox " "configuration files. See stdout for more information. The last error seen " "was in file \"%s\" line %d, with message: %s" msgstr "" -"Egy vagy több XML szintaktikai hibát találtam az Openbox konfigurációs fájl " -"olvasásakor. Nézd meg a standard kimenetet a részletekért. Az utolsó hiba " -"ebben a fájlban volt: \"%s\" a %d sorban. A hibaüzenet: %s" +"Egy vagy több XML szintaktikai hiba található az Openbox konfigurációs fájl " +"feldolgozásakor. További információkért tekintse meg a szabványos kimenetet. " +"Az utolsó hiba ebben a fájlban volt: \"%s\" (%d sor). A hibaüzenet: %s" -#: openbox/openbox.c:379 +#: openbox/openbox.c:381 msgid "Openbox Syntax Error" -msgstr "Openbox Szintaxis Hiba" +msgstr "Openbox szintaktikai hiba" -#: openbox/openbox.c:379 +#: openbox/openbox.c:381 msgid "Close" msgstr "Bezárás" -#: openbox/openbox.c:448 +#: openbox/openbox.c:463 #, c-format msgid "Restart failed to execute new executable \"%s\": %s" msgstr "Az újraindítás során ez az új program nem volt indítható \"%s\": %s" -#: openbox/openbox.c:518 openbox/openbox.c:520 +#: openbox/openbox.c:533 openbox/openbox.c:535 msgid "Copyright (c)" -msgstr "Szerzői jogok (c)" +msgstr "Copyright (c)" -#: openbox/openbox.c:529 +#: openbox/openbox.c:544 msgid "Syntax: openbox [options]\n" -msgstr "Használat: openbox [options]\n" +msgstr "Használat: openbox [opciók]\n" -#: openbox/openbox.c:530 +#: openbox/openbox.c:545 msgid "" "\n" "Options:\n"

@@ -304,115 +298,115 @@ msgstr ""

"\n" "Opciók:\n" -#: openbox/openbox.c:531 +#: openbox/openbox.c:546 msgid " --help Display this help and exit\n" msgstr " --help Súgó megjelenítése és kilépés\n" -#: openbox/openbox.c:532 +#: openbox/openbox.c:547 msgid " --version Display the version and exit\n" -msgstr " --version Verzió kiírása majd kilépés\n" +msgstr " --version Verzió kiírása és kilépés\n" -#: openbox/openbox.c:533 +#: openbox/openbox.c:548 msgid " --replace Replace the currently running window manager\n" -msgstr " --replace Futó ablakkezelő cseréje\n" +msgstr " --replace Jelenleg futó ablakkezelő cseréje\n" #. TRANSLATORS: if you translate "FILE" here, make sure to keep the "Specify..." #. aligned still, if you have to, make a new line with \n and 22 spaces. It's #. fine to leave it as FILE though. -#: openbox/openbox.c:537 +#: openbox/openbox.c:552 msgid " --config-file FILE Specify the path to the config file to use\n" msgstr "" -" --config-file FILE Megadhatod az útvonalat a konfigurációs file-hoz\n" +" --config-file FÁJL A használandó konfigurációs fájl útvonalának megadása\n" -#: openbox/openbox.c:538 +#: openbox/openbox.c:553 msgid " --sm-disable Disable connection to the session manager\n" -msgstr " --sm-disable Ne csatlakozzon a szekció-kezelőhöz\n" +msgstr " --sm-disable Ne csatlakozzon a munkamenet-kezelőhöz\n" -#: openbox/openbox.c:539 +#: openbox/openbox.c:554 msgid "" "\n" "Passing messages to a running Openbox instance:\n" msgstr "" "\n" -"Üzenet küldése a futó Openbox példánynak\n" +"Üzenet küldése a futó Openbox példánynak:\n" -#: openbox/openbox.c:540 +#: openbox/openbox.c:555 msgid " --reconfigure Reload Openbox's configuration\n" -msgstr " --reconfigure Konfiguráció úrjatöltése\n" +msgstr " --reconfigure Openbox beállításának újratöltése\n" -#: openbox/openbox.c:541 +#: openbox/openbox.c:556 msgid " --restart Restart Openbox\n" msgstr " --restart Openbox újraindítása\n" -#: openbox/openbox.c:542 +#: openbox/openbox.c:557 msgid " --exit Exit Openbox\n" msgstr " --exit Kilépés az Openboxból\n" -#: openbox/openbox.c:543 +#: openbox/openbox.c:558 msgid "" "\n" "Debugging options:\n" msgstr "" "\n" -"Debug (hibakereső) lehetőségek:\n" +"Hibakeresési opciók:\n" -#: openbox/openbox.c:544 +#: openbox/openbox.c:559 msgid " --sync Run in synchronous mode\n" msgstr " --sync Futtatás szinkron módban\n" -#: openbox/openbox.c:545 +#: openbox/openbox.c:560 msgid " --debug Display debugging output\n" -msgstr " --debug Hibakeresési információk megjelenítése\n" +msgstr " --debug Hibakeresési kimenet megjelenítése\n" -#: openbox/openbox.c:546 +#: openbox/openbox.c:561 msgid " --debug-focus Display debugging output for focus handling\n" msgstr "" -" --debug-focus Fókuszkezelésre vonatkozó hibakeresési információk " -"kiírása\n" +" --debug-focus Fókuszkezelésre vonatkozó hibakeresési kimenetek " +"megjelenítése\n" -#: openbox/openbox.c:547 +#: openbox/openbox.c:562 msgid " --debug-xinerama Split the display into fake xinerama screens\n" msgstr " --debug-xinerama Képernyő felosztása két ál-xinerama képernyőre\n" -#: openbox/openbox.c:548 +#: openbox/openbox.c:563 #, c-format msgid "" "\n" "Please report bugs at %s\n" msgstr "" "\n" -"Légyszi jelentsd a hibát itt: %s\n" +"Kérjük a hibákat itt jelentse: %s\n" -#: openbox/openbox.c:617 +#: openbox/openbox.c:645 msgid "--config-file requires an argument\n" -msgstr "--config-file használatakor paraméter megadása kötelező!\n" +msgstr "--config-file használatakor paraméter megadása kötelező\n" -#: openbox/openbox.c:660 +#: openbox/openbox.c:688 #, c-format msgid "Invalid command line argument \"%s\"\n" msgstr "Érvénytelen parancssori opció: \"%s\"\n" -#: openbox/screen.c:102 openbox/screen.c:190 +#: openbox/screen.c:103 openbox/screen.c:191 #, c-format msgid "A window manager is already running on screen %d" -msgstr "Már fut egy ablakkezelő ezen a képernyőn %d" +msgstr "Már fut egy ablakkezelő ezen a képernyőn: %d" -#: openbox/screen.c:124 +#: openbox/screen.c:125 #, c-format msgid "Could not acquire window manager selection on screen %d" -msgstr "Nem tudok ablakkezelőt váltani ezen a képernyőn %d" +msgstr "Nem lehet ablakkezelőt váltani ezen a képernyőn: %d" -#: openbox/screen.c:145 +#: openbox/screen.c:146 #, c-format msgid "The WM on screen %d is not exiting" -msgstr "Ezen a képernyőn: %d az ablakkezelő nem lép ki" +msgstr "Nem lép ki az ablakkezelő ezen a képernyőn: %d" #. TRANSLATORS: If you need to specify a different order of the #. arguments, you can use %1$d for the first one and %2$d for the #. second one. For example, #. "The current session has %2$d desktops, but Openbox is configured for %1$d ..." -#: openbox/screen.c:412 -#, fuzzy, c-format +#: openbox/screen.c:416 +#, c-format msgid "" "Openbox is configured for %d desktop, but the current session has %d. " "Overriding the Openbox configuration."

@@ -421,68 +415,66 @@ "Openbox is configured for %d desktops, but the current session has %d. "

"Overriding the Openbox configuration." msgstr[0] "" "Az Openbox %d munkaasztal használatára lett beállítva, de a jelenlegi " -"munkamenetnek %d van. Felülbíráljuk az Openbox beállítását." +"munkamenetnek %d van. Felülbíráljuk az Openbox beállítását." msgstr[1] "" "Az Openbox %d munkaasztal használatára lett beállítva, de a jelenlegi " -"munkamenetnek %d van. Felülbíráljuk az Openbox beállítását." +"munkamenetnek %d van. Felülbíráljuk az Openbox beállítását." -#: openbox/screen.c:1180 +#: openbox/screen.c:1199 #, c-format msgid "desktop %i" msgstr "%i. munkaasztal" -#: openbox/session.c:104 +#: openbox/session.c:105 #, c-format msgid "Unable to make directory \"%s\": %s" -msgstr "Nem hozható létre a könyvtár \"%s\": %s" +msgstr "Nem lehet létrehozni a könyvtárat \"%s\": %s" -#: openbox/session.c:466 +#: openbox/session.c:472 #, c-format msgid "Unable to save the session to \"%s\": %s" -msgstr "Nem tudom elmenti ide a futó környezetet \"%s\": %s" +msgstr "Nem lehet menteni ide a futó munkamenetet \"%s\": %s" -#: openbox/session.c:605 +#: openbox/session.c:611 #, c-format msgid "Error while saving the session to \"%s\": %s" -msgstr "Hiba a futási környezet mentése közben \"%s\": %s" +msgstr "Hiba a munkamenet mentése közben \"%s\": %s" -#: openbox/session.c:842 +#: openbox/session.c:848 msgid "Not connected to a session manager" -msgstr "Nem kapcsolódunk a szekciókezelőhöz" +msgstr "Nincs kapcsolódva a munkamenet-kezelőhöz" #: openbox/startupnotify.c:243 #, c-format msgid "Running %s" -msgstr "Futtatás %s" +msgstr "%s futtatása" #: openbox/translate.c:59 #, c-format msgid "Invalid modifier key \"%s\" in key/mouse binding" -msgstr "Érvénytelen módosító gomb \"%s\" egér vagy billentyűparancsnál" +msgstr "" +"Érvénytelen módosító billentyű \"%s\" billentyű vagy egér hozzárendelésnél" #: openbox/translate.c:138 #, c-format msgid "Invalid key code \"%s\" in key binding" -msgstr "Érvénytelen billentyűkód \"%s\" billentyűparancsnál" +msgstr "Érvénytelen billentyűkód \"%s\" billentyű hozzárendelésnél" #: openbox/translate.c:145 #, c-format msgid "Invalid key name \"%s\" in key binding" -msgstr "Érvénytelen billentyűnév \"%s\" billentyűparancsnál" +msgstr "Érvénytelen billentyűnév \"%s\" billentyű hozzárendelésnél" #: openbox/translate.c:151 #, c-format msgid "Requested key \"%s\" does not exist on the display" -msgstr "A kért gomb \"%s\" nem létezik a képernyőn" +msgstr "A kért billentyű \"%s\" nem létezik a képernyőn" #: openbox/xerror.c:40 #, c-format msgid "X Error: %s" -msgstr "X rendszer hiba: %s" +msgstr "X-hiba: %s" #: openbox/prompt.c:200 msgid "OK" msgstr "OK" - -#~ msgid "Failed to execute \"%s\": %s" -#~ msgstr "Nem sikerült futtatni ezt a programot \"%s\": %s"
M po/ja.popo/ja.po

@@ -296,7 +296,7 @@ msgstr "著作権 (c)"

#: openbox/openbox.c:529 msgid "Syntax: openbox [options]\n" -msgstr "使い方: openbox [オプション]\n" +msgstr "用法: openbox [オプション]\n" #: openbox/openbox.c:530 msgid ""
M po/lv.popo/lv.po

@@ -1,26 +1,27 @@

# Latvian translations for openbox. -# Copyright (C) 2009 Dana Jansens +# Copyright (C) 2010 Dana Jansens # This file is distributed under the same license as the openbox package. -# Einars Sprugis <einars8@gmail.com>, 2009. # +# Einars Sprugis <einars8@gmail.com>, 2010. msgid "" msgstr "" -"Project-Id-Version: Openbox 3.4.7\n" +"Project-Id-Version: 3.4.10\n" "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n" -"POT-Creation-Date: 2009-03-31 19:16+0200\n" -"PO-Revision-Date: 2009-03-30 19:14+0300\n" +"POT-Creation-Date: 2010-01-10 22:21+0100\n" +"PO-Revision-Date: 2010-01-08 21:11+0200\n" "Last-Translator: Einars Sprugis <einars8@gmail.com>\n" -"Language-Team: Latvian <lv@li.org>\n" +"Language-Team: Latvian <locale@laka.lv>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " "2);\n" +"X-Generator: Lokalize 1.0\n" #: openbox/actions.c:149 #, c-format msgid "Invalid action \"%s\" requested. No such action exists." -msgstr "Neatļauta darbība \"%s\". Šāda darbība neeksistē." +msgstr "Prasīta neatļauta darbība \"%s\". Šāda darbība neeksistē." #: openbox/actions/execute.c:128 msgid "No"

@@ -39,72 +40,63 @@ #, c-format

msgid "Failed to convert the path \"%s\" from utf8" msgstr "Neizdevās pārveidot ceļu \"%s\" no utf8" -#: openbox/actions/exit.c:52 openbox/actions/session.c:64 -#: openbox/client.c:3465 +#: openbox/actions/exit.c:62 openbox/client.c:3474 msgid "Cancel" msgstr "Atcelt" -#: openbox/actions/exit.c:53 +#: openbox/actions/exit.c:63 msgid "Exit" msgstr "Iziet" -#: openbox/actions/exit.c:56 +#: openbox/actions/exit.c:67 +msgid "Are you sure you want to log out?" +msgstr "Vai tiešām vēlaties atteikties?" + +#: openbox/actions/exit.c:68 +msgid "Log Out" +msgstr "Atteikties" + +#: openbox/actions/exit.c:71 msgid "Are you sure you want to exit Openbox?" msgstr "Vai tiešām vēlaties iziet no Openbox?" -#: openbox/actions/exit.c:57 +#: openbox/actions/exit.c:72 msgid "Exit Openbox" msgstr "Iziet no Openbox" -#. TRANSLATORS: Don't translate the word "SessionLogout" as it's the -#. name of the action you write in rc.xml -#: openbox/actions/session.c:43 -msgid "" -"The SessionLogout action is not available since Openbox was built without " -"session management support" -msgstr "" -"SessionLogout darbība nav pieejama, jo Openbox tika kompilēts bez sesijas " -"pārvaldes atbalsta" - -#: openbox/actions/session.c:65 openbox/actions/session.c:70 -msgid "Log Out" -msgstr "Atteikties" - -#: openbox/actions/session.c:69 -msgid "Are you sure you want to log out?" -msgstr "Vai tiešām vēlaties atteikties?" - -#: openbox/client.c:2012 +#: openbox/client.c:2016 msgid "Unnamed Window" msgstr "Logs bez nosaukuma" -#: openbox/client.c:2026 openbox/client.c:2058 +#: openbox/client.c:2030 openbox/client.c:2062 msgid "Killing..." msgstr "Nogalina..." -#: openbox/client.c:2028 openbox/client.c:2060 +#: openbox/client.c:2032 openbox/client.c:2064 msgid "Not Responding" msgstr "Neatbild" -#: openbox/client.c:3454 +#: openbox/client.c:3463 #, c-format msgid "" "The window \"%s\" does not seem to be responding. Do you want to force it " "to exit by sending the %s signal?" -msgstr "Logs \"%s\" neatbild. Vai vēlieties to piespiest, nosūtot signālu %s?" +msgstr "" +"Logs \"%s\" neatbild. Vai vēlieties to aizvērt piespiedu kārtā, nosūtot " +"signālu %s?" -#: openbox/client.c:3456 +#: openbox/client.c:3465 msgid "End Process" msgstr "Nobeigt procesu" -#: openbox/client.c:3460 +#: openbox/client.c:3469 #, c-format msgid "" "The window \"%s\" does not seem to be responding. Do you want to disconnect " "it from the X server?" msgstr "Logs \"%s\" neatbild. Vai vēlaties to atvienot no X servera?" -#: openbox/client.c:3462 +#: openbox/client.c:3471 msgid "Disconnect" msgstr "Atvienot"

@@ -122,7 +114,7 @@ msgstr "Pievienot j_aunu darbvirsmu"

#: openbox/client_list_combined_menu.c:96 openbox/client_list_menu.c:156 msgid "_Remove last desktop" -msgstr "Aizvākt pēdējo da_rbvirsmu" +msgstr "Noņemt pēdējo da_rbvirsmu" #: openbox/client_list_combined_menu.c:149 msgid "Windows"

@@ -146,7 +138,7 @@ msgstr "Vienmēr augšā"

#: openbox/client_menu.c:376 msgid "_Normal" -msgstr "_Normāli" +msgstr "_Normāls" #: openbox/client_menu.c:377 msgid "Always on _bottom"

@@ -158,7 +150,7 @@ msgstr "No_sūtīt uz darbvirsmu"

#: openbox/client_menu.c:383 msgid "Client menu" -msgstr "Klientizvēlne" +msgstr "Klienta izvēlne" #: openbox/client_menu.c:393 msgid "R_estore"

@@ -192,7 +184,7 @@ #: openbox/client_menu.c:415

msgid "_Close" msgstr "Ai_zvērt" -#: openbox/config.c:782 +#: openbox/config.c:798 #, c-format msgid "Invalid button \"%s\" specified in config file" msgstr "Konfigurācijas failā \"%s\" norādīts neatļauts taustiņš"

@@ -221,7 +213,7 @@ #, c-format

msgid "Attempted to access menu \"%s\" but it does not exist" msgstr "Mēģināja piekļūt izvēlnei \"%s\", bet tā neeksistē" -#: openbox/menu.c:367 openbox/menu.c:368 +#: openbox/menu.c:370 openbox/menu.c:371 msgid "More..." msgstr "Vairāk..."

@@ -242,7 +234,7 @@ msgstr "Nevarēja pāriet uz mājas mapi \"%s\": %s"

#: openbox/openbox.c:152 msgid "Failed to open the display from the DISPLAY environment variable." -msgstr "Neizdevās atvēŗt displeju no DISPLAY vides mainīgā." +msgstr "Neizdevās atvērt displeju no DISPLAY vides mainīgā." #: openbox/openbox.c:183 msgid "Failed to initialize the obrender library."

@@ -256,80 +248,80 @@ #: openbox/openbox.c:196

msgid "Cannot set locale modifiers for the X server." msgstr "Nevar uzstādīt lokāles modificētājus X serverim." -#: openbox/openbox.c:263 +#: openbox/openbox.c:265 msgid "Unable to find a valid config file, using some simple defaults" msgstr "" "Nevarēja atrast atļautu konfigurācijas failu, tiek izmantoti noklusējumi" -#: openbox/openbox.c:297 +#: openbox/openbox.c:299 msgid "Unable to load a theme." msgstr "Nebija iespējams ielādēt tēmu." -#: openbox/openbox.c:377 +#: openbox/openbox.c:379 #, c-format msgid "" "One or more XML syntax errors were found while parsing the Openbox " "configuration files. See stdout for more information. The last error seen " "was in file \"%s\" line %d, with message: %s" msgstr "" -"Analizējot Openbox konfigurācijas datnes, tika atrastas viena vai vairākas " +"Analizējot Openbox konfigurācijas failus, tika atrastas viena vai vairākas " "XML sintakses kļūdas. Aplūkojiet standarta izvadi, lai noskaidrotu vairāk. " "Pēdējā kļūda bija failā \"%s\" - %d rinda, kļūdas ziņojums: %s" -#: openbox/openbox.c:379 +#: openbox/openbox.c:381 msgid "Openbox Syntax Error" msgstr "Openbox sintakses kļūda" -#: openbox/openbox.c:379 +#: openbox/openbox.c:381 msgid "Close" msgstr "Aizvērt" -#: openbox/openbox.c:448 +#: openbox/openbox.c:463 #, c-format msgid "Restart failed to execute new executable \"%s\": %s" -msgstr "" +msgstr "Pārstartētājam neizdevās palaist jauno izpildāmo \"%s\": %s" -#: openbox/openbox.c:518 openbox/openbox.c:520 +#: openbox/openbox.c:533 openbox/openbox.c:535 msgid "Copyright (c)" -msgstr "Copyright (c)" +msgstr "Autortiesības (c)" -#: openbox/openbox.c:529 +#: openbox/openbox.c:544 msgid "Syntax: openbox [options]\n" -msgstr "Sintakse: openbox [iespējas]\n" +msgstr "Sintakse: openbox [opcijas]\n" -#: openbox/openbox.c:530 +#: openbox/openbox.c:545 msgid "" "\n" "Options:\n" msgstr "" "\n" -"Iespējas:\n" +"Opcijas:\n" -#: openbox/openbox.c:531 +#: openbox/openbox.c:546 msgid " --help Display this help and exit\n" msgstr " --help Parāda šo palīdzības tekstu un iziet\n" -#: openbox/openbox.c:532 +#: openbox/openbox.c:547 msgid " --version Display the version and exit\n" msgstr " --version Parāda versiju un iziet\n" -#: openbox/openbox.c:533 +#: openbox/openbox.c:548 msgid " --replace Replace the currently running window manager\n" msgstr " --replace Aizvieto pašreiz palaisto logu pārvaldnieku\n" #. TRANSLATORS: if you translate "FILE" here, make sure to keep the "Specify..." #. aligned still, if you have to, make a new line with \n and 22 spaces. It's #. fine to leave it as FILE though. -#: openbox/openbox.c:537 +#: openbox/openbox.c:552 msgid " --config-file FILE Specify the path to the config file to use\n" msgstr "" " --config-file FAILS Norāda ceļu uz izmantojamo konfigurācijas failu\n" -#: openbox/openbox.c:538 +#: openbox/openbox.c:553 msgid " --sm-disable Disable connection to the session manager\n" -msgstr " --sm-disable Atspējo savienojumu ar sesiju pārvaldnieku\n" +msgstr " --sm-disable Pārtrauc savienojumu ar sesiju pārvaldnieku\n" -#: openbox/openbox.c:539 +#: openbox/openbox.c:554 msgid "" "\n" "Passing messages to a running Openbox instance:\n"

@@ -337,19 +329,19 @@ msgstr ""

"\n" "Nodod ziņojumus esošai Openbox instancei:\n" -#: openbox/openbox.c:540 +#: openbox/openbox.c:555 msgid " --reconfigure Reload Openbox's configuration\n" msgstr " --reconfigure Pārlādē Openbox konfigurācijas failus\n" -#: openbox/openbox.c:541 +#: openbox/openbox.c:556 msgid " --restart Restart Openbox\n" msgstr " --restart Pārstartē Openbox\n" -#: openbox/openbox.c:542 +#: openbox/openbox.c:557 msgid " --exit Exit Openbox\n" msgstr " --exit Iziet no Openbox\n" -#: openbox/openbox.c:543 +#: openbox/openbox.c:558 msgid "" "\n" "Debugging options:\n"

@@ -357,24 +349,24 @@ msgstr ""

"\n" "Atkļūdošanas iespējas:\n" -#: openbox/openbox.c:544 +#: openbox/openbox.c:559 msgid " --sync Run in synchronous mode\n" msgstr " --sync Palaist sinhronajā režīmā\n" -#: openbox/openbox.c:545 +#: openbox/openbox.c:560 msgid " --debug Display debugging output\n" msgstr " --debug Rādīt atkļūdošanas izvadi\n" -#: openbox/openbox.c:546 +#: openbox/openbox.c:561 msgid " --debug-focus Display debugging output for focus handling\n" msgstr " --debug-focus Rādīt atkļūdošanas izvadi fokusēšanas darbībām\n" -#: openbox/openbox.c:547 +#: openbox/openbox.c:562 msgid " --debug-xinerama Split the display into fake xinerama screens\n" msgstr "" " --debug-xinerama Sadalīt displeju vairākos viltus xinerama ekrānos\n" -#: openbox/openbox.c:548 +#: openbox/openbox.c:563 #, c-format msgid "" "\n"

@@ -383,26 +375,26 @@ msgstr ""

"\n" "Lūdzu, ziņojiet kļūdas %s\n" -#: openbox/openbox.c:617 +#: openbox/openbox.c:645 msgid "--config-file requires an argument\n" msgstr "--config-file vajadzīgs arguments\n" -#: openbox/openbox.c:660 +#: openbox/openbox.c:688 #, c-format msgid "Invalid command line argument \"%s\"\n" msgstr "Neatļauts komandrindas arguments \"%s\"\n" -#: openbox/screen.c:102 openbox/screen.c:190 +#: openbox/screen.c:103 openbox/screen.c:191 #, c-format msgid "A window manager is already running on screen %d" -msgstr "Logu pārvaldnieks jau eksistē uz %d. ekrāna" +msgstr "Logu pārvaldnieks jau palaists uz %d. ekrāna" -#: openbox/screen.c:124 +#: openbox/screen.c:125 #, c-format msgid "Could not acquire window manager selection on screen %d" msgstr "Nevarēja iegūt logu pārvaldnieka izvēli uz %d. ekrāna" -#: openbox/screen.c:145 +#: openbox/screen.c:146 #, c-format msgid "The WM on screen %d is not exiting" msgstr "Logu pārvaldnieks uz %d. ekrāna nebeidz darbību"

@@ -411,7 +403,7 @@ #. TRANSLATORS: If you need to specify a different order of the

#. arguments, you can use %1$d for the first one and %2$d for the #. second one. For example, #. "The current session has %2$d desktops, but Openbox is configured for %1$d ..." -#: openbox/screen.c:412 +#: openbox/screen.c:416 #, c-format msgid "" "Openbox is configured for %d desktop, but the current session has %d. "

@@ -429,27 +421,27 @@ msgstr[2] ""

"Openbox ir konfigurēts %d darbvirsmām, bet pašreizējai sesijai tādu ir %d. " "Šī Openbox konfigurācijas opcija tiks ignorēta." -#: openbox/screen.c:1180 +#: openbox/screen.c:1199 #, c-format msgid "desktop %i" msgstr "darbvirsma %i" -#: openbox/session.c:104 +#: openbox/session.c:105 #, c-format msgid "Unable to make directory \"%s\": %s" -msgstr "Nav iespējams izveidot mapi \"%s\": %s" +msgstr "Nevarēja izveidot mapi \"%s\": %s" -#: openbox/session.c:466 +#: openbox/session.c:472 #, c-format msgid "Unable to save the session to \"%s\": %s" -msgstr "Nav iespējams saglabāt sesiju \"%s\": %s" +msgstr "Neizdevās saglabāt sesiju \"%s\": %s" -#: openbox/session.c:605 +#: openbox/session.c:611 #, c-format msgid "Error while saving the session to \"%s\": %s" msgstr "Kļūda saglabājot sesiju \"%s\": %s" -#: openbox/session.c:842 +#: openbox/session.c:848 msgid "Not connected to a session manager" msgstr "Nav savienots ar sesiju pārvaldnieku"

@@ -486,3 +478,10 @@

#: openbox/prompt.c:200 msgid "OK" msgstr "Labi" + +#~ msgid "" +#~ "The SessionLogout action is not available since Openbox was built without " +#~ "session management support" +#~ msgstr "" +#~ "Darbība 'SessionLogout' nav pieejama, jo Openbox ir kompilēts bez sesiju " +#~ "pārvaldības atbalsta"
M tools/obxprop/obxprop.ctools/obxprop/obxprop.c

@@ -12,7 +12,7 @@ fprintf(stderr, "%s\n", s);

else fprintf (stderr, - "Usage: obxprop [OPTIONS]\n\n" + "Usage: obxprop [OPTIONS] [--] [PROPERTIES ...]\n\n" "Options:\n" " --help Display this help and exit\n" " --display DISPLAY Connect to this X display\n"

@@ -227,7 +227,7 @@ }

return FALSE; } -void show_properties(Display *d, Window w) +void show_properties(Display *d, Window w, int argc, char **argv) { Atom* props; int i, n;

@@ -241,7 +241,19 @@

name = XGetAtomName(d, props[i]); if (read_prop(d, w, props[i], &type, &val)) { - g_print("%s(%s) = %s\n", name, type, val); + int found = 1; + if (argc) { + int i; + + found = 0; + for (i = 0; i < argc; i++) + if (!strcmp(name, argv[i])) { + found = 1; + break; + } + } + if (found) + g_print("%s(%s) = %s\n", name, type, val); g_free(val); }

@@ -261,13 +273,13 @@ gboolean root = FALSE;

for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--help")) { - return fail(0); + return fail(NULL); } else if (!strcmp(argv[i], "--root")) root = TRUE; else if (!strcmp(argv[i], "--id")) { if (++i == argc) - return fail(0); + return fail(NULL); if (argv[i][0] == '0' && argv[i][1] == 'x') { /* hex */ userid = parse_hex(argv[i]+2);

@@ -276,13 +288,22 @@ else {

/* decimal */ userid = atoi(argv[i]); } - break; + if (!userid) + return fail("Unable to parse argument to --id."); } else if (!strcmp(argv[i], "--display")) { if (++i == argc) - return fail(0); + return fail(NULL); dname = argv[i]; } + else if (*argv[i] != '-') + break; + else if (!strcmp(argv[i], "--")) { + i++; + break; + } + else + return fail(NULL); } d = XOpenDisplay(dname);

@@ -295,12 +316,13 @@ if (root)

userid = RootWindow(d, DefaultScreen(d)); if (userid == None) { - i = XGrabPointer(d, RootWindow(d, DefaultScreen(d)), + int j; + j = XGrabPointer(d, RootWindow(d, DefaultScreen(d)), False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, XCreateFontCursor(d, XC_crosshair), CurrentTime); - if (i != GrabSuccess) + if (j != GrabSuccess) return fail("Unable to grab the pointer device"); while (1) { XEvent ev;

@@ -312,14 +334,15 @@ userid = ev.xbutton.subwindow;

break; } } + id = find_client(d, userid); } - - id = find_client(d, userid); + else + id = userid; /* they picked this one */ if (id == None) return fail("Unable to find window with the requested ID"); - show_properties(d, id); + show_properties(d, id, argc - i, &argv[i]); XCloseDisplay(d);
A version.h.in

@@ -0,0 +1,6 @@

+#ifndef ob__version_h +#define ob__version_h + +#define OPENBOX_VERSION "@OPENBOX_VERSION@" + +#endif