broadway: use 'click-to-focus' approach instead of 'focus-follows-mouse'

The broadway backend would move the focus from one window to another based on
where the mouse was (i.e. 'focus-follows-mouse' approach). Handling the focus
this wait didn't play well with widgets which rely on focus-in-event and
focus-out-event, like the GtkEntry when using a completion popup window, see
e.g:
  https://bugzilla.gnome.org/show_bug.cgi?id=708984

So instead, setup broadway to require a click in a window to move the focus
(i.e. 'click-to-focus' approach):

 * The implicit GDK_FOCUS_CHANGE events that were generated upon reception of
   BROADWAY_EVENT_ENTER or BROADWAY_EVENT_LEAVE are removed.

 * The broadway daemon will now keep track of which is the focused window

 * Whenever the daemon detects an incoming BROADWAY_EVENT_BUTTON_PRESS, it will
   trigger the focused window switch, which sends a new BROADWAY_EVENT_FOCUS to
   the client, specifying which windows holds the focus.

 * Upon reception of a BROADWAY_EVENT_FOCUS, the client will generate a new
   GDK_FOCUS_CHANGE.

 * gdk_broadway_window_focus() was also implemented, which now requests the
   focus to the broadway server using a new BROADWAY_REQUEST_FOCUS_WINDOW.

This is based on an initial patch from Aleksander Morgado <aleksander@lanedo.com>.
This commit is contained in:
Alexander Larsson
2013-11-12 12:03:50 +01:00
parent f50a3af1b7
commit ddade66496
8 changed files with 83 additions and 19 deletions

View File

@ -54,6 +54,7 @@ struct _BroadwayServer {
GHashTable *id_ht;
GList *toplevels;
BroadwayWindow *root;
gint32 focused_window_id; /* -1 => none */
guint32 screen_width;
guint32 screen_height;
@ -215,6 +216,10 @@ update_event_state (BroadwayServer *server,
break;
case BROADWAY_EVENT_BUTTON_PRESS:
case BROADWAY_EVENT_BUTTON_RELEASE:
if (message->base.type == BROADWAY_EVENT_BUTTON_PRESS &&
server->focused_window_id != message->pointer.mouse_window_id)
broadway_server_focus_window (server, message->pointer.mouse_window_id);
server->last_x = message->pointer.root_x;
server->last_y = message->pointer.root_y;
server->last_state = message->pointer.state;
@ -1460,6 +1465,26 @@ broadway_server_window_move_resize (BroadwayServer *server,
return sent;
}
void
broadway_server_focus_window (BroadwayServer *server,
gint new_focused_window)
{
BroadwayInputMsg focus_msg;
if (server->focused_window_id == new_focused_window)
return;
/* Keep track of the new focused window */
server->focused_window_id = new_focused_window;
memset (&focus_msg, 0, sizeof (focus_msg));
focus_msg.base.type = BROADWAY_EVENT_FOCUS;
focus_msg.base.time = broadway_server_get_last_seen_time (server);
focus_msg.focus.id = new_focused_window;
broadway_events_got_input (&focus_msg, -1);
}
guint32
broadway_server_grab_pointer (BroadwayServer *server,
gint client_id,