@ -137,7 +137,7 @@ struct wayland_output {
struct wayland_parent_output {
struct wayland_backend * backend ; /**< convenience */
struct wayland_output * output ;
struct wayland_head * head ;
struct wl_list link ;
struct wl_output * global ;
@ -161,6 +161,11 @@ struct wayland_parent_output {
struct weston_mode * current_mode ;
} ;
struct wayland_head {
struct weston_head base ;
struct wayland_parent_output * parent_output ;
} ;
struct wayland_shm_buffer {
struct wayland_output * output ;
struct wl_list link ;
@ -210,6 +215,12 @@ struct wayland_input {
struct gl_renderer_interface * gl_renderer ;
static inline struct wayland_head *
to_wayland_head ( struct weston_head * base )
{
return container_of ( base , struct wayland_head , base ) ;
}
static inline struct wayland_output *
to_wayland_output ( struct weston_output * base )
{
@ -1275,9 +1286,59 @@ err_output:
return - 1 ;
}
static struct wayland_output *
wayland_output_create_common ( struct weston_compositor * compositor ,
const char * name )
static int
wayland_output_setup_for_parent_output ( struct wayland_output * output ,
struct wayland_parent_output * poutput ) ;
static int
wayland_output_setup_fullscreen ( struct wayland_output * output ,
struct wayland_head * head ) ;
static int
wayland_output_attach_head ( struct weston_output * output_base ,
struct weston_head * head_base )
{
struct wayland_backend * b = to_wayland_backend ( output_base - > compositor ) ;
struct wayland_output * output = to_wayland_output ( output_base ) ;
struct wayland_head * head = to_wayland_head ( head_base ) ;
if ( ! wl_list_empty ( & output - > base . head_list ) )
return - 1 ;
if ( head - > parent_output ) {
if ( wayland_output_setup_for_parent_output ( output ,
head - > parent_output ) < 0 )
return - 1 ;
} else if ( b - > fullscreen ) {
if ( wayland_output_setup_fullscreen ( output , head ) < 0 )
return - 1 ;
} else {
/* A floating window, nothing to do. */
}
return 0 ;
}
static void
wayland_output_detach_head ( struct weston_output * output_base ,
struct weston_head * head )
{
struct wayland_output * output = to_wayland_output ( output_base ) ;
/* Rely on the disable hook if the output was enabled. We do not
* support cloned heads , so detaching is guaranteed to disable the
* output .
*/
if ( output - > base . enabled )
return ;
/* undo setup fullscreen */
if ( output - > parent . surface )
wayland_backend_destroy_output_surface ( output ) ;
}
static struct weston_output *
wayland_output_create ( struct weston_compositor * compositor , const char * name )
{
struct wayland_output * output ;
char * title ;
@ -1302,29 +1363,87 @@ wayland_output_create_common(struct weston_compositor *compositor,
output - > base . destroy = wayland_output_destroy ;
output - > base . disable = wayland_output_disable ;
output - > base . enable = wayland_output_enable ;
output - > base . attach_head = wayland_output_attach_head ;
output - > base . detach_head = wayland_output_detach_head ;
weston_compositor_add_pending_output ( & output - > base , compositor ) ;
return & output - > base ;
}
static struct wayland_head *
wayland_head_create ( struct weston_compositor * compositor , const char * name )
{
struct wayland_head * head ;
assert ( name ) ;
head = zalloc ( sizeof * head ) ;
if ( ! head )
return NULL ;
weston_head_init ( & head - > base , name ) ;
weston_head_set_connection_status ( & head - > base , true ) ;
weston_compositor_add_head ( compositor , & head - > base ) ;
return output ;
return head ;
}
static int
wayland_output_create ( struct weston_compositor * compositor , const char * name )
wayland_head_create_windowed ( struct weston_compositor * compositor ,
const char * name )
{
struct wayland_output * output ;
if ( ! wayland_head_create ( compositor , name ) )
return - 1 ;
output = wayland_output_create_common ( compositor , name ) ;
if ( ! output )
return 0 ;
}
static int
wayland_head_create_for_parent_output ( struct weston_compositor * compositor ,
struct wayland_parent_output * poutput )
{
struct wayland_head * head ;
char name [ 100 ] ;
int ret ;
ret = snprintf ( name , sizeof ( name ) , " wlparent-%d " , poutput - > id ) ;
if ( ret < 1 | | ( unsigned ) ret > = sizeof ( name ) )
return - 1 ;
weston_compositor_add_pending_output ( & output - > base , compositor ) ;
head = wayland_head_create ( compositor , name ) ;
if ( ! head )
return - 1 ;
assert ( ! poutput - > head ) ;
head - > parent_output = poutput ;
poutput - > head = head ;
weston_head_set_monitor_strings ( & head - > base ,
poutput - > physical . make ,
poutput - > physical . model , NULL ) ;
weston_head_set_physical_size ( & head - > base ,
poutput - > physical . width ,
poutput - > physical . height ) ;
return 0 ;
}
static void
wayland_head_destroy ( struct wayland_head * head )
{
if ( head - > parent_output )
head - > parent_output - > head = NULL ;
weston_head_release ( & head - > base ) ;
free ( head ) ;
}
static int
wayland_output_set_size ( struct weston_output * base , int width , int height )
{
struct wayland_output * output = to_wayland_output ( base ) ;
struct weston_head * head = & output - > base . head ;
struct weston_head * head ;
int output_width , output_height ;
/* We can only be called once. */
@ -1345,6 +1464,13 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
return - 1 ;
}
wl_list_for_each ( head , & output - > base . head_list , output_link ) {
weston_head_set_monitor_strings ( head , " wayland " , " none " , NULL ) ;
/* XXX: Calculate proper size. */
weston_head_set_physical_size ( head , width , height ) ;
}
output_width = width * output - > base . scale ;
output_height = height * output - > base . scale ;
@ -1358,25 +1484,15 @@ wayland_output_set_size(struct weston_output *base, int width, int height)
output - > base . current_mode = & output - > mode ;
weston_head_set_monitor_strings ( head , " wayland " , " none " , NULL ) ;
/* XXX: Calculate proper size. */
weston_head_set_physical_size ( head , width , height ) ;
return 0 ;
}
static int
wayland_output_create _for_parent_output ( struct wayland_backend * b ,
struct wayland_parent_output * poutput )
wayland_output_setup_for_parent_output ( struct wayland_output * output ,
struct wayland_parent_output * poutput )
{
struct wayland_output * output ;
struct weston_mode * mode ;
output = wayland_output_create_common ( b - > compositor , " wlparent " ) ;
if ( ! output )
return - 1 ;
if ( poutput - > current_mode ) {
mode = poutput - > current_mode ;
} else if ( poutput - > preferred_mode ) {
@ -1386,7 +1502,7 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
struct weston_mode , link ) ;
} else {
weston_log ( " No valid modes found. Skipping output. \n " ) ;
goto out ;
return - 1 ;
}
output - > base . scale = 1 ;
@ -1394,13 +1510,6 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
output - > parent . output = poutput - > global ;
weston_head_set_monitor_strings ( & output - > base . head ,
poutput - > physical . make ,
poutput - > physical . model , NULL ) ;
weston_head_set_physical_size ( & output - > base . head ,
poutput - > physical . width ,
poutput - > physical . height ) ;
wl_list_insert_list ( & output - > base . mode_list , & poutput - > mode_list ) ;
wl_list_init ( & poutput - > mode_list ) ;
@ -1410,33 +1519,21 @@ wayland_output_create_for_parent_output(struct wayland_backend *b,
/* output->mode is unused in this path. */
weston_compositor_add_pending_output ( & output - > base , b - > compositor ) ;
return 0 ;
out :
weston_output_release ( & output - > base ) ;
free ( output - > title ) ;
free ( output ) ;
return - 1 ;
}
static int
wayland_output_create_fullscreen ( struct wayland_backend * b )
wayland_output_setup_fullscreen ( struct wayland_output * output ,
struct wayland_head * head )
{
struct wayland_output * output ;
struct wayland_backend * b = to_wayland_backend ( output - > base . compositor ) ;
int width = 0 , height = 0 ;
output = wayland_output_create_common ( b - > compositor , " wayland-fullscreen " ) ;
if ( ! output )
return - 1 ;
output - > base . scale = 1 ;
output - > base . transform = WL_OUTPUT_TRANSFORM_NORMAL ;
if ( wayland_backend_create_output_surface ( output ) < 0 )
goto err_surface ;
return - 1 ;
/* What should size be set if conditional is false? */
if ( b - > parent . xdg_shell | | b - > parent . shell ) {
@ -1456,16 +1553,15 @@ wayland_output_create_fullscreen(struct wayland_backend *b)
if ( wayland_output_set_size ( & output - > base , width , height ) < 0 )
goto err_set_size ;
weston_compositor_add_pending_output ( & output - > base , b - > compositor ) ;
/* The head is not attached yet, so set_size did not set these. */
weston_head_set_monitor_strings ( & head - > base , " wayland " , " none " , NULL ) ;
/* XXX: Calculate proper size. */
weston_head_set_physical_size ( & head - > base , width , height ) ;
return 0 ;
err_set_size :
wayland_backend_destroy_output_surface ( output ) ;
err_surface :
weston_output_release ( & output - > base ) ;
free ( output - > title ) ;
free ( output ) ;
return - 1 ;
}
@ -2286,16 +2382,32 @@ find_mode(struct wl_list *list, int32_t width, int32_t height, uint32_t refresh)
return mode ;
}
static struct weston_output *
wayland_parent_output_get_enabled_output ( struct wayland_parent_output * poutput )
{
struct wayland_head * head = poutput - > head ;
if ( ! head )
return NULL ;
if ( ! weston_head_is_enabled ( & head - > base ) )
return NULL ;
return weston_head_get_output ( & head - > base ) ;
}
static void
wayland_parent_output_mode ( void * data , struct wl_output * wl_output_proxy ,
uint32_t flags , int32_t width , int32_t height ,
int32_t refresh )
{
struct wayland_parent_output * output = data ;
struct weston_output * enabled_output ;
struct weston_mode * mode ;
if ( output - > output ) {
mode = find_mode ( & output - > output - > base . mode_list ,
enabled_output = wayland_parent_output_get_enabled_output ( output ) ;
if ( enabled_output ) {
mode = find_mode ( & enabled_output - > mode_list ,
width , height , refresh ) ;
if ( ! mode )
return ;
@ -2329,7 +2441,7 @@ output_sync_callback(void *data, struct wl_callback *callback, uint32_t unused)
assert ( output - > backend - > sprawl_across_outputs ) ;
wayland_output _create_for_parent_output ( output - > backend , output ) ;
wayland_head _create_for_parent_output ( output - > backend - > compositor , output ) ;
}
static const struct wl_callback_listener output_sync_listener = {
@ -2377,8 +2489,8 @@ wayland_parent_output_destroy(struct wayland_parent_output *output)
if ( output - > sync_cb )
wl_callback_destroy ( output - > sync_cb ) ;
if ( output - > output )
wayland_output_destroy ( & output - > output - > base ) ;
if ( output - > head )
wayland_head_destroy ( output - > head ) ;
wl_output_destroy ( output - > global ) ;
free ( output - > physical . make ) ;
@ -2483,11 +2595,15 @@ static void
wayland_destroy ( struct weston_compositor * ec )
{
struct wayland_backend * b = to_wayland_backend ( ec ) ;
struct weston_head * base , * next ;
wl_event_source_remove ( b - > parent . wl_source ) ;
weston_compositor_shutdown ( ec ) ;
wl_list_for_each_safe ( base , next , & ec - > head_list , compositor_link )
wayland_head_destroy ( to_wayland_head ( base ) ) ;
if ( b - > parent . shm )
wl_shm_destroy ( b - > parent . shm ) ;
@ -2642,6 +2758,7 @@ wayland_backend_create(struct weston_compositor *compositor,
}
b - > base . destroy = wayland_destroy ;
b - > base . create_output = wayland_output_create ;
loop = wl_display_get_event_loop ( compositor - > wl_display ) ;
@ -2686,7 +2803,7 @@ wayland_backend_destroy(struct wayland_backend *b)
static const struct weston_windowed_output_api windowed_api = {
wayland_output_set_size ,
wayland_output_create ,
wayland_head_create_windowed ,
} ;
static void
@ -2723,14 +2840,14 @@ weston_backend_init(struct weston_compositor *compositor,
wl_display_roundtrip ( b - > parent . wl_display ) ;
wl_list_for_each ( poutput , & b - > parent . output_list , link )
wayland_output_create_for_parent_output ( b , poutput ) ;
wayland_head_create_for_parent_output ( compositor , poutput ) ;
return 0 ;
}
if ( new_config . fullscreen ) {
if ( wayland_output_create_fullscreen ( b ) < 0 ) {
weston_log ( " Unable to create a fullscreen output . \n " ) ;
if ( ! wayland_head_create ( compositor , " wayland-fullscreen " ) ) {
weston_log ( " Unable to create a fullscreen head . \n " ) ;
goto err_outputs ;
}