diff --git a/src/wayland/foreign_toplevel.c b/src/wayland/foreign_toplevel.c index 5a699fdac..63a409a70 100644 --- a/src/wayland/foreign_toplevel.c +++ b/src/wayland/foreign_toplevel.c @@ -6,6 +6,9 @@ /* #include "protocols/wlr-foreign-toplevel-management-unstable-v1.h" */ #include "foreign_toplevel.h" +#include "../dunst.h" +#include "wl_output.h" +#include "wl.h" struct wl_list toplevel_list; @@ -33,16 +36,6 @@ static void print_toplevel(struct toplevel_v1 *toplevel, bool print_endl) { } static void print_toplevel_state(struct toplevel_v1 *toplevel, bool print_endl) { - if (toplevel->current.state & TOPLEVEL_STATE_MAXIMIZED) { - printf(" maximized"); - } else { - printf(" unmaximized"); - } - if (toplevel->current.state & TOPLEVEL_STATE_MINIMIZED) { - printf(" minimized"); - } else { - printf(" unminimized"); - } if (toplevel->current.state & TOPLEVEL_STATE_ACTIVATED) { printf(" active"); } else { @@ -59,30 +52,42 @@ static void print_toplevel_state(struct toplevel_v1 *toplevel, bool print_endl) static void toplevel_handle_output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel, - struct wl_output *output) { + struct wl_output *wl_output) { struct toplevel_v1 *toplevel = data; + struct toplevel_output *toplevel_output = calloc(1, sizeof(struct toplevel_output)); + struct dunst_output *dunst_output = wl_output_get_user_data(wl_output); + toplevel_output->dunst_output = dunst_output; + print_toplevel(toplevel, false); - printf(" enter output %u\n", - (uint32_t)(size_t)wl_output_get_user_data(output)); + printf(" enter output %u\n", dunst_output->global_name); + wl_list_insert(&toplevel->output_list, &toplevel_output->link); + struct toplevel_output *pos; + printf("Output list size %i\n", wl_list_length(&toplevel->output_list)); + wl_list_for_each(pos, &toplevel->output_list, link) { + printf("Testing fullscreen output %i\n", pos->dunst_output->global_name); + } } static void toplevel_handle_output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel, - struct wl_output *output) { + struct wl_output *wl_output) { struct toplevel_v1 *toplevel = data; print_toplevel(toplevel, false); - printf(" leave output %u\n", - (uint32_t)(size_t)wl_output_get_user_data(output)); + + struct dunst_output *output = wl_output_get_user_data(wl_output); + printf(" leave output %u\n", output->global_name); + struct toplevel_output *pos, *tmp; + wl_list_for_each_safe(pos, tmp, &toplevel->output_list, link){ + if (pos->dunst_output->name == output->name){ + wl_list_remove(&pos->link); + } + } } static uint32_t array_to_state(struct wl_array *array) { uint32_t state = 0; uint32_t *entry; wl_array_for_each(entry, array) { - if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED) - state |= TOPLEVEL_STATE_MAXIMIZED; - if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED) - state |= TOPLEVEL_STATE_MINIMIZED; if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED) state |= TOPLEVEL_STATE_ACTIVATED; if (*entry == ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN) @@ -102,13 +107,17 @@ static void toplevel_handle_state(void *data, static void toplevel_handle_done(void *data, struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel) { struct toplevel_v1 *toplevel = data; - bool state_changed = toplevel->current.state != toplevel->pending.state; + bool was_fullscreen = wl_have_fullscreen_window(); copy_state(&toplevel->current, &toplevel->pending); + bool is_fullscreen = wl_have_fullscreen_window(); - print_toplevel(toplevel, !state_changed); - if (state_changed) { + /* print_toplevel(toplevel, !state_changed); */ + if (was_fullscreen != is_fullscreen) { + print_toplevel(toplevel, false); print_toplevel_state(toplevel, true); + // TODO only wake up when important + wake_up(); } } @@ -118,6 +127,12 @@ static void toplevel_handle_closed(void *data, print_toplevel(toplevel, false); printf(" closed\n"); + wl_list_remove(&toplevel->link); + struct toplevel_output *pos, *tmp; + wl_list_for_each_safe(pos, tmp, &toplevel->output_list, link){ + free(pos); + } + free(toplevel); zwlr_foreign_toplevel_handle_v1_destroy(zwlr_toplevel); } @@ -144,6 +159,7 @@ static void toplevel_manager_handle_toplevel(void *data, toplevel->id = global_id++; toplevel->zwlr_toplevel = zwlr_toplevel; wl_list_insert(&toplevel_list, &toplevel->link); + wl_list_init(&toplevel->output_list); zwlr_foreign_toplevel_handle_v1_add_listener(zwlr_toplevel, &toplevel_impl, toplevel); @@ -158,3 +174,4 @@ const struct zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_impl = { .toplevel = toplevel_manager_handle_toplevel, .finished = toplevel_manager_handle_finished, }; +/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/wayland/foreign_toplevel.h b/src/wayland/foreign_toplevel.h index 57d472b4e..cae94a7c0 100644 --- a/src/wayland/foreign_toplevel.h +++ b/src/wayland/foreign_toplevel.h @@ -3,11 +3,9 @@ #include enum toplevel_state_field { - TOPLEVEL_STATE_MAXIMIZED = (1 << 0), - TOPLEVEL_STATE_MINIMIZED = (1 << 1), - TOPLEVEL_STATE_ACTIVATED = (1 << 2), - TOPLEVEL_STATE_FULLSCREEN = (1 << 3), - TOPLEVEL_STATE_INVALID = (1 << 4), + TOPLEVEL_STATE_ACTIVATED = (1 << 0), + TOPLEVEL_STATE_FULLSCREEN = (1 << 1), + TOPLEVEL_STATE_INVALID = (1 << 2), }; struct toplevel_state { @@ -17,12 +15,19 @@ struct toplevel_state { struct toplevel_v1 { struct wl_list link; struct zwlr_foreign_toplevel_handle_v1 *zwlr_toplevel; + struct wl_list output_list; uint32_t id; struct toplevel_state current, pending; }; +struct toplevel_output { + struct dunst_output *dunst_output; + struct wl_list link; +}; + extern const struct zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_impl; extern struct wl_list toplevel_list; #endif +/* vim: set ft=c tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/src/wayland/wl.c b/src/wayland/wl.c index ea7635b60..464227ca3 100644 --- a/src/wayland/wl.c +++ b/src/wayland/wl.c @@ -34,6 +34,7 @@ #include "../input.h" #include "libgwater-wayland.h" #include "foreign_toplevel.h" +#include "wl_output.h" #define MAX_TOUCHPOINTS 10 @@ -61,6 +62,7 @@ struct wl_ctx { struct wl_callback *frame_callback; struct org_kde_kwin_idle *idle_handler; struct org_kde_kwin_idle_timeout *idle_timeout; + uint32_t toplevel_manager_name; struct zwlr_foreign_toplevel_manager_v1 *toplevel_manager; bool configured; bool dirty; @@ -89,18 +91,6 @@ struct wl_ctx { struct wl_surface *cursor_surface; }; -struct dunst_output { - uint32_t global_name; - char *name; - struct wl_output *wl_output; - struct wl_list link; - - uint32_t scale; - uint32_t subpixel; // TODO do something with it - bool fullscreen; - struct zwlr_foreign_toplevel_handle_v1 *fullscreen_toplevel; // the toplevel that is fullscreened on this output -}; - struct wl_ctx ctx; static void noop() { @@ -414,12 +404,8 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0 && version >= ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN_SINCE_VERSION) { LOG_W("Found toplevel manager %i", name); - ctx.toplevel_manager = wl_registry_bind(registry, name, - &zwlr_foreign_toplevel_manager_v1_interface, - 2); - wl_list_init(&toplevel_list); - zwlr_foreign_toplevel_manager_v1_add_listener(ctx.toplevel_manager, - &toplevel_manager_impl, NULL); + ctx.toplevel_manager_name = name; + wl_list_init(&toplevel_list); } } @@ -450,10 +436,19 @@ bool wl_init() { return false; } + ctx.toplevel_manager_name = UINT32_MAX; + ctx.registry = wl_display_get_registry(ctx.display); wl_registry_add_listener(ctx.registry, ®istry_listener, NULL); LOG_W("First roundtrip"); wl_display_roundtrip(ctx.display); + if (ctx.toplevel_manager_name != UINT32_MAX) { + ctx.toplevel_manager = wl_registry_bind(ctx.registry, ctx.toplevel_manager_name, + &zwlr_foreign_toplevel_manager_v1_interface, + 2); + zwlr_foreign_toplevel_manager_v1_add_listener(ctx.toplevel_manager, + &toplevel_manager_impl, NULL); + } LOG_W("Second roundtrip"); wl_display_roundtrip(ctx.display); // load list of toplevels LOG_W("Third roundtrip"); @@ -827,33 +822,30 @@ bool wl_is_idle(void) { } bool wl_have_fullscreen_window(void) { - bool have_fullscreen = false; + struct dunst_output *current_output = get_configured_output(); + uint32_t output_name = UINT32_MAX; + if (current_output) + output_name = current_output->global_name; struct toplevel_v1 *toplevel; wl_list_for_each(toplevel, &toplevel_list, link) { - if (toplevel->current.state & TOPLEVEL_STATE_FULLSCREEN) { - LOG_D("Fullscreen queried: true"); - return true; - } - } - - struct dunst_output *current_output = get_configured_output(); - - if (!current_output) { - // Cannot detect focused output, so return true if any of the - // outputs is fullscreen. This will work even when unfocused - // outputs have fullscreen toplevels, since a toplevel has to - // be fullscreen and activate to consider an output fullscreen. - struct dunst_output *output; - wl_list_for_each(output, &ctx.outputs, link) { - have_fullscreen |= output->fullscreen; + if (!(toplevel->current.state & TOPLEVEL_STATE_FULLSCREEN && + toplevel->current.state & + TOPLEVEL_STATE_ACTIVATED)) + continue; + + struct toplevel_output *pos; + wl_list_for_each(pos, &toplevel->output_list, link) { + if (output_name == UINT32_MAX || + pos->dunst_output->global_name == + output_name) { + LOG_D("Fullscreen queried: 1"); + return true; + } } - } else { - have_fullscreen = current_output->fullscreen; } - - LOG_D("Fullscreen queried: %i", have_fullscreen); - return have_fullscreen; + LOG_D("Fullscreen queried: 0"); + return false; } double wl_get_scale(void) {