re-add focus follows mouse handling
This commit is contained in:
parent
eec762ea8f
commit
8e5a831e27
|
@ -21,7 +21,6 @@
|
||||||
int handle_key_press(void *ignored, xcb_connection_t *conn,
|
int handle_key_press(void *ignored, xcb_connection_t *conn,
|
||||||
xcb_key_press_event_t *event);
|
xcb_key_press_event_t *event);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/**
|
/**
|
||||||
* When the user moves the mouse pointer onto a window, this callback gets
|
* When the user moves the mouse pointer onto a window, this callback gets
|
||||||
* called.
|
* called.
|
||||||
|
@ -30,6 +29,7 @@ int handle_key_press(void *ignored, xcb_connection_t *conn,
|
||||||
int handle_enter_notify(void *ignored, xcb_connection_t *conn,
|
int handle_enter_notify(void *ignored, xcb_connection_t *conn,
|
||||||
xcb_enter_notify_event_t *event);
|
xcb_enter_notify_event_t *event);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* When the user moves the mouse but does not change the active window
|
* When the user moves the mouse but does not change the active window
|
||||||
* (e.g. when having no windows opened but moving mouse on the root screen
|
* (e.g. when having no windows opened but moving mouse on the root screen
|
||||||
|
|
|
@ -36,6 +36,7 @@ while (0)
|
||||||
|
|
||||||
int min(int a, int b);
|
int min(int a, int b);
|
||||||
int max(int a, int b);
|
int max(int a, int b);
|
||||||
|
bool rect_contains(Rect rect, uint32_t x, uint32_t y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates *destination with new_value and returns true if it was changed or false
|
* Updates *destination with new_value and returns true if it was changed or false
|
||||||
|
|
|
@ -486,6 +486,7 @@ workspace_name:
|
||||||
assign:
|
assign:
|
||||||
TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target
|
TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
printf("assignment of %s\n", $<string>3);
|
printf("assignment of %s\n", $<string>3);
|
||||||
|
|
||||||
struct Assignment *new = $<assignment>6;
|
struct Assignment *new = $<assignment>6;
|
||||||
|
@ -493,29 +494,36 @@ assign:
|
||||||
printf(" floating = %d\n", new->floating);
|
printf(" floating = %d\n", new->floating);
|
||||||
new->windowclass_title = $<string>3;
|
new->windowclass_title = $<string>3;
|
||||||
TAILQ_INSERT_TAIL(&assignments, new, assignments);
|
TAILQ_INSERT_TAIL(&assignments, new, assignments);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
assign_target:
|
assign_target:
|
||||||
NUMBER
|
NUMBER
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
||||||
new->workspace = $<number>1;
|
new->workspace = $<number>1;
|
||||||
new->floating = ASSIGN_FLOATING_NO;
|
new->floating = ASSIGN_FLOATING_NO;
|
||||||
$<assignment>$ = new;
|
$<assignment>$ = new;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
| '~'
|
| '~'
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
||||||
new->floating = ASSIGN_FLOATING_ONLY;
|
new->floating = ASSIGN_FLOATING_ONLY;
|
||||||
$<assignment>$ = new;
|
$<assignment>$ = new;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
| '~' NUMBER
|
| '~' NUMBER
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
struct Assignment *new = scalloc(sizeof(struct Assignment));
|
||||||
new->workspace = $<number>2;
|
new->workspace = $<number>2;
|
||||||
new->floating = ASSIGN_FLOATING;
|
new->floating = ASSIGN_FLOATING;
|
||||||
$<assignment>$ = new;
|
$<assignment>$ = new;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
SLIST_REMOVE(&modes, mode, Mode, modes);
|
SLIST_REMOVE(&modes, mode, Mode, modes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct Assignment *assign;
|
struct Assignment *assign;
|
||||||
while (!TAILQ_EMPTY(&assignments)) {
|
while (!TAILQ_EMPTY(&assignments)) {
|
||||||
assign = TAILQ_FIRST(&assignments);
|
assign = TAILQ_FIRST(&assignments);
|
||||||
|
@ -312,6 +313,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
TAILQ_REMOVE(&assignments, assign, assignments);
|
TAILQ_REMOVE(&assignments, assign, assignments);
|
||||||
FREE(assign);
|
FREE(assign);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Clear workspace names */
|
/* Clear workspace names */
|
||||||
#if 0
|
#if 0
|
||||||
|
|
163
src/handlers.c
163
src/handlers.c
|
@ -20,12 +20,12 @@
|
||||||
static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events;
|
static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events;
|
||||||
|
|
||||||
static void add_ignore_event(const int sequence) {
|
static void add_ignore_event(const int sequence) {
|
||||||
struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event));
|
struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event));
|
||||||
|
|
||||||
event->sequence = sequence;
|
event->sequence = sequence;
|
||||||
event->added = time(NULL);
|
event->added = time(NULL);
|
||||||
|
|
||||||
SLIST_INSERT_HEAD(&ignore_events, event, ignore_events);
|
SLIST_INSERT_HEAD(&ignore_events, event, ignore_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -33,26 +33,27 @@ static void add_ignore_event(const int sequence) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool event_is_ignored(const int sequence) {
|
static bool event_is_ignored(const int sequence) {
|
||||||
struct Ignore_Event *event;
|
struct Ignore_Event *event;
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) {
|
for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) {
|
||||||
if ((now - event->added) > 5) {
|
if ((now - event->added) > 5) {
|
||||||
struct Ignore_Event *save = event;
|
struct Ignore_Event *save = event;
|
||||||
event = SLIST_NEXT(event, ignore_events);
|
event = SLIST_NEXT(event, ignore_events);
|
||||||
SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events);
|
SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events);
|
||||||
free(save);
|
free(save);
|
||||||
} else event = SLIST_NEXT(event, ignore_events);
|
} else event = SLIST_NEXT(event, ignore_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLIST_FOREACH(event, &ignore_events, ignore_events) {
|
SLIST_FOREACH(event, &ignore_events, ignore_events) {
|
||||||
if (event->sequence == sequence) {
|
if (event->sequence != sequence)
|
||||||
SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events);
|
continue;
|
||||||
free(event);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events);
|
||||||
|
free(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -140,68 +141,78 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) {
|
||||||
if (first_client != NULL)
|
if (first_client != NULL)
|
||||||
set_focus(global_conn, first_client, true);
|
set_focus(global_conn, first_client, true);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the user moves the mouse pointer onto a window, this callback gets called.
|
* When the user moves the mouse pointer onto a window, this callback gets called.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event) {
|
int handle_enter_notify(void *ignored, xcb_connection_t *conn,
|
||||||
DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d\n", event->event, event->mode, event->detail, event->sequence);
|
xcb_enter_notify_event_t *event) {
|
||||||
if (event->mode != XCB_NOTIFY_MODE_NORMAL) {
|
Con *con;
|
||||||
DLOG("This was not a normal notify, ignoring\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* Some events are not interesting, because they were not generated actively by the
|
|
||||||
user, but by reconfiguration of windows */
|
|
||||||
if (event_is_ignored(event->sequence))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* This was either a focus for a client’s parent (= titlebar)… */
|
|
||||||
Client *client = table_get(&by_parent, event->event);
|
|
||||||
/* …or the client itself */
|
|
||||||
if (client == NULL)
|
|
||||||
client = table_get(&by_child, event->event);
|
|
||||||
|
|
||||||
/* Check for stack windows */
|
|
||||||
if (client == NULL) {
|
|
||||||
struct Stack_Window *stack_win;
|
|
||||||
SLIST_FOREACH(stack_win, &stack_wins, stack_windows)
|
|
||||||
if (stack_win->window == event->event) {
|
|
||||||
client = stack_win->container->currently_focused;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */
|
|
||||||
if (client == NULL) {
|
|
||||||
DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y);
|
|
||||||
check_crossing_screen_boundary(event->root_x, event->root_y);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do plausibility checks: This event may be useless for us if it occurs on a window
|
|
||||||
which is in a stacked container but not the focused one */
|
|
||||||
if (client->container != NULL &&
|
|
||||||
client->container->mode == MODE_STACK &&
|
|
||||||
client->container->currently_focused != client) {
|
|
||||||
DLOG("Plausibility check says: no\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client->workspace != c_ws && client->workspace->output == c_ws->output) {
|
|
||||||
/* This can happen when a client gets assigned to a different workspace than
|
|
||||||
* the current one (see src/mainx.c:reparent_window). Shortly after it was created,
|
|
||||||
* an enter_notify will follow. */
|
|
||||||
DLOG("enter_notify for a client on a different workspace but the same screen, ignoring\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.disable_focus_follows_mouse)
|
|
||||||
set_focus(conn, client, false);
|
|
||||||
|
|
||||||
|
DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d\n",
|
||||||
|
event->event, event->mode, event->detail, event->sequence);
|
||||||
|
DLOG("coordinates %x, %x\n", event->event_x, event->event_y);
|
||||||
|
if (event->mode != XCB_NOTIFY_MODE_NORMAL) {
|
||||||
|
DLOG("This was not a normal notify, ignoring\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
/* Some events are not interesting, because they were not generated
|
||||||
|
* actively by the user, but by reconfiguration of windows */
|
||||||
|
if (event_is_ignored(event->sequence))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Get container by frame or by child window */
|
||||||
|
if ((con = con_by_frame_id(event->event)) == NULL)
|
||||||
|
con = con_by_window_id(event->event);
|
||||||
|
|
||||||
|
/* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */
|
||||||
|
if (con == NULL) {
|
||||||
|
DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y);
|
||||||
|
//check_crossing_screen_boundary(event->root_x, event->root_y);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* see if the user entered the window on a certain window decoration */
|
||||||
|
int layout = con->layout;
|
||||||
|
Con *child;
|
||||||
|
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
|
||||||
|
if (rect_contains(child->deco_rect, event->event_x, event->event_y)) {
|
||||||
|
LOG("using child %p / %s instead!\n", child, child->name);
|
||||||
|
con = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for stacked/tabbed layout we do not want to change focus when the user
|
||||||
|
* enters the window at the decoration of any child window. */
|
||||||
|
if (layout == L_STACKED || layout == L_TABBED) {
|
||||||
|
con = TAILQ_FIRST(&(con->parent->focus_head));
|
||||||
|
LOG("using focused %p / %s instead\n", con, con->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (client->workspace != c_ws && client->workspace->output == c_ws->output) {
|
||||||
|
/* This can happen when a client gets assigned to a different workspace than
|
||||||
|
* the current one (see src/mainx.c:reparent_window). Shortly after it was created,
|
||||||
|
* an enter_notify will follow. */
|
||||||
|
DLOG("enter_notify for a client on a different workspace but the same screen, ignoring\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (config.disable_focus_follows_mouse)
|
||||||
|
return 1;
|
||||||
|
Con *next = con;
|
||||||
|
while (!TAILQ_EMPTY(&(next->focus_head)))
|
||||||
|
next = TAILQ_FIRST(&(next->focus_head));
|
||||||
|
|
||||||
|
con_focus(next);
|
||||||
|
x_push_changes(croot);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When the user moves the mouse but does not change the active window
|
* When the user moves the mouse but does not change the active window
|
||||||
|
|
7
src/nc.c
7
src/nc.c
|
@ -139,7 +139,11 @@ void parse_command(const char *command) {
|
||||||
tree_next('n', VERT);
|
tree_next('n', VERT);
|
||||||
else if (strncasecmp(command, "workspace ", strlen("workspace ")) == 0)
|
else if (strncasecmp(command, "workspace ", strlen("workspace ")) == 0)
|
||||||
workspace_show(command + strlen("workspace "));
|
workspace_show(command + strlen("workspace "));
|
||||||
|
else if (strcasecmp(command, "stack") == 0) {
|
||||||
|
focused->layout = L_STACKED;
|
||||||
|
x_push_changes(croot);
|
||||||
|
|
||||||
|
}
|
||||||
else if (strcasecmp(command, "move before h") == 0)
|
else if (strcasecmp(command, "move before h") == 0)
|
||||||
tree_move('p', HORIZ);
|
tree_move('p', HORIZ);
|
||||||
else if (strcasecmp(command, "move before v") == 0)
|
else if (strcasecmp(command, "move before v") == 0)
|
||||||
|
@ -312,6 +316,9 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
xcb_event_set_expose_handler(&evenths, handle_expose_event, NULL);
|
xcb_event_set_expose_handler(&evenths, handle_expose_event, NULL);
|
||||||
|
|
||||||
|
/* Enter window = user moved his mouse over the window */
|
||||||
|
xcb_event_set_enter_notify_handler(&evenths, handle_enter_notify, NULL);
|
||||||
|
|
||||||
|
|
||||||
/* Setup NetWM atoms */
|
/* Setup NetWM atoms */
|
||||||
#define GET_ATOM(name) \
|
#define GET_ATOM(name) \
|
||||||
|
|
|
@ -31,6 +31,13 @@ int max(int a, int b) {
|
||||||
return (a > b ? a : b);
|
return (a > b ? a : b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rect_contains(Rect rect, uint32_t x, uint32_t y) {
|
||||||
|
return (x >= rect.x &&
|
||||||
|
x <= (rect.x + rect.width) &&
|
||||||
|
y >= rect.y &&
|
||||||
|
y <= (rect.y + rect.height));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates *destination with new_value and returns true if it was changed or false
|
* Updates *destination with new_value and returns true if it was changed or false
|
||||||
* if it was the same
|
* if it was the same
|
||||||
|
|
Loading…
Reference in New Issue