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
This commit is contained in:
Dana Jansens 2010-01-11 16:20:53 -05:00
commit 567fd15eeb
26 changed files with 1940 additions and 370 deletions

View file

@ -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 @@ AC_CONFIG_FILES([
obt/obt-3.5.pc
obrender/version.h
obt/version.h
version.h
])
AC_CONFIG_COMMANDS([doc],
[test -d doc || mkdir doc])

View file

@ -696,16 +696,13 @@
# 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 @@
# 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>

View file

@ -190,9 +190,11 @@ void obt_prop_startup(void)
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)

View file

@ -211,9 +211,11 @@ typedef enum {
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;

View file

@ -31,6 +31,7 @@
#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 RrImage *client_default_icon = NULL;
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 @@ void client_manage(Window window, ObPrompt *prompt)
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 */
@ -551,6 +553,8 @@ void client_unmanage(ObClient *self)
mouse_grab_for_client(self, FALSE);
self->managed = FALSE;
/* remove the window from our save set, unless we are managing an internal
ObPrompt window */
if (!self->prompt)
@ -1078,7 +1082,9 @@ static void client_get_all(ObClient *self, gboolean real)
/* 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 @@ void client_update_wmhints(ObClient *self)
XFree(hints);
}
focus_cycle_addremove(self, TRUE);
}
void client_update_title(ObClient *self)
@ -2292,13 +2300,36 @@ static void client_get_session_ids(ObClient *self)
}
}
/*! 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 @@ static void client_iconify_recursive(ObClient *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 @@ static void client_iconify_recursive(ObClient *self,
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 @@ static void client_set_desktop_recursive(ObClient *self,
/* 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 @@ void client_set_desktop(ObClient *self, guint target,
{
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 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2)
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)

View file

@ -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 */

View file

@ -1816,7 +1816,12 @@ static gboolean event_handle_menu_input(XEvent *ev)
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;
}
@ -1829,6 +1834,16 @@ static gboolean event_handle_menu_input(XEvent *ev)
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;
}
}
/* Use KeyRelease events for running things so that the key release

View file

@ -90,6 +90,9 @@ void focus_set_client(ObClient *client)
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 @@ void focus_order_add_new(ObClient *c)
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 @@ void focus_order_add_new(ObClient *c)
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 @@ void focus_order_to_top(ObClient *c)
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 @@ void focus_order_to_bottom(ObClient *c)
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,8 +305,15 @@ gboolean focus_valid_target(ObClient *ft,
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.
do this check first because it will usually filter out the most

View file

@ -58,6 +58,10 @@ void focus_order_remove(struct _ObClient *c);
/*! 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);

View file

@ -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 @@ void focus_cycle_shutdown(gboolean reconfig)
if (reconfig) return;
}
void focus_cycle_stop(ObClient *ifclient)
void focus_cycle_addremove(ObClient *c, gboolean redraw)
{
/* 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))
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()
{
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 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops,
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 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops,
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 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
/* 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 @@ ObClient* focus_directional_cycle(ObDirection dir, gboolean dock_windows,
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 @@ done_cycle:
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);
}

View file

@ -48,6 +48,10 @@ struct _ObClient* focus_directional_cycle(ObDirection dir,
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

View file

@ -18,6 +18,7 @@
*/
#include "focus_cycle_popup.h"
#include "focus_cycle.h"
#include "popup.h"
#include "client.h"
#include "screen.h"
@ -99,12 +100,9 @@ static ObFocusCyclePopup popup;
static ObIconPopup *single_popup;
static gchar *popup_get_name (ObClient *c);
static void popup_setup (ObFocusCyclePopup *p,
static gboolean popup_setup (ObFocusCyclePopup *p,
gboolean create_targets,
gboolean iconic_windows,
gboolean all_desktops,
gboolean dock_windows,
gboolean desktop_windows);
gboolean refresh_targets);
static void popup_render (ObFocusCyclePopup *p,
const ObClient *c);
@ -242,12 +240,35 @@ void focus_cycle_popup_shutdown(gboolean reconfig)
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,13 +282,27 @@ static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
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))
{
if (focus_cycle_valid(ft)) {
GList *rit;
/* 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 */
@ -277,7 +312,8 @@ static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
if (!create_targets) {
g_free(text);
} else {
ObFocusCyclePopupTarget *t = g_new(ObFocusCyclePopupTarget, 1);
ObFocusCyclePopupTarget *t =
g_new(ObFocusCyclePopupTarget, 1);
t->client = ft;
t->text = text;
@ -288,12 +324,40 @@ static void popup_setup(ObFocusCyclePopup *p, gboolean create_targets,
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;
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 @@ void focus_cycle_popup_show(ObClient *c, gboolean iconic_windows,
/* 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 @@ void focus_cycle_popup_hide(void)
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 @@ void focus_cycle_popup_single_show(struct _ObClient *c,
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 @@ void focus_cycle_popup_single_hide(void)
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;
}

View file

@ -46,7 +46,13 @@ void focus_cycle_popup_single_show(struct _ObClient *c,
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

View file

@ -1300,7 +1300,7 @@ void menu_frame_select_previous(ObMenuFrame *self)
}
}
}
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 @@ void menu_frame_select_next(ObMenuFrame *self)
}
}
}
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);
}

View file

@ -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);

View file

@ -53,6 +53,8 @@ typedef enum
OB_KEY_DOWN,
OB_KEY_TAB,
OB_KEY_SPACE,
OB_KEY_HOME,
OB_KEY_END,
OB_NUM_KEYS
} ObKey;

View file

@ -224,6 +224,8 @@ gint main(gint argc, gchar **argv)
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 @@ gint main(gint argc, gchar **argv)
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);
}

479
openbox/prop.c Normal file
View file

@ -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);
}

267
openbox/prop.h Normal file
View file

@ -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

View file

@ -32,6 +32,7 @@
#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,15 +295,20 @@ gboolean screen_annex(void)
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();
return TRUE;
@ -705,9 +711,6 @@ void screen_set_desktop(guint num, gboolean dofocus)
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.
@ -723,6 +726,8 @@ void screen_set_desktop(guint num, gboolean dofocus)
}
}
focus_cycle_addremove(NULL, TRUE);
event_end_ignore_all_enters(ignore_start);
if (event_curtime != CurrentTime)

532
parser/parse.c Normal file
View file

@ -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;
}

266
po/hu.po
View file

@ -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 @@ msgstr ""
#: 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 @@ msgstr "Végrehajtás"
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
msgid "Are you sure you want to exit Openbox?"
msgstr "Biztos, hogy ki akarsz lépni az Openboxból?"
#: openbox/actions/exit.c:57
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
#: openbox/actions/exit.c:67
msgid "Are you sure you want to log out?"
msgstr "Biztos, hogy ki akarsz jelentkezni?"
#: openbox/client.c:2012
msgid "Unnamed Window"
msgstr "Névtelen Ablak"
#: openbox/actions/exit.c:68
msgid "Log Out"
msgstr "Kijelentkezés"
#: openbox/client.c:2026 openbox/client.c:2058
#: openbox/actions/exit.c:71
msgid "Are you sure you want to exit Openbox?"
msgstr "Biztos ki akar lépni az Openboxból?"
#: openbox/actions/exit.c:72
msgid "Exit Openbox"
msgstr "Kilépés az Openboxból"
#: openbox/client.c:2016
msgid "Unnamed Window"
msgstr "Névtelen ablak"
#: 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 @@ msgid ""
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,20 +176,20 @@ 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
@ -209,94 +199,98 @@ 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."
@ -426,63 +420,61 @@ 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."
#: 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"

View file

@ -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 ""

181
po/lv.po
View file

@ -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 @@ msgstr "Izpildīt"
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
msgid "Are you sure you want to exit Openbox?"
msgstr "Vai tiešām vēlaties iziet no Openbox?"
#: openbox/actions/exit.c:57
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
#: openbox/actions/exit.c:67
msgid "Are you sure you want to log out?"
msgstr "Vai tiešām vēlaties atteikties?"
#: openbox/client.c:2012
#: 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:72
msgid "Exit Openbox"
msgstr "Iziet no Openbox"
#: 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 @@ msgstr "Bez/Ar _dekorācijām"
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 @@ msgstr "Neatļauta izvade no skriptētās izvēlnes \"%s\""
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 @@ msgstr "X serveris neatbalsta lokāli."
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 @@ msgstr "Logu pārvaldnieks uz %d. ekrāna nebeidz darbību"
#. 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 @@ msgstr "X kļūda: %s"
#: 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"

View file

@ -12,7 +12,7 @@ gint fail(const gchar *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 @@ gboolean read_prop(Display *d, Window w, Atom prop, const gchar **type, gchar **
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,6 +241,18 @@ void show_properties(Display *d, Window w)
name = XGetAtomName(d, props[i]);
if (read_prop(d, w, props[i], &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 @@ int main(int argc, char **argv)
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 @@ int main(int argc, char **argv)
/* 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 @@ int main(int argc, char **argv)
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 @@ int main(int argc, char **argv)
break;
}
}
}
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);

6
version.h.in Normal file
View file

@ -0,0 +1,6 @@
#ifndef ob__version_h
#define ob__version_h
#define OPENBOX_VERSION "@OPENBOX_VERSION@"
#endif