all repos — openbox @ f55ae9e56945892825928cfb021b5e739d0d5224

openbox fork - make it a bit more like ryudo

Merge branch 'backport'
Dana Jansens danakj@orodu.net
commit

f55ae9e56945892825928cfb021b5e739d0d5224

parent

98b9ed97ebbcf22185359c8f6f1d539a105cd258

M CHANGELOGCHANGELOG

@@ -1,3 +1,44 @@

+3.4.4: + * Updated Traditional Chinese translation + * Updated Norwegian translation + * Fix for MoveToEdge skipping edges sometimes + * Let you specify the vertical and horizontal padding independently in themes + * Fix so that if you select an omnipresent window on another desktop in the + client list menus, it will go to that desktop + * Make the GrowToEdge action shrink once there is no more room to grow, + similar to in 3.4.2, but shrinking to edges as well + * Move the Send To and Layers submenus to the top of the client menu + * Fix race causing omnipresent windows to lose focus when switching desktops + very quickly + * Don't focus new windows on other desktops if they aren't related to the + currently focused window + * Add corner resizing areas in the inner client border (Fixes themes such + as Onyx) + * New focus stealing prevention that is smart and not intrusive and not + annoying + * Revert a small change in 3.4.3 that caused windows to be placed funny in + Smart placement when there was a dock or something on the side of the + screen + * Show a notification when switching desktops + * Fix for delayed focus-follows-mouse interrupting move/resize or menus + * Make screen edge warp keep warping without having the move the mouse 1 + pixel + * Fix for resizing terminals in the top/left sides getting a little confused + * Fix to keep oldschool (Non-EWMH) fullscreen windows from being moved and + resized inside of the struts (Fixes Acroread) + * Accept the <command> option for the Restart command, similar to the Execute + action + * Don't make clicking on dock apps sometimes act like clicking on the root + window (Don't propogate button events up) + * Fix a bug introduced in 3.4.3 which caused the Windows key as a modifier + for bindings to not work properly + * Let windows skip across monitors in a Xinerama setup when using MoveToEdge + or Shift-arrow in an interactive move + * Make move and resize take the dock into account for resistance + * Raise new windows when it makes sense, when they aren't being focused + * Change default config to use click events for mouse wheel bindings instead + of presses + 3.4.3: * Add Ukrainian translation * Updated translations:
M Makefile.amMakefile.am

@@ -249,8 +249,6 @@ openbox/popup.c \

openbox/popup.h \ openbox/prop.c \ openbox/prop.h \ - openbox/propwin.c \ - openbox/propwin.h \ openbox/resist.c \ openbox/resist.h \ openbox/screen.c \
M data/rc.xmldata/rc.xml

@@ -116,6 +116,9 @@ <name>desktop 1</name>

<name>desktop 2</name> --> </names> + <popupTime>875</popupTime> + <!-- The number of milliseconds to show the popup for when switching + desktops. Set this to 0 to disable the popup. --> </desktops> <resize>

@@ -261,9 +264,9 @@ <!-- number of pixels the mouse must move before a drag begins -->

<doubleClickTime>200</doubleClickTime> <!-- in milliseconds (1000 = 1 second) --> <screenEdgeWarpTime>400</screenEdgeWarpTime> - <!-- time before changing desktops when the pointer touches the edge of the - screen while moving a window, in milliseconds (1000 = 1 second), - 0 disables warping --> + <!-- Time before changing desktops when the pointer touches the edge of the + screen while moving a window, in milliseconds (1000 = 1 second). + Set this to 0 to disable warping --> <context name="Frame"> <mousebind button="A-Left" action="Press">
M data/rc.xsddata/rc.xsd

@@ -89,6 +89,7 @@ <xsd:complexType>

<xsd:element maxOccurs="unbounded" name="name" type="xsd:string"/> </xsd:complexType> </xsd:element> + <xsd:element minOccurs="0" name="popupTime" type="xsd:integer"/> </xsd:complexType> <xsd:complexType name="resize"> <xsd:element minOccurs="0" name="drawContents" type="ob:bool"/>
M openbox/actions/desktop.copenbox/actions/desktop.c

@@ -132,10 +132,8 @@ case ABSOLUTE:

d = o->abs.desktop; break; case RELATIVE: - d = screen_cycle_desktop(o->rel.dir, - o->rel.wrap, - o->rel.linear, - FALSE, TRUE, FALSE); + d = screen_find_desktop(screen_desktop, + o->rel.dir, o->rel.wrap, o->rel.linear); break; }
M openbox/actions/growtoedge.copenbox/actions/growtoedge.c

@@ -57,39 +57,89 @@

g_free(o); } +static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h) +{ + gint realw, realh, lw, lh; + + realw = w; + realh = h; + client_try_configure(data->client, &x, &y, &realw, &realh, + &lw, &lh, TRUE); + /* if it's going to be resized smaller than it intended, don't + move the window over */ + if (x != data->client->area.x) x += w - realw; + if (y != data->client->area.y) y += h - realh; + + if (x != data->client->area.x || y != data->client->area.y || + realw != data->client->area.width || + realh != data->client->area.height) + { + actions_client_move(data, TRUE); + client_move_resize(data->client, x, y, realw, realh); + actions_client_move(data, FALSE); + return TRUE; + } + return FALSE; +} + /* Always return FALSE because its not interactive */ static gboolean run_func(ObActionsData *data, gpointer options) { Options *o = options; - - if (data->client) { - gint x, y, w, h, realw, realh, lw, lh; + gint x, y, w, h; + ObDirection opp; + gint half; + if (!data->client || /* don't allow vertical resize if shaded */ - if (o->dir != OB_DIRECTION_NORTH || o->dir != OB_DIRECTION_SOUTH || - !data->client->shaded) - { - client_find_resize_directional(data->client, o->dir, TRUE, - &x, &y, &w, &h); - realw = w; - realh = h; - client_try_configure(data->client, &x, &y, &realw, &realh, - &lw, &lh, TRUE); - /* if it's going to be resized smaller than it intended, don't - move the window over */ - if (x != data->client->area.x) x += w - realw; - if (y != data->client->area.y) y += h - realh; + ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) && + data->client->shaded)) + { + return FALSE; + } - if (x != data->client->area.x || y != data->client->area.y || - w != data->client->area.width || - h != data->client->area.height) - { - actions_client_move(data, TRUE); - client_move_resize(data->client, x, y, realw, realh); - actions_client_move(data, FALSE); - } + /* try grow */ + client_find_resize_directional(data->client, o->dir, TRUE, + &x, &y, &w, &h); + if (do_grow(data, x, y, w, h)) + return FALSE; + + /* we couldn't grow, so try shrink! */ + opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH : + (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH : + (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST : + OB_DIRECTION_EAST))); + client_find_resize_directional(data->client, opp, FALSE, + &x, &y, &w, &h); + switch (opp) { + case OB_DIRECTION_NORTH: + half = data->client->area.y + data->client->area.height / 2; + if (y > half) { + h += y - half; + y = half; + } + break; + case OB_DIRECTION_SOUTH: + half = data->client->area.height / 2; + if (h < half) + h = half; + break; + case OB_DIRECTION_WEST: + half = data->client->area.x + data->client->area.width / 2; + if (x > half) { + w += x - half; + x = half; } + break; + case OB_DIRECTION_EAST: + half = data->client->area.width / 2; + if (w < half) + w = half; + break; + default: g_assert_not_reached(); } + if (do_grow(data, x, y, w, h)) + return FALSE; return FALSE; }
M openbox/actions/restart.copenbox/actions/restart.c

@@ -25,7 +25,9 @@ Options *o;

o = g_new0(Options, 1); - if ((n = parse_find_node("execute", node))) { + if ((n = parse_find_node("command", node)) || + (n = parse_find_node("execute", node))) + { gchar *s = parse_string(doc, n); o->cmd = parse_expand_tilde(s); g_free(s);
M openbox/actions/unfocus.copenbox/actions/unfocus.c

@@ -12,6 +12,6 @@ /* Always return FALSE because its not interactive */

static gboolean run_func(ObActionsData *data, gpointer options) { if (data->client && data->client == focus_client) - focus_fallback(FALSE, FALSE, TRUE); + focus_fallback(FALSE, FALSE, TRUE, FALSE); return FALSE; }
M openbox/client.copenbox/client.c

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

#include "event.h" #include "grab.h" #include "focus.h" -#include "propwin.h" #include "stacking.h" #include "openbox.h" #include "group.h"

@@ -213,8 +212,9 @@ XSetWindowAttributes attrib_set;

XWMHints *wmhint; gboolean activate = FALSE; ObAppSettings *settings; - gint placex, placey, placew, placeh; gboolean transient = FALSE; + Rect place, *monitor; + Time launch_time, map_time; grab_server(TRUE);

@@ -252,6 +252,8 @@ XFree(wmhint);

} ob_debug("Managing window: 0x%lx\n", window); + + map_time = event_get_server_time(); /* choose the events we want to receive on the CLIENT window */ attrib_set.event_mask = CLIENT_EVENTMASK;

@@ -269,7 +271,6 @@ /* non-zero defaults */

self->wmstate = WithdrawnState; /* make sure it gets updated first time */ self->gravity = NorthWestGravity; self->desktop = screen_num_desktops; /* always an invalid value */ - self->user_time = focus_client ? focus_client->user_time : CurrentTime; /* get all the stuff off the window */ client_get_all(self, TRUE);

@@ -300,10 +301,8 @@

/* now we have all of the window's information so we can set this up */ client_setup_decor_and_functions(self, FALSE); - { - Time t = sn_app_started(self->startup_id, self->class); - if (t) self->user_time = t; - } + /* tell startup notification that this app started */ + launch_time = sn_app_started(self->startup_id, self->class); /* do this after we have a frame.. it uses the frame to help determine the WM_STATE to apply. */

@@ -337,10 +336,8 @@ frame_adjust_area(self->frame, FALSE, TRUE, FALSE);

frame_adjust_client_area(self->frame); /* where the frame was placed is where the window was originally */ - placex = self->area.x; - placey = self->area.y; - placew = self->area.width; - placeh = self->area.height; + place = self->area; + monitor = screen_physical_area_monitor(screen_find_monitor(&place)); /* figure out placement for the window if the window is new */ if (ob_state() == OB_STATE_RUNNING) {

@@ -350,7 +347,7 @@ (self->positioned == PPosition ? "program specified" :

(self->positioned == USPosition ? "user specified" : (self->positioned == (PPosition | USPosition) ? "program + user specified" : - "BADNESS !?")))), placex, placey); + "BADNESS !?")))), place.x, place.y); ob_debug("Sized: %s @ %d %d\n", (!self->sized ? "no" :

@@ -358,14 +355,15 @@ (self->sized == PSize ? "program specified" :

(self->sized == USSize ? "user specified" : (self->sized == (PSize | USSize) ? "program + user specified" : - "BADNESS !?")))), placew, placeh); + "BADNESS !?")))), place.width, place.height); /* splash screens are also returned as TRUE for transient, and so will be forced on screen below */ - transient = place_client(self, &placex, &placey, settings); + transient = place_client(self, &place.x, &place.y, settings); /* make sure the window is visible. */ - client_find_onscreen(self, &placex, &placey, placew, placeh, + client_find_onscreen(self, &place.x, &place.y, + place.width, place.height, /* non-normal clients has less rules, and windows that are being restored from a session do also. we can assume you want

@@ -385,7 +383,13 @@ (transient ||

(!((self->positioned & USPosition) || (settings && settings->pos_given)) && client_normal(self) && - !self->session))); + !self->session && + /* don't move oldschool fullscreen windows to + fit inside the struts (fixes Acroread, which + makes its fullscreen window fit the screen + but it is not USSize'd or USPosition'd) */ + !(self->decorations == 0 && + RECT_EQUAL(place, *monitor))))); } /* if the window isn't user-sized, then make it fit inside

@@ -401,34 +405,34 @@ if (ob_state() == OB_STATE_RUNNING &&

(transient || (!(self->sized & USSize || self->positioned & USPosition) && client_normal(self) && - !self->session))) + !self->session && + /* don't shrink oldschool fullscreen windows to fit inside the + struts (fixes Acroread, which makes its fullscreen window + fit the screen but it is not USSize'd or USPosition'd) */ + !(self->decorations == 0 && RECT_EQUAL(place, *monitor))))) { - Rect placer; + Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &place); - RECT_SET(placer, placex, placey, placew, placeh); - frame_rect_to_frame(self->frame, &placer); + /* get the size of the frame */ + place.width += self->frame->size.left + self->frame->size.right; + place.height += self->frame->size.top + self->frame->size.bottom; - Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer); + /* fit the window inside the area */ + place.width = MIN(place.width, a->width); + place.height = MIN(place.height, a->height); - /* shrink by the frame's area */ - a->width -= self->frame->size.left + self->frame->size.right; - a->height -= self->frame->size.top + self->frame->size.bottom; + ob_debug("setting window size to %dx%d\n", place.width, place.height); - /* fit the window inside the area */ - if (placew > a->width || self->area.height > a->height) { - placew = MIN(self->area.width, a->width); - placeh = MIN(self->area.height, a->height); + /* get the size of the client back */ + place.width -= self->frame->size.left + self->frame->size.right; + place.height -= self->frame->size.top + self->frame->size.bottom; - ob_debug("setting window size to %dx%d\n", - self->area.width, self->area.height); - } g_free(a); } - ob_debug("placing window 0x%x at %d, %d with size %d x %d. " "some restrictions may apply\n", - self->window, placex, placey, placew, placeh); + self->window, place.x, place.y, place.width, place.height); if (self->session) ob_debug(" but session requested %d, %d %d x %d instead, " "overriding\n",

@@ -440,20 +444,25 @@ won't be all wacko!!

this also places the window */ - client_apply_startup_state(self, placex, placey, placew, placeh); + client_apply_startup_state(self, place.x, place.y, + place.width, place.height); + + g_free(monitor); + monitor = NULL; if (activate) { - guint32 last_time = focus_client ? - focus_client->user_time : CurrentTime; + gboolean raise = FALSE; /* This is focus stealing prevention */ ob_debug_type(OB_DEBUG_FOCUS, - "Want to focus new window 0x%x with time %u " - "(last time %u)\n", - self->window, self->user_time, last_time); + "Want to focus new window 0x%x at time %u " + "launched at %u (last user interaction time %u)\n", + self->window, map_time, launch_time, + event_last_user_time); if (menu_frame_visible || moveresize_in_progress) { activate = FALSE; + raise = TRUE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because the user is inside " "an Openbox menu or is move/resizing a window and "

@@ -462,12 +471,13 @@ }

/* if it's on another desktop */ else if (!(self->desktop == screen_desktop || - self->desktop == DESKTOP_ALL) && - /* the timestamp is from before you changed desktops */ - self->user_time && screen_desktop_user_time && - !event_time_after(self->user_time, screen_desktop_user_time)) + self->desktop == DESKTOP_ALL) && + /* the timestamp is from before you changed desktops */ + launch_time && screen_desktop_user_time && + !event_time_after(launch_time, screen_desktop_user_time)) { activate = FALSE; + raise = TRUE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because its on another " "desktop\n");

@@ -476,26 +486,25 @@ /* If something is focused, and it's not our relative... */

else if (focus_client && client_search_focus_tree_full(self) == NULL && client_search_focus_group_full(self) == NULL) { - /* If time stamp is old, don't steal focus */ - if (self->user_time && last_time && - !event_time_after(self->user_time, last_time)) + /* If the user is working in another window right now, then don't + steal focus */ + if (event_last_user_time && launch_time && + event_time_after(event_last_user_time, launch_time) && + event_last_user_time != launch_time && + event_time_after(event_last_user_time, + map_time - OB_EVENT_USER_TIME_DELAY)) { activate = FALSE; ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because the time is " - "too old\n"); + "Not focusing the window because the user is " + "working in another window\n"); } - /* If its a transient (and parents aren't focused) and the time - is ambiguous (either the current focus target doesn't have - a timestamp, or they are the same (we probably inherited it - from them) */ - else if (client_has_parent(self) && - (!last_time || self->user_time == last_time)) - { + /* If its a transient (and its parents aren't focused) */ + else if (client_has_parent(self)) { activate = FALSE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because it is a " - "transient, and the time is very ambiguous\n"); + "transient, and its relatives aren't focused\n"); } /* Don't steal focus from globally active clients. I stole this idea from KWin. It seems nice.

@@ -512,20 +521,33 @@ /* Don't move focus if it's not going to go to this window

anyway */ else if (client_focus_target(self) != self) { activate = FALSE; + raise = TRUE; ob_debug_type(OB_DEBUG_FOCUS, "Not focusing the window because another window " "would get the focus anyway\n"); } + else if (!(self->desktop == screen_desktop || + self->desktop == DESKTOP_ALL)) + { + activate = FALSE; + raise = TRUE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because it is on " + "another desktop and no relatives are focused "); + } } if (!activate) { ob_debug_type(OB_DEBUG_FOCUS, - "Focus stealing prevention activated for %s with " - "time %u (last time %u)\n", - self->title, self->user_time, last_time); + "Focus stealing prevention activated for %s at " + "time %u (last user interactioon time %u)\n", + self->title, map_time, event_last_user_time); /* if the client isn't focused, then hilite it so the user knows it is there */ client_hilite(self, TRUE); + /* we may want to raise it even tho we're not activating it */ + if (raise && !client_restore_session_stacking(self)) + stacking_raise(CLIENT_AS_WINDOW(self)); } } else {

@@ -653,9 +675,6 @@

/* remove the window from our save set */ XChangeSaveSet(ob_display, self->window, SetModeDelete); - /* kill the property windows */ - propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); - /* update the focus lists */ focus_order_remove(self); if (client_focused(self)) {

@@ -1095,9 +1114,6 @@

client_get_colormap(self); client_update_strut(self); client_update_icons(self); - client_update_user_time_window(self); - if (!self->user_time_window) /* check if this would have been called */ - client_update_user_time(self); client_update_icon_geometry(self); }

@@ -2098,62 +2114,6 @@ we'll get the property change any second */

frame_adjust_icon(self->frame); } -void client_update_user_time(ObClient *self) -{ - guint32 time; - gboolean got = FALSE; - - if (self->user_time_window) - got = PROP_GET32(self->user_time_window, - net_wm_user_time, cardinal, &time); - if (!got) - got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time); - - if (got) { - /* we set this every time, not just when it grows, because in practice - sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes - backward we don't want all windows to stop focusing. we'll just - assume noone is setting times older than the last one, cuz that - would be pretty stupid anyways - */ - self->user_time = time; - - /*ob_debug("window %s user time %u\n", self->title, time);*/ - } -} - -void client_update_user_time_window(ObClient *self) -{ - guint32 w; - - if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w)) - w = None; - - if (w != self->user_time_window) { - /* remove the old window */ - propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); - self->user_time_window = None; - - if (self->group && self->group->leader == w) { - ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " - "_NET_WM_USER_TYPE_WINDOW to its group leader\n"); - /* do it anyways..? */ - } - else if (w == self->window) { - ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " - "_NET_WM_USER_TIME_WINDOW to itself\n"); - w = None; /* don't do it */ - } - - /* add the new window */ - propwin_add(w, OB_PROPWIN_USER_TIME, self); - self->user_time_window = w; - - /* and update from it */ - client_update_user_time(self); - } -} - void client_update_icon_geometry(ObClient *self) { guint num;

@@ -3635,34 +3595,7 @@

void client_activate(ObClient *self, gboolean here, gboolean raise, gboolean unshade, gboolean user) { - guint32 last_time = focus_client ? focus_client->user_time : CurrentTime; - gboolean allow = FALSE; - - /* if the currently focused app doesn't set a user_time, then it can't - benefit from any focus stealing prevention. - - if the timestamp is missing in the request then let it go through - even if it is source=app, because EVERY APPLICATION DOES THIS because - GTK IS VERY BUGGY AND HARDCODES source=application... WHY!? - */ - if (!last_time || !event_curtime) - allow = TRUE; - /* otherwise, if they didn't give a time stamp or if it is too old, they - don't get focus */ - else - allow = event_time_after(event_curtime, last_time); - - ob_debug_type(OB_DEBUG_FOCUS, - "Want to activate window 0x%x with time %u (last time %u), " - "source=%s allowing? %d\n", - self->window, event_curtime, last_time, - (user ? "user" : "application"), allow); - - if (allow) - client_present(self, here, raise, unshade); - else - /* don't focus it but tell the user it wants attention */ - client_hilite(self, TRUE); + client_present(self, here, raise, unshade); } static void client_bring_windows_recursive(ObClient *self,

@@ -3872,7 +3805,7 @@ {

gint edge_start, edge_size, head, tail; gboolean skip_head = FALSE, skip_tail = FALSE; - switch(dir) { + switch (dir) { case OB_DIRECTION_NORTH: case OB_DIRECTION_SOUTH: edge_start = area.x;

@@ -3892,7 +3825,7 @@ if (!RANGES_INTERSECT(my_edge_start, my_edge_size,

edge_start, edge_size)) return; - switch(dir) { + switch (dir) { case OB_DIRECTION_NORTH: head = RECT_BOTTOM(area); tail = RECT_TOP(area);

@@ -3901,38 +3834,54 @@ case OB_DIRECTION_SOUTH:

head = RECT_TOP(area); tail = RECT_BOTTOM(area); break; + case OB_DIRECTION_WEST: + head = RECT_RIGHT(area); + tail = RECT_LEFT(area); + break; case OB_DIRECTION_EAST: head = RECT_LEFT(area); tail = RECT_RIGHT(area); break; - case OB_DIRECTION_WEST: - head = RECT_RIGHT(area); - tail = RECT_LEFT(area); - break; default: g_assert_not_reached(); } - switch(dir) { + switch (dir) { case OB_DIRECTION_NORTH: case OB_DIRECTION_WEST: + /* check if our window is past the head of this window */ if (my_head <= head + 1) skip_head = TRUE; + /* check if our window's tail is past the tail of this window */ if (my_head + my_size - 1 <= tail) skip_tail = TRUE; - if (head < *dest) + /* check if the head of this window is closer than the previously + chosen edge (take into account that the previously chosen + edge might have been a tail, not a head) */ + if (head + (*near_edge ? 0 : my_size) < *dest) skip_head = TRUE; - if (tail - my_size < *dest) + /* check if the tail of this window is closer than the previously + chosen edge (take into account that the previously chosen + edge might have been a head, not a tail) */ + if (tail - (!*near_edge ? 0 : my_size) < *dest) skip_tail = TRUE; break; case OB_DIRECTION_SOUTH: case OB_DIRECTION_EAST: + /* check if our window is past the head of this window */ if (my_head >= head - 1) skip_head = TRUE; + /* check if our window's tail is past the tail of this window */ if (my_head - my_size + 1 >= tail) skip_tail = TRUE; - if (head > *dest) + /* check if the head of this window is closer than the previously + chosen edge (take into account that the previously chosen + edge might have been a tail, not a head) */ + if (head - (*near_edge ? 0 : my_size) > *dest) skip_head = TRUE; - if (tail + my_size > *dest) + /* check if the tail of this window is closer than the previously + chosen edge (take into account that the previously chosen + edge might have been a head, not a tail) */ + if (tail + (!*near_edge ? 0 : my_size) > *dest) skip_tail = TRUE; break; default:

@@ -3951,7 +3900,6 @@ ob_debug("using far edge %d\n", tail);

*dest = tail; *near_edge = FALSE; } - } void client_find_edge_directional(ObClient *self, ObDirection dir,

@@ -3969,27 +3917,27 @@ &self->frame->area);

mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &self->frame->area); - switch(dir) { + switch (dir) { case OB_DIRECTION_NORTH: - if (my_head >= RECT_TOP(*mon)) + if (my_head >= RECT_TOP(*mon) + 1) edge = RECT_TOP(*mon) - 1; else edge = RECT_TOP(*a) - 1; break; case OB_DIRECTION_SOUTH: - if (my_head <= RECT_BOTTOM(*mon)) + if (my_head <= RECT_BOTTOM(*mon) - 1) edge = RECT_BOTTOM(*mon) + 1; else edge = RECT_BOTTOM(*a) + 1; break; case OB_DIRECTION_EAST: - if (my_head <= RECT_RIGHT(*mon)) + if (my_head <= RECT_RIGHT(*mon) - 1) edge = RECT_RIGHT(*mon) + 1; else edge = RECT_RIGHT(*a) + 1; break; case OB_DIRECTION_WEST: - if (my_head >= RECT_LEFT(*mon)) + if (my_head >= RECT_LEFT(*mon) + 1) edge = RECT_LEFT(*mon) - 1; else edge = RECT_LEFT(*a) - 1;

@@ -4001,7 +3949,7 @@ /* default to the far edge, then narrow it down */

*dest = edge; *near_edge = TRUE; - for(it = client_list; it; it = g_list_next(it)) { + for (it = client_list; it; it = g_list_next(it)) { ObClient *cur = it->data; /* skip windows to not bump into */
M openbox/client.hopenbox/client.h

@@ -289,15 +289,9 @@ guint nicons;

/*! Where the window should iconify to/from */ Rect icon_geometry; - - /*! The time when the client last received user interaction */ - guint32 user_time; - /*! A separate window for the client to update it's user_time on */ - Window user_time_window; }; extern GList *client_list; -extern GHashTable *client_user_time_window_map; void client_startup(gboolean reconfig); void client_shutdown(gboolean reconfig);

@@ -606,10 +600,6 @@ /*! Updates the strut for the client */

void client_update_strut(ObClient *self); /*! Updates the window's icons */ void client_update_icons(ObClient *self); -/*! Updates the window's user time */ -void client_update_user_time(ObClient *self); -/*! Updates the window's user time window */ -void client_update_user_time_window(ObClient *self); /*! Updates the window's icon geometry (where to iconify to/from) */ void client_update_icon_geometry(ObClient *self);
M openbox/client_list_combined_menu.copenbox/client_list_combined_menu.c

@@ -32,7 +32,7 @@ #define MENU_NAME "client-list-combined-menu"

ObMenu *combined_menu; -#define CLIENT -1 +#define SEPARATOR -1 #define ADD_DESKTOP -2 #define REMOVE_DESKTOP -3

@@ -49,7 +49,7 @@ for (desktop = 0; desktop < screen_num_desktops; desktop++) {

gboolean empty = TRUE; gboolean onlyiconic = TRUE; - menu_add_separator(menu, CLIENT, screen_desktop_names[desktop]); + menu_add_separator(menu, SEPARATOR, screen_desktop_names[desktop]); for (it = focus_order; it; it = g_list_next(it)) { ObClient *c = it->data; if (client_normal(c) && (!c->skip_taskbar || c->iconic) &&

@@ -61,11 +61,11 @@ empty = FALSE;

if (c->iconic) { gchar *title = g_strdup_printf("(%s)", c->icon_title); - e = menu_add_normal(menu, CLIENT, title, NULL, FALSE); + e = menu_add_normal(menu, desktop, title, NULL, FALSE); g_free(title); } else { onlyiconic = FALSE; - e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE); + e = menu_add_normal(menu, desktop, c->title, NULL, FALSE); } if (config_menu_client_list_icons

@@ -87,7 +87,7 @@

/* no entries or only iconified windows, so add a * way to go to this desktop without uniconifying a window */ if (!empty) - menu_add_separator(menu, CLIENT, NULL); + menu_add_separator(menu, SEPARATOR, NULL); e = menu_add_normal(menu, desktop, _("Go there..."), NULL, TRUE); if (desktop == screen_desktop)

@@ -95,7 +95,7 @@ e->data.normal.enabled = FALSE;

} } - menu_add_separator(menu, CLIENT, _("Manage desktops")); + menu_add_separator(menu, SEPARATOR, _("Manage desktops")); menu_add_normal(menu, ADD_DESKTOP, _("_Add new desktop"), NULL, TRUE); menu_add_normal(menu, REMOVE_DESKTOP, _("_Remove last desktop"), NULL, TRUE);

@@ -106,11 +106,7 @@

static void menu_execute(ObMenuEntry *self, ObMenuFrame *f, ObClient *c, guint state, gpointer data) { - if (self->id == CLIENT) { - if (self->data.normal.data) /* it's set to NULL if its destroyed */ - client_activate(self->data.normal.data, FALSE, TRUE, TRUE, TRUE); - } - else if (self->id == ADD_DESKTOP) { + if (self->id == ADD_DESKTOP) { screen_add_desktop(FALSE); menu_frame_hide_all(); }

@@ -118,8 +114,18 @@ else if (self->id == REMOVE_DESKTOP) {

screen_remove_desktop(FALSE); menu_frame_hide_all(); } - else - screen_set_desktop(self->id, TRUE); + else { + ObClient *t = self->data.normal.data; + if (t) { /* it's set to NULL if its destroyed */ + client_activate(t, FALSE, TRUE, TRUE, TRUE); + /* if the window is omnipresent then we need to go to its + desktop */ + if (t->desktop == DESKTOP_ALL) + screen_set_desktop(self->id, FALSE); + } + else + screen_set_desktop(self->id, TRUE); + } } static void client_dest(ObClient *client, gpointer data)
M openbox/client_list_menu.copenbox/client_list_menu.c

@@ -37,7 +37,7 @@ {

guint desktop; } DesktopData; -#define CLIENT -1 +#define SEPARATOR -1 #define ADD_DESKTOP -2 #define REMOVE_DESKTOP -3

@@ -63,11 +63,11 @@ empty = FALSE;

if (c->iconic) { gchar *title = g_strdup_printf("(%s)", c->icon_title); - e = menu_add_normal(menu, CLIENT, title, NULL, FALSE); + e = menu_add_normal(menu, d->desktop, title, NULL, FALSE); g_free(title); } else { onlyiconic = FALSE; - e = menu_add_normal(menu, CLIENT, c->title, NULL, FALSE); + e = menu_add_normal(menu, d->desktop, c->title, NULL, FALSE); } if (config_menu_client_list_icons

@@ -88,7 +88,7 @@

/* no entries or only iconified windows, so add a * way to go to this desktop without uniconifying a window */ if (!empty) - menu_add_separator(menu, CLIENT, NULL); + menu_add_separator(menu, SEPARATOR, NULL); e = menu_add_normal(menu, d->desktop, _("Go there..."), NULL, TRUE); if (d->desktop == screen_desktop)

@@ -101,9 +101,13 @@

static void desk_menu_execute(ObMenuEntry *self, ObMenuFrame *f, ObClient *c, guint state, gpointer data) { - if (self->id == CLIENT) { - if (self->data.normal.data) /* it's set to NULL if its destroyed */ - client_activate(self->data.normal.data, FALSE, TRUE, TRUE, TRUE); + ObClient *t = self->data.normal.data; + if (t) { /* it's set to NULL if its destroyed */ + client_activate(t, FALSE, TRUE, TRUE, TRUE); + /* if the window is omnipresent then we need to go to its + desktop */ + if (t->desktop == DESKTOP_ALL) + screen_set_desktop(self->id, FALSE); } else screen_set_desktop(self->id, TRUE);

@@ -148,7 +152,7 @@

desktop_menus = g_slist_append(desktop_menus, submenu); } - menu_add_separator(menu, CLIENT, NULL); + menu_add_separator(menu, SEPARATOR, NULL); menu_add_normal(menu, ADD_DESKTOP, _("_Add new desktop"), NULL, TRUE); menu_add_normal(menu, REMOVE_DESKTOP, _("_Remove last desktop"), NULL, TRUE);
M openbox/client_menu.copenbox/client_menu.c

@@ -377,6 +377,10 @@ menu_set_update_func(menu, client_menu_update);

menu_set_place_func(menu, client_menu_place); menu_set_execute_func(menu, client_menu_execute); + menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME); + + menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME); + e = menu_add_normal(menu, CLIENT_RESTORE, _("R_estore"), NULL, TRUE); e->data.normal.mask = ob_rr_theme->max_toggled_mask; e->data.normal.mask_normal_color = ob_rr_theme->menu_color;

@@ -408,12 +412,6 @@

menu_add_normal(menu, CLIENT_SHADE, _("_Roll up/down"), NULL, TRUE); menu_add_normal(menu, CLIENT_DECORATE, _("Un/_Decorate"), NULL, TRUE); - - menu_add_separator(menu, -1, NULL); - - menu_add_submenu(menu, CLIENT_SEND_TO, SEND_TO_MENU_NAME); - - menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME); menu_add_separator(menu, -1, NULL);
M openbox/config.copenbox/config.c

@@ -57,6 +57,7 @@

gint config_desktops_num; GSList *config_desktops_names; guint config_screen_firstdesk; +guint config_desktop_popup_time; gboolean config_resize_redraw; gboolean config_resize_four_corners;

@@ -478,7 +479,7 @@ config_focus_new = parse_bool(doc, n);

if ((n = parse_find_node("followMouse", node))) config_focus_follow = parse_bool(doc, n); if ((n = parse_find_node("focusDelay", node))) - config_focus_delay = parse_int(doc, n) * 1000; + config_focus_delay = parse_int(doc, n); if ((n = parse_find_node("raiseOnFocus", node))) config_focus_raise = parse_bool(doc, n); if ((n = parse_find_node("focusLast", node)))

@@ -634,6 +635,8 @@ parse_string(doc, nname));

nname = parse_find_node("name", nname->next); } } + if ((n = parse_find_node("popupTime", node))) + config_desktop_popup_time = parse_int(doc, n); } static void parse_resize(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,

@@ -724,9 +727,9 @@ }

if ((n = parse_find_node("autoHide", node))) config_dock_hide = parse_bool(doc, n); if ((n = parse_find_node("hideDelay", node))) - config_dock_hide_delay = parse_int(doc, n) * 1000; + config_dock_hide_delay = parse_int(doc, n); if ((n = parse_find_node("showDelay", node))) - config_dock_show_delay = parse_int(doc, n) * 1000; + config_dock_show_delay = parse_int(doc, n); if ((n = parse_find_node("moveButton", node))) { gchar *str = parse_string(doc, n); guint b, s;

@@ -900,6 +903,7 @@

config_desktops_num = 4; config_screen_firstdesk = 1; config_desktops_names = NULL; + config_desktop_popup_time = 875; parse_register(i, "desktops", parse_desktops, NULL);
M openbox/config.hopenbox/config.h

@@ -64,7 +64,7 @@ /*! Should new windows be focused */

extern gboolean config_focus_new; /*! Focus windows when the mouse enters them */ extern gboolean config_focus_follow; -/*! Timeout for focusing windows on focus follows mouse, in microseconds */ +/*! Timeout for focusing windows on focus follows mouse, in milliseconds */ extern guint config_focus_delay; /*! If windows should automatically be raised when they are focused in focus follows mouse */

@@ -109,9 +109,9 @@ /*! Whether the dock places the dockapps in it horizontally or vertically */

extern ObOrientation config_dock_orient; /*! Whether to auto-hide the dock when the pointer is not over it */ extern gboolean config_dock_hide; -/*! The number of microseconds to wait before hiding the dock */ +/*! The number of milliseconds to wait before hiding the dock */ extern guint config_dock_hide_delay; -/*! The number of microseconds to wait before showing the dock */ +/*! The number of milliseconds to wait before showing the dock */ extern guint config_dock_show_delay; /*! The mouse button to be used to move dock apps */ extern guint config_dock_app_move_button;

@@ -145,6 +145,8 @@ /*! Desktop to start on, put 5 to start in the center of a 3x3 grid */

extern guint config_screen_firstdesk; /*! Names for the desktops */ extern GSList *config_desktops_names; +/*! Amount of time to show the desktop switch dialog */ +extern guint config_desktop_popup_time; /*! The keycode of the key combo which resets the keybaord chains */ extern guint config_keyboard_reset_keycode;

@@ -165,11 +167,11 @@ extern gint config_resist_win;

/*! Number of pixels to resist while crossing a screen's edge */ extern gint config_resist_edge; -/*! delay for hiding menu when opening */ +/*! Delay for hiding menu when opening in milliseconds */ extern guint config_menu_hide_delay; /*! Center menus vertically about the parent entry */ extern gboolean config_menu_middle; -/*! delay before opening a submenu */ +/*! Delay before opening a submenu in milliseconds */ extern guint config_submenu_show_delay; /*! show icons in client_list_menu */ extern gboolean config_menu_client_list_icons;
M openbox/dock.copenbox/dock.c

@@ -30,6 +30,8 @@

#define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \ EnterWindowMask | LeaveWindowMask) #define DOCKAPP_EVENT_MASK (StructureNotifyMask) +#define DOCK_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \ + ButtonMotionMask) static ObDock *dock;

@@ -83,11 +85,13 @@ dock->hidden = TRUE;

attrib.event_mask = DOCK_EVENT_MASK; attrib.override_redirect = True; + attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK; dock->frame = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen), 0, 0, 1, 1, 0, RrDepth(ob_rr_inst), InputOutput, RrVisual(ob_rr_inst), - CWOverrideRedirect | CWEventMask, + CWOverrideRedirect | CWEventMask | + CWDontPropagate, &attrib); dock->a_frame = RrAppearanceCopy(ob_rr_theme->osd_hilite_bg); XSetWindowBorder(ob_display, dock->frame,

@@ -624,15 +628,17 @@ void dock_hide(gboolean hide)

{ if (!hide) { if (dock->hidden && config_dock_hide) { - ob_main_loop_timeout_add(ob_main_loop, config_dock_show_delay, - show_timeout, NULL, g_direct_equal, NULL); + ob_main_loop_timeout_add(ob_main_loop, + config_dock_show_delay * 1000, + show_timeout, NULL, g_direct_equal, NULL); } else if (!dock->hidden && config_dock_hide) { ob_main_loop_timeout_remove(ob_main_loop, hide_timeout); } } else { if (!dock->hidden && config_dock_hide) { - ob_main_loop_timeout_add(ob_main_loop, config_dock_hide_delay, - hide_timeout, NULL, g_direct_equal, NULL); + ob_main_loop_timeout_add(ob_main_loop, + config_dock_hide_delay * 1000, + hide_timeout, NULL, g_direct_equal, NULL); } else if (dock->hidden && config_dock_hide) { ob_main_loop_timeout_remove(ob_main_loop, show_timeout); }
M openbox/event.copenbox/event.c

@@ -34,7 +34,6 @@ #include "menu.h"

#include "menuframe.h" #include "keyboard.h" #include "modkeys.h" -#include "propwin.h" #include "mouse.h" #include "mainloop.h" #include "focus.h"

@@ -90,7 +89,6 @@ static gboolean event_handle_menu(XEvent *e);

static void event_handle_dock(ObDock *s, XEvent *e); static void event_handle_dockapp(ObDockApp *app, XEvent *e); static void event_handle_client(ObClient *c, XEvent *e); -static void event_handle_user_time_window_clients(GSList *l, XEvent *e); static void event_handle_user_input(ObClient *client, XEvent *e); static gboolean is_enter_focus_event_ignored(XEvent *e);

@@ -99,8 +97,8 @@ static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2);

static gboolean focus_delay_func(gpointer data); static void focus_delay_client_dest(ObClient *client, gpointer data); -/* The time for the current event being processed */ Time event_curtime = CurrentTime; +Time event_last_user_time = CurrentTime; static gboolean focus_left_screen = FALSE; /*! A list of ObSerialRanges which are to be ignored for mouse enter events */

@@ -238,15 +236,17 @@ explicitly */

break; } + /* watch that if we get an event earlier than the last specified user_time, + which can happen if the clock goes backwards, we erase the last + specified user_time */ + if (t && event_last_user_time && event_time_after(event_last_user_time, t)) + event_last_user_time = CurrentTime; + event_curtime = t; } static void event_hack_mods(XEvent *e) { -#ifdef XKB - XkbStateRec xkb_state; -#endif - switch (e->type) { case ButtonPress: case ButtonRelease:

@@ -437,7 +437,6 @@ ObClient *client = NULL;

ObDock *dock = NULL; ObDockApp *dockapp = NULL; ObWindow *obwin = NULL; - GSList *timewinclients = NULL; XEvent ee, *e; ObEventData *ed = data;

@@ -446,27 +445,24 @@ ee = *ec;

e = &ee; window = event_get_window(e); - if (e->type != PropertyNotify || - !(timewinclients = propwin_get_clients(window, - OB_PROPWIN_USER_TIME))) - if ((obwin = g_hash_table_lookup(window_map, &window))) { - switch (obwin->type) { - case Window_Dock: - dock = WINDOW_AS_DOCK(obwin); - break; - case Window_DockApp: - dockapp = WINDOW_AS_DOCKAPP(obwin); - break; - case Window_Client: - client = WINDOW_AS_CLIENT(obwin); - break; - case Window_Menu: - case Window_Internal: - /* not to be used for events */ - g_assert_not_reached(); - break; - } + if ((obwin = g_hash_table_lookup(window_map, &window))) { + switch (obwin->type) { + case Window_Dock: + dock = WINDOW_AS_DOCK(obwin); + break; + case Window_DockApp: + dockapp = WINDOW_AS_DOCKAPP(obwin); + break; + case Window_Client: + client = WINDOW_AS_CLIENT(obwin); + break; + case Window_Menu: + case Window_Internal: + /* not to be used for events */ + g_assert_not_reached(); + break; } + } event_set_curtime(e); event_hack_mods(e);

@@ -493,7 +489,7 @@ "Focus went to the frame window");

focus_left_screen = FALSE; - focus_fallback(FALSE, config_focus_under_mouse, TRUE); + focus_fallback(FALSE, config_focus_under_mouse, TRUE, TRUE); /* We don't get a FocusOut for this case, because it's just moving from our Inferior up to us. This happens when iconifying a

@@ -502,10 +498,10 @@ frame_adjust_focus(client->frame, FALSE);

/* focus_set_client(NULL) has already been called */ client_calc_layer(client); } - if (e->xfocus.detail == NotifyPointerRoot || - e->xfocus.detail == NotifyDetailNone || - e->xfocus.detail == NotifyInferior || - e->xfocus.detail == NotifyNonlinear) + else if (e->xfocus.detail == NotifyPointerRoot || + e->xfocus.detail == NotifyDetailNone || + e->xfocus.detail == NotifyInferior || + e->xfocus.detail == NotifyNonlinear) { XEvent ce;

@@ -545,7 +541,8 @@ worry about focusing an invalid window

*/ if (!focus_left_screen) - focus_fallback(FALSE, config_focus_under_mouse, TRUE); + focus_fallback(FALSE, config_focus_under_mouse, + TRUE, TRUE); } } else if (!client)

@@ -601,7 +598,7 @@ that isn't a client. */

ob_debug_type(OB_DEBUG_FOCUS, "Focus went to an unmanaged window 0x%x !\n", ce.xfocus.window); - focus_fallback(TRUE, config_focus_under_mouse, TRUE); + focus_fallback(TRUE, config_focus_under_mouse, TRUE, TRUE); } }

@@ -611,8 +608,7 @@ /* focus_set_client(NULL) has already been called in this

section or by focus_fallback */ client_calc_layer(client); } - } else if (timewinclients) - event_handle_user_time_window_clients(timewinclients, e); + } else if (client) event_handle_client(client, e); else if (dockapp)

@@ -758,7 +754,7 @@ data->client = client;

data->time = event_curtime; ob_main_loop_timeout_add(ob_main_loop, - config_focus_delay, + config_focus_delay * 1000, focus_delay_func, data, focus_delay_cmp, focus_delay_dest); } else {

@@ -767,15 +763,6 @@ data.client = client;

data.time = event_curtime; focus_delay_func(&data); } - } -} - -static void event_handle_user_time_window_clients(GSList *l, XEvent *e) -{ - g_assert(e->type == PropertyNotify); - if (e->xproperty.atom == prop_atoms.net_wm_user_time) { - for (; l; l = g_slist_next(l)) - client_update_user_time(l->data); } }

@@ -1292,8 +1279,11 @@ (e->xclient.data.l[0] == 1 ? "application" :

(e->xclient.data.l[0] == 2 ? "user" : "INVALID")))); /* XXX make use of data.l[2] !? */ if (e->xclient.data.l[0] == 1 || e->xclient.data.l[0] == 2) { - event_curtime = e->xclient.data.l[1]; - if (event_curtime == 0) + /* don't use the user's timestamp for client_focus, cuz if it's + an old broken timestamp (happens all the time) then focus + won't move even though we're trying to move it + event_curtime = e->xclient.data.l[1];*/ + if (e->xclient.data.l[1] == 0) ob_debug_type(OB_DEBUG_APP_BUGS, "_NET_ACTIVE_WINDOW message for window %s is" " missing a timestamp\n", client->title);

@@ -1514,10 +1504,15 @@ else if (msgtype == prop_atoms.net_wm_icon_geometry) {

client_update_icon_geometry(client); } else if (msgtype == prop_atoms.net_wm_user_time) { - client_update_user_time(client); - } - else if (msgtype == prop_atoms.net_wm_user_time_window) { - client_update_user_time_window(client); + guint32 t; + if (client == focus_client && + PROP_GET32(client->window, net_wm_user_time, cardinal, &t) && + t && !event_time_after(t, e->xproperty.time) && + (!event_last_user_time || + event_time_after(t, event_last_user_time))) + { + event_last_user_time = t; + } } #ifdef SYNC else if (msgtype == prop_atoms.net_wm_sync_request_counter) {

@@ -1844,6 +1839,9 @@ {

ObFocusDelayData *d = data; Time old = event_curtime; + /* don't move focus and kill the menu or the move/resize */ + if (menu_frame_visible || moveresize_in_progress) return FALSE; + event_curtime = d->time; if (focus_client != d->client) { if (client_focus(d->client) && config_focus_raise)

@@ -1957,3 +1955,15 @@ else

/* t2 is in the first half so t1 has to come after it */ return t1 >= t2 && t1 < (t2 + TIME_HALF); } + +Time event_get_server_time() +{ + /* Generate a timestamp */ + XEvent event; + + XChangeProperty(ob_display, screen_support_win, + prop_atoms.wm_class, prop_atoms.string, + 8, PropModeAppend, NULL, 0); + XWindowEvent(ob_display, screen_support_win, PropertyChangeMask, &event); + return event.xproperty.time; +}
M openbox/event.hopenbox/event.h

@@ -24,8 +24,14 @@ #include <glib.h>

struct _ObClient; +/*! The amount of time before a window appears that is checked for user input + to determine if the user is working in another window */ +#define OB_EVENT_USER_TIME_DELAY (500) /* 0.5 seconds */ + /*! Time at which the last event with a timestamp occured. */ extern Time event_curtime; +/*! The last user-interaction time, as given by the clients */ +extern Time event_last_user_time; void event_startup(gboolean reconfig); void event_shutdown(gboolean reconfig);

@@ -49,5 +55,7 @@

/*! Compare t1 and t2, taking into account wraparound. True if t1 comes at the same time or later than t2. */ gboolean event_time_after(Time t1, Time t2); + +Time event_get_server_time(); #endif
M openbox/focus.copenbox/focus.c

@@ -159,7 +159,7 @@ return NULL;

} ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer, - gboolean allow_omnipresent) + gboolean allow_omnipresent, gboolean focus_lost) { ObClient *new; ObClient *old = focus_client;

@@ -167,7 +167,8 @@

/* unfocus any focused clients.. they can be focused by Pointer events and such, and then when we try focus them, we won't get a FocusIn event at all for them. */ - focus_nothing(); + if (focus_lost) + focus_nothing(); new = focus_fallback_target(allow_refocus, allow_pointer, allow_omnipresent, old);
M openbox/focus.hopenbox/focus.h

@@ -46,7 +46,8 @@

/*! Call this when you need to focus something! */ struct _ObClient* focus_fallback(gboolean allow_refocus, gboolean allow_pointer, - gboolean allow_omnipresent); + gboolean allow_omnipresent, + gboolean focus_lost); /*! Add a new client into the focus order */ void focus_order_add_new(struct _ObClient *c);
M openbox/frame.copenbox/frame.c

@@ -130,6 +130,11 @@ self->innertop = createWindow(self->window, NULL, mask, &attrib);

self->innerright = createWindow(self->window, NULL, mask, &attrib); self->innerbottom = createWindow(self->window, NULL, mask, &attrib); + self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib); + self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib); + self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib); + self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib); + self->title = createWindow(self->window, NULL, mask, &attrib); self->titleleft = createWindow(self->window, NULL, mask, &attrib); self->titletop = createWindow(self->window, NULL, mask, &attrib);

@@ -388,6 +393,9 @@

/* position/size and map/unmap all the windows */ if (!fake) { + gint innercornerheight = + ob_rr_theme->grip_width - self->size.bottom; + if (self->cbwidth_l) { XMoveResizeWindow(ob_display, self->innerleft, self->size.left - self->cbwidth_l,

@@ -398,6 +406,19 @@ XMapWindow(ob_display, self->innerleft);

} else XUnmapWindow(ob_display, self->innerleft); + if (self->cbwidth_l && innercornerheight > 0) { + XMoveResizeWindow(ob_display, self->innerbll, + 0, + self->client->area.height - + (ob_rr_theme->grip_width - + self->size.bottom), + self->cbwidth_l, + ob_rr_theme->grip_width - self->size.bottom); + + XMapWindow(ob_display, self->innerbll); + } else + XUnmapWindow(ob_display, self->innerbll); + if (self->cbwidth_r) { XMoveResizeWindow(ob_display, self->innerright, self->size.left + self->client->area.width,

@@ -408,6 +429,19 @@ XMapWindow(ob_display, self->innerright);

} else XUnmapWindow(ob_display, self->innerright); + if (self->cbwidth_r && innercornerheight > 0) { + XMoveResizeWindow(ob_display, self->innerbrr, + 0, + self->client->area.height - + (ob_rr_theme->grip_width - + self->size.bottom), + self->cbwidth_r, + ob_rr_theme->grip_width - self->size.bottom); + + XMapWindow(ob_display, self->innerbrr); + } else + XUnmapWindow(ob_display, self->innerbrr); + if (self->cbwidth_t) { XMoveResizeWindow(ob_display, self->innertop, self->size.left - self->cbwidth_l,

@@ -428,9 +462,26 @@ self->client->area.width +

self->cbwidth_l + self->cbwidth_r, self->cbwidth_b); + XMoveResizeWindow(ob_display, self->innerblb, + 0, 0, + ob_rr_theme->grip_width + self->bwidth, + self->cbwidth_b); + XMoveResizeWindow(ob_display, self->innerbrb, + self->client->area.width + + self->cbwidth_l + self->cbwidth_r - + (ob_rr_theme->grip_width + self->bwidth), + 0, + ob_rr_theme->grip_width + self->bwidth, + self->cbwidth_b); + XMapWindow(ob_display, self->innerbottom); - } else + XMapWindow(ob_display, self->innerblb); + XMapWindow(ob_display, self->innerbrb); + } else { XUnmapWindow(ob_display, self->innerbottom); + XUnmapWindow(ob_display, self->innerblb); + XUnmapWindow(ob_display, self->innerbrb); + } if (self->bwidth) { gint titlesides;

@@ -598,7 +649,7 @@ ob_rr_theme->grip_width + self->bwidth,

self->bwidth); XMoveResizeWindow(ob_display, self->rgripbottom, self->size.left + self->client->area.width + - self->size.right - self->bwidth - sidebwidth - + self->size.right - self->bwidth - sidebwidth- ob_rr_theme->grip_width, self->size.top + self->client->area.height + self->size.bottom - self->bwidth,

@@ -876,12 +927,16 @@ XChangeWindowAttributes(ob_display, self->handleleft, CWCursor, &a);

XChangeWindowAttributes(ob_display, self->lgripleft, CWCursor, &a); XChangeWindowAttributes(ob_display, self->lgriptop, CWCursor, &a); XChangeWindowAttributes(ob_display, self->lgripbottom, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerbll, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerblb, CWCursor, &a); a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE); XChangeWindowAttributes(ob_display, self->rgrip, CWCursor, &a); XChangeWindowAttributes(ob_display, self->handleright, CWCursor, &a); XChangeWindowAttributes(ob_display, self->rgripright, CWCursor, &a); XChangeWindowAttributes(ob_display, self->rgriptop, CWCursor, &a); XChangeWindowAttributes(ob_display, self->rgripbottom, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerbrr, CWCursor, &a); + XChangeWindowAttributes(ob_display, self->innerbrb, CWCursor, &a); } }

@@ -1537,6 +1592,13 @@ {

r->width += self->size.left + self->size.right; r->height += self->size.top + self->size.bottom; frame_client_gravity(self, &r->x, &r->y); +} + +void frame_rect_to_client(ObFrame *self, Rect *r) +{ + r->width -= self->size.left + self->size.right; + r->height -= self->size.top + self->size.bottom; + frame_frame_gravity(self, &r->x, &r->y); } static void flash_done(gpointer data)
M openbox/frame.hopenbox/frame.h

@@ -120,6 +120,10 @@ Window innerleft; /*!< For drawing the inner client border */

Window innertop; /*!< For drawing the inner client border */ Window innerright; /*!< For drawing the inner client border */ Window innerbottom; /*!< For drawing the inner client border */ + Window innerblb; + Window innerbll; + Window innerbrb; + Window innerbrr; Window backback; /*!< A colored window shown while resizing */ Window backfront; /*!< An undrawn-in window, to prevent flashing on unmap */

@@ -236,6 +240,10 @@

/*! Convert a rectangle in client coordinates/sizes to what it would be for the frame, given its current decorations sizes */ void frame_rect_to_frame(ObFrame *self, Rect *r); + +/*! Convert a rectangle in frame coordinates/sizes to what it would be for the + client, given its current decorations sizes */ +void frame_rect_to_client(ObFrame *self, Rect *r); void frame_flash_start(ObFrame *self); void frame_flash_stop(ObFrame *self);
M openbox/framerender.copenbox/framerender.c

@@ -59,6 +59,14 @@ XSetWindowBackground(ob_display, self->innerright, px);

XClearWindow(ob_display, self->innerright); XSetWindowBackground(ob_display, self->innerbottom, px); XClearWindow(ob_display, self->innerbottom); + XSetWindowBackground(ob_display, self->innerbll, px); + XClearWindow(ob_display, self->innerbll); + XSetWindowBackground(ob_display, self->innerbrr, px); + XClearWindow(ob_display, self->innerbrr); + XSetWindowBackground(ob_display, self->innerblb, px); + XClearWindow(ob_display, self->innerblb); + XSetWindowBackground(ob_display, self->innerbrb, px); + XClearWindow(ob_display, self->innerbrb); px = (self->focused ? RrColorPixel(ob_rr_theme->frame_focused_border_color) :
M openbox/modkeys.copenbox/modkeys.c

@@ -35,7 +35,21 @@ #define nth_mask(n) (1 << n)

static void set_modkey_mask(guchar mask, KeySym sym); -static XModifierKeymap *modmap; +/* This is 8 lists of keycodes that are bound to the given mod mask. + If contains more than the one given to us by X cuz XKB is weird apparently. + We will look up all keycodes for a given keysym that is bound to the mask, + and add them all here. + + With XKB, you can have a keycode bound to a modifier that isn't in the + modifier map somehow. So this means that when we try translate from the + KeyRelease to a mod mask, we are unable to. So this array stores *all* + the KeyCodes for each KeySym for each KeyCode bound to a mod mask. + Confused? Haha... + + ModMask -> n KeyCodes -> n*m KeySyms (up to m for each KeyCode) -> + n*m*p KeyCodes (up to p for each KeySym) +*/ +static GArray *modmap[NUM_MASKS]; static KeySym *keymap; static gint min_keycode, max_keycode, keysyms_per_keycode; /* This is a bitmask of the different masks for each modifier key */

@@ -48,14 +62,15 @@ static gboolean hyper_l = FALSE;

void modkeys_startup(gboolean reconfigure) { - gint i, j, k; + static XModifierKeymap *xmodmap; + gint i, j, k, l, m; /* reset the keys to not be bound to any masks */ for (i = 0; i < OB_MODKEY_NUM_KEYS; ++i) modkeys_keys[i] = 0; - modmap = XGetModifierMapping(ob_display); - g_assert(modmap->max_keypermod > 0); + xmodmap = XGetModifierMapping(ob_display); + g_assert(xmodmap->max_keypermod > 0); XDisplayKeycodes(ob_display, &min_keycode, &max_keycode); keymap = XGetKeyboardMapping(ob_display, min_keycode,

@@ -66,17 +81,31 @@ alt_l = meta_l = super_l = hyper_l = FALSE;

/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */ for (i = 0; i < NUM_MASKS; ++i) { + /* reset the modmap list */ + modmap[i] = g_array_new(FALSE, FALSE, sizeof(KeyCode)); + /* go through each keycode that is bound to the mask */ - for (j = 0; j < modmap->max_keypermod; ++j) { + for (j = 0; j < xmodmap->max_keypermod; ++j) { KeySym sym; /* get a keycode that is bound to the mask (i) */ - KeyCode keycode = modmap->modifiermap[i*modmap->max_keypermod + j]; + KeyCode keycode = xmodmap->modifiermap[i*xmodmap->max_keypermod+j]; if (keycode) { /* go through each keysym bound to the given keycode */ for (k = 0; k < keysyms_per_keycode; ++k) { sym = keymap[(keycode-min_keycode) * keysyms_per_keycode + k]; if (sym != NoSymbol) { + /* find all keycodes for the given keysym */ + for (l = min_keycode; l <= max_keycode; ++l) + for (m = 0; m < keysyms_per_keycode; ++m) + if (keymap[(l-min_keycode) * + keysyms_per_keycode + m] == sym) + { + /* add all keycodes for the keysym to our + modmap */ + g_array_append_val(modmap[i], l); + } + /* bind the key to the mask (e.g. Alt_L => Mod1Mask) */ set_modkey_mask(nth_mask(i), sym); }

@@ -89,17 +118,22 @@ /* CapsLock, Shift, and Control are special and hard-coded */

modkeys_keys[OB_MODKEY_KEY_CAPSLOCK] = LockMask; modkeys_keys[OB_MODKEY_KEY_SHIFT] = ShiftMask; modkeys_keys[OB_MODKEY_KEY_CONTROL] = ControlMask; + + XFreeModifiermap(xmodmap); } void modkeys_shutdown(gboolean reconfigure) { - XFreeModifiermap(modmap); + guint i; + + for (i = 0; i < NUM_MASKS; ++i) + g_array_free(modmap[i], TRUE); XFree(keymap); } guint modkeys_keycode_to_mask(guint keycode) { - gint i, j; + guint i, j; guint mask = 0; if (keycode == NoSymbol) return 0;

@@ -107,9 +141,9 @@

/* go through each of the modifier masks (eg ShiftMask, CapsMask...) */ for (i = 0; i < NUM_MASKS; ++i) { /* go through each keycode that is bound to the mask */ - for (j = 0; j < modmap->max_keypermod; ++j) { + for (j = 0; j < modmap[i]->len; ++j) { /* compare with a keycode that is bound to the mask (i) */ - if (modmap->modifiermap[i*modmap->max_keypermod + j] == keycode) + if (g_array_index(modmap[i], KeyCode, j) == keycode) mask |= nth_mask(i); } }
M openbox/moveresize.copenbox/moveresize.c

@@ -55,6 +55,7 @@ static gint cur_x, cur_y, cur_w, cur_h;

static guint button; static guint32 corner; static ObDirection edge_warp_dir = -1; +static gboolean edge_warp_odd = FALSE; static ObDirection key_resize_edge = -1; #ifdef SYNC static gboolean waiting_for_sync;

@@ -120,6 +121,8 @@ {

ObCursor cur; gboolean mv = (cnr == prop_atoms.net_wm_moveresize_move || cnr == prop_atoms.net_wm_moveresize_move_keyboard); + gint up = 1; + gint left = 1; if (moveresize_in_progress || !c->frame->visible || !(mv ?

@@ -127,23 +130,28 @@ (c->functions & OB_CLIENT_FUNC_MOVE) :

(c->functions & OB_CLIENT_FUNC_RESIZE))) return; - if (cnr == prop_atoms.net_wm_moveresize_size_topleft) + if (cnr == prop_atoms.net_wm_moveresize_size_topleft) { cur = OB_CURSOR_NORTHWEST; - else if (cnr == prop_atoms.net_wm_moveresize_size_top) + up = left = -1; + } else if (cnr == prop_atoms.net_wm_moveresize_size_top) { cur = OB_CURSOR_NORTH; - else if (cnr == prop_atoms.net_wm_moveresize_size_topright) + up = -1; + } else if (cnr == prop_atoms.net_wm_moveresize_size_topright) { cur = OB_CURSOR_NORTHEAST; - else if (cnr == prop_atoms.net_wm_moveresize_size_right) + up = -1; + } else if (cnr == prop_atoms.net_wm_moveresize_size_right) cur = OB_CURSOR_EAST; else if (cnr == prop_atoms.net_wm_moveresize_size_bottomright) cur = OB_CURSOR_SOUTHEAST; else if (cnr == prop_atoms.net_wm_moveresize_size_bottom) cur = OB_CURSOR_SOUTH; - else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft) + else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft) { cur = OB_CURSOR_SOUTHWEST; - else if (cnr == prop_atoms.net_wm_moveresize_size_left) + left = -1; + } else if (cnr == prop_atoms.net_wm_moveresize_size_left) { cur = OB_CURSOR_WEST; - else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard) + left = -1; + } else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard) cur = OB_CURSOR_SOUTHEAST; else if (cnr == prop_atoms.net_wm_moveresize_move) cur = OB_CURSOR_MOVE;

@@ -172,8 +180,8 @@ /* these adjustments for the size_inc make resizing a terminal more

friendly. you essentially start the resize in the middle of the increment instead of at 0, so you have to move half an increment either way instead of a full increment one and 1 px the other. */ - start_x = x - (mv ? 0 : c->size_inc.width / 2); - start_y = y - (mv ? 0 : c->size_inc.height / 2); + start_x = x - (mv ? 0 : left * c->size_inc.width / 2); + start_y = y - (mv ? 0 : up * c->size_inc.height / 2); corner = cnr; button = b; key_resize_edge = -1;

@@ -476,12 +484,15 @@ static gboolean edge_warp_delay_func(gpointer data)

{ guint d; - d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE); - if (d != screen_desktop) screen_set_desktop(d, TRUE); + /* only fire every second time. so it's fast the first time, but slower + after that */ + if (edge_warp_odd) { + d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE); + if (d != screen_desktop) screen_set_desktop(d, TRUE); + } + edge_warp_odd = !edge_warp_odd; - edge_warp_dir = -1; - - return FALSE; /* don't repeat */ + return TRUE; /* do repeat ! */ } static void do_edge_warp(gint x, gint y)

@@ -515,13 +526,14 @@ g_free(a);

} if (dir != edge_warp_dir) { - if (dir == (ObDirection)-1) - cancel_edge_warp(); - else + cancel_edge_warp(); + if (dir != (ObDirection)-1) { + edge_warp_odd = TRUE; /* switch on the first timeout */ ob_main_loop_timeout_add(ob_main_loop, config_mouse_screenedgetime * 1000, edge_warp_delay_func, NULL, NULL, NULL); + } edge_warp_dir = dir; } }
M openbox/openbox.copenbox/openbox.c

@@ -42,7 +42,6 @@ #include "extensions.h"

#include "menuframe.h" #include "grab.h" #include "group.h" -#include "propwin.h" #include "config.h" #include "mainloop.h" #include "gettext.h"

@@ -301,7 +300,6 @@ window_startup(reconfigure);

sn_startup(reconfigure); screen_startup(reconfigure); grab_startup(reconfigure); - propwin_startup(reconfigure); group_startup(reconfigure); client_startup(reconfigure); dock_startup(reconfigure);

@@ -363,7 +361,6 @@ moveresize_shutdown(reconfigure);

dock_shutdown(reconfigure); client_shutdown(reconfigure); group_shutdown(reconfigure); - propwin_shutdown(reconfigure); grab_shutdown(reconfigure); screen_shutdown(reconfigure); focus_cycle_popup_shutdown(reconfigure);
M openbox/place.copenbox/place.c

@@ -316,9 +316,9 @@ Rect *r = sit->data;

if (r->width >= c->frame->area.width && r->height >= c->frame->area.height && - r->width > maxsize) + r->width * r->height > maxsize) { - maxsize = r->width; + maxsize = r->width * r->height; maxit = sit; } }
M openbox/prop.copenbox/prop.c

@@ -94,7 +94,7 @@ 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(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");
M openbox/prop.hopenbox/prop.h

@@ -132,7 +132,7 @@ 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_wm_user_time_window; */ Atom net_frame_extents; /* application protocols */
D openbox/propwin.c

@@ -1,127 +0,0 @@

-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - propwin.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 "propwin.h" -#include "openbox.h" -#include "client.h" -#include "debug.h" - -typedef struct _ObPropWin ObPropWin; -typedef struct _ObPropWinData ObPropWinData; - -struct _ObPropWinData -{ - GSList *clients; -}; - -struct _ObPropWin -{ - Window win; - ObPropWinData data[OB_NUM_PROPWIN_TYPES]; -}; - -/*! A hash table that maps a window to an ObPropWin */ -static GHashTable *propwin_map; - -static guint window_hash(Window *w) { return *w; } -static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } - -void propwin_startup(gboolean reconfig) -{ - if (!reconfig) - propwin_map = g_hash_table_new_full((GHashFunc)window_hash, - (GEqualFunc)window_comp, - NULL, - g_free); -} - -void propwin_shutdown(gboolean reconfig) -{ - if (!reconfig) - g_hash_table_destroy(propwin_map); - else - g_assert(g_hash_table_size(propwin_map) == 0); -} - -void propwin_add(Window win, ObPropWinType type, ObClient *client) -{ - ObPropWin *p; - - if (!win) return; - - g_assert(client); - g_assert(type < OB_NUM_PROPWIN_TYPES); - - p = g_hash_table_lookup(propwin_map, &win); - if (!p) { - p = g_new0(ObPropWin, 1); - p->win = win; - g_hash_table_insert(propwin_map, &p->win, p); - /* get property changes on this window */ - XSelectInput(ob_display, win, PropertyChangeMask); - } else - g_assert(g_slist_find(p->data[type].clients, client) == NULL); - - if (p->data[type].clients != NULL) - ob_debug("Client %s is using a property window 0x%x that is already " - "in use\n", client->title, win); - - /* add it to the clients list */ - p->data[type].clients = g_slist_prepend(p->data[type].clients, client); -} - -void propwin_remove(Window win, ObPropWinType type, ObClient *client) -{ - ObPropWin *p; - - if (!win) return; - - p = g_hash_table_lookup(propwin_map, &win); - g_assert(p); - - /* remove it to the clients list */ - g_assert(g_slist_find(p->data[type].clients, client) != NULL); - p->data[type].clients = g_slist_remove(p->data[type].clients, client); - - /* no more clients left for this type */ - if (p->data[type].clients == NULL) { - guint i; - gboolean none = TRUE; - - for (i = 0; i < OB_NUM_PROPWIN_TYPES; ++i) - if (p->data[i].clients != NULL) - none = FALSE; /* another type still has a client for this - window */ - - if (none) { - /* don't get events for this window any more */ - XSelectInput(ob_display, win, NoEventMask); - g_hash_table_remove(propwin_map, &win); - } - } -} - -GSList* propwin_get_clients(Window win, ObPropWinType type) -{ - ObPropWin *p = g_hash_table_lookup(propwin_map, &win); - if (p) - return p->data[type].clients; - else - return NULL; -}
D openbox/propwin.h

@@ -1,40 +0,0 @@

-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - - propwin.h for the Openbox window manager - Copyright (c) 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 __propwin_h -#define __propwin_h - -#include <glib.h> -#include <X11/Xlib.h> - -struct _ObClient; - -typedef enum { - OB_PROPWIN_USER_TIME, - OB_NUM_PROPWIN_TYPES -} ObPropWinType; - -void propwin_startup(gboolean reconfig); -void propwin_shutdown(gboolean reconfig); - -void propwin_add(Window win, ObPropWinType type, struct _ObClient *client); -void propwin_remove(Window win, ObPropWinType type, struct _ObClient *client); - -GSList* propwin_get_clients(Window win, ObPropWinType type); - -#endif
M openbox/resist.copenbox/resist.c

@@ -21,97 +21,114 @@ #include "client.h"

#include "frame.h" #include "stacking.h" #include "screen.h" +#include "dock.h" #include "config.h" #include "parser/parse.h" #include <glib.h> -void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) +static gboolean resist_move_window(Rect window, + Rect target, gint resist, + gint *x, gint *y) { - GList *it; gint l, t, r, b; /* requested edges */ gint cl, ct, cr, cb; /* current edges */ gint w, h; /* current size */ - ObClient *snapx = NULL, *snapy = NULL; - - if (!resist) return; - - frame_client_gravity(c->frame, x, y); + gint tl, tt, tr, tb; /* 1 past the target's edges on each side */ + gboolean snapx = 0, snapy = 0; - w = c->frame->area.width; - h = c->frame->area.height; + w = window.width; + h = window.height; l = *x; t = *y; r = l + w - 1; b = t + h - 1; - cl = RECT_LEFT(c->frame->area); - ct = RECT_TOP(c->frame->area); - cr = RECT_RIGHT(c->frame->area); - cb = RECT_BOTTOM(c->frame->area); + cl = RECT_LEFT(window); + ct = RECT_TOP(window); + cr = RECT_RIGHT(window); + cb = RECT_BOTTOM(window); + + tl = RECT_LEFT(target) - 1; + tt = RECT_TOP(target) - 1; + tr = RECT_RIGHT(target) + 1; + tb = RECT_BOTTOM(target) + 1; + + /* snapx and snapy ensure that the window snaps to the top-most + window edge available, without going all the way from + bottom-to-top in the stacking list + */ + if (!snapx) { + if (ct < tb && cb > tt) { + if (cl >= tr && l < tr && l >= tr - resist) + *x = tr, snapx = TRUE; + else if (cr <= tl && r > tl && + r <= tl + resist) + *x = tl - w + 1, snapx = TRUE; + if (snapx) { + /* try to corner snap to the window */ + if (ct > tt && t <= tt && + t > tt - resist) + *y = tt + 1, snapy = TRUE; + else if (cb < tb && b >= tb && + b < tb + resist) + *y = tb - h, snapy = TRUE; + } + } + } + if (!snapy) { + if (cl < tr && cr > tl) { + if (ct >= tb && t < tb && t >= tb - resist) + *y = tb, snapy = TRUE; + else if (cb <= tt && b > tt && + b <= tt + resist) + *y = tt - h + 1, snapy = TRUE; + if (snapy) { + /* try to corner snap to the window */ + if (cl > tl && l <= tl && + l > tl - resist) + *x = tl + 1, snapx = TRUE; + else if (cr < tr && r >= tr && + r < tr + resist) + *x = tr - w, snapx = TRUE; + } + } + } + + return snapx && snapy; +} + +void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) +{ + GList *it; + Rect dock_area; + + if (!resist) return; + + frame_client_gravity(c->frame, x, y); + for (it = stacking_list; it; it = g_list_next(it)) { ObClient *target; - gint tl, tt, tr, tb; /* 1 past the target's edges on each side */ if (!WINDOW_IS_CLIENT(it->data)) continue; target = it->data; /* don't snap to self or non-visibles */ - if (!target->frame->visible || target == c) continue; + if (!target->frame->visible || target == c) + continue; /* don't snap to windows set to below and skip_taskbar (desklets) */ - if (target->below && !c->below && target->skip_taskbar) continue; - - tl = RECT_LEFT(target->frame->area) - 1; - tt = RECT_TOP(target->frame->area) - 1; - tr = RECT_RIGHT(target->frame->area) + 1; - tb = RECT_BOTTOM(target->frame->area) + 1; - - /* snapx and snapy ensure that the window snaps to the top-most - window edge available, without going all the way from - bottom-to-top in the stacking list - */ - if (snapx == NULL) { - if (ct < tb && cb > tt) { - if (cl >= tr && l < tr && l >= tr - resist) - *x = tr, snapx = target; - else if (cr <= tl && r > tl && - r <= tl + resist) - *x = tl - w + 1, snapx = target; - if (snapx != NULL) { - /* try to corner snap to the window */ - if (ct > tt && t <= tt && - t > tt - resist) - *y = tt + 1, snapy = target; - else if (cb < tb && b >= tb && - b < tb + resist) - *y = tb - h, snapy = target; - } - } - } - if (snapy == NULL) { - if (cl < tr && cr > tl) { - if (ct >= tb && t < tb && t >= tb - resist) - *y = tb, snapy = target; - else if (cb <= tt && b > tt && - b <= tt + resist) - *y = tt - h + 1, snapy = target; - if (snapy != NULL) { - /* try to corner snap to the window */ - if (cl > tl && l <= tl && - l > tl - resist) - *x = tl + 1, snapx = target; - else if (cr < tr && r >= tr && - r < tr + resist) - *x = tr - w, snapx = target; - } - } - } + if (target->below && !c->below && target->skip_taskbar) + continue; - if (snapx && snapy) break; + if (resist_move_window(c->frame->area, target->frame->area, + resist, x, y)) + break; } + dock_get_area(&dock_area); + resist_move_window(c->frame->area, dock_area, resist, x, y); frame_frame_gravity(c->frame, x, y); }

@@ -191,101 +208,116 @@

frame_frame_gravity(c->frame, x, y); } +static gboolean resist_size_window(Rect window, Rect target, gint resist, + gint *w, gint *h, ObDirection dir) +{ + gint l, t, r, b; /* my left, top, right and bottom sides */ + gint tl, tt, tr, tb; /* target's left, top, right and bottom bottom sides*/ + gint dlt, drb; /* my destination left/top and right/bottom sides */ + gboolean snapx = 0, snapy = 0; + gint orgw, orgh; + + l = RECT_LEFT(window); + t = RECT_TOP(window); + r = RECT_RIGHT(window); + b = RECT_BOTTOM(window); + + orgw = window.width; + orgh = window.height; + + tl = RECT_LEFT(target); + tt = RECT_TOP(target); + tr = RECT_RIGHT(target); + tb = RECT_BOTTOM(target); + + if (!snapx) { + /* horizontal snapping */ + if (t < tb && b > tt) { + switch (dir) { + case OB_DIRECTION_EAST: + case OB_DIRECTION_NORTHEAST: + case OB_DIRECTION_SOUTHEAST: + case OB_DIRECTION_NORTH: + case OB_DIRECTION_SOUTH: + dlt = l; + drb = r + *w - orgw; + if (r < tl && drb >= tl && + drb < tl + resist) + *w = tl - l, snapx = TRUE; + break; + case OB_DIRECTION_WEST: + case OB_DIRECTION_NORTHWEST: + case OB_DIRECTION_SOUTHWEST: + dlt = l - *w + orgw; + drb = r; + if (l > tr && dlt <= tr && + dlt > tr - resist) + *w = r - tr, snapx = TRUE; + break; + } + } + } + + if (!snapy) { + /* vertical snapping */ + if (l < tr && r > tl) { + switch (dir) { + case OB_DIRECTION_SOUTH: + case OB_DIRECTION_SOUTHWEST: + case OB_DIRECTION_SOUTHEAST: + case OB_DIRECTION_EAST: + case OB_DIRECTION_WEST: + dlt = t; + drb = b + *h - orgh; + if (b < tt && drb >= tt && + drb < tt + resist) + *h = tt - t, snapy = TRUE; + break; + case OB_DIRECTION_NORTH: + case OB_DIRECTION_NORTHWEST: + case OB_DIRECTION_NORTHEAST: + dlt = t - *h + orgh; + drb = b; + if (t > tb && dlt <= tb && + dlt > tb - resist) + *h = b - tb, snapy = TRUE; + break; + } + } + } + + /* snapped both ways */ + return snapx && snapy; +} + void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h, ObDirection dir) { GList *it; ObClient *target; /* target */ - gint l, t, r, b; /* my left, top, right and bottom sides */ - gint dlt, drb; /* my destination left/top and right/bottom sides */ - gint tl, tt, tr, tb; /* target's left, top, right and bottom bottom sides*/ - gint incw, inch; - ObClient *snapx = NULL, *snapy = NULL; + Rect dock_area; if (!resist) return; - incw = c->size_inc.width; - inch = c->size_inc.height; - - l = RECT_LEFT(c->frame->area); - r = RECT_RIGHT(c->frame->area); - t = RECT_TOP(c->frame->area); - b = RECT_BOTTOM(c->frame->area); - for (it = stacking_list; it; it = g_list_next(it)) { if (!WINDOW_IS_CLIENT(it->data)) continue; target = it->data; /* don't snap to invisibles or ourself */ - if (!target->frame->visible || target == c) continue; + if (!target->frame->visible || target == c) + continue; /* don't snap to windows set to below and skip_taskbar (desklets) */ - if (target->below && !c->below && target->skip_taskbar) continue; - - tl = RECT_LEFT(target->frame->area); - tr = RECT_RIGHT(target->frame->area); - tt = RECT_TOP(target->frame->area); - tb = RECT_BOTTOM(target->frame->area); - - if (snapx == NULL) { - /* horizontal snapping */ - if (t < tb && b > tt) { - switch (dir) { - case OB_DIRECTION_EAST: - case OB_DIRECTION_NORTHEAST: - case OB_DIRECTION_SOUTHEAST: - case OB_DIRECTION_NORTH: - case OB_DIRECTION_SOUTH: - dlt = l; - drb = r + *w - c->frame->area.width; - if (r < tl && drb >= tl && - drb < tl + resist) - *w = tl - l, snapx = target; - break; - case OB_DIRECTION_WEST: - case OB_DIRECTION_NORTHWEST: - case OB_DIRECTION_SOUTHWEST: - dlt = l - *w + c->frame->area.width; - drb = r; - if (l > tr && dlt <= tr && - dlt > tr - resist) - *w = r - tr, snapx = target; - break; - } - } - } + if (target->below && !c->below && target->skip_taskbar) + continue; - if (snapy == NULL) { - /* vertical snapping */ - if (l < tr && r > tl) { - switch (dir) { - case OB_DIRECTION_SOUTH: - case OB_DIRECTION_SOUTHWEST: - case OB_DIRECTION_SOUTHEAST: - case OB_DIRECTION_EAST: - case OB_DIRECTION_WEST: - dlt = t; - drb = b + *h - c->frame->area.height; - if (b < tt && drb >= tt && - drb < tt + resist) - *h = tt - t, snapy = target; - break; - case OB_DIRECTION_NORTH: - case OB_DIRECTION_NORTHWEST: - case OB_DIRECTION_NORTHEAST: - dlt = t - *h + c->frame->area.height; - drb = b; - if (t > tb && dlt <= tb && - dlt > tb - resist) - *h = b - tb, snapy = target; - break; - } - } - } - - /* snapped both ways */ - if (snapx && snapy) break; + if (resist_size_window(c->frame->area, target->frame->area, + resist, w, h, dir)) + break; } + dock_get_area(&dock_area); + resist_size_window(c->frame->area, dock_area, + resist, w, h, dir); } void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h,
M openbox/screen.copenbox/screen.c

@@ -26,6 +26,7 @@ #include "grab.h"

#include "startupnotify.h" #include "moveresize.h" #include "config.h" +#include "mainloop.h" #include "screen.h" #include "client.h" #include "session.h"

@@ -53,6 +54,7 @@

static gboolean screen_validate_layout(ObDesktopLayout *l); static gboolean replace_wm(); static void screen_tell_ksplash(); +static void screen_fallback_focus(); guint screen_num_desktops; guint screen_num_monitors;

@@ -73,7 +75,7 @@ static GSList *struts_left = NULL;

static GSList *struts_right = NULL; static GSList *struts_bottom = NULL; -static ObPagerPopup *desktop_cycle_popup; +static ObPagerPopup *desktop_popup; static gboolean replace_wm() {

@@ -107,22 +109,7 @@ if (xerror_occured)

current_wm_sn_owner = None; } - { - /* Generate a timestamp */ - XEvent event; - - XSelectInput(ob_display, screen_support_win, PropertyChangeMask); - - XChangeProperty(ob_display, screen_support_win, - prop_atoms.wm_class, prop_atoms.string, - 8, PropModeAppend, NULL, 0); - XWindowEvent(ob_display, screen_support_win, - PropertyChangeMask, &event); - - XSelectInput(ob_display, screen_support_win, NoEventMask); - - timestamp = event.xproperty.time; - } + timestamp = event_get_server_time(); XSetSelectionOwner(ob_display, wm_sn_atom, screen_support_win, timestamp);

@@ -172,12 +159,14 @@ gulong *supported;

/* create the netwm support window */ attrib.override_redirect = TRUE; + attrib.event_mask = PropertyChangeMask; screen_support_win = XCreateWindow(ob_display, RootWindow(ob_display, ob_screen), -100, -100, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, - CWOverrideRedirect, &attrib); + CWEventMask | CWOverrideRedirect, + &attrib); XMapWindow(ob_display, screen_support_win); XLowerWindow(ob_display, screen_support_win);

@@ -283,7 +272,9 @@ supported[i++] = prop_atoms.net_wm_state_demands_attention;

supported[i++] = prop_atoms.net_moveresize_window; supported[i++] = prop_atoms.net_wm_moveresize; supported[i++] = prop_atoms.net_wm_user_time; +/* supported[i++] = prop_atoms.net_wm_user_time_window; +*/ supported[i++] = prop_atoms.net_frame_extents; supported[i++] = prop_atoms.net_request_frame_extents; supported[i++] = prop_atoms.net_restack_window;

@@ -353,12 +344,12 @@ gchar **names = NULL;

guint32 d; gboolean namesexist = FALSE; - desktop_cycle_popup = pager_popup_new(FALSE); - pager_popup_height(desktop_cycle_popup, POPUP_HEIGHT); + desktop_popup = pager_popup_new(FALSE); + pager_popup_height(desktop_popup, POPUP_HEIGHT); if (reconfig) { /* update the pager popup's width */ - pager_popup_text_width_to_strings(desktop_cycle_popup, + pager_popup_text_width_to_strings(desktop_popup, screen_desktop_names, screen_num_desktops); return;

@@ -441,7 +432,7 @@ }

void screen_shutdown(gboolean reconfig) { - pager_popup_free(desktop_cycle_popup); + pager_popup_free(desktop_popup); if (reconfig) return;

@@ -545,13 +536,52 @@ if (screen_desktop >= screen_num_desktops)

screen_set_desktop(num - 1, TRUE); } -void screen_set_desktop(guint num, gboolean dofocus) +static void screen_fallback_focus() { ObClient *c; + gboolean allow_omni; + + /* only allow omnipresent windows to get focus on desktop change if + an omnipresent window is already focused (it'll keep focus probably, but + maybe not depending on mouse-focus options) */ + allow_omni = focus_client && (client_normal(focus_client) && + focus_client->desktop == DESKTOP_ALL); + + /* the client moved there already so don't move focus. prevent flicker + on sendtodesktop + follow */ + if (focus_client && focus_client->desktop == screen_desktop) + return; + + /* have to try focus here because when you leave an empty desktop + there is no focus out to watch for. also, we have different rules + here. we always allow it to look under the mouse pointer if + config_focus_last is FALSE + + do this before hiding the windows so if helper windows are coming + with us, they don't get hidden + */ + if ((c = focus_fallback(TRUE, !config_focus_last, allow_omni, + !allow_omni))) + { + /* only do the flicker reducing stuff ahead of time if we are going + to call xsetinputfocus on the window ourselves. otherwise there is + no guarantee the window will actually take focus.. */ + if (c->can_focus) { + /* reduce flicker by hiliting now rather than waiting for the + server FocusIn event */ + frame_adjust_focus(c->frame, TRUE); + /* do this here so that if you switch desktops to a window with + helper windows then the helper windows won't flash */ + client_bring_helper_windows(c); + } + } +} + +void screen_set_desktop(guint num, gboolean dofocus) +{ GList *it; guint old; gulong ignore_start; - gboolean allow_omni; g_assert(num < screen_num_desktops);

@@ -583,39 +613,7 @@ client_show(c);

} } - /* only allow omnipresent windows to get focus on desktop change if - an omnipresent window is already focused (it'll keep focus probably, but - maybe not depending on mouse-focus options) */ - allow_omni = focus_client && (client_normal(focus_client) && - focus_client->desktop == DESKTOP_ALL); - - /* the client moved there already so don't move focus. prevent flicker - on sendtodesktop + follow */ - if (focus_client && focus_client->desktop == screen_desktop) - dofocus = FALSE; - - /* have to try focus here because when you leave an empty desktop - there is no focus out to watch for. also, we have different rules - here. we always allow it to look under the mouse pointer if - config_focus_last is FALSE - - do this before hiding the windows so if helper windows are coming - with us, they don't get hidden - */ - if (dofocus && (c = focus_fallback(TRUE, !config_focus_last, allow_omni))) - { - /* only do the flicker reducing stuff ahead of time if we are going - to call xsetinputfocus on the window ourselves. otherwise there is - no guarantee the window will actually take focus.. */ - if (c->can_focus) { - /* reduce flicker by hiliting now rather than waiting for the - server FocusIn event */ - frame_adjust_focus(c->frame, TRUE); - /* do this here so that if you switch desktops to a window with - helper windows then the helper windows won't flash */ - client_bring_helper_windows(c); - } - } + if (dofocus) screen_fallback_focus(); /* hide windows from bottom to top */ for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {

@@ -629,10 +627,18 @@ event_end_ignore_all_enters(ignore_start);

if (event_curtime != CurrentTime) screen_desktop_user_time = event_curtime; + + if (ob_state() == OB_STATE_RUNNING) + screen_show_desktop_popup(screen_desktop); } void screen_add_desktop(gboolean current) { + gulong ignore_start; + + /* ignore enter events caused by this */ + ignore_start = event_start_ignore_all_enters(); + screen_set_num_desktops(screen_num_desktops+1); /* move all the clients over */

@@ -651,14 +657,20 @@ client_set_desktop(c, c->desktop+1, FALSE, TRUE);

} } } + + event_end_ignore_all_enters(ignore_start); } void screen_remove_desktop(gboolean current) { guint rmdesktop, movedesktop; GList *it, *stacking_copy; + gulong ignore_start; if (screen_num_desktops <= 1) return; + + /* ignore enter events caused by this */ + ignore_start = event_start_ignore_all_enters(); /* what desktop are we removing and moving to? */ if (current)

@@ -696,15 +708,15 @@ }

} } - /* act like we're changing desktops */ + /* fallback focus like we're changing desktops */ if (screen_desktop < screen_num_desktops - 1) { - gint d = screen_desktop; - screen_desktop = screen_last_desktop; - screen_set_desktop(d, TRUE); + screen_fallback_focus(); ob_debug("fake desktop change\n"); } screen_set_num_desktops(screen_num_desktops-1); + + event_end_ignore_all_enters(ignore_start); } static void get_row_col(guint d, guint *r, guint *c)

@@ -815,25 +827,34 @@ g_assert_not_reached();

return 0; } -void screen_desktop_popup(guint d, gboolean show) +static gboolean hide_desktop_popup_func(gpointer data) +{ + pager_popup_hide(desktop_popup); + return FALSE; /* don't repeat */ +} + +void screen_show_desktop_popup(guint d) { Rect *a; - if (!show) { - pager_popup_hide(desktop_cycle_popup); - } else { - a = screen_physical_area_active(); - pager_popup_position(desktop_cycle_popup, CenterGravity, - a->x + a->width / 2, a->y + a->height / 2); - pager_popup_icon_size_multiplier(desktop_cycle_popup, - (screen_desktop_layout.columns / - screen_desktop_layout.rows) / 2, - (screen_desktop_layout.rows/ - screen_desktop_layout.columns) / 2); - pager_popup_max_width(desktop_cycle_popup, - MAX(a->width/3, POPUP_WIDTH)); - pager_popup_show(desktop_cycle_popup, screen_desktop_names[d], 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); + + 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, NULL, NULL, NULL); } guint screen_find_desktop(guint from, ObDirection dir,

@@ -942,30 +963,6 @@ }

return d; } -guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear, - gboolean dialog, gboolean done, gboolean cancel) -{ - static guint d = (guint)-1; - guint ret; - - if (d == (guint)-1) - d = screen_desktop; - - if ((!cancel && !done) || !dialog) - d = screen_find_desktop(d, dir, wrap, linear); - - if (dialog && !cancel && !done) - screen_desktop_popup(d, TRUE); - else - screen_desktop_popup(0, FALSE); - ret = d; - - if (!dialog || cancel || done) - d = (guint)-1; - - return ret; -} - static gboolean screen_validate_layout(ObDesktopLayout *l) { if (l->columns == 0 && l->rows == 0) /* both 0's is bad data.. */

@@ -1092,7 +1089,7 @@ screen_desktop_names);

} /* resize the pager for these names */ - pager_popup_text_width_to_strings(desktop_cycle_popup, + pager_popup_text_width_to_strings(desktop_popup, screen_desktop_names, screen_num_desktops); }

@@ -1142,7 +1139,7 @@ }

else if (!show_only) { ObClient *c; - if ((c = focus_fallback(TRUE, FALSE, TRUE))) { + if ((c = focus_fallback(TRUE, FALSE, TRUE, FALSE))) { /* only do the flicker reducing stuff ahead of time if we are going to call xsetinputfocus on the window ourselves. otherwise there is no guarantee the window will actually take focus.. */

@@ -1555,7 +1552,9 @@ {

Rect *a; gint x, y; - if (focus_client) + if (moveresize_client) + a = screen_physical_area_monitor(client_monitor(focus_client)); + else if (focus_client) a = screen_physical_area_monitor(client_monitor(focus_client)); else { Rect mon;
M openbox/screen.hopenbox/screen.h

@@ -72,15 +72,11 @@ void screen_add_desktop(gboolean current);

/*! Remove a desktop, either at the end or the current desktop */ void screen_remove_desktop(gboolean current); -/*! Interactively change desktops */ -guint screen_cycle_desktop(ObDirection dir, gboolean wrap, gboolean linear, - gboolean dialog, gboolean done, gboolean cancel); - guint screen_find_desktop(guint from, ObDirection dir, gboolean wrap, gboolean linear); -/*! Show/hide the desktop popup (pager) for the given desktop */ -void screen_desktop_popup(guint d, gboolean show); +/*! Show the desktop popup/notification */ +void screen_show_desktop_popup(guint d); /*! Shows and focuses the desktop and hides all the client windows, or returns to the normal state, showing client windows.
M po/no.popo/no.po

@@ -5,7 +5,7 @@ #

# Michael Kjelbergvik Thung <postlogic@switch-case.org>, 2007. msgid "" msgstr "" -"Project-Id-Version: openbox 3.4.2\n" +"Project-Id-Version: openbox 3.4.3\n" "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n" "POT-Creation-Date: 2007-07-22 08:25-0400\n" "PO-Revision-Date: 2007-05-20 18:41+0200\n"

@@ -31,15 +31,15 @@ msgstr "Gå dit..."

#: openbox/client_list_combined_menu.c:98 msgid "Manage desktops" -msgstr "" +msgstr "Behandle skrivebord" #: openbox/client_list_combined_menu.c:99 openbox/client_list_menu.c:152 msgid "_Add new desktop" -msgstr "" +msgstr "_Nytt skrivebord" #: openbox/client_list_combined_menu.c:100 openbox/client_list_menu.c:153 msgid "_Remove last desktop" -msgstr "" +msgstr "_Fjern siste skrivebord" #: openbox/client_list_combined_menu.c:146 msgid "Windows"
M po/zh_TW.popo/zh_TW.po

@@ -5,10 +5,10 @@ # Wei-Lun Chao <chaoweilun@gmail.com>, 2006, 07.

# msgid "" msgstr "" -"Project-Id-Version: openbox 3.4.2\n" +"Project-Id-Version: openbox 3.4.3\n" "Report-Msgid-Bugs-To: http://bugzilla.icculus.org\n" "POT-Creation-Date: 2007-07-22 08:25-0400\n" -"PO-Revision-Date: 2007-05-23 16:22+0200\n" +"PO-Revision-Date: 2007-07-23 23:22+0200\n" "Last-Translator: Wei-Lun Chao <chaoweilun@gmail.com>\n" "Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n" "MIME-Version: 1.0\n"

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

#: openbox/actions/execute.c:88 #, c-format msgid "Failed to convert the path '%s' from utf8" -msgstr "從 utf8 轉換路徑「%s」時失敗" +msgstr "轉換路徑「%s」自 utf8 時失敗" #: openbox/actions/execute.c:97 openbox/actions/execute.c:115 #, c-format

@@ -32,15 +32,15 @@ msgstr "到那裏去…"

#: openbox/client_list_combined_menu.c:98 msgid "Manage desktops" -msgstr "" +msgstr "管理桌面" #: openbox/client_list_combined_menu.c:99 openbox/client_list_menu.c:152 msgid "_Add new desktop" -msgstr "" +msgstr "加入新桌面(_A)" #: openbox/client_list_combined_menu.c:100 openbox/client_list_menu.c:153 msgid "_Remove last desktop" -msgstr "" +msgstr "移除尾端桌面(_R)" #: openbox/client_list_combined_menu.c:146 msgid "Windows"
M render/theme.crender/theme.c

@@ -186,7 +186,9 @@ theme->handle_height = 6;

if (!read_int(db, "padding.width", &theme->paddingx) || theme->paddingx < 0 || theme->paddingx > 100) theme->paddingx = 3; - theme->paddingy = theme->paddingx; + if (!read_int(db, "padding.height", &theme->paddingy) || + theme->paddingy < 0 || theme->paddingy > 100) + theme->paddingy = theme->paddingx; if (!read_int(db, "border.width", &theme->fbwidth) || theme->fbwidth < 0 || theme->fbwidth > 100) theme->fbwidth = 1;