@ -9,6 +9,7 @@
# include <wlr/types/wlr_cursor.h>
# include <wlr/types/wlr_cursor.h>
# include <wlr/types/wlr_output_layout.h>
# include <wlr/types/wlr_output_layout.h>
# include <wlr/types/wlr_output.h>
# include <wlr/types/wlr_output.h>
# include <wlr/types/wlr_output_swapchain_manager.h>
# include "sway/config.h"
# include "sway/config.h"
# include "sway/input/cursor.h"
# include "sway/input/cursor.h"
# include "sway/output.h"
# include "sway/output.h"
@ -716,39 +717,138 @@ struct output_config *find_output_config(struct sway_output *output) {
return get_output_config ( id , output ) ;
return get_output_config ( id , output ) ;
}
}
void apply_output_config_to_outputs ( struct output_config * oc ) {
bool apply_output_configs ( struct matched_output_config * configs ,
// Try to find the output container and apply configuration now. If
size_t configs_len , bool test_only ) {
// this is during startup then there will be no container and config
struct wlr_backend_output_state * states = calloc ( configs_len , sizeof ( * states ) ) ;
// will be applied during normal "new output" event from wlroots.
if ( ! states ) {
bool wildcard = strcmp ( oc - > name , " * " ) = = 0 ;
return false ;
struct sway_output * sway_output , * tmp ;
wl_list_for_each_safe ( sway_output , tmp , & root - > all_outputs , link ) {
if ( output_match_name_or_id ( sway_output , oc - > name ) ) {
char id [ 128 ] ;
output_get_identifier ( id , sizeof ( id ) , sway_output ) ;
struct output_config * current = get_output_config ( id , sway_output ) ;
if ( ! current ) {
// No stored output config matched, apply oc directly
sway_log ( SWAY_DEBUG , " Applying oc directly " ) ;
current = new_output_config ( oc - > name ) ;
merge_output_config ( current , oc ) ;
}
}
apply_output_config ( current , sway_output ) ;
free_output_config ( current ) ;
if ( ! wildcard ) {
sway_log ( SWAY_DEBUG , " Committing %zd outputs " , configs_len ) ;
// Stop looking if the output config isn't applicable to all
for ( size_t idx = 0 ; idx < configs_len ; idx + + ) {
// outputs
struct matched_output_config * cfg = & configs [ idx ] ;
break ;
struct wlr_backend_output_state * backend_state = & states [ idx ] ;
backend_state - > output = cfg - > output - > wlr_output ;
wlr_output_state_init ( & backend_state - > base ) ;
sway_log ( SWAY_DEBUG , " Preparing config for %s " ,
cfg - > output - > wlr_output - > name ) ;
queue_output_config ( cfg - > config , cfg - > output , & backend_state - > base ) ;
}
struct wlr_output_swapchain_manager swapchain_mgr ;
wlr_output_swapchain_manager_init ( & swapchain_mgr , server . backend ) ;
bool ok = wlr_output_swapchain_manager_prepare ( & swapchain_mgr , states , configs_len ) ;
if ( ! ok ) {
sway_log ( SWAY_ERROR , " Swapchain prepare failed " ) ;
goto out ;
}
if ( test_only ) {
// The swapchain manager already did a test for us
goto out ;
}
for ( size_t idx = 0 ; idx < configs_len ; idx + + ) {
struct matched_output_config * cfg = & configs [ idx ] ;
struct wlr_backend_output_state * backend_state = & states [ idx ] ;
struct wlr_scene_output_state_options opts = {
. swapchain = wlr_output_swapchain_manager_get_swapchain (
& swapchain_mgr , backend_state - > output ) ,
} ;
struct wlr_scene_output * scene_output = cfg - > output - > scene_output ;
struct wlr_output_state * state = & backend_state - > base ;
if ( ! wlr_scene_output_build_state ( scene_output , state , & opts ) ) {
sway_log ( SWAY_ERROR , " Building output state for '%s' failed " ,
backend_state - > output - > name ) ;
goto out ;
}
}
}
}
ok = wlr_backend_commit ( server . backend , states , configs_len ) ;
if ( ! ok ) {
sway_log ( SWAY_ERROR , " Backend commit failed " ) ;
goto out ;
}
}
sway_log ( SWAY_DEBUG , " Commit of %zd outputs succeeded " , configs_len ) ;
wlr_output_swapchain_manager_apply ( & swapchain_mgr ) ;
for ( size_t idx = 0 ; idx < configs_len ; idx + + ) {
struct matched_output_config * cfg = & configs [ idx ] ;
sway_log ( SWAY_DEBUG , " Finalizing config for %s " ,
cfg - > output - > wlr_output - > name ) ;
finalize_output_config ( cfg - > config , cfg - > output ) ;
}
out :
wlr_output_swapchain_manager_finish ( & swapchain_mgr ) ;
for ( size_t idx = 0 ; idx < configs_len ; idx + + ) {
struct wlr_backend_output_state * backend_state = & states [ idx ] ;
wlr_output_state_finish ( & backend_state - > base ) ;
}
free ( states ) ;
// Reconfigure all devices, since input config may have been applied before
// this output came online, and some config items (like map_to_output) are
// dependent on an output being present.
input_manager_configure_all_input_mappings ( ) ;
// Reconfigure the cursor images, since the scale may have changed.
input_manager_configure_xcursor ( ) ;
struct sway_seat * seat ;
struct sway_seat * seat ;
wl_list_for_each ( seat , & server . input - > seats , link ) {
wl_list_for_each ( seat , & server . input - > seats , link ) {
wlr_seat_pointer_notify_clear_focus ( seat - > wlr_seat ) ;
wlr_seat_pointer_notify_clear_focus ( seat - > wlr_seat ) ;
cursor_rebase ( seat - > cursor ) ;
cursor_rebase ( seat - > cursor ) ;
}
}
return ok ;
}
void apply_output_config_to_outputs ( struct output_config * oc ) {
size_t configs_len = wl_list_length ( & root - > all_outputs ) ;
struct matched_output_config * configs = calloc ( configs_len , sizeof ( * configs ) ) ;
if ( ! configs ) {
return ;
}
// Try to find the output container and apply configuration now. If
// this is during startup then there will be no container and config
// will be applied during normal "new output" event from wlroots.
int config_idx = 0 ;
struct sway_output * sway_output ;
wl_list_for_each ( sway_output , & root - > all_outputs , link ) {
if ( sway_output = = root - > fallback_output ) {
configs_len - - ;
continue ;
}
struct matched_output_config * config = & configs [ config_idx + + ] ;
config - > output = sway_output ;
config - > config = find_output_config ( sway_output ) ;
if ( ! output_match_name_or_id ( sway_output , oc - > name ) ) {
continue ;
}
if ( ! config - > config & & oc ) {
// No stored output config matched, apply oc directly
sway_log ( SWAY_DEBUG , " Applying oc directly " ) ;
config - > config = new_output_config ( oc - > name ) ;
merge_output_config ( config - > config , oc ) ;
}
}
apply_output_configs ( configs , configs_len , false ) ;
for ( size_t idx = 0 ; idx < configs_len ; idx + + ) {
struct matched_output_config * cfg = & configs [ idx ] ;
free_output_config ( cfg - > config ) ;
}
free ( configs ) ;
}
}
void reset_outputs ( void ) {
void reset_outputs ( void ) {