@ -93,7 +93,9 @@ struct shell_surface {
struct shell_surface * parent ;
enum shell_surface_type type ;
enum shell_surface_type prev_type ;
int32_t saved_x , saved_y ;
bool saved_position_valid ;
struct {
struct weston_transform transform ;
@ -108,6 +110,13 @@ struct shell_surface {
int32_t initial_up ;
} popup ;
struct {
enum wl_shell_surface_fullscreen_method type ;
struct weston_transform transform ; /* matrix from x, y */
uint32_t framerate ;
struct weston_surface * black_surface ;
} fullscreen ;
struct weston_output * fullscreen_output ;
struct weston_output * output ;
struct wl_list link ;
@ -133,6 +142,10 @@ struct rotate_grab {
} center ;
} ;
static void
center_on_output ( struct weston_surface * surface ,
struct weston_output * output ) ;
static void
shell_configuration ( struct wl_shell * shell )
{
@ -303,7 +316,8 @@ weston_surface_resize(struct shell_surface *shsurf,
{
struct weston_resize_grab * resize ;
/* FIXME: Reject if fullscreen */
if ( shsurf - > type = = SHELL_SURFACE_FULLSCREEN )
return 0 ;
if ( edges = = 0 | | edges > 15 | |
( edges & 3 ) = = 3 | | ( edges & 12 ) = = 12 )
@ -334,7 +348,8 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
struct weston_input_device * wd = input_resource - > data ;
struct shell_surface * shsurf = resource - > data ;
/* FIXME: Reject if fullscreen */
if ( shsurf - > type = = SHELL_SURFACE_FULLSCREEN )
return ;
if ( wd - > input_device . button_count = = 0 | |
wd - > input_device . grab_time ! = time | |
@ -352,15 +367,26 @@ get_default_output(struct weston_compositor *compositor)
struct weston_output , link ) ;
}
static void
shell_unset_fullscreen ( struct shell_surface * shsurf )
{
/* undo all fullscreen things here */
shsurf - > fullscreen . type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT ;
shsurf - > fullscreen . framerate = 0 ;
wl_list_remove ( & shsurf - > fullscreen . transform . link ) ;
wl_list_init ( & shsurf - > fullscreen . transform . link ) ;
weston_surface_destroy ( shsurf - > fullscreen . black_surface ) ;
shsurf - > fullscreen . black_surface = NULL ;
shsurf - > fullscreen_output = NULL ;
shsurf - > surface - > force_configure = 1 ;
}
static int
reset_shell_surface_type ( struct shell_surface * surface )
{
switch ( surface - > type ) {
case SHELL_SURFACE_FULLSCREEN :
weston_surface_set_position ( surface - > surface ,
surface - > saved_x ,
surface - > saved_y ) ;
surface - > fullscreen_output = NULL ;
shell_unset_fullscreen ( surface ) ;
break ;
case SHELL_SURFACE_MAXIMIZED :
surface - > output = get_default_output ( surface - > surface - > compositor ) ;
@ -386,6 +412,7 @@ reset_shell_surface_type(struct shell_surface *surface)
break ;
}
surface - > prev_type = surface - > type ;
surface - > type = SHELL_SURFACE_NONE ;
return 0 ;
}
@ -474,6 +501,7 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf - > saved_x = es - > geometry . x ;
shsurf - > saved_y = es - > geometry . y ;
shsurf - > saved_position_valid = true ;
wlshell = shell_surface_get_shell ( shsurf ) ;
panel_height = get_output_panel_height ( wlshell , es - > output ) ;
@ -487,6 +515,96 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf - > type = SHELL_SURFACE_MAXIMIZED ;
}
static struct weston_surface *
create_black_surface ( struct weston_compositor * ec ,
GLfloat x , GLfloat y , int w , int h )
{
struct weston_surface * surface = NULL ;
surface = weston_surface_create ( ec ) ;
if ( surface = = NULL ) {
fprintf ( stderr , " no memory \n " ) ;
return NULL ;
}
weston_surface_configure ( surface , x , y , w , h ) ;
weston_surface_set_color ( surface , 0.0 , 0.0 , 0.0 , 1 ) ;
return surface ;
}
/* Create black surface and append it to the associated fullscreen surface.
* Handle size dismatch and positioning according to the method . */
static void
shell_configure_fullscreen ( struct shell_surface * shsurf )
{
struct weston_output * output = shsurf - > fullscreen_output ;
struct weston_surface * surface = shsurf - > surface ;
struct weston_matrix * matrix ;
float scale ;
center_on_output ( surface , output ) ;
if ( ! shsurf - > fullscreen . black_surface )
shsurf - > fullscreen . black_surface = create_black_surface ( surface - > compositor ,
output - > x , output - > y ,
output - > current - > width , output - > current - > height ) ;
wl_list_remove ( & shsurf - > fullscreen . black_surface - > link ) ;
wl_list_insert ( & surface - > link , & shsurf - > fullscreen . black_surface - > link ) ;
shsurf - > fullscreen . black_surface - > output = output ;
switch ( shsurf - > fullscreen . type ) {
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT :
break ;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE :
matrix = & shsurf - > fullscreen . transform . matrix ;
weston_matrix_init ( matrix ) ;
scale = ( float ) output - > current - > width / ( float ) surface - > geometry . width ;
weston_matrix_scale ( matrix , scale , scale , 1 ) ;
wl_list_remove ( & shsurf - > fullscreen . transform . link ) ;
wl_list_insert ( surface - > geometry . transformation_list . prev ,
& shsurf - > fullscreen . transform . link ) ;
weston_surface_set_position ( surface , output - > x , output - > y ) ;
break ;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER :
break ;
case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL :
break ;
default :
break ;
}
}
/* make the fullscreen and black surface at the top */
static void
shell_stack_fullscreen ( struct shell_surface * shsurf )
{
struct weston_surface * surface = shsurf - > surface ;
struct wl_shell * shell = shell_surface_get_shell ( shsurf ) ;
struct wl_list * list ;
wl_list_remove ( & surface - > link ) ;
wl_list_remove ( & shsurf - > fullscreen . black_surface - > link ) ;
if ( shell - > locked ) {
wl_list_insert ( & shell - > hidden_surface_list , & surface - > link ) ;
wl_list_insert ( & surface - > link , & shsurf - > fullscreen . black_surface - > link ) ;
} else {
list = weston_compositor_top ( surface - > compositor ) ;
wl_list_insert ( list , & surface - > link ) ;
wl_list_insert ( & surface - > link , & shsurf - > fullscreen . black_surface - > link ) ;
weston_surface_damage ( surface ) ;
weston_surface_damage ( shsurf - > fullscreen . black_surface ) ;
}
}
static void
shell_map_fullscreen ( struct shell_surface * shsurf )
{
shell_configure_fullscreen ( shsurf ) ;
shell_stack_fullscreen ( shsurf ) ;
}
static void
shell_surface_set_fullscreen ( struct wl_client * client ,
struct wl_resource * resource ,
@ -496,21 +614,29 @@ shell_surface_set_fullscreen(struct wl_client *client,
{
struct shell_surface * shsurf = resource - > data ;
struct weston_surface * es = shsurf - > surface ;
struct weston_output * output ;
if ( output_resource )
shsurf - > output = output_resource - > data ;
else
shsurf - > output = get_default_output ( es - > compositor ) ;
if ( reset_shell_surface_type ( shsurf ) )
return ;
/* FIXME: Fullscreen on first output */
/* FIXME: Handle output going away */
output = get_default_output ( es - > compositor ) ;
if ( shsurf - > prev_type ! = SHELL_SURFACE_FULLSCREEN ) {
shsurf - > saved_x = es - > geometry . x ;
shsurf - > saved_y = es - > geometry . y ;
shsurf - > output = output ;
shsurf - > fullscreen_output = output ;
shsurf - > saved_position_valid = true ;
}
shsurf - > fullscreen_output = shsurf - > output ;
shsurf - > fullscreen . type = method ;
shsurf - > fullscreen . framerate = framerate ;
shsurf - > type = SHELL_SURFACE_FULLSCREEN ;
if ( es - > output )
shsurf - > surface - > force_configure = 1 ;
wl_resource_post_event ( resource ,
WL_SHELL_SURFACE_CONFIGURE ,
weston_compositor_get_time ( ) , 0 ,
@ -715,7 +841,13 @@ shell_get_shell_surface(struct wl_client *client,
( void ( * * ) ( void ) ) & shell_surface_implementation ;
shsurf - > resource . data = shsurf ;
shsurf - > saved_position_valid = false ;
shsurf - > surface = surface ;
shsurf - > fullscreen . type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT ;
shsurf - > fullscreen . framerate = 0 ;
shsurf - > fullscreen . black_surface = NULL ;
wl_list_init ( & shsurf - > fullscreen . transform . link ) ;
shsurf - > surface_destroy_listener . func = shell_handle_surface_destroy ;
wl_list_insert ( surface - > surface . resource . destroy_listener_list . prev ,
& shsurf - > surface_destroy_listener . link ) ;
@ -728,6 +860,7 @@ shell_get_shell_surface(struct wl_client *client,
weston_matrix_init ( & shsurf - > rotation . rotation ) ;
shsurf - > type = SHELL_SURFACE_NONE ;
shsurf - > prev_type = SHELL_SURFACE_NONE ;
wl_client_add_resource ( client , & shsurf - > resource ) ;
}
@ -1274,6 +1407,9 @@ activate(struct weston_shell *base, struct weston_surface *es,
& es - > link ) ;
}
break ;
case SHELL_SURFACE_FULLSCREEN :
/* should on top of panels */
break ;
default :
if ( ! shell - > locked ) {
list = weston_compositor_top ( compositor ) ;
@ -1296,8 +1432,17 @@ click_to_activate_binding(struct wl_input_device *device,
struct weston_input_device * wd = ( struct weston_input_device * ) device ;
struct weston_compositor * compositor = data ;
struct weston_surface * focus ;
struct weston_surface * upper ;
focus = ( struct weston_surface * ) device - > pointer_focus ;
upper = container_of ( focus - > link . prev , struct weston_surface , link ) ;
if ( focus - > link . prev ! = & compositor - > surface_list & &
get_shell_surface_type ( upper ) = = SHELL_SURFACE_FULLSCREEN ) {
printf ( " %s: focus is black surface, raise its fullscreen surface \n " , __func__ ) ;
shell_stack_fullscreen ( get_shell_surface ( upper ) ) ;
focus = upper ;
}
if ( state & & focus & & device - > pointer_grab = = & device - > default_pointer_grab )
activate ( compositor - > shell , focus , wd , time ) ;
}
@ -1444,9 +1589,11 @@ map(struct weston_shell *base, struct weston_surface *surface,
10 + random ( ) % 400 ) ;
break ;
case SHELL_SURFACE_SCREENSAVER :
case SHELL_SURFACE_FULLSCREEN :
center_on_output ( surface , shsurf - > fullscreen_output ) ;
break ;
case SHELL_SURFACE_FULLSCREEN :
shell_map_fullscreen ( shsurf ) ;
break ;
case SHELL_SURFACE_MAXIMIZED :
/* use surface configure to set the geometry */
panel_height = get_output_panel_height ( shell , surface - > output ) ;
@ -1496,6 +1643,9 @@ map(struct weston_shell *base, struct weston_surface *surface,
}
do_configure = 0 ;
break ;
case SHELL_SURFACE_FULLSCREEN :
do_configure = 1 ;
break ;
case SHELL_SURFACE_NONE :
do_configure = 0 ;
break ;
@ -1543,11 +1693,14 @@ configure(struct weston_shell *base, struct weston_surface *surface,
{
struct wl_shell * shell = container_of ( base , struct wl_shell , shell ) ;
enum shell_surface_type surface_type = SHELL_SURFACE_NONE ;
enum shell_surface_type prev_surface_type = SHELL_SURFACE_NONE ;
struct shell_surface * shsurf ;
shsurf = get_shell_surface ( surface ) ;
if ( shsurf )
if ( shsurf ) {
surface_type = shsurf - > type ;
prev_surface_type = shsurf - > prev_type ;
}
surface - > geometry . x = x ;
surface - > geometry . y = y ;
@ -1557,15 +1710,33 @@ configure(struct weston_shell *base, struct weston_surface *surface,
switch ( surface_type ) {
case SHELL_SURFACE_SCREENSAVER :
case SHELL_SURFACE_FULLSCREEN :
center_on_output ( surface , shsurf - > fullscreen_output ) ;
break ;
case SHELL_SURFACE_FULLSCREEN :
shell_configure_fullscreen ( shsurf ) ;
if ( prev_surface_type ! = SHELL_SURFACE_FULLSCREEN )
shell_stack_fullscreen ( shsurf ) ;
break ;
case SHELL_SURFACE_MAXIMIZED :
/* setting x, y and using configure to change that geometry */
surface - > geometry . x = surface - > output - > x ;
surface - > geometry . y = surface - > output - > y +
get_output_panel_height ( shell , surface - > output ) ;
break ;
case SHELL_SURFACE_TOPLEVEL :
if ( prev_surface_type ! = SHELL_SURFACE_TOPLEVEL ) {
if ( shsurf - > saved_position_valid & &
shsurf - > saved_x ! = surface - > geometry . x & &
shsurf - > saved_y ! = surface - > geometry . y ) {
weston_surface_set_position ( surface ,
shsurf - > saved_x ,
shsurf - > saved_y ) ;
} else if ( ! shsurf - > saved_position_valid ) {
weston_surface_set_position ( surface , 10 + random ( ) % 400 ,
10 + random ( ) % 400 ) ;
}
}
break ;
default :
break ;
}
@ -1573,6 +1744,7 @@ configure(struct weston_shell *base, struct weston_surface *surface,
/* XXX: would a fullscreen surface need the same handling? */
if ( surface - > output ) {
weston_surface_assign_output ( surface ) ;
weston_compositor_repick ( surface - > compositor ) ;
if ( surface_type = = SHELL_SURFACE_SCREENSAVER )
surface - > output = shsurf - > output ;