summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Jansens <danakj@orodu.net>2009-12-17 16:20:03 -0500
committerDana Jansens <danakj@orodu.net>2009-12-18 11:40:00 -0500
commitad812e6299223efb0cb4faee03ce99870e5c7ce5 (patch)
treee4054f2eab685827fcb7569ff59b686ef4fd6793
parent965ed8907a5dd81d5ffbc93b67a672fa78833854 (diff)
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
-rw-r--r--data/rc.xsd1
-rw-r--r--openbox/actions.c20
-rw-r--r--openbox/config.c4
-rw-r--r--openbox/config.h3
-rw-r--r--openbox/event.c69
-rw-r--r--openbox/event.h4
6 files changed, 89 insertions, 12 deletions
diff --git a/data/rc.xsd b/data/rc.xsd
index 499b81c9..06286426 100644
--- a/data/rc.xsd
+++ b/data/rc.xsd
@@ -61,6 +61,7 @@
<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">
diff --git a/openbox/actions.c b/openbox/actions.c
index 78546361..5d47b33f 100644
--- a/openbox/actions.c
+++ b/openbox/actions.c
@@ -408,13 +408,19 @@ void actions_client_move(ObActionsData *data, gboolean start)
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)
diff --git a/openbox/config.c b/openbox/config.c
index 0d28be2c..33fadeb7 100644
--- a/openbox/config.c
+++ b/openbox/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 @@ static void parse_focus(xmlNodePtr node, gpointer d)
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 @@ void config_startup(ObtParseInst *i)
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);
diff --git a/openbox/config.h b/openbox/config.h
index d9e897a1..18c97ede 100644
--- a/openbox/config.h
+++ b/openbox/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;
diff --git a/openbox/event.c b/openbox/event.c
index 63f23ff9..1b7b7739 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -97,6 +97,7 @@ static void event_ignore_enter_range(gulong start, gulong end);
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_enter_client(ObClient *client)
}
}
+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 @@ static void event_handle_client(ObClient *client, XEvent *e)
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 @@ static void event_handle_client(ObClient *client, XEvent *e)
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 @@ static gboolean focus_delay_func(gpointer data)
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 @@ void event_halt_focus_delay(void)
/* 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)
diff --git a/openbox/event.h b/openbox/event.h
index 4fd72865..4a8d7901 100644
--- a/openbox/event.h
+++ b/openbox/event.h
@@ -40,6 +40,10 @@ void event_shutdown(gboolean reconfig);
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);