From: Mikael Magnusson Date: Sun, 5 Jul 2009 20:27:25 +0000 (+0200) Subject: Merge branch 'backport' into work X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=308478e4a5f4dc76d69395dda8a9bc42cb69eec4;p=chaz%2Fopenbox Merge branch 'backport' into work Conflicts: openbox/actions/desktop.c openbox/client.c openbox/event.c openbox/extensions.c openbox/popup.c openbox/screen.c parser/parse.c --- 308478e4a5f4dc76d69395dda8a9bc42cb69eec4 diff --cc obt/paths.c index 61004998,00000000..68615433 mode 100644,000000..100644 --- a/obt/paths.c +++ b/obt/paths.c @@@ -1,247 -1,0 +1,249 @@@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + obt/paths.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 "obt/paths.h" +#include "obt/util.h" + +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif + +struct _ObtPaths +{ + gint ref; + gchar *config_home; + gchar *data_home; + gchar *cache_home; + GSList *config_dirs; + GSList *data_dirs; +}; + +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; +} + +ObtPaths* obt_paths_new(void) +{ + ObtPaths *p; + const gchar *path; + + p = g_new0(ObtPaths, 1); + p->ref = 1; + + path = g_getenv("XDG_CONFIG_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + p->config_home = g_build_filename(path, NULL); + else + p->config_home = g_build_filename(g_get_home_dir(), ".config", NULL); + + path = g_getenv("XDG_DATA_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + p->data_home = g_build_filename(path, NULL); + else + p->data_home = g_build_filename(g_get_home_dir(), ".local", + "share", NULL); + + path = g_getenv("XDG_CACHE_HOME"); + if (path && path[0] != '\0') /* not unset or empty */ + p->cache_home = g_build_filename(path, NULL); + else + p->cache_home = g_build_filename(g_get_home_dir(), ".cache", NULL); + + path = g_getenv("XDG_CONFIG_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + p->config_dirs = split_paths(path); + else { + p->config_dirs = slist_path_add(p->config_dirs, + g_strdup(CONFIGDIR), + (GSListFunc) g_slist_append); + p->config_dirs = slist_path_add(p->config_dirs, + g_build_filename + (G_DIR_SEPARATOR_S, + "etc", "xdg", NULL), + (GSListFunc) g_slist_append); + } + p->config_dirs = slist_path_add(p->config_dirs, + g_strdup(p->config_home), + (GSListFunc) g_slist_prepend); + + path = g_getenv("XDG_DATA_DIRS"); + if (path && path[0] != '\0') /* not unset or empty */ + p->data_dirs = split_paths(path); + else { + p->data_dirs = slist_path_add(p->data_dirs, + g_strdup(DATADIR), + (GSListFunc) g_slist_append); + p->data_dirs = slist_path_add(p->data_dirs, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "local", "share", NULL), + (GSListFunc) g_slist_append); + p->data_dirs = slist_path_add(p->data_dirs, + g_build_filename + (G_DIR_SEPARATOR_S, + "usr", "share", NULL), + (GSListFunc) g_slist_append); + } + p->data_dirs = slist_path_add(p->data_dirs, + g_strdup(p->data_home), + (GSListFunc) g_slist_prepend); + return p; +} + +void obt_paths_ref(ObtPaths *p) +{ + ++p->ref; +} + +void obt_paths_unref(ObtPaths *p) +{ + if (p && --p->ref == 0) { + GSList *it; + + for (it = p->config_dirs; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(p->config_dirs); + for (it = p->data_dirs; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(p->data_dirs); + g_free(p->config_home); + g_free(p->data_home); + g_free(p->cache_home); + + obt_free0(p, ObtPaths, 1); + } +} + +gchar *obt_paths_expand_tilde(const gchar *f) +{ - gchar **spl; + gchar *ret; ++ GRegex *regex; + + if (!f) + return NULL; - spl = g_strsplit(f, "~", 0); - ret = g_strjoinv(g_get_home_dir(), spl); - g_strfreev(spl); ++ ++ 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 obt_paths_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 obt_paths_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 = obt_paths_mkdir(c, mode))) + goto parse_mkdir_path_end; + *e = '/'; + } + ret = obt_paths_mkdir(c, mode); + + parse_mkdir_path_end: + g_free(c); + } + + return ret; +} + +const gchar* obt_paths_config_home(ObtPaths *p) +{ + return p->config_home; +} + +const gchar* obt_paths_data_home(ObtPaths *p) +{ + return p->data_home; +} + +const gchar* obt_paths_cache_home(ObtPaths *p) +{ + return p->cache_home; +} + +GSList* obt_paths_config_dirs(ObtPaths *p) +{ + return p->config_dirs; +} + +GSList* obt_paths_data_dirs(ObtPaths *p) +{ + return p->data_dirs; +} diff --cc openbox/actions/desktop.c index e352aa2e,07416151..edd22aa2 --- a/openbox/actions/desktop.c +++ b/openbox/actions/desktop.c @@@ -46,12 -49,12 +46,12 @@@ static gpointer setup_go_func(xmlNodePt o = g_new0(Options, 1); /* don't go anywhere if theres no options given */ o->type = ABSOLUTE; - o->abs.desktop = screen_desktop; + o->u.abs.desktop = screen_desktop; /* wrap by default - it's handy! */ - o->rel.wrap = TRUE; + o->u.rel.wrap = TRUE; - if ((n = parse_find_node("to", node))) { - gchar *s = parse_string(doc, n); + if ((n = obt_parse_find_node(node, "to"))) { + gchar *s = obt_parse_node_string(n); if (!g_ascii_strcasecmp(s, "last")) o->type = LAST; else if (!g_ascii_strcasecmp(s, "next")) { @@@ -91,8 -94,8 +91,8 @@@ g_free(s); } - if ((n = parse_find_node("wrap", node))) - o->u.rel.wrap = parse_bool(doc, n); + if ((n = obt_parse_find_node(node, "wrap"))) - o->rel.wrap = obt_parse_node_bool(n); ++ o->u.rel.wrap = obt_parse_node_bool(n); return o; } diff --cc openbox/actions/moveresizeto.c index 357c7315,acad73b5..3ee3498a --- a/openbox/actions/moveresizeto.c +++ b/openbox/actions/moveresizeto.c @@@ -84,8 -91,12 +86,12 @@@ static gpointer setup_func(xmlNodePtr n if (g_ascii_strcasecmp(s, "current") != 0) { if (!g_ascii_strcasecmp(s, "all")) o->monitor = ALL_MONITORS; + else if(!g_ascii_strcasecmp(s, "next")) + o->monitor = NEXT_MONITOR; + else if(!g_ascii_strcasecmp(s, "prev")) + o->monitor = PREV_MONITOR; else - o->monitor = parse_int(doc, n) - 1; + o->monitor = obt_parse_node_int(n) - 1; } g_free(s); } diff --cc openbox/client.c index d98ce642,c1af196b..38dc7c1a --- a/openbox/client.c +++ b/openbox/client.c @@@ -231,9 -311,14 +231,14 @@@ void client_manage(Window window, ObPro /* get all the stuff off the window */ client_get_all(self, TRUE); - ob_debug("Window type: %d\n", self->type); - ob_debug("Window group: 0x%x\n", self->group?self->group->leader:0); - ob_debug("Window name: %s class: %s role: %s\n", self->name, self->class, self->role); + ob_debug("Window type: %d", self->type); + ob_debug("Window group: 0x%x", self->group?self->group->leader:0); - ob_debug("Window name: %s class: %s", self->name, self->class); ++ ob_debug("Window name: %s class: %s role: %s", self->name, self->class, self->role); + + /* per-app settings override stuff from client_get_all, and return the + settings for other uses too. the returned settings is a shallow copy, + that needs to be freed with g_free(). */ + settings = client_get_settings_state(self); /* now we have all of the window's information so we can set this up. do this before creating the frame, so it can tell that we are still @@@ -3538,16 -3591,32 +3539,32 @@@ ObClient *client_search_modal_child(ObC return NULL; } + static gboolean client_validate_unmap(ObClient *self, int n) + { + XEvent e; + gboolean ret = TRUE; + - if (XCheckTypedWindowEvent(ob_display, self->window, UnmapNotify, &e)) { ++ if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) { + if (n < self->ignore_unmaps) // ignore this one, but look for more + ret = client_validate_unmap(self, n+1); + else + ret = FALSE; // the window is going to become unmanaged + + /* put them back on the event stack so they end up in the same order */ - XPutBackEvent(ob_display, &e); ++ XPutBackEvent(obt_display, &e); + } + + return ret; + } + gboolean client_validate(ObClient *self) { XEvent e; - XSync(ob_display, FALSE); /* get all events on the server */ + XSync(obt_display, FALSE); /* get all events on the server */ - if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e) || - XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) - { - if (XCheckTypedWindowEvent(ob_display, self->window, DestroyNotify, &e)) { - XPutBackEvent(ob_display, &e); ++ if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) { + XPutBackEvent(obt_display, &e); return FALSE; } diff --cc openbox/event.c index f69267db,ddd2e326..e2fd411f --- a/openbox/event.c +++ b/openbox/event.c @@@ -656,9 -651,10 +656,9 @@@ static void event_process(const XEvent else if (e->type == MappingNotify) { /* keyboard layout changes for modifier mapping changes. reload the modifier map, and rebind all the key bindings as appropriate */ - ob_debug("Kepboard map changed. Reloading keyboard bindings."); - ob_debug("Keyboard map changed. Reloading keyboard bindings.\n"); ++ ob_debug("Keyboard map changed. Reloading keyboard bindings."); ob_set_state(OB_STATE_RECONFIGURING); - modkeys_shutdown(TRUE); - modkeys_startup(TRUE); + obt_keyboard_reload(); keyboard_rebind(); ob_set_state(OB_STATE_RUNNING); } diff --cc openbox/popup.c index fd31846e,2a0d5960..bddf137d --- a/openbox/popup.c +++ b/openbox/popup.c @@@ -319,7 -320,7 +319,7 @@@ void popup_hide(ObPopup *self event_end_ignore_all_enters(ignore_start); } else if (self->delay_mapped) { - obt_main_loop_timeout_remove(ob_main_loop, popup_show_timeout); - ob_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE); ++ obt_main_loop_timeout_remove_data(ob_main_loop, popup_show_timeout, self, FALSE); self->delay_mapped = FALSE; } } diff --cc openbox/screen.c index 74d073c4,1bcda980..09d5003c --- a/openbox/screen.c +++ b/openbox/screen.c @@@ -922,28 -950,36 +939,36 @@@ void screen_show_desktop_popup(guint d /* 0 means don't show the popup */ if (!config_desktop_popup_time) return; - a = screen_physical_area_active(); - pager_popup_position(desktop_popup, CenterGravity, - a->x + a->width / 2, a->y + a->height / 2); - pager_popup_icon_size_multiplier(desktop_popup, - (screen_desktop_layout.columns / - screen_desktop_layout.rows) / 2, - (screen_desktop_layout.rows/ - screen_desktop_layout.columns) / 2); - pager_popup_max_width(desktop_popup, - MAX(a->width/3, POPUP_WIDTH)); - pager_popup_show(desktop_popup, screen_desktop_names[d], d); - - obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func); - obt_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000, - hide_desktop_popup_func, NULL, NULL, NULL); - g_free(a); + for (i = 0; i < screen_num_monitors; i++) { + a = screen_physical_area_monitor(i); + pager_popup_position(desktop_popup[i], CenterGravity, + a->x + a->width / 2, a->y + a->height / 2); + pager_popup_icon_size_multiplier(desktop_popup[i], + (screen_desktop_layout.columns / + screen_desktop_layout.rows) / 2, + (screen_desktop_layout.rows/ + screen_desktop_layout.columns) / 2); + pager_popup_max_width(desktop_popup[i], + MAX(a->width/3, POPUP_WIDTH)); + pager_popup_show(desktop_popup[i], screen_desktop_names[d], d); + - ob_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func); - ob_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000, - hide_desktop_popup_func, desktop_popup[i], - g_direct_equal, NULL); ++ obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func); ++ obt_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000, ++ hide_desktop_popup_func, desktop_popup[i], ++ g_direct_equal, NULL); + g_free(a); + } } void screen_hide_desktop_popup(void) { - obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func); - pager_popup_hide(desktop_popup); + guint i; + + for (i = 0; i < screen_num_monitors; i++) { - ob_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func, - desktop_popup[i], FALSE); ++ obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func, ++ desktop_popup[i], FALSE); + pager_popup_hide(desktop_popup[i]); + } } guint screen_find_desktop(guint from, ObDirection dir, @@@ -1299,54 -1338,6 +1326,55 @@@ typedef struct } \ } +static void get_xinerama_screens(Rect **xin_areas, guint *nxin) +{ + guint i; - gint l, r, t, b; ++ gint n, l, r, t, b; ++#ifdef XINERAMA ++ XineramaScreenInfo *info; ++#endif + + if (ob_debug_xinerama) { + gint w = WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen)); + gint h = HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen)); + *nxin = 2; + *xin_areas = g_new(Rect, *nxin + 1); + RECT_SET((*xin_areas)[0], 0, 0, w/2, h); + RECT_SET((*xin_areas)[1], w/2, 0, w-(w/2), h); + } +#ifdef XINERAMA - else if (obt_display_extension_xinerama) { - guint i; - gint n; - XineramaScreenInfo *info = XineramaQueryScreens(obt_display, &n); ++ else if (obt_display_extension_xinerama && ++ (info = XineramaQueryScreens(obt_display, &n))) { + *nxin = n; + *xin_areas = g_new(Rect, *nxin + 1); + for (i = 0; i < *nxin; ++i) + RECT_SET((*xin_areas)[i], info[i].x_org, info[i].y_org, + info[i].width, info[i].height); + XFree(info); + } +#endif + else { + *nxin = 1; + *xin_areas = g_new(Rect, *nxin + 1); + RECT_SET((*xin_areas)[0], 0, 0, + WidthOfScreen(ScreenOfDisplay(obt_display, ob_screen)), + HeightOfScreen(ScreenOfDisplay(obt_display, ob_screen))); + } + + /* returns one extra with the total area in it */ + l = (*xin_areas)[0].x; + t = (*xin_areas)[0].y; + r = (*xin_areas)[0].x + (*xin_areas)[0].width - 1; + b = (*xin_areas)[0].y + (*xin_areas)[0].height - 1; + for (i = 1; i < *nxin; ++i) { + l = MIN(l, (*xin_areas)[i].x); + t = MIN(l, (*xin_areas)[i].y); + r = MAX(r, (*xin_areas)[i].x + (*xin_areas)[i].width - 1); + b = MAX(b, (*xin_areas)[i].y + (*xin_areas)[i].height - 1); + } + RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1); +} + void screen_update_areas(void) { guint i, j; @@@ -1355,8 -1346,22 +1383,22 @@@ GSList *sit; g_free(monitor_area); - extensions_xinerama_screens(&monitor_area, &screen_num_monitors); + get_xinerama_screens(&monitor_area, &screen_num_monitors); + if (!desktop_popup) { + desktop_popup = g_new(ObPagerPopup*, screen_num_monitors); + for (i = 0; i < screen_num_monitors; i++) { + desktop_popup[i] = pager_popup_new(); + pager_popup_height(desktop_popup[i], POPUP_HEIGHT); + + if (screen_desktop_names) + /* update the pager popup's width */ + pager_popup_text_width_to_strings(desktop_popup[i], + screen_desktop_names, + screen_num_desktops); + } + } + /* set up the user-specified margins */ config_margins.top_start = RECT_LEFT(monitor_area[screen_num_monitors]); config_margins.top_end = RECT_RIGHT(monitor_area[screen_num_monitors]);