diff options
Diffstat (limited to 'rootston')
| -rw-r--r-- | rootston/desktop.c | 27 | ||||
| -rw-r--r-- | rootston/keyboard.c | 5 | ||||
| -rw-r--r-- | rootston/output.c | 140 | ||||
| -rw-r--r-- | rootston/rootston.ini.example | 2 | ||||
| -rw-r--r-- | rootston/seat.c | 4 | ||||
| -rw-r--r-- | rootston/wl_shell.c | 2 | ||||
| -rw-r--r-- | rootston/xdg_shell.c | 2 | ||||
| -rw-r--r-- | rootston/xdg_shell_v6.c | 2 | ||||
| -rw-r--r-- | rootston/xwayland.c | 4 | 
9 files changed, 143 insertions, 45 deletions
| diff --git a/rootston/desktop.c b/rootston/desktop.c index 6b28a41c..3628b051 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -10,6 +10,7 @@  #include <wlr/types/wlr_gamma_control.h>  #include <wlr/types/wlr_idle.h>  #include <wlr/types/wlr_output_layout.h> +#include <wlr/types/wlr_idle_inhibit_v1.h>  #include <wlr/types/wlr_primary_selection.h>  #include <wlr/types/wlr_server_decoration.h>  #include <wlr/types/wlr_wl_shell.h> @@ -22,6 +23,16 @@  #include "rootston/view.h"  #include "rootston/xcursor.h" + +struct roots_view *view_create() { +	struct roots_view *view = calloc(1, sizeof(struct roots_view)); +	if (!view) { +		return NULL; +	} +	view->alpha = 1.0f; +	return view; +} +  void view_get_box(const struct roots_view *view, struct wlr_box *box) {  	box->x = view->x;  	box->y = view->y; @@ -268,6 +279,15 @@ void view_rotate(struct roots_view *view, float rotation) {  	view_damage_whole(view);  } +void view_cycle_alpha(struct roots_view *view) { +	view->alpha -= 0.05; +	/* Don't go completely transparent */ +	if (view->alpha < 0.1) { +		view->alpha = 1.0; +	} +	view_damage_whole(view); +} +  void view_close(struct roots_view *view) {  	if (view->close) {  		view->close(view); @@ -425,13 +445,17 @@ void view_init(struct roots_view *view, struct roots_desktop *desktop) {  	view_damage_whole(view);  } -void view_setup(struct roots_view *view) { +void view_initial_focus(struct roots_view *view) {  	struct roots_input *input = view->desktop->server->input;  	// TODO what seat gets focus? the one with the last input event?  	struct roots_seat *seat;  	wl_list_for_each(seat, &input->seats, link) {  		roots_seat_set_focus(seat, view);  	} +} + +void view_setup(struct roots_view *view) { +	view_initial_focus(view);  	view_center(view);  	view_update_output(view, NULL); @@ -703,6 +727,7 @@ struct roots_desktop *desktop_create(struct roots_server *server,  	desktop->primary_selection_device_manager =  		wlr_primary_selection_device_manager_create(server->wl_display);  	desktop->idle = wlr_idle_create(server->wl_display); +	desktop->idle_inhibit = wlr_idle_inhibit_v1_create(server->wl_display);  	return desktop;  } diff --git a/rootston/keyboard.c b/rootston/keyboard.c index 6ec90c31..b5dac51c 100644 --- a/rootston/keyboard.c +++ b/rootston/keyboard.c @@ -106,6 +106,11 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,  		}  	} else if (strcmp(command, "next_window") == 0) {  		roots_seat_cycle_focus(seat); +	} else if (strcmp(command, "alpha") == 0) { +		struct roots_view *focus = roots_seat_get_focus(seat); +		if (focus != NULL) { +			view_cycle_alpha(focus); +		}  	} else if (strncmp(exec_prefix, command, strlen(exec_prefix)) == 0) {  		const char *shell_cmd = command + strlen(exec_prefix);  		pid_t pid = fork(); diff --git a/rootston/output.c b/rootston/output.c index 8ef383c3..4d0a9c05 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -182,26 +182,46 @@ static void xwayland_children_for_each_surface(  }  #endif +static void drag_icons_for_each_surface(struct roots_input *input, +		surface_iterator_func_t iterator, void *user_data) { +	struct roots_seat *seat; +	wl_list_for_each(seat, &input->seats, link) { +		struct roots_drag_icon *drag_icon; +		wl_list_for_each(drag_icon, &seat->drag_icons, link) { +			if (!drag_icon->wlr_drag_icon->mapped) { +				continue; +			} +			surface_for_each_surface(drag_icon->wlr_drag_icon->surface, +				drag_icon->x, drag_icon->y, 0, iterator, user_data); +		} +	} +} +  struct render_data {  	struct roots_output *output;  	struct timespec *when;  	pixman_region32_t *damage; +	float alpha;  };  /** - * Checks whether a surface at (lx, ly) intersects an output. Sets `box` to the - * surface box in the output, in output-local coordinates. + * Checks whether a surface at (lx, ly) intersects an output. If `box` is not + * NULL, it populates it with the surface box in the output, in output-local + * coordinates.   */  static bool surface_intersect_output(struct wlr_surface *surface,  		struct wlr_output_layout *output_layout, struct wlr_output *wlr_output,  		double lx, double ly, float rotation, struct wlr_box *box) {  	double ox = lx, oy = ly;  	wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); -	box->x = ox * wlr_output->scale; -	box->y = oy * wlr_output->scale; -	box->width = surface->current->width * wlr_output->scale; -	box->height = surface->current->height * wlr_output->scale; + +	if (box != NULL) { +		box->x = ox * wlr_output->scale; +		box->y = oy * wlr_output->scale; +		box->width = surface->current->width * wlr_output->scale; +		box->height = surface->current->height * wlr_output->scale; +	}  	struct wlr_box layout_box = {  		.x = lx, .y = ly, @@ -239,7 +259,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,  		float rotation, void *_data) {  	struct render_data *data = _data;  	struct roots_output *output = data->output; -	struct timespec *when = data->when;  	struct wlr_renderer *renderer =  		wlr_backend_get_renderer(output->wlr_output->backend);  	assert(renderer); @@ -278,11 +297,9 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,  	pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);  	for (int i = 0; i < nrects; ++i) {  		scissor_output(output, &rects[i]); -		wlr_render_with_matrix(renderer, surface->texture, &matrix); +		wlr_render_with_matrix(renderer, surface->texture, &matrix, data->alpha);  	} -	wlr_surface_send_frame_done(surface, when); -  damage_finish:  	pixman_region32_fini(&damage);  } @@ -339,7 +356,7 @@ static void render_decorations(struct roots_view *view,  	float matrix[16];  	wlr_matrix_project_box(&matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,  		view->rotation, &output->wlr_output->transform_matrix); -	float color[] = { 0.2, 0.2, 0.2, 1 }; +	float color[] = { 0.2, 0.2, 0.2, view->alpha };  	int nrects;  	pixman_box32_t *rects = @@ -360,6 +377,7 @@ static void render_view(struct roots_view *view, struct render_data *data) {  		return;  	} +	data->alpha = view->alpha;  	render_decorations(view, data);  	view_for_each_surface(view, render_surface, data);  } @@ -384,6 +402,20 @@ static bool has_standalone_surface(struct roots_view *view) {  	return true;  } +static void surface_send_frame_done(struct wlr_surface *surface, double lx, +		double ly, float rotation, void *_data) { +	struct render_data *data = _data; +	struct roots_output *output = data->output; +	struct timespec *when = data->when; + +	if (!surface_intersect_output(surface, output->desktop->layout, +			output->wlr_output, lx, ly, rotation, NULL)) { +		return; +	} + +	wlr_surface_send_frame_done(surface, when); +} +  static void render_output(struct roots_output *output) {  	struct wlr_output *wlr_output = output->wlr_output;  	struct roots_desktop *desktop = output->desktop; @@ -434,17 +466,18 @@ static void render_output(struct roots_output *output) {  		return;  	} -	if (!needs_swap) { -		// Output doesn't need swap and isn't damaged, skip rendering completely -		goto damage_finish; -	} -  	struct render_data data = {  		.output = output,  		.when = &now,  		.damage = &damage, +		.alpha = 1.0,  	}; +	if (!needs_swap) { +		// Output doesn't need swap and isn't damaged, skip rendering completely +		goto damage_finish; +	} +  	wlr_renderer_begin(renderer, wlr_output);  	if (!pixman_region32_not_empty(&damage)) { @@ -490,17 +523,8 @@ static void render_output(struct roots_output *output) {  	}  	// Render drag icons -	struct roots_drag_icon *drag_icon = NULL; -	struct roots_seat *seat = NULL; -	wl_list_for_each(seat, &server->input->seats, link) { -		wl_list_for_each(drag_icon, &seat->drag_icons, link) { -			if (!drag_icon->wlr_drag_icon->mapped) { -				continue; -			} -			render_surface(drag_icon->wlr_drag_icon->surface, -				drag_icon->x, drag_icon->y, 0, &data); -		} -	} +	data.alpha = 1.0; +	drag_icons_for_each_surface(server->input, render_surface, &data);  renderer_end:  	wlr_renderer_scissor(renderer, NULL); @@ -512,12 +536,32 @@ renderer_end:  damage_finish:  	pixman_region32_fini(&damage); -} -static void output_damage_handle_frame(struct wl_listener *listener, -		void *data) { -	struct roots_output *output = wl_container_of(listener, output, frame); -	render_output(output); +	// Send frame done events to all surfaces +	if (output->fullscreen_view != NULL) { +		struct roots_view *view = output->fullscreen_view; +		if (wlr_output->fullscreen_surface == view->wlr_surface) { +			// The surface is managed by the wlr_output +			return; +		} + +		view_for_each_surface(view, surface_send_frame_done, &data); + +#ifdef WLR_HAS_XWAYLAND +		if (view->type == ROOTS_XWAYLAND_VIEW) { +			xwayland_children_for_each_surface(view->xwayland_surface, +				surface_send_frame_done, &data); +		} +#endif +	} else { +		struct roots_view *view; +		wl_list_for_each_reverse(view, &desktop->views, link) { +			view_for_each_surface(view, surface_send_frame_done, &data); +		} + +		drag_icons_for_each_surface(server->input, surface_send_frame_done, +			&data); +	}  }  void output_damage_whole(struct roots_output *output) { @@ -681,19 +725,37 @@ static void set_mode(struct wlr_output *output,  	}  } -static void output_handle_destroy(struct wl_listener *listener, void *data) { -	struct roots_output *output = wl_container_of(listener, output, destroy); - +static void output_destroy(struct roots_output *output) {  	// TODO: cursor  	//example_config_configure_cursor(sample->config, sample->cursor,  	//	sample->compositor);  	wl_list_remove(&output->link);  	wl_list_remove(&output->destroy.link); -	wl_list_remove(&output->frame.link); +	wl_list_remove(&output->damage_frame.link); +	wl_list_remove(&output->damage_destroy.link);  	free(output);  } +static void output_handle_destroy(struct wl_listener *listener, void *data) { +	struct roots_output *output = wl_container_of(listener, output, destroy); +	output_destroy(output); +} + +static void output_damage_handle_frame(struct wl_listener *listener, +		void *data) { +	struct roots_output *output = +		wl_container_of(listener, output, damage_frame); +	render_output(output); +} + +static void output_damage_handle_destroy(struct wl_listener *listener, +		void *data) { +	struct roots_output *output = +		wl_container_of(listener, output, damage_destroy); +	output_destroy(output); +} +  void handle_new_output(struct wl_listener *listener, void *data) {  	struct roots_desktop *desktop = wl_container_of(listener, desktop,  		new_output); @@ -722,8 +784,10 @@ void handle_new_output(struct wl_listener *listener, void *data) {  	output->destroy.notify = output_handle_destroy;  	wl_signal_add(&wlr_output->events.destroy, &output->destroy); -	output->frame.notify = output_damage_handle_frame; -	wl_signal_add(&output->damage->events.frame, &output->frame); +	output->damage_frame.notify = output_damage_handle_frame; +	wl_signal_add(&output->damage->events.frame, &output->damage_frame); +	output->damage_destroy.notify = output_damage_handle_destroy; +	wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);  	struct roots_output_config *output_config =  		roots_config_get_output(config, wlr_output); diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example index a6619767..6f29a35d 100644 --- a/rootston/rootston.ini.example +++ b/rootston/rootston.ini.example @@ -42,8 +42,10 @@ meta-key = Logo  # - "exec" to execute a shell command  # - "close" to close the current view  # - "next_window" to cycle through windows +# - "alpha" to cycle a window's alpha channel  [bindings]  Logo+Shift+e = exit  Logo+q = close  Logo+m = maximize  Alt+Tab = next_window +Ctrl+Shift+a = alpha diff --git a/rootston/seat.c b/rootston/seat.c index 38c26628..9acbb737 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -408,10 +408,10 @@ static void handle_keyboard_destroy(struct wl_listener *listener, void *data) {  	struct roots_keyboard *keyboard =  		wl_container_of(listener, keyboard, device_destroy);  	struct roots_seat *seat = keyboard->seat; -	roots_keyboard_destroy(keyboard);  	wl_list_remove(&keyboard->device_destroy.link);  	wl_list_remove(&keyboard->keyboard_key.link);  	wl_list_remove(&keyboard->keyboard_modifiers.link); +	roots_keyboard_destroy(keyboard);  	seat_update_capabilities(seat);  } @@ -721,7 +721,7 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) {  #ifdef WLR_HAS_XWAYLAND  	if (view && view->type == ROOTS_XWAYLAND_VIEW && -			view->xwayland_surface->override_redirect) { +			wlr_xwayland_surface_is_unmanaged(view->xwayland_surface)) {  		return;  	}  #endif diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 44a65cf5..899df1c6 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -227,7 +227,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {  	roots_surface->surface_commit.notify = handle_surface_commit;  	wl_signal_add(&surface->surface->events.commit, &roots_surface->surface_commit); -	struct roots_view *view = calloc(1, sizeof(struct roots_view)); +	struct roots_view *view = view_create();  	if (!view) {  		free(roots_surface);  		return; diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index 8340de46..9368ce0b 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -333,7 +333,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {  	roots_surface->new_popup.notify = handle_new_popup;  	wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); -	struct roots_view *view = calloc(1, sizeof(struct roots_view)); +	struct roots_view *view = view_create();  	if (!view) {  		free(roots_surface);  		return; diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 8e6674ab..eda349cb 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -333,7 +333,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {  	roots_surface->new_popup.notify = handle_new_popup;  	wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); -	struct roots_view *view = calloc(1, sizeof(struct roots_view)); +	struct roots_view *view = view_create();  	if (!view) {  		free(roots_surface);  		return; diff --git a/rootston/xwayland.c b/rootston/xwayland.c index e9e0d5e0..56f068ea 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -317,7 +317,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {  	wl_signal_add(&surface->surface->events.commit,  		&roots_surface->surface_commit); -	struct roots_view *view = calloc(1, sizeof(struct roots_view)); +	struct roots_view *view = view_create();  	if (view == NULL) {  		free(roots_surface);  		return; @@ -350,5 +350,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {  		}  		view_setup(view); +	} else { +		view_initial_focus(view);  	}  } | 
