@ -47,48 +47,36 @@ void seat_destroy(struct sway_seat *seat) {
seat_device_destroy ( seat_device ) ;
seat_device_destroy ( seat_device ) ;
}
}
sway_cursor_destroy ( seat - > cursor ) ;
sway_cursor_destroy ( seat - > cursor ) ;
wl_list_remove ( & seat - > new_ container . link ) ;
wl_list_remove ( & seat - > new_ node . link ) ;
wl_list_remove ( & seat - > new_drag_icon . link ) ;
wl_list_remove ( & seat - > new_drag_icon . link ) ;
wl_list_remove ( & seat - > link ) ;
wl_list_remove ( & seat - > link ) ;
wlr_seat_destroy ( seat - > wlr_seat ) ;
wlr_seat_destroy ( seat - > wlr_seat ) ;
}
}
static struct sway_seat_ container * seat_container_from_container (
static struct sway_seat_ node * seat_node_from_node (
struct sway_seat * seat , struct sway_ container * con ) ;
struct sway_seat * seat , struct sway_ node * node ) ;
static void seat_container_destroy ( struct sway_seat_container * seat_con ) {
static void seat_node_destroy ( struct sway_seat_node * seat_node ) {
struct sway_container * con = seat_con - > container ;
wl_list_remove ( & seat_node - > destroy . link ) ;
struct sway_container * child = NULL ;
wl_list_remove ( & seat_node - > link ) ;
free ( seat_node ) ;
if ( con - > children ! = NULL ) {
for ( int i = 0 ; i < con - > children - > length ; + + i ) {
child = con - > children - > items [ i ] ;
struct sway_seat_container * seat_child =
seat_container_from_container ( seat_con - > seat , child ) ;
seat_container_destroy ( seat_child ) ;
}
}
wl_list_remove ( & seat_con - > destroy . link ) ;
wl_list_remove ( & seat_con - > link ) ;
free ( seat_con ) ;
}
}
/**
/**
* Activate all views within this container recursively .
* Activate all views within this container recursively .
*/
*/
static void seat_send_activate ( struct sway_container * con ,
static void seat_send_activate ( struct sway_node * node , struct sway_seat * seat ) {
struct sway_seat * seat ) {
if ( node_is_view ( node ) ) {
if ( con - > type = = C_VIEW ) {
if ( ! seat_is_input_allowed ( seat , node - > sway_container - > view - > surface ) ) {
if ( ! seat_is_input_allowed ( seat , con - > sway_view - > surface ) ) {
wlr_log ( WLR_DEBUG , " Refusing to set focus, input is inhibited " ) ;
wlr_log ( WLR_DEBUG , " Refusing to set focus, input is inhibited " ) ;
return ;
return ;
}
}
view_set_activated ( con- > sway_ view, true ) ;
view_set_activated ( node - > sway_container - > view , true ) ;
} else {
} else {
for ( int i = 0 ; i < con - > children - > length ; + + i ) {
list_t * children = node_get_children ( node ) ;
struct sway_container * child = con - > children - > items [ i ] ;
for ( int i = 0 ; i < children - > length ; + + i ) {
seat_send_activate ( child , seat ) ;
struct sway_container * child = children - > items [ i ] ;
seat_send_activate ( & child - > node , seat ) ;
}
}
}
}
}
}
@ -98,14 +86,15 @@ static void seat_send_activate(struct sway_container *con,
* If con is a container , set all child views as active and don ' t enable
* If con is a container , set all child views as active and don ' t enable
* keyboard input on any .
* keyboard input on any .
*/
*/
static void seat_send_focus ( struct sway_container * con ,
static void seat_send_focus ( struct sway_node * node , struct sway_seat * seat ) {
struct sway_seat * seat ) {
seat_send_activate ( node , seat ) ;
seat_send_activate ( con , seat ) ;
if ( con - > type = = C_VIEW
struct sway_view * view = node - > type = = N_CONTAINER ?
& & seat_is_input_allowed ( seat , con - > sway_view - > surface ) ) {
node - > sway_container - > view : NULL ;
if ( view & & seat_is_input_allowed ( seat , view - > surface ) ) {
# ifdef HAVE_XWAYLAND
# ifdef HAVE_XWAYLAND
if ( con - > sway_view - > type = = SWAY_VIEW_XWAYLAND ) {
if ( view- > type = = SWAY_VIEW_XWAYLAND ) {
struct wlr_xwayland * xwayland =
struct wlr_xwayland * xwayland =
seat - > input - > server - > xwayland . wlr_xwayland ;
seat - > input - > server - > xwayland . wlr_xwayland ;
wlr_xwayland_set_seat ( xwayland , seat - > wlr_seat ) ;
wlr_xwayland_set_seat ( xwayland , seat - > wlr_seat ) ;
@ -114,71 +103,67 @@ static void seat_send_focus(struct sway_container *con,
struct wlr_keyboard * keyboard = wlr_seat_get_keyboard ( seat - > wlr_seat ) ;
struct wlr_keyboard * keyboard = wlr_seat_get_keyboard ( seat - > wlr_seat ) ;
if ( keyboard ) {
if ( keyboard ) {
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat ,
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat ,
con- > sway_ view- > surface , keyboard - > keycodes ,
view- > surface , keyboard - > keycodes ,
keyboard - > num_keycodes , & keyboard - > modifiers ) ;
keyboard - > num_keycodes , & keyboard - > modifiers ) ;
} else {
} else {
wlr_seat_keyboard_notify_enter (
wlr_seat_keyboard_notify_enter (
seat - > wlr_seat , con- > sway_ view- > surface , NULL , 0 , NULL ) ;
seat - > wlr_seat , view- > surface , NULL , 0 , NULL ) ;
}
}
}
}
}
}
void seat_focus_inactive_children_for_each ( struct sway_seat * seat ,
void seat_for_each_node ( struct sway_seat * seat ,
struct sway_container * container ,
void ( * f ) ( struct sway_node * node , void * data ) , void * data ) {
void ( * f ) ( struct sway_container * container , void * data ) , void * data ) {
struct sway_seat_node * current = NULL ;
struct sway_seat_container * current = NULL ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
if ( current - > container - > parent = = NULL ) {
f ( current - > node , data ) ;
continue ;
}
if ( current - > container - > parent = = container ) {
f ( current - > container , data ) ;
}
}
}
}
}
struct sway_container * seat_get_focus_inactive_view ( struct sway_seat * seat ,
struct sway_container * seat_get_focus_inactive_view ( struct sway_seat * seat ,
struct sway_ container * ancestor ) {
struct sway_node * ancestor ) {
if ( ancestor - > type = = C_VIEW ) {
if ( ancestor - > type = = N_CONTAINER & & ancestor - > sway_container - > view ) {
return ancestor ;
return ancestor - > sway_container ;
}
}
struct sway_seat_ container * current ;
struct sway_seat_ node * current ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
struct sway_container * con = current - > container ;
struct sway_node * node = current - > node ;
if ( con - > type = = C_VIEW & & container_has_ancestor ( con , ancestor ) ) {
if ( node - > type = = N_CONTAINER & & node - > sway_container - > view & &
return con ;
node_has_ancestor ( node , ancestor ) ) {
return node - > sway_container ;
}
}
}
}
return NULL ;
return NULL ;
}
}
static void handle_seat_container_destroy ( struct wl_listener * listener ,
static void handle_seat_node_destroy ( struct wl_listener * listener , void * data ) {
void * data ) {
struct sway_seat_node * seat_node =
struct sway_seat_container * seat_con =
wl_container_of ( listener , seat_node , destroy ) ;
wl_container_of ( listener , seat_con , destroy ) ;
struct sway_seat * seat = seat_node - > seat ;
struct sway_seat * seat = seat_con - > seat ;
struct sway_node * node = seat_node - > node ;
struct sway_container * con = seat_con - > container ;
struct sway_node * parent = node_get_parent ( node ) ;
struct sway_container * parent = con - > parent ;
struct sway_node * focus = seat_get_focus ( seat ) ;
struct sway_container * focus = seat_get_focus ( seat ) ;
bool set_focus =
bool set_focus =
focus ! = NULL & &
focus ! = NULL & &
( focus = = con | | container_has_ancestor ( focus , con ) ) & &
( focus = = node | | node_has_ancestor ( focus , node ) ) & &
con- > type ! = C_WORKSPACE ;
node- > type = = N_CONTAINER ;
seat_ container_destroy( seat_con ) ;
seat_ node_destroy( seat_node ) ;
if ( set_focus ) {
if ( set_focus ) {
struct sway_ container * next_focus = NULL ;
struct sway_ node * next_focus = NULL ;
while ( next_focus = = NULL ) {
while ( next_focus = = NULL ) {
next_focus = seat_get_focus_inactive_view ( seat , parent ) ;
struct sway_container * con =
seat_get_focus_inactive_view ( seat , parent ) ;
next_focus = con ? & con - > node : NULL ;
if ( next_focus = = NULL & & parent - > type = = C_WORKSPACE ) {
if ( next_focus = = NULL & & parent - > type = = N _WORKSPACE) {
next_focus = parent ;
next_focus = parent ;
break ;
break ;
}
}
parent = parent - > parent ;
parent = node_get_parent ( parent ) ;
}
}
// the structure change might have caused it to move up to the top of
// the structure change might have caused it to move up to the top of
@ -191,39 +176,39 @@ static void handle_seat_container_destroy(struct wl_listener *listener,
}
}
}
}
static struct sway_seat_ container * seat_container_from_container (
static struct sway_seat_ node * seat_node_from_node (
struct sway_seat * seat , struct sway_ container * con ) {
struct sway_seat * seat , struct sway_ node * node ) {
if ( con- > type = = C_ROOT | | con - > type = = C _OUTPUT) {
if ( node- > type = = N_ROOT | | node - > type = = N _OUTPUT) {
// these don't get seat container s ever
// these don't get seat node s ever
return NULL ;
return NULL ;
}
}
struct sway_seat_ container * seat_con = NULL ;
struct sway_seat_ node * seat_node = NULL ;
wl_list_for_each ( seat_ con , & seat - > focus_stack , link ) {
wl_list_for_each ( seat_ node , & seat - > focus_stack , link ) {
if ( seat_ con- > container = = con ) {
if ( seat_ node- > node = = node ) {
return seat_ con ;
return seat_ node ;
}
}
}
}
seat_ con = calloc ( 1 , sizeof ( struct sway_seat_ container ) ) ;
seat_ node = calloc ( 1 , sizeof ( struct sway_seat_ node ) ) ;
if ( seat_ con = = NULL ) {
if ( seat_ node = = NULL ) {
wlr_log ( WLR_ERROR , " could not allocate seat container " ) ;
wlr_log ( WLR_ERROR , " could not allocate seat node " ) ;
return NULL ;
return NULL ;
}
}
seat_ con- > container = con ;
seat_ node- > node = node ;
seat_ con - > seat = seat ;
seat_ node - > seat = seat ;
wl_list_insert ( seat - > focus_stack . prev , & seat_ con - > link ) ;
wl_list_insert ( seat - > focus_stack . prev , & seat_ node - > link ) ;
wl_signal_add ( & con- > events . destroy , & seat_con - > destroy ) ;
wl_signal_add ( & node- > events . destroy , & seat_node - > destroy ) ;
seat_ con- > destroy . notify = handle_seat_container _destroy;
seat_ node- > destroy . notify = handle_seat_node _destroy;
return seat_ con ;
return seat_ node ;
}
}
static void handle_new_ container ( struct wl_listener * listener , void * data ) {
static void handle_new_ node ( struct wl_listener * listener , void * data ) {
struct sway_seat * seat = wl_container_of ( listener , seat , new_ container ) ;
struct sway_seat * seat = wl_container_of ( listener , seat , new_ node ) ;
struct sway_ container * con = data ;
struct sway_ node * node = data ;
seat_ container_from_container( seat , con ) ;
seat_ node_from_node( seat , node ) ;
}
}
static void drag_icon_damage_whole ( struct sway_drag_icon * icon ) {
static void drag_icon_damage_whole ( struct sway_drag_icon * icon ) {
@ -272,8 +257,7 @@ static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) {
drag_icon_damage_whole ( icon ) ;
drag_icon_damage_whole ( icon ) ;
}
}
static void drag_icon_handle_destroy ( struct wl_listener * listener ,
static void drag_icon_handle_destroy ( struct wl_listener * listener , void * data ) {
void * data ) {
struct sway_drag_icon * icon = wl_container_of ( listener , icon , destroy ) ;
struct sway_drag_icon * icon = wl_container_of ( listener , icon , destroy ) ;
icon - > wlr_drag_icon - > data = NULL ;
icon - > wlr_drag_icon - > data = NULL ;
wl_list_remove ( & icon - > link ) ;
wl_list_remove ( & icon - > link ) ;
@ -305,20 +289,29 @@ static void handle_new_drag_icon(struct wl_listener *listener, void *data) {
icon - > destroy . notify = drag_icon_handle_destroy ;
icon - > destroy . notify = drag_icon_handle_destroy ;
wl_signal_add ( & wlr_drag_icon - > events . destroy , & icon - > destroy ) ;
wl_signal_add ( & wlr_drag_icon - > events . destroy , & icon - > destroy ) ;
wl_list_insert ( & root _container. sway_root - > drag_icons , & icon - > link ) ;
wl_list_insert ( & root - > drag_icons , & icon - > link ) ;
drag_icon_update_position ( icon ) ;
drag_icon_update_position ( icon ) ;
}
}
static void collect_focus_iter ( struct sway_ container * con , void * data ) {
static void collect_focus_iter ( struct sway_ node * node , void * data ) {
struct sway_seat * seat = data ;
struct sway_seat * seat = data ;
struct sway_seat_container * seat_con =
struct sway_seat_node * seat_node = seat_node_from_node ( seat , node ) ;
seat_container_from_container ( seat , con ) ;
if ( ! seat_node ) {
if ( ! seat_con ) {
return ;
return ;
}
}
wl_list_remove ( & seat_con - > link ) ;
wl_list_remove ( & seat_node - > link ) ;
wl_list_insert ( & seat - > focus_stack , & seat_con - > link ) ;
wl_list_insert ( & seat - > focus_stack , & seat_node - > link ) ;
}
static void collect_focus_workspace_iter ( struct sway_workspace * workspace ,
void * data ) {
collect_focus_iter ( & workspace - > node , data ) ;
}
static void collect_focus_container_iter ( struct sway_container * container ,
void * data ) {
collect_focus_iter ( & container - > node , data ) ;
}
}
struct sway_seat * seat_create ( struct sway_input_manager * input ,
struct sway_seat * seat_create ( struct sway_input_manager * input ,
@ -345,12 +338,11 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
// init the focus stack
// init the focus stack
wl_list_init ( & seat - > focus_stack ) ;
wl_list_init ( & seat - > focus_stack ) ;
root_for_each_workspace ( collect_focus_ iter, seat ) ;
root_for_each_workspace ( collect_focus_ workspace_ iter, seat ) ;
root_for_each_container ( collect_focus_ iter, seat ) ;
root_for_each_container ( collect_focus_ container_ iter, seat ) ;
wl_signal_add ( & root_container . sway_root - > events . new_container ,
wl_signal_add ( & root - > events . new_node , & seat - > new_node ) ;
& seat - > new_container ) ;
seat - > new_node . notify = handle_new_node ;
seat - > new_container . notify = handle_new_container ;
wl_signal_add ( & seat - > wlr_seat - > events . new_drag_icon , & seat - > new_drag_icon ) ;
wl_signal_add ( & seat - > wlr_seat - > events . new_drag_icon , & seat - > new_drag_icon ) ;
seat - > new_drag_icon . notify = handle_new_drag_icon ;
seat - > new_drag_icon . notify = handle_new_drag_icon ;
@ -388,19 +380,11 @@ static void seat_apply_input_config(struct sway_seat *seat,
if ( mapped_to_output ! = NULL ) {
if ( mapped_to_output ! = NULL ) {
wlr_log ( WLR_DEBUG , " Mapping input device %s to output %s " ,
wlr_log ( WLR_DEBUG , " Mapping input device %s to output %s " ,
sway_device - > input_device - > identifier , mapped_to_output ) ;
sway_device - > input_device - > identifier , mapped_to_output ) ;
struct sway_container * output = NULL ;
struct sway_output * output = output_by_name ( mapped_to_output ) ;
for ( int i = 0 ; i < root_container . children - > length ; + + i ) {
struct sway_container * _output = root_container . children - > items [ i ] ;
if ( strcasecmp ( _output - > name , mapped_to_output ) = = 0 ) {
output = _output ;
break ;
}
}
if ( output ) {
if ( output ) {
wlr_cursor_map_input_to_output ( seat - > cursor - > cursor ,
wlr_cursor_map_input_to_output ( seat - > cursor - > cursor ,
sway_device - > input_device - > wlr_device ,
sway_device - > input_device - > wlr_device , output - > wlr_output ) ;
output - > sway_output - > wlr_output ) ;
wlr_log ( WLR_DEBUG , " Mapped to output %s " , output - > wlr_output - > name ) ;
wlr_log ( WLR_DEBUG , " Mapped to output %s " , output - > name ) ;
}
}
}
}
}
}
@ -423,12 +407,12 @@ static void seat_configure_keyboard(struct sway_seat *seat,
sway_keyboard_configure ( seat_device - > keyboard ) ;
sway_keyboard_configure ( seat_device - > keyboard ) ;
wlr_seat_set_keyboard ( seat - > wlr_seat ,
wlr_seat_set_keyboard ( seat - > wlr_seat ,
seat_device - > input_device - > wlr_device ) ;
seat_device - > input_device - > wlr_device ) ;
struct sway_ container * focus = seat_get_focus ( seat ) ;
struct sway_ node * focus = seat_get_focus ( seat ) ;
if ( focus & & focus - > type = = C_VIEW ) {
if ( focus & & node_is_view ( focus ) ) {
// force notify reenter to pick up the new configuration
// force notify reenter to pick up the new configuration
wlr_seat_keyboard_clear_focus ( seat - > wlr_seat ) ;
wlr_seat_keyboard_clear_focus ( seat - > wlr_seat ) ;
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat ,
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat ,
focus - > sway_ view- > surface , wlr_keyboard - > keycodes ,
focus - > sway_ container- > view- > surface , wlr_keyboard - > keycodes ,
wlr_keyboard - > num_keycodes , & wlr_keyboard - > modifiers ) ;
wlr_keyboard - > num_keycodes , & wlr_keyboard - > modifiers ) ;
}
}
}
}
@ -461,8 +445,7 @@ static struct sway_seat_device *seat_get_device(struct sway_seat *seat,
void seat_configure_device ( struct sway_seat * seat ,
void seat_configure_device ( struct sway_seat * seat ,
struct sway_input_device * input_device ) {
struct sway_input_device * input_device ) {
struct sway_seat_device * seat_device =
struct sway_seat_device * seat_device = seat_get_device ( seat , input_device ) ;
seat_get_device ( seat , input_device ) ;
if ( ! seat_device ) {
if ( ! seat_device ) {
return ;
return ;
}
}
@ -512,8 +495,7 @@ void seat_add_device(struct sway_seat *seat,
void seat_remove_device ( struct sway_seat * seat ,
void seat_remove_device ( struct sway_seat * seat ,
struct sway_input_device * input_device ) {
struct sway_input_device * input_device ) {
struct sway_seat_device * seat_device =
struct sway_seat_device * seat_device = seat_get_device ( seat , input_device ) ;
seat_get_device ( seat , input_device ) ;
if ( ! seat_device ) {
if ( ! seat_device ) {
return ;
return ;
@ -539,11 +521,9 @@ void seat_configure_xcursor(struct sway_seat *seat) {
}
}
}
}
for ( int i = 0 ; i < root_container . children - > length ; + + i ) {
for ( int i = 0 ; i < root - > outputs - > length ; + + i ) {
struct sway_container * output_container =
struct sway_output * sway_output = root - > outputs - > items [ i ] ;
root_container . children - > items [ i ] ;
struct wlr_output * output = sway_output - > wlr_output ;
struct wlr_output * output =
output_container - > sway_output - > wlr_output ;
bool result =
bool result =
wlr_xcursor_manager_load ( seat - > cursor - > xcursor_manager ,
wlr_xcursor_manager_load ( seat - > cursor - > xcursor_manager ,
output - > scale ) ;
output - > scale ) ;
@ -566,17 +546,20 @@ bool seat_is_input_allowed(struct sway_seat *seat,
return ! seat - > exclusive_client | | seat - > exclusive_client = = client ;
return ! seat - > exclusive_client | | seat - > exclusive_client = = client ;
}
}
static void send_unfocus ( struct sway_container * con , void * data ) {
if ( con - > view ) {
view_set_activated ( con - > view , false ) ;
}
}
// Unfocus the container and any children (eg. when leaving `focus parent`)
// Unfocus the container and any children (eg. when leaving `focus parent`)
static void seat_send_unfocus ( struct sway_container * container ,
static void seat_send_unfocus ( struct sway_node * node , struct sway_seat * seat ) {
struct sway_seat * seat ) {
wlr_seat_keyboard_clear_focus ( seat - > wlr_seat ) ;
if ( container - > type = = C_VIEW ) {
if ( node - > type = = N_WORKSPACE ) {
wlr_seat_keyboard_clear_focus ( seat - > wlr_seat ) ;
workspace_for_each_container ( node - > sway_workspace , send_unfocus , seat ) ;
view_set_activated ( container - > sway_view , false ) ;
} else {
} else {
for ( int i = 0 ; i < container - > children - > length ; + + i ) {
send_unfocus ( node - > sway_container , seat ) ;
struct sway_container * child = container - > children - > items [ i ] ;
container_for_each_child ( node - > sway_container , send_unfocus , seat ) ;
seat_send_unfocus ( child , seat ) ;
}
}
}
}
}
@ -586,26 +569,23 @@ static int handle_urgent_timeout(void *data) {
return 0 ;
return 0 ;
}
}
void seat_set_focus_warp ( struct sway_seat * seat ,
void seat_set_focus_warp ( struct sway_seat * seat , struct sway_node * node ,
struct sway_container * container , bool warp , bool notify ) {
bool warp , bool notify ) {
if ( seat - > focused_layer ) {
if ( seat - > focused_layer ) {
return ;
return ;
}
}
struct sway_ container * last_focus = seat_get_focus ( seat ) ;
struct sway_ node * last_focus = seat_get_focus ( seat ) ;
if ( last_focus = = container ) {
if ( last_focus = = node ) {
return ;
return ;
}
}
struct sway_container * last_workspace = last_focus ;
struct sway_workspace * last_workspace = seat_get_focused_workspace ( seat ) ;
if ( last_workspace & & last_workspace - > type ! = C_WORKSPACE ) {
last_workspace = container_parent ( last_workspace , C_WORKSPACE ) ;
}
if ( container = = NULL ) {
if ( node = = NULL ) {
// Close any popups on the old focus
// Close any popups on the old focus
if ( last_focus - > type = = C_VIEW ) {
if ( node_is_view ( last_focus ) ) {
view_close_popups ( last_focus - > sway_ view) ;
view_close_popups ( last_focus - > sway_ container- > view) ;
}
}
seat_send_unfocus ( last_focus , seat ) ;
seat_send_unfocus ( last_focus , seat ) ;
seat - > has_focus = false ;
seat - > has_focus = false ;
@ -613,69 +593,70 @@ void seat_set_focus_warp(struct sway_seat *seat,
return ;
return ;
}
}
struct sway_ container * new_workspace = container ;
struct sway_ workspace * new_workspace = node - > type = = N_WORKSPACE ?
if ( new_workspace - > type ! = C_WORKSPACE ) {
node - > sway_workspace : node - > sway_container - > workspace ;
new_workspace = container_parent ( new_workspace , C_WORKSPACE ) ;
struct sway_container * container = node - > type = = N_CONTAINER ?
}
node - > sway_container : NULL ;
if ( last_workspace = = new_workspace
// Deny setting focus to a view which is hidden by a fullscreen container
& & last_workspace - > sway _workspace- > fullscreen
if ( new_workspace & & new _workspace- > fullscreen & & container & &
&& !container_is_fullscreen_or_child ( container ) ) {
!container_is_fullscreen_or_child ( container ) ) {
return ;
return ;
}
}
struct sway_container * last_output = last_focus ;
struct sway_output * last_output = last_workspace ?
if ( last_output & & last_output - > type ! = C_OUTPUT ) {
last_workspace - > output : NULL ;
last_output = container_parent ( last_output , C_OUTPUT ) ;
struct sway_output * new_output = new_workspace - > output ;
}
struct sway_container * new_output = container ;
if ( new_output - > type ! = C_OUTPUT ) {
new_output = container_parent ( new_output , C_OUTPUT ) ;
}
// find new output's old workspace, which might have to be removed if empty
// find new output's old workspace, which might have to be removed if empty
struct sway_ container * new_output_last_ws = NULL ;
struct sway_workspace * new_output_last_ws = NULL ;
if ( new_output & & last_output ! = new_output ) {
if ( new_output & & last_output ! = new_output ) {
new_output_last_ws = seat_get_active_child( seat , new_output ) ;
new_output_last_ws = output_get_active_workspace ( new_output ) ;
}
}
if ( container - > parent ) {
// Put the container parents on the focus stack, then the workspace, then
struct sway_seat_container * seat_con =
// the focused container.
seat_container_from_container ( seat , container ) ;
if ( container ) {
if ( seat_con = = NULL ) {
struct sway_container * parent = container - > parent ;
return ;
}
// put all the ancestors of this container on top of the focus stack
struct sway_seat_container * parent =
seat_container_from_container ( seat , container - > parent ) ;
while ( parent ) {
while ( parent ) {
wl_list_remove ( & parent - > link ) ;
struct sway_seat_node * seat_node =
wl_list_insert ( & seat - > focus_stack , & parent - > link ) ;
seat_node_from_node ( seat , & parent - > node ) ;
container_set_dirty( parent - > container ) ;
wl_list_remove ( & seat_node - > link ) ;
wl_list_insert ( & seat - > focus_stack , & seat_node - > link ) ;
parent = seat_container_from_container ( seat ,
node_set_dirty ( & parent - > node ) ;
parent - > container - > parent ) ;
parent = parent - > parent ;
}
}
}
wl_list_remove ( & seat_con - > link ) ;
if ( new_workspace ) {
wl_list_insert ( & seat - > focus_stack , & seat_con - > link ) ;
struct sway_seat_node * seat_node =
seat_node_from_node ( seat , & new_workspace - > node ) ;
wl_list_remove ( & seat_node - > link ) ;
wl_list_insert ( & seat - > focus_stack , & seat_node - > link ) ;
node_set_dirty ( & new_workspace - > node ) ;
}
if ( container ) {
struct sway_seat_node * seat_node =
seat_node_from_node ( seat , & container - > node ) ;
wl_list_remove ( & seat_node - > link ) ;
wl_list_insert ( & seat - > focus_stack , & seat_node - > link ) ;
node_set_dirty ( & container - > node ) ;
if ( last_focus ) {
if ( last_focus ) {
seat_send_unfocus ( last_focus , seat ) ;
seat_send_unfocus ( last_focus , seat ) ;
container_set_dirty ( last_focus ) ;
node_set_dirty ( last_focus ) ;
struct sway_node * last_parent = node_get_parent ( last_focus ) ;
if ( last_parent ) {
node_set_dirty ( last_parent ) ;
}
}
}
seat_send_focus ( container , seat ) ;
seat_send_focus ( & container - > node , seat ) ;
container_set_dirty ( container ) ;
container_set_dirty ( container - > parent ) ; // for focused_inactive_child
}
}
// emit ipc events
// emit ipc events
if ( notify & & new_workspace & & last_workspace ! = new_workspace ) {
if ( notify & & new_workspace & & last_workspace ! = new_workspace ) {
ipc_event_workspace ( last_workspace , new_workspace , " focus " ) ;
ipc_event_workspace ( last_workspace , new_workspace , " focus " ) ;
}
}
if ( container - > type = = C_VIEW ) {
if ( container & & container - > view ) {
ipc_event_window ( container , " focus " ) ;
ipc_event_window ( container , " focus " ) ;
}
}
@ -684,14 +665,14 @@ void seat_set_focus_warp(struct sway_seat *seat,
}
}
// Close any popups on the old focus
// Close any popups on the old focus
if ( last_focus & & last_focus - > type = = C_VIEW ) {
if ( last_focus & & node_is_view ( last_focus ) ) {
view_close_popups ( last_focus - > sway_ view) ;
view_close_popups ( last_focus - > sway_ container- > view) ;
}
}
// If urgent, either unset the urgency or start a timer to unset it
// If urgent, either unset the urgency or start a timer to unset it
if ( container - > type = = C_VIEW & & view_is_urgent ( container - > sway_ view) & &
if ( container & & container - > view & & view_is_urgent ( container - > view) & &
! container - > sway_ view- > urgent_timer ) {
! container - > view- > urgent_timer ) {
struct sway_view * view = container - > sway_ view;
struct sway_view * view = container - > view;
if ( last_workspace & & last_workspace ! = new_workspace & &
if ( last_workspace & & last_workspace ! = new_workspace & &
config - > urgent_timeout > 0 ) {
config - > urgent_timeout > 0 ) {
view - > urgent_timer = wl_event_loop_add_timer ( server . wl_event_loop ,
view - > urgent_timer = wl_event_loop_add_timer ( server . wl_event_loop ,
@ -711,12 +692,15 @@ void seat_set_focus_warp(struct sway_seat *seat,
// If we've focused a floating container, bring it to the front.
// If we've focused a floating container, bring it to the front.
// We do this by putting it at the end of the floating list.
// We do this by putting it at the end of the floating list.
struct sway_container * floater = container ;
if ( container ) {
while ( floater - > parent & & floater - > parent - > type ! = C_WORKSPACE ) {
struct sway_container * floater = container ;
floater = floater - > parent ;
while ( floater - > parent ) {
}
floater = floater - > parent ;
if ( container_is_floating ( floater ) ) {
}
list_move_to_end ( floater - > parent - > sway_workspace - > floating , floater ) ;
if ( container_is_floating ( floater ) ) {
list_move_to_end ( floater - > workspace - > floating , floater ) ;
node_set_dirty ( & floater - > workspace - > node ) ;
}
}
}
if ( last_focus ) {
if ( last_focus ) {
@ -727,11 +711,8 @@ void seat_set_focus_warp(struct sway_seat *seat,
if ( config - > mouse_warping & & warp & & new_output ! = last_output ) {
if ( config - > mouse_warping & & warp & & new_output ! = last_output ) {
double x = container - > x + container - > width / 2.0 ;
double x = container - > x + container - > width / 2.0 ;
double y = container - > y + container - > height / 2.0 ;
double y = container - > y + container - > height / 2.0 ;
struct wlr_output * wlr_output =
if ( ! wlr_output_layout_contains_point ( root - > output_layout ,
new_output - > sway_output - > wlr_output ;
new_output - > wlr_output , seat - > cursor - > cursor - > x ,
if ( ! wlr_output_layout_contains_point (
root_container . sway_root - > output_layout ,
wlr_output , seat - > cursor - > cursor - > x ,
seat - > cursor - > cursor - > y ) ) {
seat - > cursor - > cursor - > y ) ) {
wlr_cursor_warp ( seat - > cursor - > cursor , NULL , x , y ) ;
wlr_cursor_warp ( seat - > cursor - > cursor , NULL , x , y ) ;
cursor_send_pointer_motion ( seat - > cursor , 0 , true ) ;
cursor_send_pointer_motion ( seat - > cursor , 0 , true ) ;
@ -744,9 +725,8 @@ void seat_set_focus_warp(struct sway_seat *seat,
update_debug_tree ( ) ;
update_debug_tree ( ) ;
}
}
void seat_set_focus ( struct sway_seat * seat ,
void seat_set_focus ( struct sway_seat * seat , struct sway_node * node ) {
struct sway_container * container ) {
seat_set_focus_warp ( seat , node , true , true ) ;
seat_set_focus_warp ( seat , container , true , true ) ;
}
}
void seat_set_focus_surface ( struct sway_seat * seat ,
void seat_set_focus_surface ( struct sway_seat * seat ,
@ -755,12 +735,11 @@ void seat_set_focus_surface(struct sway_seat *seat,
return ;
return ;
}
}
if ( seat - > has_focus & & unfocus ) {
if ( seat - > has_focus & & unfocus ) {
struct sway_ container * focus = seat_get_focus ( seat ) ;
struct sway_ node * focus = seat_get_focus ( seat ) ;
seat_send_unfocus ( focus , seat ) ;
seat_send_unfocus ( focus , seat ) ;
seat - > has_focus = false ;
seat - > has_focus = false ;
}
}
struct wlr_keyboard * keyboard =
struct wlr_keyboard * keyboard = wlr_seat_get_keyboard ( seat - > wlr_seat ) ;
wlr_seat_get_keyboard ( seat - > wlr_seat ) ;
if ( keyboard ) {
if ( keyboard ) {
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat , surface ,
wlr_seat_keyboard_notify_enter ( seat - > wlr_seat , surface ,
keyboard - > keycodes , keyboard - > num_keycodes , & keyboard - > modifiers ) ;
keyboard - > keycodes , keyboard - > num_keycodes , & keyboard - > modifiers ) ;
@ -773,11 +752,8 @@ void seat_set_focus_layer(struct sway_seat *seat,
struct wlr_layer_surface * layer ) {
struct wlr_layer_surface * layer ) {
if ( ! layer & & seat - > focused_layer ) {
if ( ! layer & & seat - > focused_layer ) {
seat - > focused_layer = NULL ;
seat - > focused_layer = NULL ;
struct sway_container * previous =
struct sway_node * previous = seat_get_focus_inactive ( seat , & root - > node ) ;
seat_get_focus_inactive ( seat , & root_container ) ;
if ( previous ) {
if ( previous ) {
wlr_log ( WLR_DEBUG , " Returning focus to %p %s '%s' " , previous ,
container_type_to_str ( previous - > type ) , previous - > name ) ;
// Hack to get seat to re-focus the return value of get_focus
// Hack to get seat to re-focus the return value of get_focus
seat_set_focus ( seat , NULL ) ;
seat_set_focus ( seat , NULL ) ;
seat_set_focus ( seat , previous ) ;
seat_set_focus ( seat , previous ) ;
@ -798,13 +774,9 @@ void seat_set_exclusive_client(struct sway_seat *seat,
seat - > exclusive_client = client ;
seat - > exclusive_client = client ;
// Triggers a refocus of the topmost surface layer if necessary
// Triggers a refocus of the topmost surface layer if necessary
// TODO: Make layer surface focus per-output based on cursor position
// TODO: Make layer surface focus per-output based on cursor position
for ( int i = 0 ; i < root_container . children - > length ; + + i ) {
for ( int i = 0 ; i < root - > outputs - > length ; + + i ) {
struct sway_container * output = root_container . children - > items [ i ] ;
struct sway_output * output = root - > outputs - > items [ i ] ;
if ( ! sway_assert ( output - > type = = C_OUTPUT ,
arrange_layers ( output ) ;
" root container has non-output child " ) ) {
continue ;
}
arrange_layers ( output - > sway_output ) ;
}
}
return ;
return ;
}
}
@ -814,9 +786,9 @@ void seat_set_exclusive_client(struct sway_seat *seat,
}
}
}
}
if ( seat - > has_focus ) {
if ( seat - > has_focus ) {
struct sway_ container * focus = seat_get_focus ( seat ) ;
struct sway_ node * focus = seat_get_focus ( seat ) ;
if ( focus - > type = = C_VIEW & & wl_resource_get_client (
if ( node_is_view ( focus ) & & wl_resource_get_client (
focus - > sway_ view- > surface - > resource ) ! = client ) {
focus - > sway_ container- > view- > surface - > resource ) ! = client ) {
seat_set_focus ( seat , NULL ) ;
seat_set_focus ( seat , NULL ) ;
}
}
}
}
@ -837,79 +809,101 @@ void seat_set_exclusive_client(struct sway_seat *seat,
seat - > exclusive_client = client ;
seat - > exclusive_client = client ;
}
}
struct sway_container * seat_get_focus_inactive ( struct sway_seat * seat ,
struct sway_node * seat_get_focus_inactive ( struct sway_seat * seat ,
struct sway_container * con ) {
struct sway_node * node ) {
if ( con - > type = = C_WORKSPACE & & ! con - > children - > length & &
if ( node_is_view ( node ) ) {
! con - > sway_workspace - > floating - > length ) {
return node ;
return con ;
}
if ( con - > type = = C_VIEW ) {
return con ;
}
}
struct sway_seat_ container * current ;
struct sway_seat_node * current ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
if ( container_has_ancestor( current - > container , con ) ) {
if ( node_has_ancestor ( current - > node , node ) ) {
return current - > container ;
return current - > node ;
}
}
}
}
if ( node - > type = = N_WORKSPACE ) {
return node ;
}
return NULL ;
return NULL ;
}
}
struct sway_container * seat_get_focus_inactive_tiling ( struct sway_seat * seat ,
struct sway_container * seat_get_focus_inactive_tiling ( struct sway_seat * seat ,
struct sway_ container * ancestor ) {
struct sway_ workspace * workspace ) {
if ( ancestor - > type = = C_WORKSPACE & & ! ancestor - > children - > length ) {
if ( ! workspace - > tiling - > length ) {
return ancestor ;
return NULL ;
}
}
struct sway_seat_ container * current ;
struct sway_seat_ node * current ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
struct sway_container * con = current - > container ;
struct sway_node * node = current - > node ;
if ( ! container_is_floating_or_child ( con ) & &
if ( node - > type = = N_CONTAINER & &
container_has_ancestor ( current - > container , ancestor ) ) {
! container_is_floating_or_child ( node - > sway_container ) & &
return con ;
node - > sway_container - > workspace = = workspace ) {
return node - > sway_container ;
}
}
}
}
return NULL ;
return NULL ;
}
}
struct sway_container * seat_get_focus_inactive_floating ( struct sway_seat * seat ,
struct sway_container * seat_get_focus_inactive_floating ( struct sway_seat * seat ,
struct sway_container * ancestor ) {
struct sway_workspace * workspace ) {
if ( ancestor - > type = = C_WORKSPACE & &
if ( ! workspace - > floating - > length ) {
! ancestor - > sway_workspace - > floating - > length ) {
return NULL ;
return NULL ;
}
}
struct sway_seat_ container * current ;
struct sway_seat_ node * current ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
struct sway_container * con = current - > container ;
struct sway_node * node = current - > node ;
if ( container_is_floating_or_child ( con ) & &
if ( node - > type = = N_CONTAINER & &
container_has_ancestor ( current - > container , ancestor ) ) {
container_is_floating_or_child ( node - > sway_container ) & &
return con ;
node - > sway_container - > workspace = = workspace ) {
return node - > sway_container ;
}
}
}
}
return NULL ;
return NULL ;
}
}
struct sway_ container * seat_get_active_child ( struct sway_seat * seat ,
struct sway_ node * seat_get_active_child ( struct sway_seat * seat ,
struct sway_ container * parent ) {
struct sway_ node * parent ) {
if ( parent - > type = = C_VIEW ) {
if ( node_is_view ( parent ) ) {
return parent ;
return parent ;
}
}
struct sway_seat_ container * current ;
struct sway_seat_ node * current ;
wl_list_for_each ( current , & seat - > focus_stack , link ) {
wl_list_for_each ( current , & seat - > focus_stack , link ) {
struct sway_ container * con = current - > container ;
struct sway_ node * node = current - > node ;
if ( con - > parent = = parent ) {
if ( node_get_parent ( node ) = = parent ) {
return con ;
return node ;
}
}
}
}
return NULL ;
return NULL ;
}
}
struct sway_ container * seat_get_focus ( struct sway_seat * seat ) {
struct sway_ node * seat_get_focus ( struct sway_seat * seat ) {
if ( ! seat - > has_focus ) {
if ( ! seat - > has_focus ) {
return NULL ;
return NULL ;
}
}
struct sway_seat_ container * current =
struct sway_seat_ node * current =
wl_container_of ( seat - > focus_stack . next , current , link ) ;
wl_container_of ( seat - > focus_stack . next , current , link ) ;
return current - > container ;
return current - > node ;
}
struct sway_workspace * seat_get_focused_workspace ( struct sway_seat * seat ) {
struct sway_node * focus = seat_get_focus ( seat ) ;
if ( ! focus ) {
return NULL ;
}
if ( focus - > type = = N_CONTAINER ) {
return focus - > sway_container - > workspace ;
}
if ( focus - > type = = N_WORKSPACE ) {
return focus - > sway_workspace ;
}
return NULL ; // unreachable
}
struct sway_container * seat_get_focused_container ( struct sway_seat * seat ) {
struct sway_node * focus = seat_get_focus ( seat ) ;
if ( focus & & focus - > type = = N_CONTAINER ) {
return focus - > sway_container ;
}
return NULL ;
}
}
void seat_apply_config ( struct sway_seat * seat ,
void seat_apply_config ( struct sway_seat * seat ,