all repos — openbox @ ad812e6299223efb0cb4faee03ce99870e5c7ce5

openbox fork - make it a bit more like ryudo

Add a focus option, unfocusOnLeave that removes focus from a window when the pointer leaves it

This uses the same delay to unfocus as is used for focusing on enter
Dana Jansens danakj@orodu.net
commit

ad812e6299223efb0cb4faee03ce99870e5c7ce5

parent

965ed8907a5dd81d5ffbc93b67a672fa78833854

6 files changed, 89 insertions(+), 12 deletions(-)

jump to
M data/rc.xsddata/rc.xsd

@@ -61,6 +61,7 @@ <xsd:element minOccurs="0" name="followMouse" type="ob:bool"/>

<xsd:element minOccurs="0" name="underMouse" type="ob:bool"/> <xsd:element minOccurs="0" name="focusDelay" type="xsd:integer"/> <xsd:element minOccurs="0" name="raiseOnFocus" type="ob:bool"/> + <xsd:element minOccurs="0" name="unfocusOnLeave" type="ob:bool"/> </xsd:all> </xsd:complexType> <xsd:complexType name="placement">
M openbox/actions.copenbox/actions.c

@@ -408,13 +408,19 @@ don't do this if there is a grab on the pointer. enter events

are ignored during a grab, so don't force fake ones when they should be ignored */ - if ((c = client_under_pointer()) && c != data->client && - !grab_on_pointer()) - { - ob_debug_type(OB_DEBUG_FOCUS, - "Generating fake enter because we did a " - "mouse-event action"); - event_enter_client(c); + if (!grab_on_pointer()) { + if ((c = client_under_pointer()) && c != data->client) { + ob_debug_type(OB_DEBUG_FOCUS, + "Generating fake enter because we did a " + "mouse-event action"); + event_enter_client(c); + } + else if (!c && c != data->client) { + ob_debug_type(OB_DEBUG_FOCUS, + "Generating fake leave because we did a " + "mouse-event action"); + event_enter_client(data->client); + } } } else if (!data->button && !config_focus_under_mouse)
M openbox/config.copenbox/config.c

@@ -34,6 +34,7 @@ guint config_focus_delay;

gboolean config_focus_raise; gboolean config_focus_last; gboolean config_focus_under_mouse; +gboolean config_unfocus_leave; ObPlacePolicy config_place_policy; gboolean config_place_center;

@@ -504,6 +505,8 @@ if ((n = obt_parse_find_node(node, "focusLast")))

config_focus_last = obt_parse_node_bool(n); if ((n = obt_parse_find_node(node, "underMouse"))) config_focus_under_mouse = obt_parse_node_bool(n); + if ((n = obt_parse_find_node(node, "unfocusOnLeave"))) + config_unfocus_leave = obt_parse_node_bool(n); } static void parse_placement(xmlNodePtr node, gpointer d)

@@ -926,6 +929,7 @@ config_focus_delay = 0;

config_focus_raise = FALSE; config_focus_last = TRUE; config_focus_under_mouse = FALSE; + config_unfocus_leave = FALSE; obt_parse_register(i, "focus", parse_focus, NULL);
M openbox/config.hopenbox/config.h

@@ -73,6 +73,9 @@ extern gboolean config_focus_last;

/*! Try keep focus on the window under the mouse when the mouse is not moving */ extern gboolean config_focus_under_mouse; +/*! Remove focus from windows when the mouse leaves them + */ +extern gboolean config_unfocus_leave; /*! The algorithm to use for placing new windows */ extern ObPlacePolicy config_place_policy;
M openbox/event.copenbox/event.c

@@ -97,6 +97,7 @@

static void focus_delay_dest(gpointer data); static gboolean focus_delay_cmp(gconstpointer d1, gconstpointer d2); static gboolean focus_delay_func(gpointer data); +static gboolean unfocus_delay_func(gpointer data); static void focus_delay_client_dest(ObClient *client, gpointer data); Time event_curtime = CurrentTime;

@@ -845,6 +846,41 @@ }

} } +void event_leave_client(ObClient *client) +{ + g_assert(config_focus_follow); + + if (is_enter_focus_event_ignored(event_curserial)) { + ob_debug_type(OB_DEBUG_FOCUS, "Ignoring leave event with serial %lu\n" + "on client 0x%x", event_curserial, client->window); + return; + } + + if (client == focus_client) { + if (config_focus_delay) { + ObFocusDelayData *data; + + obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); + + data = g_new(ObFocusDelayData, 1); + data->client = client; + data->time = event_curtime; + data->serial = event_curserial; + + obt_main_loop_timeout_add(ob_main_loop, + config_focus_delay * 1000, + unfocus_delay_func, + data, focus_delay_cmp, focus_delay_dest); + } else { + ObFocusDelayData data; + data.client = client; + data.time = event_curtime; + data.serial = event_curserial; + unfocus_delay_func(&data); + } + } +} + static gboolean *context_to_button(ObFrame *f, ObFrameContext con, gboolean press) { if (press) {

@@ -1014,15 +1050,18 @@ e->xcrossing.mode,

e->xcrossing.detail, (client?client->window:0)); if (grab_on_keyboard()) break; - if (config_focus_follow && config_focus_delay && + if (config_focus_follow && /* leave inferior events can happen when the mouse goes onto the window's border and then into the window before the delay is up */ e->xcrossing.detail != NotifyInferior) { - obt_main_loop_timeout_remove_data(ob_main_loop, - focus_delay_func, - client, FALSE); + if (config_focus_delay) + obt_main_loop_timeout_remove_data(ob_main_loop, + focus_delay_func, + client, FALSE); + if (config_unfocus_leave) + event_leave_client(client); } break; default:

@@ -1069,8 +1108,13 @@ e->xcrossing.mode,

e->xcrossing.detail, e->xcrossing.serial, (client?client->window:0)); - if (config_focus_follow) + if (config_focus_follow) { + if (config_focus_delay) + obt_main_loop_timeout_remove_data(ob_main_loop, + unfocus_delay_func, + client, FALSE); event_enter_client(client); + } } break; default:

@@ -1956,10 +2000,24 @@ event_curtime = old;

return FALSE; /* no repeat */ } +static gboolean unfocus_delay_func(gpointer data) +{ + ObFocusDelayData *d = data; + Time old = event_curtime; + + event_curtime = d->time; + event_curserial = d->serial; + focus_nothing(); + event_curtime = old; + return FALSE; /* no repeat */ +} + static void focus_delay_client_dest(ObClient *client, gpointer data) { obt_main_loop_timeout_remove_data(ob_main_loop, focus_delay_func, client, FALSE); + obt_main_loop_timeout_remove_data(ob_main_loop, unfocus_delay_func, + client, FALSE); } void event_halt_focus_delay(void)

@@ -1967,6 +2025,7 @@ {

/* ignore all enter events up till the event which caused this to occur */ if (event_curserial) event_ignore_enter_range(1, event_curserial); obt_main_loop_timeout_remove(ob_main_loop, focus_delay_func); + obt_main_loop_timeout_remove(ob_main_loop, unfocus_delay_func); } gulong event_start_ignore_all_enters(void)
M openbox/event.hopenbox/event.h

@@ -40,6 +40,10 @@ /*! Make as if the mouse just entered the client, use only when using focus

follows mouse */ void event_enter_client(struct _ObClient *client); +/*! Make as if the mouse just left the client, use only when using focus + follows mouse */ +void event_leave_client(struct _ObClient *client); + /*! Make mouse focus not move at all from the stuff that happens between these two function calls. */ gulong event_start_ignore_all_enters(void);