diff options
| -rw-r--r-- | include/rootston/desktop.h | 2 | ||||
| -rw-r--r-- | include/rootston/view.h | 27 | ||||
| -rw-r--r-- | rootston/desktop.c | 90 | ||||
| -rw-r--r-- | rootston/output.c | 38 | ||||
| -rw-r--r-- | rootston/wl_shell.c | 3 | ||||
| -rw-r--r-- | rootston/xdg_shell_v6.c | 3 | ||||
| -rw-r--r-- | rootston/xwayland.c | 17 | 
7 files changed, 162 insertions, 18 deletions
diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 812bb42a..388fb55d 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -64,7 +64,7 @@ struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx,  	double ly, struct wlr_surface **surface, double *sx, double *sy);  void view_init(struct roots_view *view, struct roots_desktop *desktop); -void view_destroy(struct roots_view *view); +void view_finish(struct roots_view *view);  void view_activate(struct roots_view *view, bool activate);  void view_apply_damage(struct roots_view *view);  void view_damage_whole(struct roots_view *view); diff --git a/include/rootston/view.h b/include/rootston/view.h index 579b148a..6c5e0573 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -91,7 +91,11 @@ struct roots_view {  		struct roots_xwayland_surface *roots_xwayland_surface;  #endif  	}; +  	struct wlr_surface *wlr_surface; +	struct wl_list children; // roots_view_child::link + +	struct wl_listener new_subsurface;  	struct {  		struct wl_signal destroy; @@ -112,6 +116,21 @@ struct roots_view {  	void (*close)(struct roots_view *view);  }; +struct roots_view_child { +	struct roots_view *view; +	struct wlr_surface *wlr_surface; +	struct wl_list link; + +	struct wl_listener commit; +	struct wl_listener new_subsurface; +}; + +struct roots_subsurface { +	struct roots_view_child view_child; +	struct wlr_subsurface *wlr_subsurface; +	struct wl_listener destroy; +}; +  void view_get_box(const struct roots_view *view, struct wlr_box *box);  void view_activate(struct roots_view *view, bool active);  void view_move(struct roots_view *view, double x, double y); @@ -126,4 +145,12 @@ bool view_center(struct roots_view *view);  void view_setup(struct roots_view *view);  void view_teardown(struct roots_view *view); +void view_child_init(struct roots_view_child *child, struct roots_view *view, +	struct wlr_surface *wlr_surface); +void view_child_finish(struct roots_view_child *child); + +struct roots_subsurface *subsurface_create(struct roots_view *view, +	struct wlr_subsurface *wlr_subsurface); +void subsurface_destroy(struct roots_subsurface *subsurface); +  #endif diff --git a/rootston/desktop.c b/rootston/desktop.c index e36ae6a4..191338a8 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -254,20 +254,106 @@ bool view_center(struct roots_view *view) {  	return true;  } -void view_destroy(struct roots_view *view) { +void view_child_finish(struct roots_view_child *child) { +	if (child == NULL) { +		return; +	} +	view_damage_whole(child->view); +	wl_list_remove(&child->link); +	wl_list_remove(&child->commit.link); +	wl_list_remove(&child->new_subsurface.link); +} + +static void view_child_handle_commit(struct wl_listener *listener, +		void *data) { +	struct roots_view_child *child = wl_container_of(listener, child, commit); +	view_apply_damage(child->view); +} + +static void view_child_handle_new_subsurface(struct wl_listener *listener, +		void *data) { +	struct roots_view_child *child = +		wl_container_of(listener, child, new_subsurface); +	struct wlr_subsurface *wlr_subsurface = data; +	subsurface_create(child->view, wlr_subsurface); +} + +void view_child_init(struct roots_view_child *child, struct roots_view *view, +		struct wlr_surface *wlr_surface) { +	child->view = view; +	child->wlr_surface = wlr_surface; +	child->commit.notify = view_child_handle_commit; +	wl_signal_add(&wlr_surface->events.commit, &child->commit); +	child->new_subsurface.notify = view_child_handle_new_subsurface; +	wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface); +	wl_list_insert(&view->children, &child->link); +} + +static void subsurface_handle_destroy(struct wl_listener *listener, +		void *data) { +	struct roots_subsurface *subsurface = +		wl_container_of(listener, subsurface, destroy); +	subsurface_destroy(subsurface); +} + +struct roots_subsurface *subsurface_create(struct roots_view *view, +		struct wlr_subsurface *wlr_subsurface) { +	struct roots_subsurface *subsurface = +		calloc(1, sizeof(struct roots_subsurface)); +	if (subsurface == NULL) { +		return NULL; +	} +	subsurface->wlr_subsurface = wlr_subsurface; +	view_child_init(&subsurface->view_child, view, wlr_subsurface->surface); +	subsurface->destroy.notify = subsurface_handle_destroy; +	wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); +	return subsurface; +} + +void subsurface_destroy(struct roots_subsurface *subsurface) { +	if (subsurface == NULL) { +		return; +	} +	wl_list_remove(&subsurface->destroy.link); +	view_child_finish(&subsurface->view_child); +	free(subsurface); +} + +void view_finish(struct roots_view *view) {  	view_damage_whole(view);  	wl_signal_emit(&view->events.destroy, view); +	wl_list_remove(&view->new_subsurface.link); +  	if (view->fullscreen_output) {  		view->fullscreen_output->fullscreen_view = NULL;  	} +} -	free(view); +static void view_handle_new_subsurface(struct wl_listener *listener, +		void *data) { +	struct roots_view *view = wl_container_of(listener, view, new_subsurface); +	struct wlr_subsurface *wlr_subsurface = data; +	subsurface_create(view, wlr_subsurface);  }  void view_init(struct roots_view *view, struct roots_desktop *desktop) { +	assert(view->wlr_surface); +  	view->desktop = desktop;  	wl_signal_init(&view->events.destroy); +	wl_list_init(&view->children); + +	struct wlr_subsurface *subsurface; +	wl_list_for_each(subsurface, &view->wlr_surface->subsurface_list, +			parent_link) { +		subsurface_create(view, subsurface); +	} + +	view->new_subsurface.notify = view_handle_new_subsurface; +	wl_signal_add(&view->wlr_surface->events.new_subsurface, +		&view->new_subsurface); +  	view_damage_whole(view);  } diff --git a/rootston/output.c b/rootston/output.c index f8da9c77..1c966e08 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -444,7 +444,7 @@ static void output_damage_whole(struct roots_output *output) {  }  static void output_damage_whole_surface(struct roots_output *output, -		struct wlr_surface *surface, double lx, double ly) { +		struct wlr_surface *surface, double lx, double ly, float rotation) {  	if (!wlr_surface_has_buffer(surface)) {  		return;  	} @@ -460,6 +460,18 @@ static void output_damage_whole_surface(struct roots_output *output,  		box.x, box.y, box.width, box.height);  	schedule_render(output); + +	struct wlr_subsurface *subsurface; +	wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { +		struct wlr_surface_state *state = subsurface->surface->current; +		double sx = state->subsurface_position.x; +		double sy = state->subsurface_position.y; +		rotate_child_position(&sx, &sy, state->width, state->height, +			surface->current->width, surface->current->height, rotation); + +		output_damage_whole_surface(output, subsurface->surface, +			lx + sx, ly + sy, rotation); +	}  }  void output_damage_whole_view(struct roots_output *output, @@ -469,14 +481,15 @@ void output_damage_whole_view(struct roots_output *output,  	}  	if (view->wlr_surface != NULL) { -		output_damage_whole_surface(output, view->wlr_surface, view->x, view->y); +		output_damage_whole_surface(output, view->wlr_surface, +			view->x, view->y, view->rotation);  	} -	// TODO: subsurfaces, popups, etc +	// TODO: popups, etc  }  static void output_damage_from_surface(struct roots_output *output, -		struct wlr_surface *surface, double lx, double ly) { +		struct wlr_surface *surface, double lx, double ly, float rotation) {  	if (!wlr_surface_has_buffer(surface)) {  		return;  	} @@ -497,6 +510,18 @@ static void output_damage_from_surface(struct roots_output *output,  	pixman_region32_fini(&damage);  	schedule_render(output); + +	struct wlr_subsurface *subsurface; +	wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { +		struct wlr_surface_state *state = subsurface->surface->current; +		double sx = state->subsurface_position.x; +		double sy = state->subsurface_position.y; +		rotate_child_position(&sx, &sy, state->width, state->height, +			surface->current->width, surface->current->height, rotation); + +		output_damage_from_surface(output, subsurface->surface, +			lx + sx, ly + sy, rotation); +	}  }  void output_damage_from_view(struct roots_output *output, @@ -506,10 +531,11 @@ void output_damage_from_view(struct roots_output *output,  	}  	if (view->wlr_surface != NULL) { -		output_damage_from_surface(output, view->wlr_surface, view->x, view->y); +		output_damage_from_surface(output, view->wlr_surface, +			view->x, view->y, view->rotation);  	} -	// TODO: subsurfaces, popups, etc +	// TODO: popups, etc  }  static void output_handle_mode(struct wl_listener *listener, void *data) { diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index f7b09db0..be658f40 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -118,7 +118,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {  	wl_list_remove(&roots_surface->set_state.link);  	wl_list_remove(&roots_surface->surface_commit.link);  	wl_list_remove(&roots_surface->view->link); -	view_destroy(roots_surface->view); +	view_finish(roots_surface->view); +	free(roots_surface->view);  	free(roots_surface);  } diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 295be6a2..7337fb1e 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -231,7 +231,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {  	wl_list_remove(&roots_xdg_surface->request_move.link);  	wl_list_remove(&roots_xdg_surface->request_resize.link);  	wl_list_remove(&roots_xdg_surface->view->link); -	view_destroy(roots_xdg_surface->view); +	view_finish(roots_xdg_surface->view); +	free(roots_xdg_surface->view);  	free(roots_xdg_surface);  } diff --git a/rootston/xwayland.c b/rootston/xwayland.c index 81f91b4f..6f9912e6 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -121,7 +121,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {  	if (xwayland_surface->mapped) {  		wl_list_remove(&roots_surface->view->link);  	} -	view_destroy(roots_surface->view); +	view_finish(roots_surface->view); +	free(roots_surface->view);  	free(roots_surface);  } @@ -233,24 +234,26 @@ static void handle_map_notify(struct wl_listener *listener, void *data) {  	view->wlr_surface = xsurface->surface;  	view->x = xsurface->x;  	view->y = xsurface->y; +	wl_list_insert(&desktop->views, &view->link); +  	view_damage_whole(view);  	roots_surface->surface_commit.notify = handle_surface_commit;  	wl_signal_add(&xsurface->surface->events.commit,  		&roots_surface->surface_commit); - -	wl_list_insert(&desktop->views, &view->link);  }  static void handle_unmap_notify(struct wl_listener *listener, void *data) {  	struct roots_xwayland_surface *roots_surface =  		wl_container_of(listener, roots_surface, unmap_notify); +	struct roots_view *view = roots_surface->view; -	view_damage_whole(roots_surface->view); - -	roots_surface->view->wlr_surface = NULL;  	wl_list_remove(&roots_surface->surface_commit.link); -	wl_list_remove(&roots_surface->view->link); + +	view_damage_whole(view); + +	view->wlr_surface = NULL; +	wl_list_remove(&view->link);  }  void handle_xwayland_surface(struct wl_listener *listener, void *data) {  | 
