Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
addopts = -n 4
23 changes: 23 additions & 0 deletions scroll.lua
Original file line number Diff line number Diff line change
Expand Up @@ -653,4 +653,27 @@ function scroll.add_callback(event, cb_func, cb_data) end
--- @return integer
function scroll.remove_callback(id) end

---
--- Returns true if there is an active animation running.
---
--- This is primarily intended for use via the IPC interface for testing and
--- debugging. It is generally not useful when called synchronously within a
--- Lua script, as animations only start after the script execution completes.
---
--- @return boolean
---
function scroll.animating() end

---
--- Returns true if there are pending transactions that haven't been applied yet.
---
--- This is primarily intended for use via the IPC interface for testing and
--- debugging. It is generally not useful when called synchronously within a
--- Lua script, as transactions are not processed while the script is running
--- and blocking the main thread.
---
--- @return boolean
---
function scroll.pending_transactions() end

return scroll
29 changes: 22 additions & 7 deletions sway/desktop/xdg_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,20 @@ static const struct sway_view_impl view_impl = {
.destroy = destroy,
};

static bool is_commit_stale(struct sway_view *view, struct wlr_xdg_surface *xdg_surface) {
uint32_t latest_serial = 0;
if (xdg_surface->configure_idle != NULL) {
latest_serial = xdg_surface->scheduled_serial;
} else if (!wl_list_empty(&xdg_surface->configure_list)) {
struct wlr_xdg_surface_configure *configure =
wl_container_of(xdg_surface->configure_list.prev, configure, link);
latest_serial = configure->serial;
} else {
return false;
}
return xdg_surface->current.configure_serial < latest_serial;
}

static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, commit);
Expand Down Expand Up @@ -341,20 +355,21 @@ static void handle_commit(struct wl_listener *listener, void *data) {
new_geo->height != view->geometry.height ||
new_geo->x != view->geometry.x ||
new_geo->y != view->geometry.y;

if (new_size) {
// The client changed its surface size in this commit. For floating
// containers, we resize the container to match. For tiling containers,
// we only recenter the surface.
memcpy(&view->geometry, new_geo, sizeof(struct wlr_box));
if (container_is_floating(view->container)) {
view_update_size(view);
// Only set the toplevel size the current container actually has a size.
if (view->container->current.width) {
wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width,
view->geometry.height);
if (!is_commit_stale(view, xdg_surface)) {
view_update_size(view);
// Only set the toplevel size the current container actually has a size.
if (view->container->current.width) {
wlr_xdg_toplevel_set_size(
view->wlr_xdg_toplevel, view->geometry.width, view->geometry.height);
}
transaction_commit_dirty_client();
}
transaction_commit_dirty_client();
}

view_center_and_clip_surface(view);
Expand Down
17 changes: 17 additions & 0 deletions sway/lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "sway/desktop/launcher.h"
#include "sway/ipc-server.h"
#include "sway/desktop/transaction.h"
#include "sway/server.h"

#if 0
static void print_table(lua_State *L, int index);
Expand Down Expand Up @@ -1727,7 +1728,20 @@ static int scroll_remove_callback(lua_State *L) {
return 0;
}

static int scroll_animating(lua_State *L) {
lua_pushboolean(L, animation_animating());
return 1;
}

static int scroll_pending_transactions(lua_State *L) {
bool pending = server.queued_transaction != NULL || server.pending_transaction != NULL ||
server.dirty_nodes->length > 0;
lua_pushboolean(L, pending);
return 1;
}

// Module functions
/* clang-format off */
static luaL_Reg const scroll_lib[] = {
{ "log", scroll_log },
{ "state_set_value", scroll_state_set_value },
Expand Down Expand Up @@ -1798,8 +1812,11 @@ static luaL_Reg const scroll_lib[] = {
{ "scratchpad_hide", scroll_scratchpad_hide },
{ "add_callback", scroll_add_callback },
{ "remove_callback", scroll_remove_callback },
{ "animating", scroll_animating },
{ "pending_transactions", scroll_pending_transactions },
{ NULL, NULL }
};
/* clang-format on */

// Module Loader
int luaopen_scroll(lua_State *L) {
Expand Down
22 changes: 21 additions & 1 deletion sway/scroll.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -2402,7 +2402,27 @@ local process_data = scroll.exec_process("kitty")
Removes a callback set earlier using *add_callback*. _id_ is the unique
identifier returned by *add_callback*.

Examples:
## TESTING AND DEBUGGING API

These functions are primarily intended for use via the IPC interface (see
*scroll-ipc*(7)) for testing and debugging purposes, and are generally not
useful when called synchronously from standard Lua scripts or event callbacks.

Because scroll's Lua integration executes scripts synchronously on the main
compositor thread, the event loop is blocked during execution. This means that
any compositor actions triggered by the script (such as applying window layouts
or starting animations) will only occur after the script completes.
Consequently, calling these functions synchronously within a script will not
reflect the state changes of commands run immediately before them.

*animating()*
Returns _true_ if there is an active animation running.

*pending_transactions()*
Returns _true_ if there are pending transactions that haven't been applied
yet.

## EXAMPLES

Calling this script from the configuration file, you will get focus on every
window that gets the *urgent* attribute:
Expand Down
20 changes: 19 additions & 1 deletion tests/clients/wayland-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct client_state {
struct xdg_toplevel *xdg_toplevel;
struct wl_buffer *buffer;
int width, height;
int buffer_width, buffer_height;
void *shm_data;
};

Expand Down Expand Up @@ -51,6 +52,14 @@ static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, u
struct client_state *state = data;
xdg_surface_ack_configure(xdg_surface, serial);

if (state->buffer &&
(state->buffer_width != state->width || state->buffer_height != state->height)) {
wl_buffer_destroy(state->buffer);
state->buffer = NULL;
munmap(state->shm_data, state->buffer_width * 4 * state->buffer_height);
state->shm_data = NULL;
}

if (!state->buffer) {
int stride = state->width * 4;
int size = stride * state->height;
Expand Down Expand Up @@ -78,6 +87,8 @@ static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, u
for (int i = 0; i < state->width * state->height; ++i) {
pixels[i] = 0xFF0000FF; // Blue
}
state->buffer_width = state->width;
state->buffer_height = state->height;
}

wl_surface_attach(state->surface, state->buffer, 0, 0);
Expand All @@ -86,7 +97,14 @@ static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, u
}
static const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure };

static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) {}
static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width,
int32_t height, struct wl_array *states) {
struct client_state *state = data;
if (width > 0 && height > 0) {
state->width = width;
state->height = height;
}
}
static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) {
exit(0);
}
Expand Down
Loading