aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/desktop.c27
-rw-r--r--rootston/keyboard.c5
-rw-r--r--rootston/output.c140
-rw-r--r--rootston/rootston.ini.example2
-rw-r--r--rootston/seat.c4
-rw-r--r--rootston/wl_shell.c2
-rw-r--r--rootston/xdg_shell.c2
-rw-r--r--rootston/xdg_shell_v6.c2
-rw-r--r--rootston/xwayland.c4
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);
}
}